From 7e0c26066a5c59af742ae56bddaff9635debe034 Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Thu, 29 Dec 2022 15:31:40 +0100 Subject: External auth can set more user fields videoQuota, videoQuotaDaily, adminFlags --- server/lib/auth/oauth-model.ts | 22 ++++++---------------- 1 file changed, 6 insertions(+), 16 deletions(-) (limited to 'server/lib/auth/oauth-model.ts') diff --git a/server/lib/auth/oauth-model.ts b/server/lib/auth/oauth-model.ts index 322b69e3a..603cc0f5f 100644 --- a/server/lib/auth/oauth-model.ts +++ b/server/lib/auth/oauth-model.ts @@ -5,7 +5,6 @@ import { MOAuthClient } from '@server/types/models' import { MOAuthTokenUser } from '@server/types/models/oauth/oauth-token' import { MUser } from '@server/types/models/user/user' import { pick } from '@shared/core-utils' -import { UserRole } from '@shared/models/users/user-role' import { logger } from '../../helpers/logger' import { CONFIG } from '../../initializers/config' import { OAuthClientModel } from '../../models/oauth/oauth-client' @@ -13,6 +12,7 @@ import { OAuthTokenModel } from '../../models/oauth/oauth-token' import { UserModel } from '../../models/user/user' import { findAvailableLocalActorName } from '../local-actor' import { buildUser, createUserAccountAndChannelAndPlaylist } from '../user' +import { ExternalUser } from './external-auth' import { TokensCache } from './tokens-cache' type TokenInfo = { @@ -26,12 +26,7 @@ export type BypassLogin = { bypass: boolean pluginName: string authName?: string - user: { - username: string - email: string - displayName: string - role: UserRole - } + user: ExternalUser } async function getAccessToken (bearerToken: string) { @@ -219,16 +214,11 @@ export { // --------------------------------------------------------------------------- -async function createUserFromExternal (pluginAuth: string, options: { - username: string - email: string - role: UserRole - displayName: string -}) { - const username = await findAvailableLocalActorName(options.username) +async function createUserFromExternal (pluginAuth: string, userOptions: ExternalUser) { + const username = await findAvailableLocalActorName(userOptions.username) const userToCreate = buildUser({ - ...pick(options, [ 'email', 'role' ]), + ...pick(userOptions, [ 'email', 'role', 'adminFlags', 'videoQuota', 'videoQuotaDaily' ]), username, emailVerified: null, @@ -238,7 +228,7 @@ async function createUserFromExternal (pluginAuth: string, options: { const { user } = await createUserAccountAndChannelAndPlaylist({ userToCreate, - userDisplayName: options.displayName + userDisplayName: userOptions.displayName }) return user -- cgit v1.2.3 From 60b880acdfa85eab5c9ec09ba1283f82ae58ec85 Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Fri, 30 Dec 2022 10:12:20 +0100 Subject: External auth can update user on login --- server/lib/auth/oauth-model.ts | 53 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 52 insertions(+), 1 deletion(-) (limited to 'server/lib/auth/oauth-model.ts') diff --git a/server/lib/auth/oauth-model.ts b/server/lib/auth/oauth-model.ts index 603cc0f5f..43909284f 100644 --- a/server/lib/auth/oauth-model.ts +++ b/server/lib/auth/oauth-model.ts @@ -1,10 +1,13 @@ import express from 'express' import { AccessDeniedError } from '@node-oauth/oauth2-server' import { PluginManager } from '@server/lib/plugins/plugin-manager' +import { AccountModel } from '@server/models/account/account' +import { AuthenticatedResultUpdaterFieldName, RegisterServerAuthenticatedResult } from '@server/types' import { MOAuthClient } from '@server/types/models' import { MOAuthTokenUser } from '@server/types/models/oauth/oauth-token' -import { MUser } from '@server/types/models/user/user' +import { MUser, MUserDefault } from '@server/types/models/user/user' import { pick } from '@shared/core-utils' +import { AttributesOnly } from '@shared/typescript-utils' import { logger } from '../../helpers/logger' import { CONFIG } from '../../initializers/config' import { OAuthClientModel } from '../../models/oauth/oauth-client' @@ -27,6 +30,7 @@ export type BypassLogin = { pluginName: string authName?: string user: ExternalUser + userUpdater: RegisterServerAuthenticatedResult['userUpdater'] } async function getAccessToken (bearerToken: string) { @@ -84,7 +88,9 @@ async function getUser (usernameOrEmail?: string, password?: string, bypassLogin logger.info('Bypassing oauth login by plugin %s.', bypassLogin.pluginName) let user = await UserModel.loadByEmail(bypassLogin.user.email) + if (!user) user = await createUserFromExternal(bypassLogin.pluginName, bypassLogin.user) + else user = await updateUserFromExternal(user, bypassLogin.user, bypassLogin.userUpdater) // Cannot create a user if (!user) throw new AccessDeniedError('Cannot create such user: an actor with that name already exists.') @@ -234,6 +240,51 @@ async function createUserFromExternal (pluginAuth: string, userOptions: External return user } +async function updateUserFromExternal ( + user: MUserDefault, + userOptions: ExternalUser, + userUpdater: RegisterServerAuthenticatedResult['userUpdater'] +) { + if (!userUpdater) return user + + { + type UserAttributeKeys = keyof AttributesOnly + const mappingKeys: { [ id in UserAttributeKeys ]?: AuthenticatedResultUpdaterFieldName } = { + role: 'role', + adminFlags: 'adminFlags', + videoQuota: 'videoQuota', + videoQuotaDaily: 'videoQuotaDaily' + } + + for (const modelKey of Object.keys(mappingKeys)) { + const pluginOptionKey = mappingKeys[modelKey] + + const newValue = userUpdater({ fieldName: pluginOptionKey, currentValue: user[modelKey], newValue: userOptions[pluginOptionKey] }) + user.set(modelKey, newValue) + } + } + + { + type AccountAttributeKeys = keyof Partial> + const mappingKeys: { [ id in AccountAttributeKeys ]?: AuthenticatedResultUpdaterFieldName } = { + name: 'displayName' + } + + for (const modelKey of Object.keys(mappingKeys)) { + const optionKey = mappingKeys[modelKey] + + const newValue = userUpdater({ fieldName: optionKey, currentValue: user.Account[modelKey], newValue: userOptions[optionKey] }) + user.Account.set(modelKey, newValue) + } + } + + logger.debug('Updated user %s with plugin userUpdated function.', user.email, { user, userOptions }) + + user.Account = await user.Account.save() + + return user.save() +} + function checkUserValidityOrThrow (user: MUser) { if (user.blocked) throw new AccessDeniedError('User is blocked.') } -- cgit v1.2.3