# Managing sign in/out + displaying name ## Create the Vuex store ### state Your state should contain 3 items: - authorized:bool = flag if logged in or not. - user: str = user object. - userEmail: str = username or email. ### mutations You should define two mutations (to update this state): ```javascript mutations: { user(state, user) { state.authorized = !!user && user.attributes && user.attributes.email_verified; state.user = user; }, userEmail(state, userEmail) { state.userEmail = userEmail; } }, ``` - When you set the user state you should check to make sure the user object you pass in exists and set the authorized flag at the same time. ### actions You should define an action that fetches the user. This should call the `getUser` method of whatever auth system you're using and pass this in to the method. This `getUser` dispatch should either get the user and set the store state, or set it to null if no user exists. This way, any interaction with `getUser` will make sure the store is up to date. ```javascript actions: { async fetchUser({ commit }) { try { const user = await Auth.currentAuthenticatedUser(); const expires = user.getSignInUserSession().getIdToken().payload.exp - Math.floor(new Date().getTime() / 1000); console.log(`Token expires in ${expires} seconds.`); commit("user", user); commit("userEmail", user.attributes.email); } catch (err) { commit("user", null); commit("userEmail", null); } } }, ``` ### getters You should define getters to access the state. These getters will cache - so they will only update if one of the things used to calculate the state updates. ```javascript getters: { userEmail: state => { return state.userEmail; }, authorized: state => { return state.authorized; } } ``` ## Triggering state for apps In addition to getting the user to determine router actions, you should get the user in the main component so you can set the state. In the main view (parent of all components `App.vue`) you should define a `created` method. This method should: - Fetch the user. - Change the state to reflect this. ```javascript async created() { try { await this.$store.dispatch("fetchUser"); } catch (error) { console.log(error); } finally { console.log(this.email); console.log(this.$store.state.userEmail); } }, ``` This needs to be done right at the start to make sure this triggers a state change before anything else. In the views for signing in/out/registering etc you should make sure that when you call the auth methods you wrote, that you also update the state at this time. This way, any component in the app can use the state to determine if someone is logged in, and display/toggle components dynamically. A signin method for a button might look like: ```javascript async submit() { if (this.$refs.form.validate()) { console.log( `SIGN IN username: ${this.username}, password: ${this.password}` ); try { await signIn(this.username, this.password); } catch (err) { console.log(err); } finally { this.$store.dispatch("fetchUser"); } console.log("Signed in"); } } ``` A sign out button might look like: ```javascript async dosignOut() { try { await signOut(); } finally { this.$store.dispatch("fetchUser"); } } ``` Remember: - Call `this.$store.dispatch("fetchUser)` when you sign in - do it in a try/finally block to make sure the state gets updated after the ajax call. - Call `this.$store.dispatch("fetchUser)` when you sign out do it in a try/finally bock to make sure the state gets updated after the ajax call.