I am writing an ember app (using ember 2.3.0) using emberfire & torii for authentication. After a user logs in, their uid is available to me in the torii session
object. I also have a user
model and would like to access other data related to the current user in my templates, routes, etc.
I can get this to work in a single 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 would like to prevent having to write this for each route/controller that needs to access it.
Could anyone advise on the best way to do this? Is the best way to use a service? If so, how can I ensure that the code in my service is executed after my session object is available?
Update
I managed to get my application to work with the following solution:
Create a method to login user using firebase
I created a mixin to handle the logging in behaviour. This is then used on both the login page and the sign up 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 a user
service
This is used to associate the user
model with the authentication user.
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();
}
});
}
});
Inject user
service into application route
The application route is called whenever the application is loaded (when the user refreshes the page for example). Therefore, as @Deovandski mentioned in his answer, you need to inject it on the Application route in order for the user account to be available globally.
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');
});
}
});
Inject the user
service wherever it is needed
You can then access the current user in the following manner:
user: Ember.inject.service()
...
let currentUser = this.get('user').get('currentUser');