mirror of
https://gitlab.com/openstapps/openstapps.git
synced 2026-01-21 17:12:43 +00:00
refactor: read auth provider info from app config
This commit is contained in:
committed by
Rainer Killinger
parent
a1592f84cc
commit
fb7b3fd1d2
@@ -12,7 +12,7 @@
|
|||||||
* You should have received a copy of the GNU General Public License along with
|
* You should have received a copy of the GNU General Public License along with
|
||||||
* this program. If not, see <https://www.gnu.org/licenses/>.
|
* this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
import {SCBackendAggregationConfiguration, SCThingType} from '@openstapps/core';
|
import {SCAuthorizationProvider, SCBackendAggregationConfiguration, SCThingType} from '@openstapps/core';
|
||||||
|
|
||||||
// provides sample aggregations to be used in tests or backendless development
|
// provides sample aggregations to be used in tests or backendless development
|
||||||
export const sampleAggregations: SCBackendAggregationConfiguration[] = [
|
export const sampleAggregations: SCBackendAggregationConfiguration[] = [
|
||||||
@@ -65,3 +65,27 @@ export const sampleAggregations: SCBackendAggregationConfiguration[] = [
|
|||||||
fieldName: 'type',
|
fieldName: 'type',
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
export const sampleAuthConfiguration: {
|
||||||
|
default: SCAuthorizationProvider;
|
||||||
|
paia: SCAuthorizationProvider;
|
||||||
|
} = {
|
||||||
|
default: {
|
||||||
|
client: {clientId: '', scopes: '', url: ''},
|
||||||
|
endpoints: {
|
||||||
|
authorization: '',
|
||||||
|
mapping: {id: '', name: ''},
|
||||||
|
token: '',
|
||||||
|
userinfo: '',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
paia: {
|
||||||
|
client: {clientId: '', scopes: '', url: ''},
|
||||||
|
endpoints: {
|
||||||
|
authorization: '',
|
||||||
|
mapping: {id: '', name: ''},
|
||||||
|
token: '',
|
||||||
|
userinfo: '',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ import {SettingsProvider} from './modules/settings/settings.provider';
|
|||||||
import {NGXLogger} from 'ngx-logger';
|
import {NGXLogger} from 'ngx-logger';
|
||||||
import {RouterTestingModule} from '@angular/router/testing';
|
import {RouterTestingModule} from '@angular/router/testing';
|
||||||
import {ScheduleSyncService} from './modules/background/schedule/schedule-sync.service';
|
import {ScheduleSyncService} from './modules/background/schedule/schedule-sync.service';
|
||||||
|
import {sampleAuthConfiguration} from './_helpers/data/sample-configuration';
|
||||||
|
|
||||||
describe('AppComponent', () => {
|
describe('AppComponent', () => {
|
||||||
let platformReadySpy: any;
|
let platformReadySpy: any;
|
||||||
@@ -38,7 +39,6 @@ describe('AppComponent', () => {
|
|||||||
let configProvider: jasmine.SpyObj<ConfigProvider>;
|
let configProvider: jasmine.SpyObj<ConfigProvider>;
|
||||||
let ngxLogger: jasmine.SpyObj<NGXLogger>;
|
let ngxLogger: jasmine.SpyObj<NGXLogger>;
|
||||||
let scheduleSyncServiceSpy: jasmine.SpyObj<ScheduleSyncService>;
|
let scheduleSyncServiceSpy: jasmine.SpyObj<ScheduleSyncService>;
|
||||||
|
|
||||||
let platformIsSpy;
|
let platformIsSpy;
|
||||||
|
|
||||||
beforeEach(
|
beforeEach(
|
||||||
@@ -65,7 +65,15 @@ describe('AppComponent', () => {
|
|||||||
'getDifferences',
|
'getDifferences',
|
||||||
'postDifferencesNotification',
|
'postDifferencesNotification',
|
||||||
]);
|
]);
|
||||||
configProvider = jasmine.createSpyObj('ConfigProvider', ['init']);
|
configProvider = jasmine.createSpyObj('ConfigProvider', [
|
||||||
|
'init',
|
||||||
|
'getAnyValue',
|
||||||
|
]);
|
||||||
|
configProvider.getAnyValue = jasmine
|
||||||
|
.createSpy()
|
||||||
|
.and.callFake(function () {
|
||||||
|
return sampleAuthConfiguration;
|
||||||
|
});
|
||||||
ngxLogger = jasmine.createSpyObj('NGXLogger', ['log', 'error', 'warn']);
|
ngxLogger = jasmine.createSpyObj('NGXLogger', ['log', 'error', 'warn']);
|
||||||
|
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
|
|||||||
@@ -22,9 +22,9 @@ import {ConfigProvider} from './modules/config/config.provider';
|
|||||||
import {SettingsProvider} from './modules/settings/settings.provider';
|
import {SettingsProvider} from './modules/settings/settings.provider';
|
||||||
import {PAIAAuthService} from './modules/auth/paia/paia-auth.service';
|
import {PAIAAuthService} from './modules/auth/paia/paia-auth.service';
|
||||||
import {DefaultAuthService} from './modules/auth/default-auth.service';
|
import {DefaultAuthService} from './modules/auth/default-auth.service';
|
||||||
import {environment} from '../environments/environment';
|
|
||||||
import {AuthHelperService} from './modules/auth/auth-helper.service';
|
import {AuthHelperService} from './modules/auth/auth-helper.service';
|
||||||
import {ScheduleSyncService} from './modules/background/schedule/schedule-sync.service';
|
import {ScheduleSyncService} from './modules/background/schedule/schedule-sync.service';
|
||||||
|
import {environment} from '../environments/environment';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO
|
* TODO
|
||||||
@@ -88,7 +88,7 @@ export class AppComponent implements AfterContentInit {
|
|||||||
async initializeApp() {
|
async initializeApp() {
|
||||||
App.addListener('appUrlOpen', (event: URLOpenListenerEvent) => {
|
App.addListener('appUrlOpen', (event: URLOpenListenerEvent) => {
|
||||||
this.zone.run(() => {
|
this.zone.run(() => {
|
||||||
const slug = event.url.split(environment.appDomain).pop();
|
const slug = event.url.split(environment.app_host).pop();
|
||||||
if (slug) {
|
if (slug) {
|
||||||
this.router.navigateByUrl(slug);
|
this.router.navigateByUrl(slug);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import {CanActivate, Router, RouterStateSnapshot} from '@angular/router';
|
|||||||
import {DefaultAuthService} from './default-auth.service';
|
import {DefaultAuthService} from './default-auth.service';
|
||||||
import {PAIAAuthService} from './paia/paia-auth.service';
|
import {PAIAAuthService} from './paia/paia-auth.service';
|
||||||
import {IAuthService} from 'ionic-appauth';
|
import {IAuthService} from 'ionic-appauth';
|
||||||
import {ActivatedAuthRouteSnapshot} from './auth-routes';
|
import {ActivatedProtectedRouteSnapshot} from './protected.routes';
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root',
|
providedIn: 'root',
|
||||||
@@ -18,7 +18,7 @@ export class AuthGuardService implements CanActivate {
|
|||||||
) {}
|
) {}
|
||||||
|
|
||||||
public async canActivate(
|
public async canActivate(
|
||||||
route: ActivatedAuthRouteSnapshot,
|
route: ActivatedProtectedRouteSnapshot,
|
||||||
_state: RouterStateSnapshot,
|
_state: RouterStateSnapshot,
|
||||||
) {
|
) {
|
||||||
switch (route.data.authProvider) {
|
switch (route.data.authProvider) {
|
||||||
|
|||||||
@@ -1,20 +1,33 @@
|
|||||||
import {Injectable} from '@angular/core';
|
import {Injectable} from '@angular/core';
|
||||||
import {
|
|
||||||
SCAuthorizationProviderType,
|
|
||||||
SCUserConfiguration,
|
|
||||||
userMapping,
|
|
||||||
} from '../profile/user';
|
|
||||||
import {IPAIAAuthAction} from './paia/paia-auth-action';
|
import {IPAIAAuthAction} from './paia/paia-auth-action';
|
||||||
import {AuthActions, IAuthAction} from 'ionic-appauth';
|
import {AuthActions, IAuthAction} from 'ionic-appauth';
|
||||||
import {TranslateService} from '@ngx-translate/core';
|
import {TranslateService} from '@ngx-translate/core';
|
||||||
import {JSONFile} from '@angular/cli/utilities/json-file';
|
import {JSONFile} from '@angular/cli/utilities/json-file';
|
||||||
import {JSONPath} from 'jsonpath-plus';
|
import {JSONPath} from 'jsonpath-plus';
|
||||||
|
import {
|
||||||
|
SCAuthorizationProvider,
|
||||||
|
SCAuthorizationProviderType,
|
||||||
|
SCUserConfiguration,
|
||||||
|
SCUserConfigurationMap,
|
||||||
|
} from '@openstapps/core';
|
||||||
|
import {ConfigProvider} from '../config/config.provider';
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root',
|
providedIn: 'root',
|
||||||
})
|
})
|
||||||
export class AuthHelperService {
|
export class AuthHelperService {
|
||||||
constructor(private translateService: TranslateService) {}
|
userConfigurationMap: SCUserConfigurationMap;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private translateService: TranslateService,
|
||||||
|
private configProvider: ConfigProvider,
|
||||||
|
) {
|
||||||
|
this.userConfigurationMap = (
|
||||||
|
this.configProvider.getAnyValue('auth') as {
|
||||||
|
default: SCAuthorizationProvider;
|
||||||
|
}
|
||||||
|
).default.endpoints.mapping;
|
||||||
|
}
|
||||||
|
|
||||||
public getAuthMessage(
|
public getAuthMessage(
|
||||||
provider: SCAuthorizationProviderType,
|
provider: SCAuthorizationProviderType,
|
||||||
@@ -38,9 +51,11 @@ export class AuthHelperService {
|
|||||||
|
|
||||||
getUserFromUserInfo(userInfo: JSONFile) {
|
getUserFromUserInfo(userInfo: JSONFile) {
|
||||||
const user: SCUserConfiguration = {id: '', name: '', role: 'student'};
|
const user: SCUserConfiguration = {id: '', name: '', role: 'student'};
|
||||||
for (const key in userMapping) {
|
for (const key in this.userConfigurationMap) {
|
||||||
user[key as keyof SCUserConfiguration] = JSONPath({
|
user[key as keyof SCUserConfiguration] = JSONPath({
|
||||||
path: userMapping[key as keyof SCUserConfiguration] as string,
|
path: this.userConfigurationMap[
|
||||||
|
key as keyof SCUserConfiguration
|
||||||
|
] as string,
|
||||||
json: userInfo,
|
json: userInfo,
|
||||||
})[0];
|
})[0];
|
||||||
}
|
}
|
||||||
|
|||||||
26
src/app/modules/auth/auth-paths.ts
Normal file
26
src/app/modules/auth/auth-paths.ts
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
/*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
import {SCAuthorizationProviderType} from '@openstapps/core';
|
||||||
|
|
||||||
|
export const authPaths: {
|
||||||
|
[key in SCAuthorizationProviderType]: {redirect_path: string};
|
||||||
|
} = {
|
||||||
|
default: {
|
||||||
|
redirect_path: 'auth/callback',
|
||||||
|
},
|
||||||
|
paia: {
|
||||||
|
redirect_path: 'auth/paia/callback',
|
||||||
|
},
|
||||||
|
};
|
||||||
@@ -17,10 +17,17 @@ import {RouterModule, Routes} from '@angular/router';
|
|||||||
import {NgModule} from '@angular/core';
|
import {NgModule} from '@angular/core';
|
||||||
import {AuthCallbackPageComponent} from './auth-callback/page/auth-callback-page.component';
|
import {AuthCallbackPageComponent} from './auth-callback/page/auth-callback-page.component';
|
||||||
import {PAIAAuthCallbackPageComponent} from './paia/auth-callback/page/auth-callback-page.component';
|
import {PAIAAuthCallbackPageComponent} from './paia/auth-callback/page/auth-callback-page.component';
|
||||||
|
import {authPaths} from './auth-paths';
|
||||||
|
|
||||||
const authRoutes: Routes = [
|
const authRoutes: Routes = [
|
||||||
{path: 'auth/callback', component: AuthCallbackPageComponent},
|
{
|
||||||
{path: 'auth/paia/callback', component: PAIAAuthCallbackPageComponent},
|
path: authPaths.default.redirect_path,
|
||||||
|
component: AuthCallbackPageComponent,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: authPaths.paia.redirect_path,
|
||||||
|
component: PAIAAuthCallbackPageComponent,
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import {AuthRoutingModule} from './auth-routing.module';
|
|||||||
import {TranslateModule} from '@ngx-translate/core';
|
import {TranslateModule} from '@ngx-translate/core';
|
||||||
import {AuthCallbackPageComponent} from './auth-callback/page/auth-callback-page.component';
|
import {AuthCallbackPageComponent} from './auth-callback/page/auth-callback-page.component';
|
||||||
import {PAIAAuthCallbackPageComponent} from './paia/auth-callback/page/auth-callback-page.component';
|
import {PAIAAuthCallbackPageComponent} from './paia/auth-callback/page/auth-callback-page.component';
|
||||||
|
import {ConfigProvider} from '../config/config.provider';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [AuthCallbackPageComponent, PAIAAuthCallbackPageComponent],
|
declarations: [AuthCallbackPageComponent, PAIAAuthCallbackPageComponent],
|
||||||
@@ -35,12 +36,12 @@ import {PAIAAuthCallbackPageComponent} from './paia/auth-callback/page/auth-call
|
|||||||
{
|
{
|
||||||
provide: DefaultAuthService,
|
provide: DefaultAuthService,
|
||||||
useFactory: authFactory,
|
useFactory: authFactory,
|
||||||
deps: [Requestor, Browser, StorageBackend],
|
deps: [Requestor, Browser, StorageBackend, ConfigProvider],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
provide: PAIAAuthService,
|
provide: PAIAAuthService,
|
||||||
useFactory: paiaAuthFactory,
|
useFactory: paiaAuthFactory,
|
||||||
deps: [Requestor, Browser, StorageBackend],
|
deps: [Requestor, Browser, StorageBackend, ConfigProvider],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -17,21 +17,36 @@ import {
|
|||||||
StorageBackend,
|
StorageBackend,
|
||||||
Requestor,
|
Requestor,
|
||||||
AuthorizationServiceConfiguration,
|
AuthorizationServiceConfiguration,
|
||||||
|
AuthorizationServiceConfigurationJson,
|
||||||
} from '@openid/appauth';
|
} from '@openid/appauth';
|
||||||
import {Browser} from 'ionic-appauth';
|
import {Browser, IAuthConfig} from 'ionic-appauth';
|
||||||
import {environment} from 'src/environments/environment';
|
|
||||||
import {DefaultAuthService} from '../default-auth.service';
|
|
||||||
import {PAIAAuthService} from '../paia/paia-auth.service';
|
import {PAIAAuthService} from '../paia/paia-auth.service';
|
||||||
|
import config from '../../../../../capacitor.config';
|
||||||
|
import {ConfigProvider} from '../../config/config.provider';
|
||||||
|
import {
|
||||||
|
SCAuthorizationProvider,
|
||||||
|
SCAuthorizationProviderType,
|
||||||
|
} from '@openstapps/core';
|
||||||
|
import {DefaultAuthService} from '../default-auth.service';
|
||||||
|
import {Capacitor} from '@capacitor/core';
|
||||||
|
import {authPaths} from '../auth-paths';
|
||||||
|
import {environment} from '../../../../environments/environment';
|
||||||
|
|
||||||
export const authFactory = (
|
export const authFactory = (
|
||||||
requestor: Requestor,
|
requestor: Requestor,
|
||||||
browser: Browser,
|
browser: Browser,
|
||||||
storage: StorageBackend,
|
storage: StorageBackend,
|
||||||
|
configProvider: ConfigProvider,
|
||||||
) => {
|
) => {
|
||||||
const authService = new DefaultAuthService(browser, storage, requestor);
|
const authService = new DefaultAuthService(browser, storage, requestor);
|
||||||
authService.authConfig = environment.oauth2.client.his;
|
const authConfig = configProvider.getAnyValue('auth') as {
|
||||||
|
default: SCAuthorizationProvider;
|
||||||
|
};
|
||||||
|
|
||||||
|
authService.authConfig = getClientConfig('default', authConfig);
|
||||||
|
|
||||||
authService.localConfiguration = new AuthorizationServiceConfiguration(
|
authService.localConfiguration = new AuthorizationServiceConfiguration(
|
||||||
environment.oauth2.service.his,
|
getEndpointsConfig('default', authConfig),
|
||||||
);
|
);
|
||||||
|
|
||||||
return authService;
|
return authService;
|
||||||
@@ -41,12 +56,67 @@ export const paiaAuthFactory = (
|
|||||||
requestor: Requestor,
|
requestor: Requestor,
|
||||||
browser: Browser,
|
browser: Browser,
|
||||||
storage: StorageBackend,
|
storage: StorageBackend,
|
||||||
|
configProvider: ConfigProvider,
|
||||||
) => {
|
) => {
|
||||||
const authService = new PAIAAuthService(browser, storage, requestor);
|
const authService = new PAIAAuthService(browser, storage, requestor);
|
||||||
authService.authConfig = environment.oauth2.client.paia;
|
const authConfig = configProvider.getAnyValue('auth') as {
|
||||||
|
paia: SCAuthorizationProvider;
|
||||||
|
};
|
||||||
|
|
||||||
|
authService.authConfig = getClientConfig('paia', authConfig);
|
||||||
|
|
||||||
authService.localConfiguration = new AuthorizationServiceConfiguration(
|
authService.localConfiguration = new AuthorizationServiceConfiguration(
|
||||||
environment.oauth2.service.paia,
|
getEndpointsConfig('paia', authConfig),
|
||||||
);
|
);
|
||||||
|
|
||||||
return authService;
|
return authService;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get configuration of an OAuth2 client
|
||||||
|
*/
|
||||||
|
function getClientConfig(
|
||||||
|
providerType: SCAuthorizationProviderType,
|
||||||
|
authConfig: {
|
||||||
|
default?: SCAuthorizationProvider;
|
||||||
|
paia?: SCAuthorizationProvider;
|
||||||
|
},
|
||||||
|
): IAuthConfig {
|
||||||
|
const providerConfig = authConfig[providerType] as SCAuthorizationProvider;
|
||||||
|
return {
|
||||||
|
end_session_redirect_url: '',
|
||||||
|
pkce: true,
|
||||||
|
scopes: providerConfig.client.scopes,
|
||||||
|
server_host: providerConfig.client.url,
|
||||||
|
client_id: providerConfig.client.clientId,
|
||||||
|
redirect_url: getRedirectUrl(authPaths[providerType].redirect_path),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get configuration about endpoints of an OAuth2 server
|
||||||
|
*/
|
||||||
|
function getEndpointsConfig(
|
||||||
|
providerType: SCAuthorizationProviderType,
|
||||||
|
authConfig: {
|
||||||
|
default?: SCAuthorizationProvider;
|
||||||
|
paia?: SCAuthorizationProvider;
|
||||||
|
},
|
||||||
|
): AuthorizationServiceConfigurationJson {
|
||||||
|
const providerConfig = authConfig[providerType] as SCAuthorizationProvider;
|
||||||
|
return {
|
||||||
|
authorization_endpoint: providerConfig.endpoints.authorization,
|
||||||
|
end_session_endpoint: providerConfig.endpoints.endSession,
|
||||||
|
revocation_endpoint: providerConfig.endpoints.revoke ?? '',
|
||||||
|
token_endpoint: providerConfig.endpoints.token,
|
||||||
|
userinfo_endpoint: providerConfig.endpoints.userinfo,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a URL of the app, depending on the platform where it is running
|
||||||
|
*/
|
||||||
|
function getRedirectUrl(routePath: string): string {
|
||||||
|
const appSchema = Capacitor.isNativePlatform() ? config.appId : 'https';
|
||||||
|
return `${appSchema}://${environment.app_host}/${routePath}`;
|
||||||
|
}
|
||||||
|
|||||||
@@ -14,9 +14,9 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import {ActivatedRouteSnapshot, Data, Route} from '@angular/router';
|
import {ActivatedRouteSnapshot, Data, Route} from '@angular/router';
|
||||||
import {SCAuthorizationProviderType} from '../profile/user';
|
import {SCAuthorizationProviderType} from '@openstapps/core';
|
||||||
|
|
||||||
export interface AuthRoute extends Route {
|
export interface ProtectedRoute extends Route {
|
||||||
data: {
|
data: {
|
||||||
authProvider: SCAuthorizationProviderType;
|
authProvider: SCAuthorizationProviderType;
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
@@ -24,8 +24,8 @@ export interface AuthRoute extends Route {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ActivatedAuthRouteSnapshot extends ActivatedRouteSnapshot {
|
export class ActivatedProtectedRouteSnapshot extends ActivatedRouteSnapshot {
|
||||||
data: Data & {authProvider: AuthRoute['data']['authProvider']};
|
data: Data & {authProvider: ProtectedRoute['data']['authProvider']};
|
||||||
}
|
}
|
||||||
|
|
||||||
export type AuthRoutes = AuthRoute[];
|
export type ProtectedRoutes = ProtectedRoute[];
|
||||||
@@ -117,6 +117,18 @@ export class ConfigProvider {
|
|||||||
throw new ConfigValueNotAvailable(attribute);
|
throw new ConfigValueNotAvailable(attribute);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a value of the configuration (not only app configuration)
|
||||||
|
*
|
||||||
|
* @param attribute requested attribute from the configuration
|
||||||
|
*/
|
||||||
|
public getAnyValue(attribute: keyof SCIndexResponse) {
|
||||||
|
if (typeof this.config[attribute] !== 'undefined') {
|
||||||
|
return this.config[attribute];
|
||||||
|
}
|
||||||
|
throw new ConfigValueNotAvailable(attribute);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialises the ConfigProvider
|
* Initialises the ConfigProvider
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import {IonicModule} from '@ionic/angular';
|
|||||||
import {RouterModule, Routes} from '@angular/router';
|
import {RouterModule, Routes} from '@angular/router';
|
||||||
import {TranslateModule} from '@ngx-translate/core';
|
import {TranslateModule} from '@ngx-translate/core';
|
||||||
import {LibraryAccountPageComponent} from './account/account.page';
|
import {LibraryAccountPageComponent} from './account/account.page';
|
||||||
import {AuthRoutes} from '../auth/auth-routes';
|
|
||||||
import {ProfilePageComponent} from './account/profile/profile-page.component';
|
import {ProfilePageComponent} from './account/profile/profile-page.component';
|
||||||
import {CheckedOutPageComponent} from './account/checked-out/checked-out-page.component';
|
import {CheckedOutPageComponent} from './account/checked-out/checked-out-page.component';
|
||||||
import {HoldsAndReservationsPageComponent} from './account/holds-and-reservations/holds-and-reservations-page.component';
|
import {HoldsAndReservationsPageComponent} from './account/holds-and-reservations/holds-and-reservations-page.component';
|
||||||
@@ -13,8 +12,9 @@ import {FinesPageComponent} from './account/fines/fines-page.component';
|
|||||||
import {PAIAItemComponent} from './account/elements/paia-item/paiaitem.component';
|
import {PAIAItemComponent} from './account/elements/paia-item/paiaitem.component';
|
||||||
import {FirstLastNamePipe} from './account/first-last-name.pipe';
|
import {FirstLastNamePipe} from './account/first-last-name.pipe';
|
||||||
import {AuthGuardService} from '../auth/auth-guard.service';
|
import {AuthGuardService} from '../auth/auth-guard.service';
|
||||||
|
import {ProtectedRoutes} from '../auth/protected.routes';
|
||||||
|
|
||||||
const routes: AuthRoutes | Routes = [
|
const routes: ProtectedRoutes | Routes = [
|
||||||
{
|
{
|
||||||
path: 'library-account',
|
path: 'library-account',
|
||||||
component: LibraryAccountPageComponent,
|
component: LibraryAccountPageComponent,
|
||||||
|
|||||||
@@ -22,20 +22,6 @@ export class NavigationService {
|
|||||||
this.logger.error(`error from loading menu entries: ${error}`);
|
this.logger.error(`error from loading menu entries: ${error}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: move this menu item to the config (backend)
|
|
||||||
menu[1].items.unshift({
|
|
||||||
icon: 'library',
|
|
||||||
route: '/library-account',
|
|
||||||
title: 'library account',
|
|
||||||
translations: {
|
|
||||||
de: {
|
|
||||||
title: 'Bibliothekskonto',
|
|
||||||
},
|
|
||||||
en: {
|
|
||||||
title: 'Library account',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
return menu;
|
return menu;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,12 +20,23 @@ import {RouterTestingModule} from '@angular/router/testing';
|
|||||||
import {AuthModule} from '../../auth/auth.module';
|
import {AuthModule} from '../../auth/auth.module';
|
||||||
import {ProfilePageComponent} from './profile-page.component';
|
import {ProfilePageComponent} from './profile-page.component';
|
||||||
import {TranslateModule} from '@ngx-translate/core';
|
import {TranslateModule} from '@ngx-translate/core';
|
||||||
|
import {ConfigProvider} from '../../config/config.provider';
|
||||||
|
import {sampleAuthConfiguration} from '../../../_helpers/data/sample-configuration';
|
||||||
|
|
||||||
describe('ProfilePage', () => {
|
describe('ProfilePage', () => {
|
||||||
let component: ProfilePageComponent;
|
let component: ProfilePageComponent;
|
||||||
let fixture: ComponentFixture<ProfilePageComponent>;
|
let fixture: ComponentFixture<ProfilePageComponent>;
|
||||||
|
let configProvider: ConfigProvider;
|
||||||
|
|
||||||
beforeEach(async(() => {
|
beforeEach(async(() => {
|
||||||
|
configProvider = jasmine.createSpyObj('ConfigProvider', [
|
||||||
|
'init',
|
||||||
|
'getAnyValue',
|
||||||
|
]);
|
||||||
|
configProvider.getAnyValue = jasmine.createSpy().and.callFake(function () {
|
||||||
|
return sampleAuthConfiguration;
|
||||||
|
});
|
||||||
|
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
declarations: [ProfilePageComponent],
|
declarations: [ProfilePageComponent],
|
||||||
imports: [
|
imports: [
|
||||||
@@ -34,6 +45,7 @@ describe('ProfilePage', () => {
|
|||||||
AuthModule,
|
AuthModule,
|
||||||
TranslateModule.forRoot(),
|
TranslateModule.forRoot(),
|
||||||
],
|
],
|
||||||
|
providers: [{provide: ConfigProvider, useValue: configProvider}],
|
||||||
schemas: [CUSTOM_ELEMENTS_SCHEMA],
|
schemas: [CUSTOM_ELEMENTS_SCHEMA],
|
||||||
}).compileComponents();
|
}).compileComponents();
|
||||||
}));
|
}));
|
||||||
|
|||||||
@@ -18,9 +18,12 @@ import {IonicUserInfoHandler} from 'ionic-appauth';
|
|||||||
import {DefaultAuthService} from '../../auth/default-auth.service';
|
import {DefaultAuthService} from '../../auth/default-auth.service';
|
||||||
import {Requestor, TokenResponse} from '@openid/appauth';
|
import {Requestor, TokenResponse} from '@openid/appauth';
|
||||||
import {PAIAAuthService} from '../../auth/paia/paia-auth.service';
|
import {PAIAAuthService} from '../../auth/paia/paia-auth.service';
|
||||||
import {SCAuthorizationProviderType, SCUserConfiguration} from '../user';
|
|
||||||
import {Subscription} from 'rxjs';
|
import {Subscription} from 'rxjs';
|
||||||
import {AuthHelperService} from '../../auth/auth-helper.service';
|
import {AuthHelperService} from '../../auth/auth-helper.service';
|
||||||
|
import {
|
||||||
|
SCAuthorizationProviderType,
|
||||||
|
SCUserConfiguration,
|
||||||
|
} from '@openstapps/core';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-home',
|
selector: 'app-home',
|
||||||
|
|||||||
@@ -1,82 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* TODO: Take it from the StApps Core
|
|
||||||
*/
|
|
||||||
import {SCAcademicPriceGroup} from '@openstapps/core';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A user configuration
|
|
||||||
*/
|
|
||||||
export interface SCUserConfiguration {
|
|
||||||
/**
|
|
||||||
* User's e-mail
|
|
||||||
*/
|
|
||||||
email?: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* User's family name
|
|
||||||
*/
|
|
||||||
familyName?: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* User's given name
|
|
||||||
*/
|
|
||||||
givenName?: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* ID given to the user
|
|
||||||
*/
|
|
||||||
id: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The complete name of the user combining all the parts of the name into one
|
|
||||||
*/
|
|
||||||
name: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Role assigned to the user
|
|
||||||
*/
|
|
||||||
role: keyof SCAcademicPriceGroup;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Student ID given to the user
|
|
||||||
*/
|
|
||||||
studentId?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* TODO: Take it from the backend's config
|
|
||||||
*/
|
|
||||||
type mapping = {[key in keyof SCUserConfiguration]: string};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* TODO: Take it from the backend's config
|
|
||||||
*/
|
|
||||||
export const userMapping: mapping = {
|
|
||||||
id: 'id',
|
|
||||||
name: 'sn',
|
|
||||||
role: 'attributes.eduPersonPrimaryAffiliation',
|
|
||||||
email: 'attributes.mailPrimaryAddress',
|
|
||||||
studentId: 'attributes.employeeNumber',
|
|
||||||
givenName: 'attributes.givenName',
|
|
||||||
familyName: 'attributes.sn',
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* TODO: Take it from the StApps Core
|
|
||||||
*/
|
|
||||||
export type SCAuthorizationProviderType = 'default' | 'paia';
|
|
||||||
@@ -16,65 +16,14 @@
|
|||||||
// The build system defaults to the dev environment which uses `environment.ts`, but if you do
|
// The build system defaults to the dev environment which uses `environment.ts`, but if you do
|
||||||
// `ng build --env=prod` then `environment.prod.ts` will be used instead.
|
// `ng build --env=prod` then `environment.prod.ts` will be used instead.
|
||||||
// The list of which env maps to which file can be found in `.angular-cli.json`.
|
// The list of which env maps to which file can be found in `.angular-cli.json`.
|
||||||
import {AuthorizationServiceConfigurationJson} from '@openid/appauth';
|
|
||||||
import {IAuthConfig} from 'ionic-appauth';
|
|
||||||
// import config from 'capacitor.config';
|
|
||||||
|
|
||||||
const appDomain = 'mobile.app.uni-frankfurt.de';
|
|
||||||
|
|
||||||
export const environment = {
|
export const environment = {
|
||||||
backend_url: 'https://mobile.server.uni-frankfurt.de',
|
backend_url: 'https://mobile.server.uni-frankfurt.de',
|
||||||
daia_url: 'https://daia.hebis.de/DAIA2/UB_Frankfurt',
|
daia_url: 'https://daia.hebis.de/DAIA2/UB_Frankfurt',
|
||||||
appDomain: 'mobile.app.uni-frankfurt.de',
|
app_host: 'mobile.app.uni-frankfurt.de',
|
||||||
backend_version: '2.0.0',
|
backend_version: '2.0.0',
|
||||||
use_fake_backend: true,
|
use_fake_backend: true,
|
||||||
production: false,
|
production: false,
|
||||||
oauth2: {
|
|
||||||
client: {
|
|
||||||
his: {
|
|
||||||
client_id: '1cac3f99-33fa-4234-8438-979f07e0cdab',
|
|
||||||
client_secret: 'CLIENT_SECRET',
|
|
||||||
server_host: 'https://cas.rz.uni-frankfurt.de/cas/oauth2.0',
|
|
||||||
redirect_url: `https://${appDomain}/auth/callback`,
|
|
||||||
scopes: '',
|
|
||||||
pkce: true,
|
|
||||||
} as IAuthConfig,
|
|
||||||
paia: {
|
|
||||||
client_id: '',
|
|
||||||
client_secret: '',
|
|
||||||
server_host:
|
|
||||||
'https://hds.hebis.de/Shibboleth.sso/UBFFM?target=https://hds.hebis.de/ubffm/paia_login_stub.php',
|
|
||||||
// TODO: Use Custom URL Scheme (ideally bundle ID from capacitor.config)
|
|
||||||
redirect_url: `https://${appDomain}/auth/paia/callback`,
|
|
||||||
scopes: '',
|
|
||||||
pkce: true,
|
|
||||||
} as IAuthConfig,
|
|
||||||
},
|
|
||||||
service: {
|
|
||||||
his: {
|
|
||||||
authorization_endpoint:
|
|
||||||
'https://cas.rz.uni-frankfurt.de/cas/oauth2.0/authorize',
|
|
||||||
token_endpoint:
|
|
||||||
'https://cas.rz.uni-frankfurt.de/cas/oauth2.0/accessToken',
|
|
||||||
userinfo_endpoint:
|
|
||||||
'https://cas.rz.uni-frankfurt.de/cas/oauth2.0/profile',
|
|
||||||
} as AuthorizationServiceConfigurationJson,
|
|
||||||
paia: {
|
|
||||||
authorization_endpoint:
|
|
||||||
'https://hds.hebis.de/Shibboleth.sso/UBFFM?target=https://hds.hebis.de/ubffm/paia_login_stub.php',
|
|
||||||
token_endpoint: 'https://hds.hebis.de:8443/auth/login',
|
|
||||||
userinfo_endpoint: 'https://hds.hebis.de:8443/core',
|
|
||||||
} as AuthorizationServiceConfigurationJson,
|
|
||||||
},
|
|
||||||
endpointMappings: {
|
|
||||||
userinfo: {
|
|
||||||
id: 'employeeNumber',
|
|
||||||
given_name: 'givenName',
|
|
||||||
family_name: 'sn',
|
|
||||||
email: 'mailPrimaryAddress',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -16,65 +16,14 @@
|
|||||||
// The build system defaults to the dev environment which uses `environment.ts`, but if you do
|
// The build system defaults to the dev environment which uses `environment.ts`, but if you do
|
||||||
// `ng build --env=prod` then `environment.prod.ts` will be used instead.
|
// `ng build --env=prod` then `environment.prod.ts` will be used instead.
|
||||||
// The list of which env maps to which file can be found in `.angular-cli.json`.
|
// The list of which env maps to which file can be found in `.angular-cli.json`.
|
||||||
import {AuthorizationServiceConfigurationJson} from '@openid/appauth';
|
|
||||||
import {IAuthConfig} from 'ionic-appauth';
|
|
||||||
// import config from 'capacitor.config';
|
|
||||||
|
|
||||||
const appDomain = 'mobile.app.uni-frankfurt.de';
|
|
||||||
|
|
||||||
export const environment = {
|
export const environment = {
|
||||||
backend_url: 'https://mobile.server.uni-frankfurt.de',
|
backend_url: 'https://mobile.server.uni-frankfurt.de',
|
||||||
daia_url: 'https://daia.hebis.de/DAIA2/UB_Frankfurt',
|
daia_url: 'https://daia.hebis.de/DAIA2/UB_Frankfurt',
|
||||||
appDomain: 'mobile.app.uni-frankfurt.de',
|
app_host: 'mobile.app.uni-frankfurt.de',
|
||||||
backend_version: '2.0.0',
|
backend_version: '2.0.0',
|
||||||
use_fake_backend: false,
|
use_fake_backend: false,
|
||||||
production: false,
|
production: true,
|
||||||
oauth2: {
|
|
||||||
client: {
|
|
||||||
his: {
|
|
||||||
client_id: '1cac3f99-33fa-4234-8438-979f07e0cdab',
|
|
||||||
client_secret: 'CLIENT_SECRET',
|
|
||||||
server_host: 'https://cas.rz.uni-frankfurt.de/cas/oauth2.0',
|
|
||||||
redirect_url: `https://${appDomain}/auth/callback`,
|
|
||||||
scopes: '',
|
|
||||||
pkce: true,
|
|
||||||
} as IAuthConfig,
|
|
||||||
paia: {
|
|
||||||
client_id: '',
|
|
||||||
client_secret: '',
|
|
||||||
server_host:
|
|
||||||
'https://hds.hebis.de/Shibboleth.sso/UBFFM?target=https://hds.hebis.de/ubffm/paia_login_stub.php',
|
|
||||||
// TODO: Use Custom URL Scheme (ideally bundle ID from capacitor.config)
|
|
||||||
redirect_url: `https://${appDomain}/auth/paia/callback`,
|
|
||||||
scopes: '',
|
|
||||||
pkce: true,
|
|
||||||
} as IAuthConfig,
|
|
||||||
},
|
|
||||||
service: {
|
|
||||||
his: {
|
|
||||||
authorization_endpoint:
|
|
||||||
'https://cas.rz.uni-frankfurt.de/cas/oauth2.0/authorize',
|
|
||||||
token_endpoint:
|
|
||||||
'https://cas.rz.uni-frankfurt.de/cas/oauth2.0/accessToken',
|
|
||||||
userinfo_endpoint:
|
|
||||||
'https://cas.rz.uni-frankfurt.de/cas/oauth2.0/profile',
|
|
||||||
} as AuthorizationServiceConfigurationJson,
|
|
||||||
paia: {
|
|
||||||
authorization_endpoint:
|
|
||||||
'https://hds.hebis.de/Shibboleth.sso/UBFFM?target=https://hds.hebis.de/ubffm/paia_login_stub.php',
|
|
||||||
token_endpoint: 'https://hds.hebis.de:8443/auth/login',
|
|
||||||
userinfo_endpoint: 'https://hds.hebis.de:8443/core',
|
|
||||||
} as AuthorizationServiceConfigurationJson,
|
|
||||||
},
|
|
||||||
endpointMappings: {
|
|
||||||
userinfo: {
|
|
||||||
id: 'employeeNumber',
|
|
||||||
given_name: 'givenName',
|
|
||||||
family_name: 'sn',
|
|
||||||
email: 'mailPrimaryAddress',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -16,65 +16,14 @@
|
|||||||
// The build system defaults to the dev environment which uses `environment.ts`, but if you do
|
// The build system defaults to the dev environment which uses `environment.ts`, but if you do
|
||||||
// `ng build --env=prod` then `environment.prod.ts` will be used instead.
|
// `ng build --env=prod` then `environment.prod.ts` will be used instead.
|
||||||
// The list of which env maps to which file can be found in `.angular-cli.json`.
|
// The list of which env maps to which file can be found in `.angular-cli.json`.
|
||||||
import {AuthorizationServiceConfigurationJson} from '@openid/appauth';
|
|
||||||
import {IAuthConfig} from 'ionic-appauth';
|
|
||||||
// import config from 'capacitor.config';
|
|
||||||
|
|
||||||
const appDomain = 'mobile.app.uni-frankfurt.de';
|
|
||||||
|
|
||||||
export const environment = {
|
export const environment = {
|
||||||
backend_url: 'https://mobile.server.uni-frankfurt.de',
|
backend_url: 'https://mobile.server.uni-frankfurt.de',
|
||||||
daia_url: 'https://daia.hebis.de/DAIA2/UB_Frankfurt',
|
daia_url: 'https://daia.hebis.de/DAIA2/UB_Frankfurt',
|
||||||
appDomain: 'mobile.app.uni-frankfurt.de',
|
app_host: 'mobile.app.uni-frankfurt.de',
|
||||||
backend_version: '2.0.0',
|
backend_version: '2.0.0',
|
||||||
use_fake_backend: false,
|
use_fake_backend: false,
|
||||||
production: false,
|
production: false,
|
||||||
oauth2: {
|
|
||||||
client: {
|
|
||||||
his: {
|
|
||||||
client_id: '1cac3f99-33fa-4234-8438-979f07e0cdab',
|
|
||||||
client_secret: '',
|
|
||||||
server_host: 'https://cas.rz.uni-frankfurt.de/cas/oauth2.0',
|
|
||||||
redirect_url: `https://${appDomain}/auth/callback`,
|
|
||||||
scopes: '',
|
|
||||||
pkce: true,
|
|
||||||
} as IAuthConfig,
|
|
||||||
paia: {
|
|
||||||
client_id: '',
|
|
||||||
client_secret: '',
|
|
||||||
server_host:
|
|
||||||
'https://hds.hebis.de/Shibboleth.sso/UBFFM?target=https://hds.hebis.de/ubffm/paia_login_stub.php',
|
|
||||||
// TODO: Use Custom URL Scheme (ideally bundle ID from capacitor.config)
|
|
||||||
redirect_url: `https://${appDomain}/auth/paia/callback`,
|
|
||||||
scopes: '',
|
|
||||||
pkce: true,
|
|
||||||
} as IAuthConfig,
|
|
||||||
},
|
|
||||||
service: {
|
|
||||||
his: {
|
|
||||||
authorization_endpoint:
|
|
||||||
'https://cas.rz.uni-frankfurt.de/cas/oauth2.0/authorize',
|
|
||||||
token_endpoint:
|
|
||||||
'https://cas.rz.uni-frankfurt.de/cas/oauth2.0/accessToken',
|
|
||||||
userinfo_endpoint:
|
|
||||||
'https://cas.rz.uni-frankfurt.de/cas/oauth2.0/profile',
|
|
||||||
} as AuthorizationServiceConfigurationJson,
|
|
||||||
paia: {
|
|
||||||
authorization_endpoint:
|
|
||||||
'https://hds.hebis.de/Shibboleth.sso/UBFFM?target=https://hds.hebis.de/ubffm/paia_login_stub.php',
|
|
||||||
token_endpoint: 'https://hds.hebis.de:8443/auth/login',
|
|
||||||
userinfo_endpoint: 'https://hds.hebis.de:8443/core',
|
|
||||||
} as AuthorizationServiceConfigurationJson,
|
|
||||||
},
|
|
||||||
endpointMappings: {
|
|
||||||
userinfo: {
|
|
||||||
id: 'employeeNumber',
|
|
||||||
given_name: 'givenName',
|
|
||||||
family_name: 'sn',
|
|
||||||
email: 'mailPrimaryAddress',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
Reference in New Issue
Block a user