Skip to content

Commit 7445955

Browse files
authored
Merge pull request #157 from EBISPOT/develop
Develop
2 parents 2b31c21 + 9829c38 commit 7445955

File tree

17 files changed

+105
-123
lines changed

17 files changed

+105
-123
lines changed

package-lock.json

Lines changed: 8 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
"test": "ng test",
99
"lint": "ng lint",
1010
"e2e": "ng e2e",
11-
"start-json-server" : "json-server --watch json-server/db.json --delay 800 --routes json-server/routes.json",
11+
"start-json-server": "json-server --watch json-server/db.json --delay 800 --routes json-server/routes.json",
1212
"start-fake": "(start npm run start-json-server && ng serve) || (npm run start-json-server & ng serve)"
1313
},
1414
"private": true,
@@ -23,6 +23,7 @@
2323
"@angular/platform-browser": "~11.2.6",
2424
"@angular/platform-browser-dynamic": "~11.2.6",
2525
"@angular/router": "~11.2.6",
26+
"angular-oauth2-oidc": "^10.0.3",
2627
"json-server": "^0.16.3",
2728
"jwt-decode": "^2.2.0",
2829
"ng2-file-upload": "^1.4.0",

src/app/app-routing.module.ts

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,32 @@
11
import { NgModule } from '@angular/core';
22
import { RouterModule, Routes } from '@angular/router';
3+
import { AuthGuard } from './core/guards/auth.guard';
34

45
const routes: Routes = [
56
{
67
path: 'submissions',
7-
loadChildren: () => import('./feature/submission/submission.module').then(m => m.SubmissionModule)
8+
loadChildren: () => import('./feature/submission/submission.module').then(m => m.SubmissionModule),
9+
canActivate: [AuthGuard]
810
},
911
{
1012
path: 'reported-traits',
11-
loadChildren: () => import('./feature/reported-trait/reported-trait.module').then(m => m.ReportedTraitModule)
13+
loadChildren: () => import('./feature/reported-trait/reported-trait.module').then(m => m.ReportedTraitModule),
14+
canActivate: [AuthGuard]
1215
},
1316
{
1417
path: 'efo-traits',
15-
loadChildren: () => import('./feature/efo-trait/efo-trait.module').then(m => m.EfoTraitModule)
18+
loadChildren: () => import('./feature/efo-trait/efo-trait.module').then(m => m.EfoTraitModule),
19+
canActivate: [AuthGuard]
1620
},
1721
{
1822
path: 'studies',
19-
loadChildren: () => import('./feature/study/study.module').then(m => m.StudyModule)
23+
loadChildren: () => import('./feature/study/study.module').then(m => m.StudyModule),
24+
canActivate: [AuthGuard]
2025
},
2126
{
2227
path: 'publications',
23-
loadChildren: () => import('./feature/publication/publication.module').then(m => m.PublicationModule)
28+
loadChildren: () => import('./feature/publication/publication.module').then(m => m.PublicationModule),
29+
canActivate: [AuthGuard]
2430
},
2531
{
2632
path: 'login',

src/app/app.component.ts

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,21 @@
1-
import { Component } from '@angular/core';
1+
import { Component, OnInit } from '@angular/core';
22
import {ActivationEnd, Router} from '@angular/router';
33

44
@Component({
55
selector: 'app-root',
66
templateUrl: 'app.component.html',
77
styleUrls: ['app.component.css']
88
})
9-
export class AppComponent {
10-
11-
routePath: string;
9+
export class AppComponent implements OnInit {
1210
constructor(private router: Router) {
13-
router.events.subscribe((val) => {
11+
this.router.events.subscribe((val) => {
1412
if (val instanceof ActivationEnd) {
1513
this.routePath = val.snapshot.routeConfig.path;
1614
}
1715
});
1816
}
17+
18+
routePath: string;
19+
20+
ngOnInit() {}
1921
}

src/app/app.module.ts

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,30 @@
11
import { BrowserModule } from '@angular/platform-browser';
2-
import { NgModule } from '@angular/core';
2+
import { APP_INITIALIZER, NgModule } from '@angular/core';
33
import { AppRoutingModule } from './app-routing.module';
44
import { AppComponent } from './app.component';
55
import { CoreModule } from './core/core.module';
66
import { SharedModule } from './shared/shared.module';
7+
import { AuthConfig, OAuthModule, OAuthService, OAuthStorage } from 'angular-oauth2-oidc';
8+
9+
export function storageFactory(): OAuthStorage {
10+
return localStorage;
11+
}
12+
13+
export function initializeApp(oauthService: OAuthService) {
14+
return (): Promise<any> => {
15+
const authConfig: AuthConfig = {
16+
issuer: 'https://www.ebi.ac.uk/mi/keycloak/realms/gwas',
17+
redirectUri: `${window.location.origin}/gwas/depo-curation`,
18+
clientId: 'deposition',
19+
responseType: 'code',
20+
scope: 'profile email',
21+
// showDebugInformation: true,
22+
disablePKCE: false
23+
};
24+
oauthService.configure(authConfig);
25+
return oauthService.loadDiscoveryDocumentAndTryLogin();
26+
};
27+
}
728

829
@NgModule({
930
declarations: [
@@ -13,9 +34,18 @@ import { SharedModule } from './shared/shared.module';
1334
BrowserModule,
1435
AppRoutingModule,
1536
CoreModule,
16-
SharedModule
37+
SharedModule,
38+
OAuthModule.forRoot()
39+
],
40+
providers: [
41+
{
42+
provide: APP_INITIALIZER,
43+
useFactory: initializeApp,
44+
deps: [OAuthService],
45+
multi: true
46+
},
47+
{ provide: OAuthStorage, useFactory: storageFactory }
1748
],
18-
providers: [],
1949
bootstrap: [AppComponent]
2050
})
2151
export class AppModule {

src/app/core/guards/auth.guard.ts

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,18 @@
11
import { Injectable } from '@angular/core';
2-
import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, Router } from '@angular/router';
2+
import { ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot } from '@angular/router';
33
import { AuthService } from '../services/auth.service';
4-
import { TokenStorageService } from '../services/token-storage.service';
54

65
@Injectable({
76
providedIn: 'root'
87
})
98
export class AuthGuard implements CanActivate {
10-
11-
constructor(private authService: AuthService, private tss: TokenStorageService) {
12-
}
9+
constructor(private authService: AuthService, private router: Router) {}
1310

1411
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
15-
if (this.authService.loggedIn() && this.authService.isCurator()) {
12+
if (this.authService.isLoggedIn()) {
1613
return true;
1714
} else {
18-
this.tss.signOut(state.url);
15+
this.router.navigate(['/login'], { queryParams: { returnUrl: state.url } });
1916
return false;
2017
}
2118
}
Lines changed: 15 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -1,87 +1,40 @@
11
import { Injectable } from '@angular/core';
2-
import { HttpClient } from '@angular/common/http';
3-
import { TokenStorageService } from './token-storage.service';
4-
import jwt_decode from 'jwt-decode';
52
import { environment } from '../../../environments/environment';
3+
import { AuthConfig, OAuthService } from 'angular-oauth2-oidc';
64
import { Router } from '@angular/router';
75

86
@Injectable({
97
providedIn: 'root'
108
})
119
export class AuthService {
1210

13-
constructor(private http: HttpClient, private tokenStorageService: TokenStorageService, private router: Router) {
14-
15-
}
16-
17-
loggedIn() {
18-
return !!this.tokenStorageService.getToken();
11+
constructor(public oauthService: OAuthService, private router: Router) {
1912
}
2013

2114
isCurator() {
22-
if (environment.WHITELISTED_CURATORS.indexOf(this.getDecodedToken()?.email) > -1) {
15+
if (environment.WHITELISTED_CURATORS.indexOf(this.getEmail()) > -1) {
2316
return true;
2417
}
25-
return this.getDecodedToken()?.domains?.indexOf('self.GWAS_Curator') > -1;
26-
}
27-
28-
getDecodedToken() {
29-
const jwtToken = this.tokenStorageService.getToken();
30-
const decoded = jwt_decode(jwtToken);
31-
if (Date.now() > decoded.exp * 1000) {
32-
this.tokenStorageService.signOut();
33-
}
34-
return decoded;
18+
return this.getDomains().indexOf('self.GWAS_Curator') > -1;
3519
}
3620

3721
login() {
38-
const width = 650;
39-
const height = 1000;
40-
let left = -1;
41-
let top = -1;
42-
43-
if (left < 0) {
44-
const screenWidth = window.screen.width;
45-
if (screenWidth > width) {
46-
left = Math.round((screenWidth - width) / 2);
47-
}
48-
}
49-
if (top < 0) {
50-
const screenHeight = window.screen.height;
51-
if (screenHeight > height) {
52-
top = Math.round((screenHeight - height) / 2);
53-
}
54-
}
22+
this.oauthService.initLoginFlow();
23+
}
5524

56-
const windowOptions = [
57-
`width=${width}`,
58-
`height=${height}`,
59-
`left=${left}`,
60-
`top=${top}`,
61-
'personalbar=no',
62-
'toolbar=no',
63-
'scrollbars=yes',
64-
'resizable=yes',
65-
'directories=no',
66-
'location=no',
67-
'menubar=no',
68-
'titlebar=no',
69-
'toolbar=no'
70-
];
71-
const loginWindow = window.open(environment.AAPURL + '/sso?from=' + location.origin + '&ttl=180',
72-
'Sign in to Elixir', windowOptions.join(','));
25+
isLoggedIn(): boolean {
26+
return this.oauthService.hasValidAccessToken();
27+
}
7328

74-
if (loginWindow) {
75-
loginWindow.focus();
76-
}
77-
return loginWindow;
29+
logout() {
30+
this.oauthService.logOut();
7831
}
7932

80-
saveToken(token: string) {
81-
this.tokenStorageService.saveToken(token);
33+
getEmail() {
34+
return this.oauthService.getIdentityClaims['email'];
8235
}
8336

84-
logout() {
85-
window.localStorage.removeItem('id_token');
37+
getDomains() {
38+
return this.oauthService.getIdentityClaims['domains'];
8639
}
8740
}

src/app/core/services/token-storage.service.ts

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { Injectable } from '@angular/core';
22
import { Router, RouterStateSnapshot } from '@angular/router';
33
import { MatDialog } from '@angular/material/dialog';
44

5-
const TOKEN_KEY = 'id_token';
5+
const TOKEN_KEY = 'access_token';
66

77
@Injectable({
88
providedIn: 'root'
@@ -13,15 +13,10 @@ export class TokenStorageService {
1313
}
1414

1515
signOut(guardReturnUri?: string) {
16-
setTimeout('alert("SESSION EXPIRED")', 1);
17-
this.dialog.closeAll();
16+
// setTimeout('alert("SESSION EXPIRED")', 1);
17+
// this.dialog.closeAll();
1818
this.router.navigate(['/login'], {queryParams: {returnUrl: guardReturnUri ? guardReturnUri : 'home'}}).then();
19-
window.localStorage.removeItem(TOKEN_KEY);
20-
}
21-
22-
public saveToken(token: string) {
23-
window.localStorage.removeItem(TOKEN_KEY);
24-
window.localStorage.setItem(TOKEN_KEY, token);
19+
// window.localStorage.removeItem(TOKEN_KEY);
2520
}
2621

2722
public getToken(): string {

src/app/feature/authentication/pages/login/login.component.css

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
.login-divider-container{
2-
margin-left: 65px; margin-bottom: 40px; margin-top: 40px;
2+
margin: 40px;
33
}
44
.login-divider-container .mat-divider{
55
width: 37%; display: inline-block;

src/app/feature/authentication/pages/login/login.component.html

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,12 @@
88

99
<div class="text-center text-2xl mt-4 mb-8"> GWAS Curation App </div>
1010

11-
<div class="mb-4">
12-
<button class="gwas-button-wide card-3b " (click)="login()" mat-raised-button color="primary">
13-
<img class="inline h-8 w-8" src="assets/images/elixir-white-orange-logo.png" alt="">-
14-
Sign in with Elixir identity!
15-
</button>
11+
<div class="mb-4 flex justify-center items-center">
12+
<img class="card-3b cursor-pointer" (click)="login()" alt="CILogon" src="https://cilogon.org/images/cilogon-ci-32-g.png"/>
1613
</div>
1714

1815
<div class="login-divider-container">
19-
<mat-divider></mat-divider>
20-
<span> or </span>
21-
<mat-divider></mat-divider>
16+
<mat-divider class="w-full"></mat-divider>
2217
</div>
2318

2419
<div class="mb-4">

0 commit comments

Comments
 (0)