Important: When accessing a related model, the effective ACL (the one considered to resolve access permission) is the one for the model you are primarily calling. So if a given model has no ACL, then all the endpoints accessible through the model relations will be open, even if a related model has DENY ALL permissions set.
This can be a security risk since, for example, GET /OpenModel/{id}/ACLSecuredModel
will allow full access to ACLSecuredModel
through the OpenModel
relations.
Restricting access to related models
When two models have a relationship between them (see Creating model relations), LoopBack automatically creates a set of related model methods corresponding to the API routes defined for the relationship.
In the following list, modelName is the name of the related model and modelNamePlural is the plural form of the related model name.
Note:
In the method names below, the separators are double underscores, __.
belongsTo:
- __get__relatedModelName
hasOne:
- __create__relatedModelName
- __get__relatedModelName
- __update__relatedModelName
- __destroy__relatedModelName
hasMany:
- __count__relatedModelNamePlural
- __create__relatedModelNamePlural
- __delete__relatedModelNamePlural
- __destroyById__relatedModelNamePlural
- __findById__relatedModelNamePlural
- __get__relatedModelNamePlural
- __updateById__relatedModelNamePlural
hasManyThrough:
- __count__relatedModelNamePlural
- __create__relatedModelNamePlural
- __delete__relatedModelNamePlural
- __destroyById__relatedModelNamePlural
- __exists__relatedModelNamePlural (through only)
- __findById__relatedModelNamePlural
- __get__relatedModelNamePlural
- __link__relatedModelNamePlural (through only)
- __updateById__relatedModelNamePlural
- __unlink__relatedModelNamePlural (through only)
hasAndBelongsToMany:
- __link__relatedModelNamePlural
- __unlink__relatedModelNamePlural
You can use these related model methods to control access to the related routes.
For example, if a User hasMany projects, LoopBack creates these routes (among others) and the corresponding related model methods:
/api/users/count
- standard method iscount
/api/users/:id/projects
- related model method is__get__projects
/api/users/:id/projects/count
- related model method is__count__projects
Important:
If a model has a DENY ALL
permission (for example a built-in model such as the User model), but related models have no ACLs,the related models will still not be accessible through the User model.
So, for example, even if the books model’s default ACL is ALLOW $authenticated
for GET /books
,
the route GET /user/{id}/books
default will still be DENY ALL.
To configure access control to such routes, set the permission on the related model methods in the model definition JSON file.
For example, the ACL for the User model definition JSON file (user.json
) for these routes might look like this, for example:
"acls": [{
"principalType": "ROLE",
"principalId": "$authenticated",
"permission": "ALLOW",
"property": "count"
}, {
"principalType": "ROLE",
"principalId": "$owner",
"permission": "ALLOW",
"property": "__get__projects"
}, {
"principalType": "ROLE",
"principalId": "$authenticated",
"permission": "ALLOW",
"property": "__count__projects"
}]
Querying related models
Important:
This feature requires LoopBack 2.16.0 or later.
When querying a model, you may also want to return data from its related models.
For example, suppose you have three models: User
, Report
, and LineItem
, where:
- A user can have many reports; that is, there is a HasMany relation
between
User
andReport
(User hasMany Report). - A report can have many line items; that is, there is a HasMany relation
between
Report
andLineitem
(Report hasMany LineItem).
Additionally, the ReportModel is configured with the following ACLs so that authenticated users can create new records and users can update their own records:
[{
"principalType": "ROLE",
"principalId": "$everyone",
"permission": "DENY"
}, {
"principalType": "ROLE",
"principalId": "$owner",
"permission": "ALLOW",
"property": "findById"
},
...
]
Assume the LineItem model has the same ACL defined.
Now, suppose you want to fetch a model owned by your user and also get at its related models.
Here is how you do it with findById()
using the Node API:
Report.findById(1, {include: 'lineitems'});
Using the REST API:
GET /api/Reports/110?filter={"include":["lineItems"]}
Example results:
{
"name": "january report - bob",
"id": 110,
"userId": 100,
"lineItemModels": [{
"name": "lunch",
"id": 111,
"reportModelId": 110
}, {
"name": "dinner",
"id": 112,
"reportModelId": 110
}]
}