There is a model Message, which has two belongsTo relations to different Users: sender and receiver. However, the $owner of the model is defined by the first relation in model declaration. While the second relation still exists, it does not qualify related user as the owner. Is this the expected behavior? Is there a way to work this around, without introducing a new custom role?
The code stops at the 1st belongsTo user relation. See https://github.com/strongloop/loopback/blob/master/common/models/role.js#L199-L208. I wonder if it makes sense to allow multiple belongsTo relations.
Or, if it is allowed to have multiple belongsTo, does it make sense to:
In any case, with the current implementation if you have two belongsTo, then $owner depends on how you define the order of relations in Model declaration. Which I think is not very obvious, and it would be great to make it more transparent.
So what would be the suggested way to configure multiple owners of the same Model?
I propose that we add the ability to tag the belongsTo relation with a roles property, for example,
"order": {
"properties": {...},
"relations": {
"user": {
"type": "belongsTo",
"model": "User",
"roles": ["owner"]
}
}
}
Any updates on this? I am facing the same problem. How to handle relation if sender and reciever both belong to the same Messenger model.
Does hasMany relationtionship will work for the Messenger(User) model where Messenger hasMany messages can be defined.
yes this is an issue for sure. More than one owner should be allowed
Hey, at least this ticket is here... i spent a couple of hours on this issue, not knowing that it is not possible. since there is no mention, that this is not supported and the API is created, but wont work on the second owner. Is there a best practice on this?
I guess i ditch then the whole belongsTo relation if i have two owner and do it manually
Is there any update on this issue? I have a similar problem. I have two models Merchant and Consumer, data model belongs to both merchant and consumer. I want to use owner relation on this data. But only consumer is working because it is declared first. Is there any way to use both of them?
+1
+1
+1
+1
+1
+1
+1
A way around this issue is to set up custom role resolvers, for example:
{
"name": "Message",
"plural": "Messages",
"base": "PersistedModel",
"idInjection": true,
"options": {
"validateUpsert": true
},
"properties": {
"text": {
"type": "string",
"required": true
},
"created": {
"type": "date",
"required": true,
"default": "$now"
}
},
"validations": [],
"relations": {
"conversation": {
"type": "belongsTo",
"model": "Conversation",
"foreignKey": ""
},
"author": {
"type": "belongsTo",
"model": "Creator",
"foreignKey": ""
},
"readBy": {
"type": "hasMany",
"model": "Creator",
"foreignKey": "",
"through": "MessageReader"
}
},
"acls": [
{
"accessType": "*",
"principalType": "ROLE",
"principalId": "$everyone",
"permission": "DENY"
},
{
"accessType": "EXECUTE",
"principalType": "ROLE",
"principalId": "messageAuthor",
"permission": "ALLOW",
"property": "get"
},
{
"accessType": "EXECUTE",
"principalType": "ROLE",
"principalId": "messageAuthor",
"permission": "ALLOW",
"property": "find"
},
{
"accessType": "EXECUTE",
"principalType": "ROLE",
"principalId": "messageAuthor",
"permission": "ALLOW",
"property": "findById"
}
],
"methods": {}
}
Note that there are multiple creators (users) present in the message model. If using $owner, it will always default to the first creator (user) it encounters. If you apply a custom role resolver via the principalId, you can run custom code to determine if the user querying the route should have access or not. In this case it would be as simple as ensuring that the message author attribute is used instead of the user(s) that have read the message.
Role.registerResolver('messageAuthor', function(role, ctx, callback) {
var userId = ctx.accessToken.userId;
if(ctx.modelName !== 'Message') {
return process.nextTick(() => callback(new Error('Invalid usage of messageAuthor role resolver on ' + ctx.modelName + ' model.'), false));
}
if(!userId) {
var error = new Error('Authorization required.');
error.statusCode = 401;
return process.nextTick(() => callback(error, false));
}
var messageId = ctx.remotingContext.args.id;
app.models.Message.findOne(
{
where: {
id: messageId,
authorId: userId
}
},
function(error, conversationMember) {
if(error) {
return callback(error);
}
if(!conversationMember) {
var error = new Error('Authorization required.');
error.statusCode = 401;
return callback(error);
}
return callback(null, true);
}
);
});
+1
+1
+1
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
This issue has been closed due to continued inactivity. Thank you for your understanding. If you believe this to be in error, please contact one of the code owners, listed in the CODEOWNERS file at the top-level of this repository.
Since 3.13.0 has broken even the current working $owner relations and introduced "ownerRelations" as per ef7175a and now that this warning appears:
The app configuration follows the multiple user models setup as described in http://ibm.biz/setup-loopback-auth The built-in role resolver $owner is not currently compatible with this configuration and should not be used in production
Is there any documentation on how and where to use "ownerRelations"?
Where to place {ownerRelations: true}? In every model that extends the User model? Under which object?
@raymondfeng
@pierreclr
@shaheero I believe this is related to #3644.
I don't think adding {ownerRelations: true} will make the warning go away, but as far as I undersand, you would need to add it to to the root level of your model.json files.
+1
There is a model
Message, which has twobelongsTorelations to different Users:senderandreceiver. However, the $owner of the model is defined by the first relation in model declaration. While the second relation still exists, it does not qualify related user as the owner. Is this the expected behavior? Is there a way to work this around, without introducing a new custom role?
You can simply create two relations and also create the fields (senderId, receiverId) in the message table as foreign Keys :
"relations": {
"receiver": {
"type": "belongsTo",
"model": "User",
"foreignKey": "receiverId"
},
"sender": {
"type": "belongsTo",
"model": "User",
"foreignKey": "senderId"
}
}
Most helpful comment
A way around this issue is to set up custom role resolvers, for example:
Message.json
Note that there are multiple creators (users) present in the message model. If using $owner, it will always default to the first creator (user) it encounters. If you apply a custom role resolver via the principalId, you can run custom code to determine if the user querying the route should have access or not. In this case it would be as simple as ensuring that the message author attribute is used instead of the user(s) that have read the message.
Message Author Role Resolver