I am writing an ember application (using ember 2.3.0) using emberfire and torii for authentication. When a user logs in, their uid is available to me in the torii object session. I also have a model userand you want to access other data related to the current user in my templates, routes, etc.
I can get this to work in one route by doing something like:
let uid = this.get('session').get('uid');
this.store.findRecord('user', uid).then(user => {
console.log(user.get('firstName'));
});
but I would like to prohibit writing this for each route / controller that needs to access it.
Can anyone advise a better way to do this? Best way to use the service? If so, how can I guarantee that the code in my service will be executed after my session object?
Update
I managed to get my application to work with the following solution:
Create a user login method using firebase
I created mixin to handle logging. Then it is used both on the login page and on the registration page.
// Mixin to handle logging in
import Ember from 'ember';
export default Ember.Mixin.create({
user: Ember.inject.service(),
email: null,
errorMsg: null,
logInUser(email, password) {
// logout existing user if any and then login new user
this.get('session').close()
.then(() => {
// if already a user logged in
this.firebaseLogin(email, password);
})
.catch(() => {
// if no user logged in
this.firebaseLogin(email, password);
});
},
firebaseLogin(email, password) {
this.get("session").open("firebase", {
provider: 'password',
email: email,
password: password
})
.then((data) => {
// If successful, fetch the user and transition to home page
console.log("Successfully logged in as ", data);
this.get('user').loadCurrentUser().then(() => {
this.transitionToRoute('index');
});
})
.catch(error => {
this.set('errorMsg', error);
});
},
});
Create service user
This is used to map the model userto user authentication.
app/services/user.js
import Ember from 'ember';
export default Ember.Service.extend({
store: Ember.inject.service(),
session: Ember.inject.service(),
currentUser: null,
loadCurrentUser() {
return new Ember.RSVP.Promise((resolve, reject) => {
const uid = this.get('session').get('uid');
if (!Ember.isEmpty(uid)) {
return this.get('store').find('user', uid).then((user) => {
this.set('currentUser', user);
resolve();
}, reject);
} else {
this.set('currentUser', null);
resolve();
}
});
}
});
Insert userservice into application route
The application route is called whenever the application loads (when the user refreshes the page, for example). Therefore, as @Deovandski noted in his answer, you need to enter it on the application route so that the user account is accessible all over the world.
app/routes/application.js
import Ember from 'ember';
export default Ember.Route.extend({
user: Ember.inject.service(),
beforeModel() {
return this.get("session").fetch()
.then(() => {
// Session retrieved successfully
console.log('session retrieved');
return this.get('user').loadCurrentUser();
})
.catch(() => {
// Session could not be retrieved
this.transitionTo('login');
});
}
});
Implement service userwhere necessary
Then you can access the current user as follows:
user: Ember.inject.service()
...
let currentUser = this.get('user').get('currentUser');