| @@ -8,14 +8,15 @@ import { RecipeStartComponent } from './recipes/recipe-start/recipe-start.compon | |||||
| import { RecipeEditComponent } from './recipes/recipe-edit/recipe-edit.component'; | import { RecipeEditComponent } from './recipes/recipe-edit/recipe-edit.component'; | ||||
| import { SignupComponent } from './auth/signup/signup.component'; | import { SignupComponent } from './auth/signup/signup.component'; | ||||
| import { SigninComponent } from './auth/signin/signin.component'; | import { SigninComponent } from './auth/signin/signin.component'; | ||||
| import { AuthGuard } from './auth/auth-guard.service'; | |||||
| const appRoutes: Routes = [ | const appRoutes: Routes = [ | ||||
| { path: '', redirectTo: '/recipes', pathMatch: 'full' }, | { path: '', redirectTo: '/recipes', pathMatch: 'full' }, | ||||
| { path: 'recipes' , component: RecipesComponent, children: [ | { path: 'recipes' , component: RecipesComponent, children: [ | ||||
| { path: '', component: RecipeStartComponent }, | { path: '', component: RecipeStartComponent }, | ||||
| { path: 'new', component: RecipeEditComponent }, | |||||
| { path: 'new', component: RecipeEditComponent, canActivate: [AuthGuard] }, | |||||
| { path: ':id', component: RecipeDetailComponent }, | { path: ':id', component: RecipeDetailComponent }, | ||||
| { path: ':id/edit', component: RecipeEditComponent} | |||||
| { path: ':id/edit', component: RecipeEditComponent, canActivate: [AuthGuard]} | |||||
| ] }, | ] }, | ||||
| { path: 'shopping-list', component: ShoppingListComponent }, | { path: 'shopping-list', component: ShoppingListComponent }, | ||||
| { path: 'signup', component: SignupComponent }, | { path: 'signup', component: SignupComponent }, | ||||
| @@ -23,6 +23,7 @@ import { DataStorageService } from './shared/data-storage.service'; | |||||
| import { SignupComponent } from './auth/signup/signup.component'; | import { SignupComponent } from './auth/signup/signup.component'; | ||||
| import { SigninComponent } from './auth/signin/signin.component'; | import { SigninComponent } from './auth/signin/signin.component'; | ||||
| import { AuthService } from './auth/auth.service'; | import { AuthService } from './auth/auth.service'; | ||||
| import { AuthGuard } from './auth/auth-guard.service'; | |||||
| @NgModule({ | @NgModule({ | ||||
| @@ -49,7 +50,12 @@ import { AuthService } from './auth/auth.service'; | |||||
| HttpModule, | HttpModule, | ||||
| AppRoutingModule | AppRoutingModule | ||||
| ], | ], | ||||
| providers: [ShoppingListService, RecipeService, DataStorageService, AuthService], | |||||
| providers: [ | |||||
| ShoppingListService, | |||||
| RecipeService, | |||||
| DataStorageService, | |||||
| AuthService, | |||||
| AuthGuard], | |||||
| bootstrap: [AppComponent] | bootstrap: [AppComponent] | ||||
| }) | }) | ||||
| export class AppModule { } | export class AppModule { } | ||||
| @@ -0,0 +1,14 @@ | |||||
| import { CanActivate } from "@angular/router"; | |||||
| import { ActivatedRouteSnapshot, RouterStateSnapshot } from "@angular/router/src/router_state"; | |||||
| import { Injectable } from "@angular/core"; | |||||
| import { AuthService } from "./auth.service"; | |||||
| @Injectable() | |||||
| export class AuthGuard implements CanActivate { | |||||
| constructor(private authService: AuthService) {} | |||||
| canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) { | |||||
| return this.authService.isAuthenticated(); | |||||
| } | |||||
| } | |||||
| @@ -1,8 +1,13 @@ | |||||
| import * as firebase from 'firebase'; | import * as firebase from 'firebase'; | ||||
| import { Router } from '@angular/router'; | |||||
| import { Injectable } from '@angular/core'; | |||||
| @Injectable() | |||||
| export class AuthService { | export class AuthService { | ||||
| token: string; | token: string; | ||||
| constructor(private router: Router) {} | |||||
| signupUser(email: string, password: string) { | signupUser(email: string, password: string) { | ||||
| firebase.auth().createUserWithEmailAndPassword(email, password).catch( | firebase.auth().createUserWithEmailAndPassword(email, password).catch( | ||||
| error => console.log(error) | error => console.log(error) | ||||
| @@ -13,6 +18,7 @@ export class AuthService { | |||||
| firebase.auth().signInWithEmailAndPassword(email, password) | firebase.auth().signInWithEmailAndPassword(email, password) | ||||
| .then( | .then( | ||||
| response => { | response => { | ||||
| this.router.navigate(['/']); | |||||
| firebase.auth().currentUser.getIdToken() | firebase.auth().currentUser.getIdToken() | ||||
| .then( | .then( | ||||
| (token: string) => this.token = token | (token: string) => this.token = token | ||||
| @@ -24,6 +30,11 @@ export class AuthService { | |||||
| ); | ); | ||||
| } | } | ||||
| logout() { | |||||
| firebase.auth().signOut(); | |||||
| this.token = null; | |||||
| } | |||||
| getToken() { | getToken() { | ||||
| firebase.auth().currentUser.getIdToken() | firebase.auth().currentUser.getIdToken() | ||||
| .then( | .then( | ||||
| @@ -31,4 +42,8 @@ export class AuthService { | |||||
| ); | ); | ||||
| return this.token; | return this.token; | ||||
| } | } | ||||
| isAuthenticated() { | |||||
| return this.token != null; | |||||
| } | |||||
| } | } | ||||
| @@ -10,9 +10,12 @@ | |||||
| <li routerLinkActive="active"><a routerLink="/shopping-list">Shopping List</a></li> | <li routerLinkActive="active"><a routerLink="/shopping-list">Shopping List</a></li> | ||||
| </ul> | </ul> | ||||
| <ul class="nav navbar-nav navbar-right"> | <ul class="nav navbar-nav navbar-right"> | ||||
| <li><a routerLink="/signup">Register</a></li> | |||||
| <li><a routerLink="/signin">Login</a></li> | |||||
| <li class="dropdown" appDropdown> | |||||
| <ng-template [ngIf]="!authService.isAuthenticated()"> | |||||
| <li><a routerLink="/signup">Register</a></li> | |||||
| <li><a routerLink="/signin">Login</a></li> | |||||
| </ng-template> | |||||
| <li><a style="cursor: pointer;" (click)="onLogout()" *ngIf="authService.isAuthenticated()">Logout</a></li> | |||||
| <li class="dropdown" appDropdown *ngIf="authService.isAuthenticated()"> | |||||
| <a style="cursor: pointer;" class="dropdown-toggle" role="button">Manage <span class="caret"></span></a> | <a style="cursor: pointer;" class="dropdown-toggle" role="button">Manage <span class="caret"></span></a> | ||||
| <ul class="dropdown-menu"> | <ul class="dropdown-menu"> | ||||
| <li><a style="cursor: pointer;" (click)="onSaveData()">Save</a></li> | <li><a style="cursor: pointer;" (click)="onSaveData()">Save</a></li> | ||||
| @@ -1,5 +1,6 @@ | |||||
| import { Component } from "@angular/core"; | import { Component } from "@angular/core"; | ||||
| import { DataStorageService } from "../shared/data-storage.service"; | import { DataStorageService } from "../shared/data-storage.service"; | ||||
| import { AuthService } from "../auth/auth.service"; | |||||
| @Component({ | @Component({ | ||||
| selector: 'app-header', | selector: 'app-header', | ||||
| @@ -7,7 +8,7 @@ import { DataStorageService } from "../shared/data-storage.service"; | |||||
| }) | }) | ||||
| export class HeaderComponent { | export class HeaderComponent { | ||||
| constructor(private dataStorageService: DataStorageService) {} | |||||
| constructor(private dataStorageService: DataStorageService, private authService: AuthService) {} | |||||
| onSaveData() { | onSaveData() { | ||||
| this.dataStorageService.storeRecipes().subscribe( | this.dataStorageService.storeRecipes().subscribe( | ||||
| @@ -20,4 +21,8 @@ export class HeaderComponent { | |||||
| onFetchData() { | onFetchData() { | ||||
| this.dataStorageService.fetchRecipes(); | this.dataStorageService.fetchRecipes(); | ||||
| } | } | ||||
| onLogout() { | |||||
| this.authService.logout(); | |||||
| } | |||||
| } | } | ||||