Commit c5fa6a0d authored by Daniel Gerhardt's avatar Daniel Gerhardt Committed by Tom Käsler

Load config from backend API

The configuration is loaded at application initialization provided via
the new ApiConfigService. It includes properties for authentication
providers, feature settings and UI settings.

Refs arsnova-backend!161.
parent 557e0c51
Pipeline #31865 canceled with stages
in 8 minutes and 5 seconds
......@@ -5,6 +5,7 @@ import { NotificationService } from './services/util/notification.service';
import { MatIconRegistry } from '@angular/material';
import { DomSanitizer } from '@angular/platform-browser';
import { Rescale } from './models/rescale';
import { ApiConfigService } from './services/http/api-config.service';
@Component({
selector: 'app-root',
......@@ -24,7 +25,8 @@ export class AppComponent implements OnInit {
private update: SwUpdate,
public notification: NotificationService,
private matIconRegistry: MatIconRegistry,
private domSanitizer: DomSanitizer) {
private domSanitizer: DomSanitizer,
private apiConfigService: ApiConfigService) {
translationService.setDefaultLang(this.translationService.getBrowserLang());
sessionStorage.setItem('currentLang', this.translationService.getBrowserLang());
for (const icon of this.icons) {
......@@ -54,6 +56,7 @@ export class AppComponent implements OnInit {
}
});
});
this.apiConfigService.load();
}
public getRescale(): Rescale {
......
......@@ -43,6 +43,7 @@ import { HomeParticipantPageComponent } from './components/home/home-participant
import { CommentSettingsService } from './services/http/comment-settings.service';
import { ModeratorModule } from './components/moderator/moderator.module';
import { ImprintComponent } from './components/home/_dialogs/imprint/imprint.component';
import { ApiConfigService } from './services/http/api-config.service';
import { DataProtectionComponent } from './components/home/_dialogs/data-protection/data-protection.component';
import { HelpPageComponent } from './components/shared/_dialogs/help-page/help-page.component';
import { CookiesComponent } from './components/home/_dialogs/cookies/cookies.component';
......@@ -151,6 +152,7 @@ export function initializeApp(appConfig: AppConfig) {
ModeratorService,
CommentSettingsService,
WsConnectorService,
ApiConfigService,
{
provide: MatDialogRef,
useValue: {
......
export enum AuthenticationProviderType {
ANONYMOUS = 'ANONYMOUS',
USERNAME_PASSWORD = 'USERNAME_PASSWORD',
SSO = 'SSO'
}
export enum AuthenticationProviderRole {
MODERATOR = 'MODERATOR',
PARTICIPANT = 'PARTICIPANT'
}
export interface AuthenticationProvider {
id: string;
title: string;
type: AuthenticationProviderType;
order: number;
allowedRoles: AuthenticationProviderRole[];
}
export interface Feature {
enabled: boolean;
}
export interface UiConfig {
[configName: string]: any;
}
export class ApiConfig {
constructor(
public authenticationProviders: AuthenticationProvider[],
public features: { [featureName: string]: Feature },
public ui: UiConfig) {
}
}
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';
import { BaseHttpService } from './base-http.service';
import { ApiConfig, AuthenticationProvider, Feature, UiConfig } from '../../models/api-config';
@Injectable()
export class ApiConfigService extends BaseHttpService {
private readonly apiUris = {
/* TODO: API base URI should be injected. */
base: '/api',
configPart: '/configuration',
get config() {
return this.base + this.configPart;
}
};
private config$: Observable<ApiConfig>;
private config: ApiConfig;
constructor(private http: HttpClient) {
super();
this.config$ = this.http.get<ApiConfig>(this.apiUris.config);
this.config = new ApiConfig([], {}, {});
this.freezeRecursively(this.config);
}
load() {
console.log('Loading API configuration...');
this.config$.subscribe((config) => {
config.authenticationProviders.sort((p1, p2) => {
return p1.order < p2.order ? -1 : p1.order > p2.order ? 1 : 0;
});
this.freezeRecursively(config);
this.config = config;
console.log('API configuration loaded.');
});
}
get loaded() {
return !!this.config;
}
getAuthProviders(): AuthenticationProvider[] {
return this.config.authenticationProviders;
}
getFeatureConfig(feature: string): Feature {
return this.config.features[feature];
}
getUiConfig(): UiConfig {
return this.config.ui;
}
private freezeRecursively(obj: object) {
/* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze */
if (Object.freeze) {
const propNames = Object.getOwnPropertyNames(obj);
/* Freeze properties before freezing self */
for (const name of propNames) {
const value = obj[name];
obj[name] = value && typeof value === 'object'
? this.freezeRecursively(value) : value;
}
}
return Object.freeze(obj);
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment