forked from faucetsdn/udmi
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #127 from Buildings-IOT/faucetsdn#652-Login
faucetsdn#652 login
- Loading branch information
Showing
27 changed files
with
2,212 additions
and
972 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
import { TestBed } from '@angular/core/testing'; | ||
import { ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router'; | ||
import { RouterTestingModule } from '@angular/router/testing'; | ||
import { BehaviorSubject } from 'rxjs'; | ||
import { AuthGuard } from './auth.guard'; | ||
import { AuthService } from './auth.service'; | ||
|
||
describe('AuthGuard', () => { | ||
let guard: AuthGuard; | ||
let mockAuthService: jasmine.SpyObj<AuthService>; | ||
let route: ActivatedRouteSnapshot; | ||
let state: RouterStateSnapshot; | ||
|
||
beforeEach(() => { | ||
mockAuthService = jasmine.createSpyObj(AuthService, ['isLoggedIn$']); | ||
mockAuthService.isLoggedIn$ = new BehaviorSubject<boolean | null>(null); | ||
|
||
TestBed.configureTestingModule({ | ||
imports: [RouterTestingModule], | ||
providers: [{ provide: AuthService, useValue: mockAuthService }], | ||
}); | ||
guard = TestBed.inject(AuthGuard); | ||
}); | ||
|
||
it('should be created', () => { | ||
expect(guard).toBeTruthy(); | ||
}); | ||
|
||
it('should redirect to the login screen when not logged in', () => { | ||
mockAuthService.isLoggedIn$.next(false); | ||
guard.canActivate(route, state).subscribe((res) => expect(res.toString()).toEqual('/login')); | ||
}); | ||
|
||
it('should proceed when logged in', () => { | ||
mockAuthService.isLoggedIn$.next(true); | ||
guard.canActivate(route, state).subscribe((res) => expect(res).toEqual(true)); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import { Injectable } from '@angular/core'; | ||
import { ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot, UrlTree } from '@angular/router'; | ||
import { filter, map, Observable } from 'rxjs'; | ||
import { AuthService } from './auth.service'; | ||
|
||
@Injectable({ | ||
providedIn: 'root', | ||
}) | ||
export class AuthGuard implements CanActivate { | ||
constructor(private authService: AuthService, private router: Router) {} | ||
|
||
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean | UrlTree> { | ||
return this.authService.isLoggedIn$.pipe( | ||
filter((isLoggedIn) => isLoggedIn !== null), // loading, so short circuit | ||
map((isLoggedIn) => { | ||
if (!isLoggedIn) { | ||
return this.router.parseUrl('/login'); | ||
} else { | ||
return true; | ||
} | ||
}) | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
import { NgModule } from '@angular/core'; | ||
import { GoogleLoginProvider, SocialAuthServiceConfig, SocialLoginModule } from '@abacritt/angularx-social-login'; | ||
|
||
@NgModule({ | ||
imports: [SocialLoginModule], | ||
providers: [ | ||
{ | ||
provide: 'SocialAuthServiceConfig', | ||
useValue: { | ||
autoLogin: true, | ||
providers: [ | ||
{ | ||
id: GoogleLoginProvider.PROVIDER_ID, | ||
provider: new GoogleLoginProvider( | ||
'257845957103-qdi3hno6v1bf4lli44km2av2gijrs758.apps.googleusercontent.com' | ||
), | ||
}, | ||
], | ||
} as SocialAuthServiceConfig, | ||
}, | ||
], | ||
}) | ||
export class AuthModule {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
import { SocialAuthService, SocialUser } from '@abacritt/angularx-social-login'; | ||
import { TestBed } from '@angular/core/testing'; | ||
import { Router } from '@angular/router'; | ||
import { Apollo } from 'apollo-angular'; | ||
import { Observable } from 'rxjs'; | ||
import { AuthService } from './auth.service'; | ||
|
||
describe('AuthService', () => { | ||
let service: AuthService; | ||
let mockSocialAuthService: jasmine.SpyObj<SocialAuthService>; | ||
let mockApollo: jasmine.SpyObj<Apollo>; | ||
let mockRouter: jasmine.SpyObj<Router>; | ||
|
||
beforeEach(() => { | ||
mockSocialAuthService = jasmine.createSpyObj(SocialAuthService, ['signIn', 'signOut']); | ||
mockApollo = jasmine.createSpyObj(Apollo, ['client']); | ||
mockRouter = jasmine.createSpyObj(Router, ['navigateByUrl']); | ||
|
||
TestBed.configureTestingModule({ | ||
providers: [ | ||
{ provide: SocialAuthService, useValue: { ...mockSocialAuthService, authState: new Observable() } }, | ||
{ provide: Apollo, useValue: mockApollo }, | ||
{ provide: Router, useValue: mockRouter }, | ||
], | ||
}); | ||
service = TestBed.inject(AuthService); | ||
}); | ||
|
||
it('should be created', () => { | ||
expect(service).toBeTruthy(); | ||
}); | ||
|
||
it('should route the user back into the app after login', async () => { | ||
const user: SocialUser = {} as SocialUser; | ||
|
||
mockApollo.client.clearStore = jasmine.createSpy(); | ||
mockSocialAuthService.signIn.and.returnValue(new Promise((resolve, reject) => resolve(user))); | ||
|
||
await service.loginWithGoogle(); | ||
|
||
expect(mockRouter.navigateByUrl).toHaveBeenCalledWith('/devices'); | ||
}); | ||
|
||
it('should route the user to the login page and should clear the cache after logout', async () => { | ||
mockApollo.client.clearStore = jasmine.createSpy(); | ||
mockSocialAuthService.signOut.and.returnValue(new Promise((resolve, reject) => resolve())); | ||
|
||
await service.logout(); | ||
|
||
expect(mockRouter.navigateByUrl).toHaveBeenCalledWith('/login'); | ||
expect(mockApollo.client.clearStore).toHaveBeenCalled(); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
import { GoogleLoginProvider, SocialAuthService, SocialUser } from '@abacritt/angularx-social-login'; | ||
import { Injectable } from '@angular/core'; | ||
import { Router } from '@angular/router'; | ||
import { Apollo } from 'apollo-angular'; | ||
import { BehaviorSubject } from 'rxjs'; | ||
|
||
@Injectable({ | ||
providedIn: 'root', | ||
}) | ||
export class AuthService { | ||
user$ = new BehaviorSubject<SocialUser | null>(null); | ||
isLoggedIn$ = new BehaviorSubject<boolean | null>(null); | ||
|
||
constructor(private socialAuthService: SocialAuthService, private router: Router, private apollo: Apollo) { | ||
this.socialAuthService.authState.subscribe((user) => { | ||
this.user$.next(user); | ||
this.isLoggedIn$.next(user !== null); | ||
}); | ||
} | ||
|
||
async loginWithGoogle(): Promise<void> { | ||
await this.socialAuthService.signIn(GoogleLoginProvider.PROVIDER_ID); // TODO:: try option {ux_mode: 'redirect'} | ||
this.router.navigateByUrl('/devices'); | ||
} | ||
|
||
async logout(): Promise<void> { | ||
await this.socialAuthService.signOut(); | ||
this.router.navigateByUrl('/login'); | ||
this.apollo.client.clearStore(); // clear apollo cache | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
import { NgModule } from '@angular/core'; | ||
import { RouterModule, Routes } from '@angular/router'; | ||
import { LoginComponent } from './login.component'; | ||
|
||
const routes: Routes = [ | ||
{ | ||
path: '', | ||
component: LoginComponent, | ||
}, | ||
]; | ||
|
||
@NgModule({ | ||
imports: [RouterModule.forChild(routes)], | ||
exports: [RouterModule], | ||
}) | ||
export class LoginRoutingModule {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
<div class="login-container"> | ||
<mat-card class="login-widget"> | ||
<mat-card-header> | ||
<mat-card-title>UDMI</mat-card-title> | ||
<mat-card-subtitle>Device Management Console</mat-card-subtitle> | ||
</mat-card-header> | ||
<mat-card-actions align="end"> | ||
<button class="google-login-button" mat-button (click)="loginWithGoogle()"> | ||
<img class="google-icon-svg" src="assets/images/google-logo.svg" /> | ||
<span>Sign in with Google</span> | ||
</button> | ||
</mat-card-actions> | ||
</mat-card> | ||
</div> |
Oops, something went wrong.