|
@@ -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<UserModel>
|
|
|
+ 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<AttributesOnly<AccountModel>>
|
|
|
+ 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.')
|
|
|
}
|