From 998edcb5cdfb588c2986f466f4a2951f172a8bb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jovan=20Kruni=C4=87?= Date: Fri, 14 Oct 2022 21:49:48 +0200 Subject: [PATCH] fix: user info card Closes #305 --- src/app/_helpers/data/sample-configuration.ts | 167 +++++++++++++++++- .../modules/auth/auth-helper.service.spec.ts | 136 ++++++++++++++ src/app/modules/auth/auth-helper.service.ts | 17 +- .../modules/config/config.provider.spec.ts | 167 +----------------- src/app/modules/config/config.provider.ts | 4 +- .../modules/profile/page/profile-page.html | 5 +- .../modules/profile/page/profile-page.scss | 2 +- 7 files changed, 323 insertions(+), 175 deletions(-) create mode 100644 src/app/modules/auth/auth-helper.service.spec.ts diff --git a/src/app/_helpers/data/sample-configuration.ts b/src/app/_helpers/data/sample-configuration.ts index 3f838705..d65c781e 100644 --- a/src/app/_helpers/data/sample-configuration.ts +++ b/src/app/_helpers/data/sample-configuration.ts @@ -12,8 +12,15 @@ * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ -import {SCAuthorizationProvider, SCBackendAggregationConfiguration, SCThingType} from '@openstapps/core'; +import { + SCAboutPageContentType, + SCAuthorizationProvider, + SCBackendAggregationConfiguration, + SCIndexResponse, SCSettingInputType, SCThingOriginType, + SCThingType +} from '@openstapps/core'; import {Polygon} from 'geojson'; +import packageJson from "../../../../package.json"; // provides sample aggregations to be used in tests or backendless development export const sampleAggregations: SCBackendAggregationConfiguration[] = [ @@ -118,3 +125,161 @@ export const sampleDefaultPolygon: Polygon = { ], "type": "Polygon" } + +const scVersion = packageJson.dependencies['@openstapps/core']; + +export const sampleIndexResponse: SCIndexResponse = { + app: { + aboutPages: { + about: { + title: 'About', + content: [ + { + value: 'This is the about page', + type: SCAboutPageContentType.MARKDOWN, + translations: { + en: { + value: 'This is the about page', + }, + }, + }, + ], + translations: { + en: { + title: 'About', + }, + }, + }, + }, + campusPolygon: { + coordinates: [[[1, 2]], [[1, 2]]], + type: 'Polygon', + }, + features: {}, + menus: [ + { + icon: 'icon', + id: 'main', + items: [ + { + icon: 'icon', + route: '/index', + title: 'start', + translations: { + de: { + title: 'Start', + }, + en: { + title: 'start', + }, + }, + }, + ], + name: 'main', + translations: { + de: { + name: 'Haupt', + }, + en: { + name: 'main', + }, + }, + }, + ], + name: 'StApps', + privacyPolicyUrl: 'foo.bar', + settings: [ + { + categories: ['credentials'], + defaultValue: '', + inputType: SCSettingInputType.Text, + name: 'username', + order: 0, + origin: { + indexed: '2018-09-11T12:30:00Z', + name: 'Dummy', + type: SCThingOriginType.Remote, + }, + translations: { + de: { + name: 'Benutzername', + }, + en: { + name: 'Username', + }, + }, + type: SCThingType.Setting, + uid: '', + }, + ], + }, + auth: {}, + backend: { + SCVersion: scVersion, + externalRequestTimeout: 5000, + hiddenTypes: [SCThingType.DateSeries, SCThingType.Diff, SCThingType.Floor], + mappingIgnoredTags: [], + maxMultiSearchRouteQueries: 5, + maxRequestBodySize: 512 * 1024, + name: 'Technische Universität Berlin', + namespace: '909a8cbc-8520-456c-b474-ef1525f14209', + sortableFields: [ + { + fieldName: 'name', + sortTypes: ['ducet'], + }, + { + fieldName: 'type', + sortTypes: ['ducet'], + }, + { + fieldName: 'categories', + onlyOnTypes: [ + SCThingType.AcademicEvent, + SCThingType.Building, + SCThingType.Catalog, + SCThingType.Dish, + SCThingType.PointOfInterest, + SCThingType.Room, + ], + sortTypes: ['ducet'], + }, + { + fieldName: 'geo', + onlyOnTypes: [ + SCThingType.Building, + SCThingType.PointOfInterest, + SCThingType.Room, + ], + sortTypes: ['distance'], + }, + { + fieldName: 'geo', + onlyOnTypes: [ + SCThingType.Building, + SCThingType.PointOfInterest, + SCThingType.Room, + ], + sortTypes: ['distance'], + }, + { + fieldName: 'inPlace.geo', + onlyOnTypes: [ + SCThingType.DateSeries, + SCThingType.Dish, + SCThingType.Floor, + SCThingType.Organization, + SCThingType.PointOfInterest, + SCThingType.Room, + SCThingType.Ticket, + ], + sortTypes: ['distance'], + }, + { + fieldName: 'offers', + onlyOnTypes: [SCThingType.Dish], + sortTypes: ['price'], + }, + ], + }, +}; diff --git a/src/app/modules/auth/auth-helper.service.spec.ts b/src/app/modules/auth/auth-helper.service.spec.ts new file mode 100644 index 00000000..2a016d89 --- /dev/null +++ b/src/app/modules/auth/auth-helper.service.spec.ts @@ -0,0 +1,136 @@ +/* + * Copyright (C) 2022 StApps + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + */ +import {TestBed} from '@angular/core/testing'; +import {AuthHelperService} from './auth-helper.service'; +import {ConfigProvider} from '../config/config.provider'; +import {StorageProvider} from '../storage/storage.provider'; +import {DefaultAuthService} from './default-auth.service'; +import {Browser} from 'ionic-appauth'; +import {Requestor, StorageBackend} from '@openid/appauth'; +import {TranslateService} from '@ngx-translate/core'; +import {PAIAAuthService} from './paia/paia-auth.service'; +import {LoggerConfig, LoggerModule, NGXLogger} from 'ngx-logger'; +import {StAppsWebHttpClient} from '../data/stapps-web-http-client.provider'; +import {HttpClientModule} from '@angular/common/http'; + +describe('AuthHelperService', () => { + let authHelperService: AuthHelperService; + const storageProviderSpy = jasmine.createSpyObj('StorageProvider', [ + 'init', + 'get', + 'has', + 'put', + 'search', + ]); + const translateServiceSpy = jasmine.createSpyObj('TranslateService', [ + 'setDefaultLang', + 'use', + ]); + const defaultAuthServiceMock = jasmine.createSpyObj('DefaultAuthService', [ + 'init', + 'setupConfiguration', + ]); + const paiaAuthServiceMock = jasmine.createSpyObj('PAIAAuthService', [ + 'init', + 'setupConfiguration', + ]); + const authHelperServiceMock = jasmine.createSpyObj('AuthHelperService', [ + 'constructor', + ]); + const configProvider = jasmine.createSpyObj('ConfigProvider', { + getAnyValue: { + default: { + endpoints: { + mapping: { + id: '$.id', + email: '$.attributes.mailPrimaryAddress', + givenName: '$.attributes.givenName', + familyName: '$.attributes.sn', + name: '$.attributes.sn', + role: '$.attributes.eduPersonPrimaryAffiliation', + studentId: '$.attributes.employeeNumber', + }, + }, + }, + }, + }); + + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [HttpClientModule, LoggerModule], + providers: [ + NGXLogger, + StAppsWebHttpClient, + LoggerConfig, + { + provide: TranslateService, + useValue: translateServiceSpy, + }, + { + provide: StorageProvider, + useValue: storageProviderSpy, + }, + { + provider: DefaultAuthService, + useValue: defaultAuthServiceMock, + }, + { + provider: PAIAAuthService, + useValue: paiaAuthServiceMock, + }, + { + provide: ConfigProvider, + useValue: configProvider, + }, + Browser, + StorageBackend, + Requestor, + { + provider: AuthHelperService, + useValue: authHelperServiceMock, + }, + ], + }); + authHelperService = TestBed.inject(AuthHelperService); + }); + + describe('getUserFromUserInfo', () => { + it('should provide user configuration from userInfo', async () => { + const userConfiguration = authHelperService.getUserFromUserInfo({ + attributes: { + eduPersonPrimaryAffiliation: 'student', + employeeNumber: '123456', + givenName: 'Erika', + mailPrimaryAddress: 'emuster@anyschool.de', + oauthClientId: '123-abc-123', + sn: 'Musterfrau', + uid: 'emuster', + }, + id: 'emuster', + client_id: '123-abc-123', + }); + + expect(userConfiguration).toEqual({ + id: 'emuster', + givenName: 'Erika', + familyName: 'Musterfrau', + name: 'Erika Musterfrau', + email: 'emuster@anyschool.de', + role: 'student', + studentId: '123456', + }); + }); + }); +}); diff --git a/src/app/modules/auth/auth-helper.service.ts b/src/app/modules/auth/auth-helper.service.ts index ac2b4821..8c78e31a 100644 --- a/src/app/modules/auth/auth-helper.service.ts +++ b/src/app/modules/auth/auth-helper.service.ts @@ -2,7 +2,6 @@ import {Injectable} from '@angular/core'; import {IPAIAAuthAction} from './paia/paia-auth-action'; import {AuthActions, IAuthAction} from 'ionic-appauth'; import {TranslateService} from '@ngx-translate/core'; -import {JSONFile} from '@angular/cli/utilities/json-file'; import {JSONPath} from 'jsonpath-plus'; import { SCAuthorizationProvider, @@ -56,8 +55,12 @@ export class AuthHelperService { return message; } - getUserFromUserInfo(userInfo: JSONFile) { - const user: SCUserConfiguration = {id: '', name: '', role: 'student'}; + getUserFromUserInfo(userInfo: object) { + const user: SCUserConfiguration = { + id: '', + name: '', + role: 'student', + }; for (const key in this.userConfigurationMap) { user[key as keyof SCUserConfiguration] = JSONPath({ path: this.userConfigurationMap[ @@ -67,6 +70,14 @@ export class AuthHelperService { preventEval: true, })[0]; } + if ( + user.givenName && + user.givenName.length > 0 && + user.familyName && + user.familyName.length > 0 + ) { + user.name = `${user.givenName} ${user.familyName}`; + } return user; } diff --git a/src/app/modules/config/config.provider.spec.ts b/src/app/modules/config/config.provider.spec.ts index 88dd9c64..4c64f2b2 100644 --- a/src/app/modules/config/config.provider.spec.ts +++ b/src/app/modules/config/config.provider.spec.ts @@ -13,13 +13,6 @@ * this program. If not, see . */ import {TestBed} from '@angular/core/testing'; -import { - SCAboutPageContentType, - SCIndexResponse, - SCSettingInputType, - SCThingOriginType, - SCThingType, -} from '@openstapps/core'; import {StAppsWebHttpClient} from '../data/stapps-web-http-client.provider'; import {StorageProvider} from '../storage/storage.provider'; import {ConfigProvider, STORAGE_KEY_CONFIG} from './config.provider'; @@ -30,7 +23,7 @@ import { WrongConfigVersionInStorage, } from './errors'; import {NGXLogger} from 'ngx-logger'; -import packageJson from '../../../../package.json'; +import {sampleIndexResponse} from '../../_helpers/data/sample-configuration'; describe('ConfigProvider', () => { let configProvider: ConfigProvider; @@ -192,161 +185,3 @@ describe('ConfigProvider', () => { ); }); }); - -const scVersion = packageJson.dependencies['@openstapps/core']; - -const sampleIndexResponse: SCIndexResponse = { - app: { - aboutPages: { - about: { - title: 'About', - content: [ - { - value: 'This is the about page', - type: SCAboutPageContentType.MARKDOWN, - translations: { - en: { - value: 'This is the about page', - }, - }, - }, - ], - translations: { - en: { - title: 'About', - }, - }, - }, - }, - campusPolygon: { - coordinates: [[[1, 2]], [[1, 2]]], - type: 'Polygon', - }, - features: {}, - menus: [ - { - icon: 'icon', - id: 'main', - items: [ - { - icon: 'icon', - route: '/index', - title: 'start', - translations: { - de: { - title: 'Start', - }, - en: { - title: 'start', - }, - }, - }, - ], - name: 'main', - translations: { - de: { - name: 'Haupt', - }, - en: { - name: 'main', - }, - }, - }, - ], - name: 'StApps', - privacyPolicyUrl: 'foo.bar', - settings: [ - { - categories: ['credentials'], - defaultValue: '', - inputType: SCSettingInputType.Text, - name: 'username', - order: 0, - origin: { - indexed: '2018-09-11T12:30:00Z', - name: 'Dummy', - type: SCThingOriginType.Remote, - }, - translations: { - de: { - name: 'Benutzername', - }, - en: { - name: 'Username', - }, - }, - type: SCThingType.Setting, - uid: '', - }, - ], - }, - auth: {}, - backend: { - SCVersion: scVersion, - externalRequestTimeout: 5000, - hiddenTypes: [SCThingType.DateSeries, SCThingType.Diff, SCThingType.Floor], - mappingIgnoredTags: [], - maxMultiSearchRouteQueries: 5, - maxRequestBodySize: 512 * 1024, - name: 'Technische Universität Berlin', - namespace: '909a8cbc-8520-456c-b474-ef1525f14209', - sortableFields: [ - { - fieldName: 'name', - sortTypes: ['ducet'], - }, - { - fieldName: 'type', - sortTypes: ['ducet'], - }, - { - fieldName: 'categories', - onlyOnTypes: [ - SCThingType.AcademicEvent, - SCThingType.Building, - SCThingType.Catalog, - SCThingType.Dish, - SCThingType.PointOfInterest, - SCThingType.Room, - ], - sortTypes: ['ducet'], - }, - { - fieldName: 'geo', - onlyOnTypes: [ - SCThingType.Building, - SCThingType.PointOfInterest, - SCThingType.Room, - ], - sortTypes: ['distance'], - }, - { - fieldName: 'geo', - onlyOnTypes: [ - SCThingType.Building, - SCThingType.PointOfInterest, - SCThingType.Room, - ], - sortTypes: ['distance'], - }, - { - fieldName: 'inPlace.geo', - onlyOnTypes: [ - SCThingType.DateSeries, - SCThingType.Dish, - SCThingType.Floor, - SCThingType.Organization, - SCThingType.PointOfInterest, - SCThingType.Room, - SCThingType.Ticket, - ], - sortTypes: ['distance'], - }, - { - fieldName: 'offers', - onlyOnTypes: [SCThingType.Dish], - sortTypes: ['price'], - }, - ], - }, -}; diff --git a/src/app/modules/config/config.provider.ts b/src/app/modules/config/config.provider.ts index b7288222..2470c8a1 100644 --- a/src/app/modules/config/config.provider.ts +++ b/src/app/modules/config/config.provider.ts @@ -38,7 +38,9 @@ export const STORAGE_KEY_CONFIG = 'stapps.config'; /** * Provides configuration */ -@Injectable() +@Injectable({ + providedIn: 'root', +}) export class ConfigProvider { /** * Api client diff --git a/src/app/modules/profile/page/profile-page.html b/src/app/modules/profile/page/profile-page.html index 501d21cd..636339c4 100644 --- a/src/app/modules/profile/page/profile-page.html +++ b/src/app/modules/profile/page/profile-page.html @@ -50,8 +50,7 @@ class="main-info" > - {{ userInfo?.givenName }} - {{ userInfo?.familyName }} + {{ userInfo?.name }}
@@ -65,7 +64,7 @@ {{ 'profile.userInfo.username' | translate | uppercase }} - {{ userInfo?.name }} + {{ userInfo?.id }}