Skip to content

Commit

Permalink
fix(circular dependencies): extract getToken function to a separate file
Browse files Browse the repository at this point in the history
the getToken function has been extracted to a separate file to remove the warnings about circular
dependencies which were generated by having getToken function within the app.module.ts file
  • Loading branch information
EnricoPicci committed Jun 28, 2019
1 parent 6c3873e commit 4974a7a
Show file tree
Hide file tree
Showing 6 changed files with 55 additions and 57 deletions.
2 changes: 1 addition & 1 deletion .talismanrc
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ fileignoreconfig:
checksum: 96f4f7aa4bd17b66037dcd3c066dfa5d1e11fa2d44ea6ba3f9d7ad02ec41bff8
ignore_detectors: []
- filename: src/app/modules/login/login.component.ts
checksum: 0ac91d9d13996d2f4ddbf714fb797389d6cb621282440cee481a5f850b08e95f
checksum: 510ff54745a0315fdaa5de0cf6923cc4e30081789e358120baf277f8cd1b5379
ignore_detectors: []
- filename: src/app/services/backend.service.spec.ts
checksum: dcf98ba54329a81de976728ca53eb91cbf13ac54a659422bdf0571ef237acf31
Expand Down
13 changes: 13 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ The following is a set of guidelines, not rules, for contributing. Feel free to
- [Release versioning](#release-versioning)
- [Typescript Styleguide](#typescript-styleguide)
- [Testing](#testing)
- [Run the continuous integration on local](#run-the-continuous-integration-on-local)
- [Build the application for Production](#build-the-application-for-production)
- [Build the docker image](#build-the-docker-image)

Expand Down Expand Up @@ -145,6 +146,8 @@ Please follow these steps to have your contribution considered by the maintainer

While the prerequisites above must be satisfied prior to having your pull request reviewed, the reviewer(s) may ask you to complete additional design work, tests, or other changes before your pull request can be ultimately accepted.

Note: consider that the Continuous Integration logic runs lint checks and uses the prettier module - if you use VSCode it is recommended to install the "Prettier - Code formatter" extension to avoid lint errors.


## Guidelines

Expand Down Expand Up @@ -196,6 +199,16 @@ If not executed in CI mode, the above commands will prompt the user for executin

- **E2E tests**: *TODO (make unit actual unit, add e2e and move not-unitable tests to e2e)*


### Run the continuous integration on local

You can run the CI logic on local via the command:

```shell
make ci_all
```


### Build the application for Production

To build the app for production use:
Expand Down
11 changes: 6 additions & 5 deletions src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,11 @@ import { VoteModule } from './modules/vote/vote.module';
import { HttpErrorHandler } from './shared/http-error-handler/http-error-handler.service';
import { EventsService } from './services/events.service';
import { environment } from '../environments/environment';
import { getToken } from './utils/get-token';

export function getToken() {
return localStorage.getItem('access_token');
}
// export function getToken() {
// return localStorage.getItem('access_token');
// }

export function apiDomain() {
return [new URL(environment.serviceUrl).hostname + ':' + new URL(environment.serviceUrl).port];
Expand All @@ -29,7 +30,7 @@ export function jwtOptionsFactory() {
return {
tokenGetter: getToken,
whitelistedDomains: apiDomain()
}
};
}

@NgModule({
Expand All @@ -53,4 +54,4 @@ export function jwtOptionsFactory() {
providers: [HttpErrorHandler, EventsService],
bootstrap: [AppComponent]
})
export class AppModule { }
export class AppModule {}
20 changes: 10 additions & 10 deletions src/app/modules/login/auth.guard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,26 @@ import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, Router } from
import { Observable } from 'rxjs';

import { AuthService } from './auth.service';
import {getToken} from "../../app.module";
import { getToken } from '../../utils/get-token';

@Injectable({
providedIn: 'root'
})
export class AuthGuard implements CanActivate {
constructor(private authService: AuthService, private router: Router) {}

canActivate(
next: ActivatedRouteSnapshot,
state: RouterStateSnapshot): Observable<boolean> | Promise<boolean> | boolean {
const url: string = state.url;

return this.checkLogin(url);
canActivate(next: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> | Promise<boolean> | boolean {
const url: string = state.url;

return this.checkLogin(url);
}

checkLogin(url: string): boolean {
if (this.authService.isLoggedIn) { return true; }
else if (getToken()) { return true; }
if (this.authService.isLoggedIn) {
return true;
} else if (getToken()) {
return true;
}

// Store the attempted URL for redirecting
this.authService.redirectUrl = url;
Expand All @@ -30,5 +31,4 @@ export class AuthGuard implements CanActivate {
this.router.navigate(['/login']);
return false;
}

}
63 changes: 22 additions & 41 deletions src/app/modules/login/login.component.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { Component, OnInit, ViewChild, ElementRef, AfterViewInit, OnDestroy } from '@angular/core';
import { Observable, Subject, fromEvent, combineLatest, never, Subscription, merge, throwError, } from 'rxjs';
import { map, share, switchMap, catchError, } from 'rxjs/operators';
import { Observable, Subject, fromEvent, combineLatest, never, Subscription, merge, throwError } from 'rxjs';
import { map, share, switchMap, catchError } from 'rxjs/operators';
import { Router } from '@angular/router';

import { AuthService } from './auth.service';
import { ErrorService } from 'src/app/services/error.service';
import { ERRORS } from 'src/app/services/errors';
import {getToken} from "../../app.module";
import { getToken } from '../../utils/get-token';

@Component({
selector: 'byor-login',
Expand All @@ -18,7 +18,7 @@ export class LoginComponent implements OnInit, AfterViewInit, OnDestroy {
password$: Observable<string>;
inputData$: Observable<any>;
isValidInputData$: Observable<boolean>;
clickOnLogin$: Observable<{user: string, password: string}>;
clickOnLogin$: Observable<{ user: string; password: string }>;
message$ = new Subject<string>();

loginSubscription: Subscription;
Expand All @@ -27,42 +27,30 @@ export class LoginComponent implements OnInit, AfterViewInit, OnDestroy {
@ViewChild('pwd') pwd: ElementRef;
@ViewChild('loginButton', { read: ElementRef }) loginButtonRef: ElementRef;

constructor(
public authService: AuthService,
public router: Router,
public errorService: ErrorService,
) { }
constructor(public authService: AuthService, public router: Router, public errorService: ErrorService) {}

ngOnInit() {
if (getToken()) {
this.router.navigate(['admin'])
this.router.navigate(['admin']);
}
}

ngAfterViewInit() {
const _user$ = fromEvent(this.userid.nativeElement, 'keyup')
.pipe(
map(() => this.userid.nativeElement.value)
);
const _password$ = fromEvent(this.pwd.nativeElement, 'keyup')
.pipe(
map(() => this.pwd.nativeElement.value)
);
const _user$ = fromEvent(this.userid.nativeElement, 'keyup').pipe(map(() => this.userid.nativeElement.value));
const _password$ = fromEvent(this.pwd.nativeElement, 'keyup').pipe(map(() => this.pwd.nativeElement.value));
const _loginButtonClick$ = fromEvent(this.loginButtonRef.nativeElement, 'click');

this.loginSubscription = this.logIn$(_user$, _password$, _loginButtonClick$)
.subscribe(
authResp => {
this.loginSubscription = this.logIn$(_user$, _password$, _loginButtonClick$).subscribe(
(authResp) => {
this.authService.isLoggedIn = authResp;
const redirect = this.authService.redirectUrl ? this.authService.redirectUrl : '/admin';
this.router.navigate([redirect]);
},
error => {
(error) => {
this.errorService.setError(error);
this.router.navigate(['error']);
}
);

}
ngOnDestroy() {
if (this.loginSubscription) {
Expand All @@ -77,48 +65,42 @@ export class LoginComponent implements OnInit, AfterViewInit, OnDestroy {
// we need to create an Observable which emits the initial value of the inpuf field.
// This is because, in case of error, the `catchError` operator returns the source Observable and, at that point,
// this merge function would be re-executed and it would be important to emit the current content of the input field
new Observable(subscriber => {
new Observable((subscriber) => {
subscriber.next(this.userid.nativeElement.value);
subscriber.complete();
}),
userId$,
userId$
);
this.password$ = merge(
// we need to create an Observable which emits the initial value of the inpuf field.
// This is because, in case of error, the `catchError` operator returns the source Observable and, at that point,
// this merge function would be re-executed and it would be important to emit the current content of the input field
new Observable(subscriber => {
new Observable((subscriber) => {
subscriber.next(this.pwd.nativeElement.value);
subscriber.complete();
}),
pwd$,
pwd$
);

this.inputData$ = combineLatest(this.user$, this.password$);
this.isValidInputData$ = this.inputData$
.pipe(
this.isValidInputData$ = this.inputData$.pipe(
map(([user, password]) => this.isInputDataValid(user, password)),
share(), // isValidInputData$ is subscribed in the template via asyc pipe - any other subscriber should use this subscription
share() // isValidInputData$ is subscribed in the template via asyc pipe - any other subscriber should use this subscription
);

this.clickOnLogin$ = combineLatest(this.isValidInputData$, this.inputData$)
.pipe(
this.clickOnLogin$ = combineLatest(this.isValidInputData$, this.inputData$).pipe(
switchMap(([isValid, [user, password]]) => {
if (isValid) {
return loginButtonClick$
.pipe(
map(() => ({user, password}))
);
return loginButtonClick$.pipe(map(() => ({ user, password })));
} else {
return never();
}
})
);

let credentials;
return this.clickOnLogin$
.pipe(
switchMap(_credentials => {
return this.clickOnLogin$.pipe(
switchMap((_credentials) => {
credentials = _credentials;
return this.authService.login(credentials.user, credentials.password);
}),
Expand All @@ -130,12 +112,11 @@ export class LoginComponent implements OnInit, AfterViewInit, OnDestroy {
this.message$.next(err.message);
return caught;
}
}),
})
);
}

isInputDataValid(user: string, password: string) {
return user.trim().length > 0 && password.trim().length > 0;
}

}
3 changes: 3 additions & 0 deletions src/app/utils/get-token.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export function getToken() {
return localStorage.getItem('access_token');
}

0 comments on commit 4974a7a

Please sign in to comment.