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 }}
diff --git a/src/app/modules/profile/page/profile-page.scss b/src/app/modules/profile/page/profile-page.scss
index 95a31c28..46dc5c3d 100644
--- a/src/app/modules/profile/page/profile-page.scss
+++ b/src/app/modules/profile/page/profile-page.scss
@@ -72,7 +72,7 @@
height: 100%;
width: 50%;
margin-left: calc(var(--spacing-md) * -4);
- object-position: left 50%;
+ object-position: left bottom;
}
.main-info {