In my app I need users to be given access to organisations according to a many-to-many relationship like this:
App.User = DS.Model.extend({
fullname: DS.attr('string'),
password: DS.attr('string'),
administrator: DS.attr('boolean'),
organisation_users: DS.hasMany('organisation_user', {async: true})
});
App.OrganisationUser = DS.Model.extend({
organisation: DS.belongsTo('organisation', {async: true}),
user: DS.belongsTo('user', {async: true}),
administrator: DS.attr('boolean')
});
App.Organisation = DS.Model.extend({
fullname: DS.attr('string', {defaultValue: 'Unnamed University'}),
description: DS.attr('string'),
organisation_users: DS.hasMany('organisation_user', {asynch: false}),
});
I am using Ember SimpleAuth for authentication. So based on this answer to a previous question I have implemented isAuthorised on my OrganisationController like this:
App.OrganisationController = Ember.Controller.extend({
//Determine whether the logged in user is authorised
isAuthorised: function() {
if(!this.get('session.isAuthenticated')) {
console.log("Not logged in...");
return false;
}
console.log("Does user [" + this.get('session.user.id') + "] have access to organisation [" + this.get('model.id') + "]?");
if(this.get('session.user.administrator')) {
console.log("Yes, because they are an administrator.");
return true;
} else {
console.log("Well, they are not an administrator so...");
}
console.log("We need to check " + this.get('model.fullname') + " for authorised users.");
this.get('model.organisation_users').forEach(function(org_user){
org_user.get('user').then(function(user) {
console.log(user.get('fullname') + " has access");
});
});
}.property('model', 'session.user'),
The problem is, I don't know how to return a value from this. Also, when I load the OrganisationRoute it seems to work OK but when I load a different route and transition into this route, it fails with
Uncaught TypeError: Cannot read property 'resolve' of undefined
and
Uncaught Error: Something you did caused a view to re-render after it rendered but before it was inserted into the DOM.
I think your bug is stemming from this chunk of code (you are having some sideloading issues, I think):
this.get('model.organisation_users').forEach(function(org_user){
org_user.get('user').then(function(user) { // org_user hasn't loaded its user record?
console.log(user.get('fullname') + " has access");
});
});
I would probably go with a pattern like this:
return this.get('organisation_users').any(function (item) {
return item.get('user.id') === this.get('session.user.id');
});
.any
will enumerate until the callback returns true. If true, the outer scope will return true, which is what you want.
If nothing matches, you get false. Pretty straightforward.
The other piece to this puzzle is the sideloading, as I mentioned earlier in the answer.