Hey,
I would like to know, if it is possible, to use ember-data REST Adapter (or other DS.Store things) for a custom authenticator.
I think it is not possible atm, because the order of the initializers does not allow it, but i would like to show some advantages, it mit bring with it, to be able to use the ember-data store:
Current-Code:
// app/authenticators/custom.js
import Base from 'simple-auth/authenticators/base';
import Ember from 'ember';
export default Base.extend({
restore: function (data) {
return new Ember.RSVP.Promise(function(resolve, reject) {
if(Ember.isEmpty(data)) {
reject();
}
Ember.$.getJSON('/api/sessions').then(function(responseObject) {
if(responseObject.sessions.length === 0) {
reject();
return;
}
if(responseObject.sessions[0].id !== data.id) {
reject();
return;
}
resolve(responseObject.sessions[0]);
}, function(jqXHR) {
reject(jqXHR);
});
});
},
authenticate: function (options) {
return new Ember.RSVP.Promise(function(resolve, reject) {
Ember.$.ajax({
url: '/api/sessions',
type: 'POST',
data: {
session: options
},
dataType: 'json'
}).then(function(responseObject/*, statusText, jqXHR*/) {
Ember.run(function() {
resolve(responseObject.sessions[0]);
});
}, function(jqXHR/*, textStatus, errorThrown*/) {
Ember.run(function() {
reject(jqXHR);
});
});
});
},
invalidate: function (data) {
console.log('invalidate', data);
}
});
Possible improvements with a store (just kind of Pseudo Code because it does not work atm):
import Base from 'simple-auth/authenticators/base';
import Ember from 'ember';
export default Base.extend({
restore: function (data) {
var _this = this;
return new Ember.RSVP.Promise(function(resolve, reject) {
if(Ember.isEmpty(data)) {
reject();
}
_this.get('store').find('session', data.id).then(function() {
resolve();
}, function() {
reject();
});
});
},
authenticate: function (options) {
var session = this.get('store').createRecord('session', options);
session.save().then(function() {
resolve();
}, function() {
reject();
});
},
invalidate: function (data) {
// same with delete record
}
});
It is not just the simple usage of the store, but also the real "model behaviour", which would be interesting. So you could do something like:
App.Session = DS.Model.extend({
created: DS.attr('date'),
modified: DS.attr('date'),
user: DS.belongsTo('user'),
roles: DS.hasMany('role')
});
And it is all resolved in the session to perform RBAC or something similar.
Conclusion:
// ...
if(this.get('session').isGranted('MYROLE'))
// ...
What do you think? Is it worth it?
Perhaps in an BaseDataAuthenticator which requires ember-data...?
You can always implement a custom authenticator that works as you describe above. Not sure what you suggest to change in Ember Simple Auth here.
The store is not accessible / undefined, when I try to use it in CustomAuthenticator:
// app/authenticators/custom.js
import Base from 'simple-auth/authenticators/base';
import Ember from 'ember';
export default Base.extend({
restore: function (data) {
// ...
// undefined
console.log(this.get('store'));
// ...
},
authenticate: function (options) {
// ...
// undefined
console.log(this.get('store'));
// ...
},
invalidate: function (data) {
// ...
// undefined
console.log(this.get('store'));
// ...
}
});
In a controller for example i could use it like:
var user = this.get('store').createRecord('user', { username: 'sandreas'});
You have to inject the store into your authenticator in an initializer.
I'm sorry, but could you provide an example for this? I did not manage to get the store in here:
// app/initializers/initializer-authentication.js
import CustomAuthenticator from '../authenticators/custom';
import CustomAuthorizer from '../authorizers/custom';
export default {
name: 'authentication',
before: 'simple-auth',
initialize: function(container, application) {
container.register('simple-auth-authenticator:custom', CustomAuthenticator);
container.register('simple-auth-authorizer:custom', CustomAuthorizer);
// undefined
console.log("store", application.get('store'));
}
};
// app/initializers/initializer-store-for-auth.js
export default {
name: 'store-for-auth',
after: 'store',
initialize: function(container, application) {
console.log("store", application.get('store:main'));
}
};
// app/initializers/initializer-authentication.js
import CustomAuthenticator from '../authenticators/custom';
import CustomAuthorizer from '../authorizers/custom';
export default {
name: 'authentication',
before: 'simple-auth',
after: 'store',
initialize: function(container, application) {
var store = container.lookup('store:main');
var authenticator = CustomAuthenticator.create({ store: store });
container.register('simple-auth-authenticator:custom', authenticator, { instantiate: false });
container.register('simple-auth-authorizer:custom', CustomAuthorizer);
}
};
Hey Marco,
thank you very much. You are indeed providing premium support! ;) After some research i found a slightly more elegant looking solution based on your sample. Works for me. Just wanted to provide it for others:
// app/initializers/initializer-authentication.js
import CustomAuthenticator from '../authenticators/custom';
import CustomAuthorizer from '../authorizers/custom';
export default {
name: 'authentication',
before: 'simple-auth',
after: 'store',
initialize: function (container, application) {
container.register('simple-auth-authenticator:custom', CustomAuthenticator);
container.register('simple-auth-authorizer:custom', CustomAuthorizer);
application.inject('simple-auth-authenticator:custom', 'store', 'store:main');
}
};
@sandreas: you're right - that's better
I was trying to do this same thing, and I found this from http://emberjs.com/blog/2015/03/23/ember-data-1-0-beta-16-released.html
The store has now been registered as a service. So when you are using Ember Data 1.0.0-beta.16 with > Ember 1.10+ you can now inject the store into any Ember object managed by the container.
Instead of using an initializer, my custom authenticator looks like
export default Base.extend({
store: Ember.inject.service(),
@kielni Thank you so much for adding this here! Helped me a lot.
Most helpful comment
I was trying to do this same thing, and I found this from http://emberjs.com/blog/2015/03/23/ember-data-1-0-beta-16-released.html
Instead of using an initializer, my custom authenticator looks like