Skip to content

Commit

Permalink
Merge pull request #459 from NUM-Forschungsdatenplattform/develop
Browse files Browse the repository at this point in the history
release 1.13.0
  • Loading branch information
richardbartha committed Jun 7, 2023
2 parents a59fb07 + 9dee2ee commit eaa05fe
Show file tree
Hide file tree
Showing 38 changed files with 1,379 additions and 670 deletions.
Binary file modified docs/01_user_account/images/sign_up_with_open_modal.en.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
229 changes: 131 additions & 98 deletions package-lock.json

Large diffs are not rendered by default.

7 changes: 5 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "num-portal-webapp",
"version": "1.12.0",
"version": "1.13.0",
"scripts": {
"postinstall": "ngcc",
"ng": "ng",
Expand Down Expand Up @@ -42,6 +42,8 @@
"@fortawesome/free-regular-svg-icons": "^5.15.4",
"@fortawesome/free-solid-svg-icons": "^5.15.4",
"@juggle/resize-observer": "^3.3.1",
"@ng-idle/core": "^11.1.0",
"@ng-idle/keepalive": "^11.0.3",
"@ngx-translate/core": "^14.0.0",
"@ngx-translate/http-loader": "^7.0.0",
"@swimlane/ngx-charts": "^19.2.0",
Expand Down Expand Up @@ -98,7 +100,8 @@
"node-forge": ">=1.3.0",
"terser": ">=5.14.2",
"node-fetch": ">=2.6.7",
"d3-color": ">=3.1.0"
"d3-color": ">=3.1.0",
"webpack": "^5.76.0"
},
"husky": {
"hooks": {
Expand Down
77 changes: 72 additions & 5 deletions src/app/core/auth/auth.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,15 @@
* limitations under the License.
*/

import { HttpClient } from '@angular/common/http'
import { HttpClient, HttpErrorResponse } from '@angular/common/http'
import { Router } from '@angular/router'
import { Idle } from '@ng-idle/core'
import { Keepalive } from '@ng-idle/keepalive'
import { OAuthEvent, OAuthService } from 'angular-oauth2-oidc'
import { of, Subject } from 'rxjs'
import { of, Subject, throwError } from 'rxjs'
import { AppConfigService } from 'src/app/config/app-config.service'
import { IAuthUserProfile } from 'src/app/shared/models/user/auth-user-profile.interface'
import { mockOAuthUser } from 'src/mocks/data-mocks/admin.mock'
import { mockOAuthUser, mockUsers } from 'src/mocks/data-mocks/admin.mock'
import { ProfileService } from '../services/profile/profile.service'
import { AuthService } from './auth.service'

Expand All @@ -47,13 +49,30 @@ describe('Auth Service', () => {
} as unknown as OAuthService

const httpClient = {
post: jest.fn(),
get: jest.fn(),
post: jest.fn().mockImplementation(() => of()),
} as unknown as HttpClient

const profileService = {
get: jest.fn(),
} as unknown as ProfileService

const idle = {
watch: () => jest.fn(),
setIdle: () => jest.fn(),
setTimeout: () => jest.fn(),
setIdleTime: () => jest.fn(),
setInterrupts: () => jest.fn(),
setTimeoutTime: () => jest.fn(),
onIdleEnd: { subscribe: () => {} },
onTimeout: { subscribe: () => {} },
} as unknown as Idle

const keepAlive = {
interval: () => jest.fn(),
onPing: { subscribe: () => {} },
} as unknown as Keepalive

const mockRouter = {
navigate: () => jest.fn(),
} as unknown as Router
Expand All @@ -67,10 +86,19 @@ describe('Auth Service', () => {
} as AppConfigService

beforeEach(() => {
authService = new AuthService(oauthService, profileService, appConfig, httpClient, mockRouter)
authService = new AuthService(
oauthService,
profileService,
appConfig,
httpClient,
mockRouter,
idle,
keepAlive
)
jest.spyOn(profileService, 'get').mockImplementation(() => of())
eventSubject = new Subject<OAuthEvent>()
oauthService.events = eventSubject.asObservable()

jest.clearAllMocks()
})

Expand All @@ -89,6 +117,45 @@ describe('Auth Service', () => {
})
})

describe('When initIdle is called', () => {
it('initIdle called', () => {
authService.initIdle()
})
})

describe('When createUser is called', () => {
it('createUser called', () => {
jest.spyOn(httpClient, 'post').mockImplementation(() => of())
authService.createUser('test')
})
})

describe('When createUser is called with error', () => {
it('createUser called with error', () => {
jest.spyOn(httpClient, 'post').mockImplementation(() => throwError('Error'))
authService.createUser('test')
})
})

describe('When the user wants goes afk idle process should be used', () => {
it('Should call the resetIdle method, than logout', () => {
jest.spyOn(authService, 'initIdle')
jest.spyOn(authService, 'logout')
idle.setIdleTime(1)
idle.setTimeoutTime(1)
expect(authService.resetIdle).toHaveBeenCalled
expect(oauthService.logOut).toHaveBeenCalled
})
})

describe('When reseting idle process', () => {
it('timeout should be set to false', () => {
jest.spyOn(authService, 'resetIdle')
authService.resetIdle()
expect(authService.timedOut).toBeFalsy()
})
})

describe('When the user wants to logout', () => {
it('Calls the logOut method', () => {
jest.spyOn(oauthService, 'logOut')
Expand Down
49 changes: 45 additions & 4 deletions src/app/core/auth/auth.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
import { HttpClient } from '@angular/common/http'
import { Injectable } from '@angular/core'
import { Router } from '@angular/router'
import { DEFAULT_INTERRUPTSOURCES, Idle } from '@ng-idle/core'
import { Keepalive } from '@ng-idle/keepalive'
import { OAuthService } from 'angular-oauth2-oidc'
import { BehaviorSubject, Observable, of } from 'rxjs'
import { catchError } from 'rxjs/operators'
Expand All @@ -25,21 +27,32 @@ import { IAuthUserInfo } from 'src/app/shared/models/user/auth-user-info.interfa
import { IAuthUserProfile } from 'src/app/shared/models/user/auth-user-profile.interface'
import { ProfileService } from '../services/profile/profile.service'

const TIME_BEFORE_START_IDLE = 1
const TIME_TO_WAIT_IDLE = 3600

@Injectable({
providedIn: 'root',
})
export class AuthService {
private userInfo: IAuthUserInfo = { sub: undefined }
private userInfoSubject$ = new BehaviorSubject(this.userInfo)
public userInfoObservable$ = this.userInfoSubject$.asObservable()
public timedOut = false
public lastPing?: Date = null

constructor(
private oauthService: OAuthService,
private profileService: ProfileService,
private appConfig: AppConfigService,
private httpClient: HttpClient,
private router: Router
) {}
private router: Router,
public idle: Idle,
private keepAlive: Keepalive
) {
if (this.isLoggedIn) {
this.initIdle()
}
}

public initTokenHandling(): void {
if (this.oauthService.state) {
Expand All @@ -54,6 +67,23 @@ export class AuthService {
})
}

public initIdle(): void {
this.idle.setIdle(TIME_BEFORE_START_IDLE)
this.idle.setTimeout(TIME_TO_WAIT_IDLE)
this.idle.setInterrupts(DEFAULT_INTERRUPTSOURCES)
this.idle.onIdleEnd.subscribe(() => {
this.resetIdle()
})
this.idle.onTimeout.subscribe(() => {
this.timedOut = true
this.logout()
})

this.keepAlive.interval(TIME_TO_WAIT_IDLE)
this.keepAlive.onPing.subscribe(() => (this.lastPing = new Date()))
this.resetIdle()
}

public get isLoggedIn(): boolean {
return this.oauthService.hasValidIdToken() && this.oauthService.hasValidAccessToken()
}
Expand All @@ -67,7 +97,12 @@ export class AuthService {
this.oauthService.logOut()
}

private createUser(userId: string): Observable<any> {
public resetIdle(): void {
this.idle.watch()
this.timedOut = false
}

public createUser(userId: string): Observable<any> {
const httpOptions = {
responseType: 'text' as 'json',
}
Expand Down Expand Up @@ -95,7 +130,13 @@ export class AuthService {
}

if (this.userInfo.sub !== userInfo?.info?.sub) {
await this.createUser(userInfo.info.sub).toPromise()
await this.createUser(userInfo.info.sub)
.toPromise()
.finally(() => {
if (!this.idle.isIdling()) {
this.initIdle()
}
})
}

this.userInfo = userInfo.info
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,5 @@ describe('GenericDialogComponent', () => {

it('should close the dialog with undefined on a close attempt', () => {
component.handleDialogClose()

expect(matDialogRef.close).toBeCalledWith()
})
})
9 changes: 8 additions & 1 deletion src/app/core/core.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,16 @@ import { GenericDialogComponent } from './components/generic-dialog/generic-dial
import { LayoutModule } from '../layout/layout.module'
import { SharedModule } from '../shared/shared.module'
import { OAuthModule } from 'angular-oauth2-oidc'
import { NgIdleKeepaliveModule } from '@ng-idle/keepalive'

@NgModule({
imports: [CommonModule, LayoutModule, SharedModule, OAuthModule.forRoot()],
imports: [
CommonModule,
LayoutModule,
SharedModule,
OAuthModule.forRoot(),
NgIdleKeepaliveModule.forRoot(),
],
providers: [AqlService, CohortService],
declarations: [GenericDialogComponent],
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,17 +131,6 @@ describe('AqlCategoriesManagementComponent', () => {
expect(component).toBeTruthy()
})

describe('When the components gets initialized', () => {
beforeEach(() => {
jest.spyOn(mockAqlCategoryService, 'getAll').mockImplementation(() => of(mockAqlCategories))
})
it('should call the getAll method', async () => {
fixture.detectChanges()
await fixture.whenStable()
expect(mockAqlCategoryService.getAll).toHaveBeenCalled()
})
})

describe('When the dialog is used to edit aql data', () => {
const dialogConfig: DialogConfig = {
...EDIT_AQL_CATEGORY_DIALOG_CONFIG,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ import { AqlCategoriesTableComponent } from '../aql-categories-table/aql-categor
templateUrl: './aql-categories-management.component.html',
styleUrls: ['./aql-categories-management.component.scss'],
})
export class AqlCategoriesManagementComponent implements OnDestroy, OnInit {
export class AqlCategoriesManagementComponent implements OnDestroy {
availableRoles = AvailableRoles

private subscriptions = new Subscription()
Expand All @@ -48,10 +48,6 @@ export class AqlCategoriesManagementComponent implements OnDestroy, OnInit {
private toast: ToastMessageService
) {}

ngOnInit(): void {
this.subscriptions.add(this.aqlCategoryService.getAll().subscribe())
}

ngOnDestroy(): void {
this.subscriptions.unsubscribe()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -159,11 +159,6 @@ describe('AqlEditorComponent', () => {
const element = nativeElement.querySelector('.editmode-on')
expect(element).toBeFalsy()
})

it('should load available categories on init', () => {
fixture.detectChanges()
expect(component.availableCategories).toHaveLength(mockAqlCategories.length)
})
})

describe('On the attempt to save the AQL', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -160,11 +160,6 @@ describe('AqlEditorComponent', () => {
const element = nativeElement.querySelector('.editmode-on')
expect(element).toBeTruthy()
})

it('should load available categories on init', () => {
fixture.detectChanges()
expect(component.availableCategories).toHaveLength(mockAqlCategories.length)
})
})

describe('On the attempt to save the AQL', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,8 @@ import { DELETE_APPROVAL_DIALOG_CONFIG } from './constants'
import { ToastMessageService } from 'src/app/core/services/toast-message/toast-message.service'
import { ToastMessageType } from 'src/app/shared/models/toast-message-type.enum'
import { AqlTableColumns } from 'src/app/shared/models/aql/aql-table.interface'
import { compareLocaleStringValues } from 'src/app/core/utils/sort.utils'
import { SortableTable } from 'src/app/shared/models/sortable-table.model'
import { TranslateService } from '@ngx-translate/core'
import { IAqlCategoryApi } from 'src/app/shared/models/aql/category/aql-category.interface'
import { AqlCategoryService } from 'src/app/core/services/aql-category/aql-category.service'
import { IAqlCategoryIdNameMap } from 'src/app/shared/models/aql/category/aql-category-id-name-map.interface'

Expand Down Expand Up @@ -131,7 +129,6 @@ export class AqlTableComponent extends SortableTable<IAqlApi> implements OnDestr
)

this.lang = this.translateService.currentLang || 'en'
this.aqlCategoryService.getAll().subscribe()
}

handleSortChangeTable(sort: Sort): void {
Expand Down
13 changes: 3 additions & 10 deletions src/app/modules/aqls/components/aqls/aqls.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,20 +14,13 @@
* limitations under the License.
*/

import { Component, OnInit } from '@angular/core'
import { AqlCategoryService } from 'src/app/core/services/aql-category/aql-category.service'
import { AqlService } from 'src/app/core/services/aql/aql.service'
import { Component } from '@angular/core'

@Component({
selector: 'num-aqls',
templateUrl: './aqls.component.html',
styleUrls: ['./aqls.component.scss'],
})
export class AqlsComponent implements OnInit {
constructor(private aqlCategoryService: AqlCategoryService, private aqlService: AqlService) {}

ngOnInit(): void {
this.aqlService.getAll().subscribe()
this.aqlCategoryService.getAll().subscribe()
}
export class AqlsComponent {
constructor() {}
}
Loading

0 comments on commit eaa05fe

Please sign in to comment.