Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
"@types/datatables.net-buttons": "1.4.3",
"angular-calendar": "0.28.26",
"angular-datatables": "9.0.2",
"angularx-social-login": "^3.5.7",
"bootstrap": "4.4.1",
"datatables.net": "1.10.22",
"datatables.net-buttons": "1.6.2",
Expand Down
19 changes: 18 additions & 1 deletion src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,8 @@ import { CalendarComponent } from './modules/time-entries/components/calendar/ca
import { DropdownComponent } from './modules/shared/components/dropdown/dropdown.component';
import { NgSelectModule } from '@ng-select/ng-select';
import { DarkModeComponent } from './modules/shared/components/dark-mode/dark-mode.component';
import { SocialLoginModule, SocialAuthServiceConfig } from 'angularx-social-login';
import { GoogleLoginProvider } from 'angularx-social-login';

const maskConfig: Partial<IConfig> = {
validation: false,
Expand Down Expand Up @@ -184,7 +186,8 @@ const maskConfig: Partial<IConfig> = {
provide: DateAdapter,
useFactory: adapterFactory,
}),
NgSelectModule
NgSelectModule,
SocialLoginModule
],
providers: [
{
Expand All @@ -194,6 +197,20 @@ const maskConfig: Partial<IConfig> = {
},
DatePipe,
CookieService,
{
provide: 'SocialAuthServiceConfig',
useValue: {
autoLogin: false,
providers: [
{
id: GoogleLoginProvider.PROVIDER_ID,
provider: new GoogleLoginProvider(
'565556796659-hscrj9e6m2krc41cfng898793ocfnb8j.apps.googleusercontent.com'
)
}
]
} as SocialAuthServiceConfig,
}
],
bootstrap: [AppComponent],
})
Expand Down
39 changes: 36 additions & 3 deletions src/app/guards/login-guard/login.guard.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ import { Router } from '@angular/router';

import { AzureAdB2CService } from '../../modules/login/services/azure.ad.b2c.service';
import { LoginGuard } from './login.guard';
import { LoginService } from '../../modules/login/services/login.service';
import { HttpClientTestingModule } from '@angular/common/http/testing';
import { SocialAuthService } from 'angularx-social-login';


describe('LoginGuard', () => {
Expand All @@ -15,29 +18,49 @@ describe('LoginGuard', () => {
return true;
}
};
let loginService: LoginService;
const loginServiceStub = {
isLogin() {
return true;
}
};
const socialAuthServiceStub = jasmine.createSpyObj('SocialAuthService', ['']);
beforeEach(() => {
TestBed.configureTestingModule({
imports: [ RouterTestingModule ],
imports: [ RouterTestingModule, HttpClientTestingModule ],
providers: [
{ providers: AzureAdB2CService, useValue: azureAdB2CServiceStub},
{ providers: LoginService, useValue: loginServiceStub},
{ provide: SocialAuthService, useValue: socialAuthServiceStub }
]
});
loginGuard = TestBed.inject(LoginGuard);
azureAdB2CService = TestBed.inject(AzureAdB2CService);
loginService = TestBed.inject(LoginService);
});

it('should be created', () => {
expect(loginGuard).toBeTruthy();
});

it('can activate the route when user is logged-in', () => {
it('can activate the route when user is logged-in on Production', () => {
loginGuard.isProduction = true;
spyOn(azureAdB2CService, 'isLogin').and.returnValue(true);
const canActivate = loginGuard.canActivate();
expect(azureAdB2CService.isLogin).toHaveBeenCalled();
expect(canActivate).toEqual(true);
});

it('can not active the route and is redirected to login if user is not logged-in', inject([Router], (router: Router) => {
it('can activate the route when user is logged-in Locally', () => {
loginGuard.isProduction = false;
spyOn(loginService, 'isLogin').and.returnValue(true);
const canActivate = loginGuard.canActivate();
expect(loginService.isLogin).toHaveBeenCalled();
expect(canActivate).toEqual(true);
});

it('can not active the route and is redirected to login if user is not logged-in on Production', inject([Router], (router: Router) => {
loginGuard.isProduction = true;
spyOn(azureAdB2CService, 'isLogin').and.returnValue(false);
spyOn(router, 'navigate').and.stub();
const canActivate = loginGuard.canActivate();
Expand All @@ -46,4 +69,14 @@ describe('LoginGuard', () => {
expect(router.navigate).toHaveBeenCalledWith(['login']);
}));

it('can not active the route and is redirected to login if user is not logged-in Locally', inject([Router], (router: Router) => {
loginGuard.isProduction = false;
spyOn(loginService, 'isLogin').and.returnValue(false);
spyOn(router, 'navigate').and.stub();
const canActivate = loginGuard.canActivate();
expect(loginService.isLogin).toHaveBeenCalled();
expect(canActivate).toEqual(false);
expect(router.navigate).toHaveBeenCalledWith(['login']);
}));

});
24 changes: 20 additions & 4 deletions src/app/guards/login-guard/login.guard.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,37 @@
import { Injectable } from '@angular/core';
import { Router, CanActivate } from '@angular/router';
import { AzureAdB2CService } from '../../modules/login/services/azure.ad.b2c.service';
import { LoginService } from '../../modules/login/services/login.service';
import { environment } from 'src/environments/environment';

@Injectable({
providedIn: 'root'
providedIn: 'root',
})
export class LoginGuard implements CanActivate {

constructor(private azureAdB2CService: AzureAdB2CService, private router: Router) { }
isProduction = environment.production;
constructor(
private azureAdB2CService: AzureAdB2CService,
private router: Router,
private loginService: LoginService
) {}

canActivate() {
if (this.azureAdB2CService.isLogin()) {
if (this.isProduction) {
if (this.azureAdB2CService.isLogin()) {
this.azureAdB2CService.setCookies();
return true;
} else {
this.router.navigate(['login']);
return false;
}
} else {
if (this.loginService.isLogin()) {
this.loginService.setCookies();
return true;
} else {
this.router.navigate(['login']);
return false;
}
}
}
}
7 changes: 6 additions & 1 deletion src/app/modules/home/home.component.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { MockStore, provideMockStore } from '@ngrx/store/testing';
import { AzureAdB2CService } from '../login/services/azure.ad.b2c.service';
import { LoadUser } from '../user/store/user.actions';
import { HomeComponent } from './home.component';
import { LoginService } from '../login/services/login.service';

describe('HomeComponent', () => {
let component: HomeComponent;
Expand All @@ -13,6 +14,9 @@ describe('HomeComponent', () => {
const azureB2CServiceStub = {
getUserId: () => 'user_id',
};
const loginServiceStub = {
getUserId: () => 'user_id',
};

beforeEach(
waitForAsync(() => {
Expand All @@ -21,6 +25,7 @@ describe('HomeComponent', () => {
providers: [
provideMockStore({ initialState }),
{ provide: AzureAdB2CService, useValue: azureB2CServiceStub },
{ provide: LoginService, useValue: loginServiceStub },
],
}).compileComponents();
})
Expand All @@ -30,7 +35,6 @@ describe('HomeComponent', () => {
fixture = TestBed.createComponent(HomeComponent);
azureAdB2CService = TestBed.inject(AzureAdB2CService);
store = TestBed.inject(MockStore);

component = fixture.componentInstance;
fixture.detectChanges();
store.setState(initialState);
Expand All @@ -41,6 +45,7 @@ describe('HomeComponent', () => {
});

it('onInit, LoadUser action is dispatched', () => {
component.isProduction = true;
const userId = 'user_id';
spyOn(azureAdB2CService, 'getUserId').and.returnValue(userId);
spyOn(store, 'dispatch');
Expand Down
7 changes: 5 additions & 2 deletions src/app/modules/home/home.component.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,25 @@
import { Component, OnInit } from '@angular/core';
import { Store } from '@ngrx/store';
import { LoadUser } from 'src/app/modules/user/store/user.actions';
import { environment } from 'src/environments/environment';
import { AzureAdB2CService } from '../login/services/azure.ad.b2c.service';
import { LoginService } from '../login/services/login.service';

@Component({
selector: 'app-home',
templateUrl: './home.component.html',
styleUrls: ['./home.component.scss'],
})
export class HomeComponent implements OnInit {

isProduction = environment.production;
constructor(
private azureAdB2CService: AzureAdB2CService,
private loginService: LoginService,
private store: Store
) { }

ngOnInit(): void {
const userId = this.azureAdB2CService.getUserId();
const userId = this.isProduction ? this.azureAdB2CService.getUserId() : this.loginService.getUserId();
this.store.dispatch(new LoadUser(userId));
}
}
2 changes: 1 addition & 1 deletion src/app/modules/login/login.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ <h3>Please log in</h3>
</div>

<div class="login-controls">
<button (click)="login()" class="btn btn-primary">login</button>
<button (click)="isProduction ? login() : loginWithGoogle() " class="btn btn-primary">login</button>
</div>

</div>
52 changes: 48 additions & 4 deletions src/app/modules/login/login.component.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,15 @@ import { of } from 'rxjs';
import { LoginComponent } from './login.component';
import { Router } from '@angular/router';
import { FeatureToggleCookiesService } from '../shared/feature-toggles/feature-toggle-cookies/feature-toggle-cookies.service';
import { LoginService } from './services/login.service';
import { HttpClientTestingModule } from '@angular/common/http/testing';
import { SocialAuthService } from 'angularx-social-login';

describe('LoginComponent', () => {
let component: LoginComponent;
let fixture: ComponentFixture<LoginComponent>;
let azureAdB2CService: AzureAdB2CService;
let loginService: LoginService;
let featureToggleCookiesService: FeatureToggleCookiesService;

const azureAdB2CServiceStub = {
Expand All @@ -23,29 +27,45 @@ describe('LoginComponent', () => {
}
};

const loginServiceStub = {
isLogin() {
return true;
},
signIn() {
return of();
},
setCookies() {
}
};

const featureToggleCookiesServiceStub = {
setCookies() {
return null;
}
};

const socialAuthServiceStub = jasmine.createSpyObj('SocialAuthService', ['signIn', 'authState']);
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
imports: [ RouterTestingModule ],
imports: [ RouterTestingModule, HttpClientTestingModule],
declarations: [ LoginComponent ],
providers: [
{ providers: AzureAdB2CService, useValue: azureAdB2CServiceStub},
{ providers: FeatureToggleCookiesService, useValue: featureToggleCookiesServiceStub}
{ providers: FeatureToggleCookiesService, useValue: featureToggleCookiesServiceStub},
{ providers: LoginService, useValue: loginServiceStub},
{ provide: SocialAuthService, useValue: socialAuthServiceStub }
]
})
.compileComponents();
}));

beforeEach(() => {
socialAuthServiceStub.authState = of('some value');
fixture = TestBed.createComponent(LoginComponent);
component = fixture.componentInstance;
fixture.detectChanges();
azureAdB2CService = TestBed.inject(AzureAdB2CService);
loginService = TestBed.inject(LoginService);
featureToggleCookiesService = TestBed.inject(FeatureToggleCookiesService);
});

Expand All @@ -65,7 +85,7 @@ describe('LoginComponent', () => {
expect(component).toBeTruthy();
});

it('should sign up or login with google if is not logged-in into the app', inject([Router], (router: Router) => {
it('should sign up or login with google if is not logged-in into the app on Production', inject([Router], (router: Router) => {
spyOn(azureAdB2CService, 'isLogin').and.returnValue(false);
spyOn(azureAdB2CService, 'setCookies').and.returnValue();
spyOn(azureAdB2CService, 'signIn').and.returnValue(of(() => {}));
Expand All @@ -78,11 +98,35 @@ describe('LoginComponent', () => {
expect(featureToggleCookiesService.setCookies).toHaveBeenCalled();
}));

it('should not sign-up or login with google if is already logged-in into the app', inject([Router], (router: Router) => {
it('should sign up or login with google if is not logged-in into the app Locally', inject([Router], (router: Router) => {
spyOn(loginService, 'isLogin').and.returnValue(false);
spyOn(loginService, 'setLocalStorage').and.returnValue();
spyOn(loginService, 'getUser').and.returnValue(of(() => {}));
spyOn(loginService, 'setCookies').and.returnValue();
spyOn(loginService, 'signIn').and.returnValue();
spyOn(featureToggleCookiesService, 'setCookies').and.returnValue(featureToggleCookiesService.setCookies());

component.ngOnInit();
component.loginWithGoogle();

expect(loginService.signIn).toHaveBeenCalled();
expect(loginService.setCookies).toHaveBeenCalled();
expect(featureToggleCookiesService.setCookies).toHaveBeenCalled();
}));

it('should not sign-up or login with google if is already logged-in into the app on Production', inject([Router], (router: Router) => {
spyOn(azureAdB2CService, 'isLogin').and.returnValue(true);
spyOn(router, 'navigate').and.stub();
component.login();
expect(azureAdB2CService.isLogin).toHaveBeenCalled();
expect(router.navigate).toHaveBeenCalledWith(['']);
}));

it('should not sign-up or login with google if is already logged-in into the app Locally', inject([Router], (router: Router) => {
spyOn(loginService, 'isLogin').and.returnValue(true);
spyOn(router, 'navigate').and.stub();
component.loginWithGoogle();
expect(loginService.isLogin).toHaveBeenCalled();
expect(router.navigate).toHaveBeenCalledWith(['']);
}));
});
Loading