refactor(frontend-config): return auth providers as array

This change removes the customAuthNames property and redefines the
authProviders property of the frontend-config DTO. Instead of an
map from auth providers to their enabled-state (boolean), there is
now an array that just includes the configured auth providers while
also having the identifier and providerName of custom auth providers.

Signed-off-by: Erik Michelson <github@erik.michelson.eu>
This commit is contained in:
Erik Michelson 2021-12-28 01:16:42 +01:00 committed by David Mehren
parent dcfb00adc1
commit 20b0ded223
No known key found for this signature in database
GPG key ID: 185982BA4C42B7C3
3 changed files with 229 additions and 234 deletions

View file

@ -16,68 +16,67 @@ import { URL } from 'url';
import { ServerVersion } from '../monitoring/server-status.dto'; import { ServerVersion } from '../monitoring/server-status.dto';
export class AuthProviders { export enum AuthProviderType {
/** LOCAL = 'local',
* Is Facebook available as a auth provider? LDAP = 'ldap',
*/ SAML = 'saml',
@IsBoolean() OAUTH2 = 'oauth2',
facebook: boolean; GITLAB = 'gitlab',
FACEBOOK = 'facebook',
/** GITHUB = 'github',
* Is GitHub available as a auth provider? TWITTER = 'twitter',
*/ DROPBOX = 'dropbox',
@IsBoolean() GOOGLE = 'google',
github: boolean;
/**
* Is Twitter available as a auth provider?
*/
@IsBoolean()
twitter: boolean;
/**
* Is at least one GitLab server available as a auth provider?
*/
@IsBoolean()
gitlab: boolean;
/**
* Is DropBox available as a auth provider?
*/
@IsBoolean()
dropbox: boolean;
/**
* Is at least one LDAP server available as a auth provider?
*/
@IsBoolean()
ldap: boolean;
/**
* Is Google available as a auth provider?
*/
@IsBoolean()
google: boolean;
/**
* Is at least one SAML provider available as a auth provider?
*/
@IsBoolean()
saml: boolean;
/**
* Is at least one OAuth2 provider available as a auth provider?
*/
@IsBoolean()
oauth2: boolean;
/**
* Is local auth available?
*/
@IsBoolean()
local: boolean;
} }
export type AuthProviderTypeWithCustomName =
| AuthProviderType.LDAP
| AuthProviderType.OAUTH2
| AuthProviderType.SAML
| AuthProviderType.GITLAB;
export type AuthProviderTypeWithoutCustomName =
| AuthProviderType.LOCAL
| AuthProviderType.FACEBOOK
| AuthProviderType.GITHUB
| AuthProviderType.TWITTER
| AuthProviderType.DROPBOX
| AuthProviderType.GOOGLE;
export class AuthProviderWithoutCustomNameDto {
/**
* The type of the auth provider.
*/
@IsString()
type: AuthProviderTypeWithoutCustomName;
}
export class AuthProviderWithCustomNameDto {
/**
* The type of the auth provider.
*/
@IsString()
type: AuthProviderTypeWithCustomName;
/**
* The identifier with which the auth provider can be called
* @example gitlab-fsorg
*/
@IsString()
identifier: string;
/**
* The name given to the auth provider
* @example GitLab fachschaften.org
*/
@IsString()
providerName: string;
}
export type AuthProviderDto =
| AuthProviderWithCustomNameDto
| AuthProviderWithoutCustomNameDto;
export class BrandingDto { export class BrandingDto {
/** /**
* The name to be displayed next to the HedgeDoc logo * The name to be displayed next to the HedgeDoc logo
@ -96,52 +95,6 @@ export class BrandingDto {
logo?: URL; logo?: URL;
} }
export class CustomAuthEntry {
/**
* The identifier with which the auth provider can be called
* @example gitlab
*/
@IsString()
identifier: string;
/**
* The name given to the auth provider
* @example GitLab
*/
@IsString()
providerName: string;
}
export class CustomAuthNamesDto {
/**
* All configured GitLab server
*/
@IsArray()
@ValidateNested({ each: true })
gitlab: CustomAuthEntry[];
/**
* All configured LDAP server
*/
@IsArray()
@ValidateNested({ each: true })
ldap: CustomAuthEntry[];
/**
* All configured OAuth2 provider
*/
@IsArray()
@ValidateNested({ each: true })
oauth2: CustomAuthEntry[];
/**
* All configured SAML provider
*/
@IsArray()
@ValidateNested({ each: true })
saml: CustomAuthEntry[];
}
export class SpecialUrlsDto { export class SpecialUrlsDto {
/** /**
* A link to the privacy notice * A link to the privacy notice
@ -200,10 +153,11 @@ export class FrontendConfigDto {
allowRegister: boolean; allowRegister: boolean;
/** /**
* Which auth providers are available? * Which auth providers are enabled and how are they configured?
*/ */
@ValidateNested() @IsArray()
authProviders: AuthProviders; @ValidateNested({ each: true })
authProviders: AuthProviderDto[];
/** /**
* Individual branding information * Individual branding information
@ -211,12 +165,6 @@ export class FrontendConfigDto {
@ValidateNested() @ValidateNested()
branding: BrandingDto; branding: BrandingDto;
/**
* The custom names of auth providers, which can be specified multiple times
*/
@ValidateNested()
customAuthNames: CustomAuthNamesDto;
/** /**
* Is an image proxy enabled? * Is an image proxy enabled?
*/ */

View file

@ -14,6 +14,7 @@ import { GitlabScope, GitlabVersion } from '../config/gitlab.enum';
import { Loglevel } from '../config/loglevel.enum'; import { Loglevel } from '../config/loglevel.enum';
import { LoggerModule } from '../logger/logger.module'; import { LoggerModule } from '../logger/logger.module';
import { getServerVersionFromPackageJson } from '../utils/serverVersion'; import { getServerVersionFromPackageJson } from '../utils/serverVersion';
import { AuthProviderType } from './frontend-config.dto';
import { FrontendConfigService } from './frontend-config.service'; import { FrontendConfigService } from './frontend-config.service';
/* eslint-disable /* eslint-disable
@ -250,85 +251,113 @@ describe('FrontendConfigService', () => {
expect(config.allowRegister).toEqual( expect(config.allowRegister).toEqual(
enableRegister, enableRegister,
); );
expect(config.authProviders.dropbox).toEqual( if (authConfig.dropbox.clientID) {
!!authConfig.dropbox.clientID, expect(config.authProviders).toContainEqual({
); type: AuthProviderType.DROPBOX,
expect(config.authProviders.facebook).toEqual( });
!!authConfig.facebook.clientID, }
); if (authConfig.facebook.clientID) {
expect(config.authProviders.github).toEqual( expect(config.authProviders).toContainEqual({
!!authConfig.github.clientID, type: AuthProviderType.FACEBOOK,
); });
expect(config.authProviders.google).toEqual( }
!!authConfig.google.clientID, if (authConfig.google.clientID) {
); expect(config.authProviders).toContainEqual({
expect(config.authProviders.local).toEqual( type: AuthProviderType.GOOGLE,
enableLogin, });
); }
expect(config.authProviders.twitter).toEqual( if (authConfig.github.clientID) {
!!authConfig.twitter.consumerKey, expect(config.authProviders).toContainEqual({
); type: AuthProviderType.GITHUB,
expect(config.authProviders.gitlab).toEqual( });
authConfig.gitlab.length !== 0, }
); if (authConfig.local.enableLogin) {
expect(config.authProviders.ldap).toEqual( expect(config.authProviders).toContainEqual({
authConfig.ldap.length !== 0, type: AuthProviderType.LOCAL,
); });
expect(config.authProviders.saml).toEqual( }
authConfig.saml.length !== 0, if (authConfig.twitter.consumerKey) {
); expect(config.authProviders).toContainEqual({
expect(config.authProviders.oauth2).toEqual( type: AuthProviderType.TWITTER,
authConfig.oauth2.length !== 0, });
); }
expect(
config.authProviders.filter(
(provider) =>
provider.type === AuthProviderType.GITLAB,
).length,
).toEqual(authConfig.gitlab.length);
expect(
config.authProviders.filter(
(provider) =>
provider.type === AuthProviderType.LDAP,
).length,
).toEqual(authConfig.ldap.length);
expect(
config.authProviders.filter(
(provider) =>
provider.type === AuthProviderType.SAML,
).length,
).toEqual(authConfig.saml.length);
expect(
config.authProviders.filter(
(provider) =>
provider.type === AuthProviderType.OAUTH2,
).length,
).toEqual(authConfig.oauth2.length);
if (authConfig.gitlab.length > 0) {
expect(
config.authProviders.find(
(provider) =>
provider.type === AuthProviderType.GITLAB,
),
).toEqual({
type: AuthProviderType.GITLAB,
providerName: authConfig.gitlab[0].providerName,
identifier: authConfig.gitlab[0].identifier,
});
}
if (authConfig.ldap.length > 0) {
expect(
config.authProviders.find(
(provider) =>
provider.type === AuthProviderType.LDAP,
),
).toEqual({
type: AuthProviderType.LDAP,
providerName: authConfig.ldap[0].providerName,
identifier: authConfig.ldap[0].identifier,
});
}
if (authConfig.saml.length > 0) {
expect(
config.authProviders.find(
(provider) =>
provider.type === AuthProviderType.SAML,
),
).toEqual({
type: AuthProviderType.SAML,
providerName: authConfig.saml[0].providerName,
identifier: authConfig.saml[0].identifier,
});
}
if (authConfig.oauth2.length > 0) {
expect(
config.authProviders.find(
(provider) =>
provider.type === AuthProviderType.OAUTH2,
),
).toEqual({
type: AuthProviderType.OAUTH2,
providerName: authConfig.oauth2[0].providerName,
identifier: authConfig.oauth2[0].identifier,
});
}
expect(config.allowAnonymous).toEqual(false); expect(config.allowAnonymous).toEqual(false);
expect(config.branding.name).toEqual(customName); expect(config.branding.name).toEqual(customName);
expect(config.branding.logo).toEqual( expect(config.branding.logo).toEqual(
customLogo ? new URL(customLogo) : undefined, customLogo ? new URL(customLogo) : undefined,
); );
expect(
config.customAuthNames.gitlab.length,
).toEqual(authConfig.gitlab.length);
if (config.customAuthNames.gitlab.length === 1) {
expect(
config.customAuthNames.gitlab[0].identifier,
).toEqual(authConfig.gitlab[0].identifier);
expect(
config.customAuthNames.gitlab[0].providerName,
).toEqual(authConfig.gitlab[0].providerName);
}
expect(config.customAuthNames.ldap.length).toEqual(
authConfig.ldap.length,
);
if (config.customAuthNames.ldap.length === 1) {
expect(
config.customAuthNames.ldap[0].identifier,
).toEqual(authConfig.ldap[0].identifier);
expect(
config.customAuthNames.ldap[0].providerName,
).toEqual(authConfig.ldap[0].providerName);
}
expect(config.customAuthNames.saml.length).toEqual(
authConfig.saml.length,
);
if (config.customAuthNames.saml.length === 1) {
expect(
config.customAuthNames.saml[0].identifier,
).toEqual(authConfig.saml[0].identifier);
expect(
config.customAuthNames.saml[0].providerName,
).toEqual(authConfig.saml[0].providerName);
}
expect(
config.customAuthNames.oauth2.length,
).toEqual(authConfig.oauth2.length);
if (config.customAuthNames.oauth2.length === 1) {
expect(
config.customAuthNames.oauth2[0].identifier,
).toEqual(authConfig.oauth2[0].identifier);
expect(
config.customAuthNames.oauth2[0].providerName,
).toEqual(authConfig.oauth2[0].providerName);
}
expect( expect(
config.iframeCommunication.editorOrigin, config.iframeCommunication.editorOrigin,
).toEqual(new URL(appConfig.domain)); ).toEqual(new URL(appConfig.domain));

View file

@ -17,9 +17,9 @@ import externalServicesConfiguration, {
import { ConsoleLoggerService } from '../logger/console-logger.service'; import { ConsoleLoggerService } from '../logger/console-logger.service';
import { getServerVersionFromPackageJson } from '../utils/serverVersion'; import { getServerVersionFromPackageJson } from '../utils/serverVersion';
import { import {
AuthProviders, AuthProviderDto,
AuthProviderType,
BrandingDto, BrandingDto,
CustomAuthNamesDto,
FrontendConfigDto, FrontendConfigDto,
IframeCommunicationDto, IframeCommunicationDto,
SpecialUrlsDto, SpecialUrlsDto,
@ -48,7 +48,6 @@ export class FrontendConfigService {
allowRegister: this.authConfig.local.enableRegister, allowRegister: this.authConfig.local.enableRegister,
authProviders: this.getAuthProviders(), authProviders: this.getAuthProviders(),
branding: this.getBranding(), branding: this.getBranding(),
customAuthNames: this.getCustomAuthNames(),
iframeCommunication: this.getIframeCommunication(), iframeCommunication: this.getIframeCommunication(),
maxDocumentLength: this.appConfig.maxDocumentLength, maxDocumentLength: this.appConfig.maxDocumentLength,
plantUmlServer: this.externalServicesConfig.plantUmlServer plantUmlServer: this.externalServicesConfig.plantUmlServer
@ -60,48 +59,67 @@ export class FrontendConfigService {
}; };
} }
private getAuthProviders(): AuthProviders { private getAuthProviders(): AuthProviderDto[] {
return { const providers: AuthProviderDto[] = [];
dropbox: !!this.authConfig.dropbox.clientID, if (this.authConfig.local.enableLogin) {
facebook: !!this.authConfig.facebook.clientID, providers.push({
github: !!this.authConfig.github.clientID, type: AuthProviderType.LOCAL,
gitlab: this.authConfig.gitlab.length !== 0, });
google: !!this.authConfig.google.clientID, }
local: this.authConfig.local.enableLogin, if (this.authConfig.dropbox.clientID) {
ldap: this.authConfig.ldap.length !== 0, providers.push({
oauth2: this.authConfig.oauth2.length !== 0, type: AuthProviderType.DROPBOX,
saml: this.authConfig.saml.length !== 0, });
twitter: !!this.authConfig.twitter.consumerKey, }
}; if (this.authConfig.facebook.clientID) {
} providers.push({
type: AuthProviderType.FACEBOOK,
private getCustomAuthNames(): CustomAuthNamesDto { });
return { }
gitlab: this.authConfig.gitlab.map((entry) => { if (this.authConfig.github.clientID) {
return { providers.push({
identifier: entry.identifier, type: AuthProviderType.GITHUB,
providerName: entry.providerName, });
}; }
}), if (this.authConfig.google.clientID) {
ldap: this.authConfig.ldap.map((entry) => { providers.push({
return { type: AuthProviderType.GOOGLE,
identifier: entry.identifier, });
providerName: entry.providerName, }
}; if (this.authConfig.twitter.consumerKey) {
}), providers.push({
oauth2: this.authConfig.oauth2.map((entry) => { type: AuthProviderType.TWITTER,
return { });
identifier: entry.identifier, }
providerName: entry.providerName, this.authConfig.gitlab.forEach((gitLabEntry) => {
}; providers.push({
}), type: AuthProviderType.GITLAB,
saml: this.authConfig.saml.map((entry) => { providerName: gitLabEntry.providerName,
return { identifier: gitLabEntry.identifier,
identifier: entry.identifier, });
providerName: entry.providerName, });
}; this.authConfig.ldap.forEach((ldapEntry) => {
}), providers.push({
}; type: AuthProviderType.LDAP,
providerName: ldapEntry.providerName,
identifier: ldapEntry.identifier,
});
});
this.authConfig.oauth2.forEach((oauth2Entry) => {
providers.push({
type: AuthProviderType.OAUTH2,
providerName: oauth2Entry.providerName,
identifier: oauth2Entry.identifier,
});
});
this.authConfig.saml.forEach((samlEntry) => {
providers.push({
type: AuthProviderType.SAML,
providerName: samlEntry.providerName,
identifier: samlEntry.identifier,
});
});
return providers;
} }
private getBranding(): BrandingDto { private getBranding(): BrandingDto {