feat(server): storage label claim (#3278)

* feat: storage label claim

* chore: open api
This commit is contained in:
Jason Rasmussen 2023-07-15 15:50:29 -04:00 committed by GitHub
parent ed594c1987
commit f55d63fae8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 64 additions and 6 deletions

View File

@ -2596,6 +2596,12 @@ export interface SystemConfigOAuthDto {
* @memberof SystemConfigOAuthDto
*/
'scope': string;
/**
*
* @type {string}
* @memberof SystemConfigOAuthDto
*/
'storageLabelClaim': string;
/**
*
* @type {string}

View File

@ -13,6 +13,7 @@ Name | Type | Description | Notes
**clientId** | **String** | |
**clientSecret** | **String** | |
**scope** | **String** | |
**storageLabelClaim** | **String** | |
**buttonText** | **String** | |
**autoRegister** | **bool** | |
**autoLaunch** | **bool** | |

View File

@ -18,6 +18,7 @@ class SystemConfigOAuthDto {
required this.clientId,
required this.clientSecret,
required this.scope,
required this.storageLabelClaim,
required this.buttonText,
required this.autoRegister,
required this.autoLaunch,
@ -35,6 +36,8 @@ class SystemConfigOAuthDto {
String scope;
String storageLabelClaim;
String buttonText;
bool autoRegister;
@ -52,6 +55,7 @@ class SystemConfigOAuthDto {
other.clientId == clientId &&
other.clientSecret == clientSecret &&
other.scope == scope &&
other.storageLabelClaim == storageLabelClaim &&
other.buttonText == buttonText &&
other.autoRegister == autoRegister &&
other.autoLaunch == autoLaunch &&
@ -66,6 +70,7 @@ class SystemConfigOAuthDto {
(clientId.hashCode) +
(clientSecret.hashCode) +
(scope.hashCode) +
(storageLabelClaim.hashCode) +
(buttonText.hashCode) +
(autoRegister.hashCode) +
(autoLaunch.hashCode) +
@ -73,7 +78,7 @@ class SystemConfigOAuthDto {
(mobileRedirectUri.hashCode);
@override
String toString() => 'SystemConfigOAuthDto[enabled=$enabled, issuerUrl=$issuerUrl, clientId=$clientId, clientSecret=$clientSecret, scope=$scope, buttonText=$buttonText, autoRegister=$autoRegister, autoLaunch=$autoLaunch, mobileOverrideEnabled=$mobileOverrideEnabled, mobileRedirectUri=$mobileRedirectUri]';
String toString() => 'SystemConfigOAuthDto[enabled=$enabled, issuerUrl=$issuerUrl, clientId=$clientId, clientSecret=$clientSecret, scope=$scope, storageLabelClaim=$storageLabelClaim, buttonText=$buttonText, autoRegister=$autoRegister, autoLaunch=$autoLaunch, mobileOverrideEnabled=$mobileOverrideEnabled, mobileRedirectUri=$mobileRedirectUri]';
Map<String, dynamic> toJson() {
final json = <String, dynamic>{};
@ -82,6 +87,7 @@ class SystemConfigOAuthDto {
json[r'clientId'] = this.clientId;
json[r'clientSecret'] = this.clientSecret;
json[r'scope'] = this.scope;
json[r'storageLabelClaim'] = this.storageLabelClaim;
json[r'buttonText'] = this.buttonText;
json[r'autoRegister'] = this.autoRegister;
json[r'autoLaunch'] = this.autoLaunch;
@ -103,6 +109,7 @@ class SystemConfigOAuthDto {
clientId: mapValueOfType<String>(json, r'clientId')!,
clientSecret: mapValueOfType<String>(json, r'clientSecret')!,
scope: mapValueOfType<String>(json, r'scope')!,
storageLabelClaim: mapValueOfType<String>(json, r'storageLabelClaim')!,
buttonText: mapValueOfType<String>(json, r'buttonText')!,
autoRegister: mapValueOfType<bool>(json, r'autoRegister')!,
autoLaunch: mapValueOfType<bool>(json, r'autoLaunch')!,
@ -160,6 +167,7 @@ class SystemConfigOAuthDto {
'clientId',
'clientSecret',
'scope',
'storageLabelClaim',
'buttonText',
'autoRegister',
'autoLaunch',

View File

@ -41,6 +41,11 @@ void main() {
// TODO
});
// String storageLabelClaim
test('to test the property `storageLabelClaim`', () async {
// TODO
});
// String buttonText
test('to test the property `buttonText`', () async {
// TODO

View File

@ -6503,6 +6503,9 @@
"scope": {
"type": "string"
},
"storageLabelClaim": {
"type": "string"
},
"buttonText": {
"type": "string"
},
@ -6525,6 +6528,7 @@
"clientId",
"clientSecret",
"scope",
"storageLabelClaim",
"buttonText",
"autoRegister",
"autoLaunch",

View File

@ -240,11 +240,19 @@ export class AuthService {
}
this.logger.log(`Registering new user: ${profile.email}/${profile.sub}`);
this.logger.verbose(`OAuth Profile: ${JSON.stringify(profile)}`);
let storageLabel: string | null = profile[config.oauth.storageLabelClaim as keyof OAuthProfile] as string;
if (typeof storageLabel !== 'string') {
storageLabel = null;
}
user = await this.userCore.createUser({
firstName: profile.given_name || '',
lastName: profile.family_name || '',
email: profile.email,
oauthId: profile.sub,
storageLabel,
});
}

View File

@ -25,6 +25,9 @@ export class SystemConfigOAuthDto {
@IsString()
scope!: string;
@IsString()
storageLabelClaim!: string;
@IsString()
buttonText!: string;

View File

@ -48,6 +48,7 @@ export const defaults = Object.freeze<SystemConfig>({
mobileOverrideEnabled: false,
mobileRedirectUri: '',
scope: 'openid email profile',
storageLabelClaim: 'preferred_username',
buttonText: 'Login with OAuth',
autoRegister: true,
autoLaunch: false,

View File

@ -53,6 +53,7 @@ const updatedConfig = Object.freeze<SystemConfig>({
mobileOverrideEnabled: false,
mobileRedirectUri: '',
scope: 'openid email profile',
storageLabelClaim: 'preferred_username',
},
passwordLogin: {
enabled: true,

View File

@ -8,9 +8,9 @@ import {
} from '@nestjs/common';
import { constants, createReadStream, ReadStream } from 'fs';
import fs from 'fs/promises';
import sanitize from 'sanitize-filename';
import { AuthUserDto } from '../auth';
import { ICryptoRepository } from '../crypto';
import { CreateAdminDto, CreateUserDto, CreateUserOAuthDto } from './dto/create-user.dto';
import { IUserRepository, UserListFilter } from './user.repository';
const SALT_ROUNDS = 10;
@ -67,13 +67,13 @@ export class UserCore {
}
}
async createUser(createUserDto: CreateUserDto | CreateAdminDto | CreateUserOAuthDto): Promise<UserEntity> {
const user = await this.userRepository.getByEmail(createUserDto.email);
async createUser(dto: Partial<UserEntity> & { email: string }): Promise<UserEntity> {
const user = await this.userRepository.getByEmail(dto.email);
if (user) {
throw new BadRequestException('User exists');
}
if (!(createUserDto as CreateAdminDto).isAdmin) {
if (!dto.isAdmin) {
const localAdmin = await this.userRepository.getAdmin();
if (!localAdmin) {
throw new BadRequestException('The first registered account must the administrator.');
@ -81,10 +81,13 @@ export class UserCore {
}
try {
const payload: Partial<UserEntity> = { ...createUserDto };
const payload: Partial<UserEntity> = { ...dto };
if (payload.password) {
payload.password = await this.cryptoRepository.hashBcrypt(payload.password, SALT_ROUNDS);
}
if (payload.storageLabel) {
payload.storageLabel = sanitize(payload.storageLabel);
}
return this.userRepository.create(payload);
} catch (e) {
Logger.error(e, 'Create new user');

View File

@ -40,6 +40,7 @@ export enum SystemConfigKey {
OAUTH_CLIENT_ID = 'oauth.clientId',
OAUTH_CLIENT_SECRET = 'oauth.clientSecret',
OAUTH_SCOPE = 'oauth.scope',
OAUTH_STORAGE_LABEL_CLAIM = 'oauth.storageLabelClaim',
OAUTH_AUTO_LAUNCH = 'oauth.autoLaunch',
OAUTH_BUTTON_TEXT = 'oauth.buttonText',
OAUTH_AUTO_REGISTER = 'oauth.autoRegister',
@ -89,6 +90,7 @@ export interface SystemConfig {
clientId: string;
clientSecret: string;
scope: string;
storageLabelClaim: string;
buttonText: string;
autoRegister: boolean;
autoLaunch: boolean;

View File

@ -2596,6 +2596,12 @@ export interface SystemConfigOAuthDto {
* @memberof SystemConfigOAuthDto
*/
'scope': string;
/**
*
* @type {string}
* @memberof SystemConfigOAuthDto
*/
'storageLabelClaim': string;
/**
*
* @type {string}

View File

@ -155,6 +155,16 @@
isEdited={!(oauthConfig.scope == savedConfig.scope)}
/>
<SettingInputField
inputType={SettingInputFieldType.TEXT}
label="STORAGE LABEL CLAIM"
desc="Automatically set the user's storage label to the value of this claim."
bind:value={oauthConfig.storageLabelClaim}
required={true}
disabled={!oauthConfig.storageLabelClaim}
isEdited={!(oauthConfig.storageLabelClaim == savedConfig.storageLabelClaim)}
/>
<SettingInputField
inputType={SettingInputFieldType.TEXT}
label="BUTTON TEXT"