Merge pull request #1934 from hedgedoc/refactor/frontend-config/auth-providers

This commit is contained in:
David Mehren 2022-01-04 10:08:58 +01:00 committed by GitHub
commit 85e7643b95
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
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';
export class AuthProviders {
/**
* Is Facebook available as a auth provider?
*/
@IsBoolean()
facebook: boolean;
/**
* Is GitHub available as a auth provider?
*/
@IsBoolean()
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 enum AuthProviderType {
LOCAL = 'local',
LDAP = 'ldap',
SAML = 'saml',
OAUTH2 = 'oauth2',
GITLAB = 'gitlab',
FACEBOOK = 'facebook',
GITHUB = 'github',
TWITTER = 'twitter',
DROPBOX = 'dropbox',
GOOGLE = 'google',
}
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 {
/**
* The name to be displayed next to the HedgeDoc logo
@ -96,52 +95,6 @@ export class BrandingDto {
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 {
/**
* A link to the privacy notice
@ -200,10 +153,11 @@ export class FrontendConfigDto {
allowRegister: boolean;
/**
* Which auth providers are available?
* Which auth providers are enabled and how are they configured?
*/
@ValidateNested()
authProviders: AuthProviders;
@IsArray()
@ValidateNested({ each: true })
authProviders: AuthProviderDto[];
/**
* Individual branding information
@ -211,12 +165,6 @@ export class FrontendConfigDto {
@ValidateNested()
branding: BrandingDto;
/**
* The custom names of auth providers, which can be specified multiple times
*/
@ValidateNested()
customAuthNames: CustomAuthNamesDto;
/**
* 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 { LoggerModule } from '../logger/logger.module';
import { getServerVersionFromPackageJson } from '../utils/serverVersion';
import { AuthProviderType } from './frontend-config.dto';
import { FrontendConfigService } from './frontend-config.service';
/* eslint-disable
@ -250,85 +251,113 @@ describe('FrontendConfigService', () => {
expect(config.allowRegister).toEqual(
enableRegister,
);
expect(config.authProviders.dropbox).toEqual(
!!authConfig.dropbox.clientID,
);
expect(config.authProviders.facebook).toEqual(
!!authConfig.facebook.clientID,
);
expect(config.authProviders.github).toEqual(
!!authConfig.github.clientID,
);
expect(config.authProviders.google).toEqual(
!!authConfig.google.clientID,
);
expect(config.authProviders.local).toEqual(
enableLogin,
);
expect(config.authProviders.twitter).toEqual(
!!authConfig.twitter.consumerKey,
);
expect(config.authProviders.gitlab).toEqual(
authConfig.gitlab.length !== 0,
);
expect(config.authProviders.ldap).toEqual(
authConfig.ldap.length !== 0,
);
expect(config.authProviders.saml).toEqual(
authConfig.saml.length !== 0,
);
expect(config.authProviders.oauth2).toEqual(
authConfig.oauth2.length !== 0,
);
if (authConfig.dropbox.clientID) {
expect(config.authProviders).toContainEqual({
type: AuthProviderType.DROPBOX,
});
}
if (authConfig.facebook.clientID) {
expect(config.authProviders).toContainEqual({
type: AuthProviderType.FACEBOOK,
});
}
if (authConfig.google.clientID) {
expect(config.authProviders).toContainEqual({
type: AuthProviderType.GOOGLE,
});
}
if (authConfig.github.clientID) {
expect(config.authProviders).toContainEqual({
type: AuthProviderType.GITHUB,
});
}
if (authConfig.local.enableLogin) {
expect(config.authProviders).toContainEqual({
type: AuthProviderType.LOCAL,
});
}
if (authConfig.twitter.consumerKey) {
expect(config.authProviders).toContainEqual({
type: AuthProviderType.TWITTER,
});
}
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.branding.name).toEqual(customName);
expect(config.branding.logo).toEqual(
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(
config.iframeCommunication.editorOrigin,
).toEqual(new URL(appConfig.domain));

View file

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