]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/commitdiff
External auth can set more user fields
authorChocobozzz <me@florianbigard.com>
Thu, 29 Dec 2022 14:31:40 +0000 (15:31 +0100)
committerChocobozzz <me@florianbigard.com>
Wed, 4 Jan 2023 10:41:29 +0000 (11:41 +0100)
videoQuota, videoQuotaDaily, adminFlags

server/lib/auth/external-auth.ts
server/lib/auth/oauth-model.ts
server/tests/fixtures/peertube-plugin-test-external-auth-one/main.js
server/tests/plugins/external-auth.ts
server/types/plugins/register-server-auth.model.ts

index 0531128016afbe7b8e8b51858daf80aa433328ce..155ec03d826ef0b43c4d966ec254d054de640fa2 100644 (file)
@@ -1,26 +1,33 @@
 
-import { isUserDisplayNameValid, isUserRoleValid, isUserUsernameValid } from '@server/helpers/custom-validators/users'
+import {
+  isUserAdminFlagsValid,
+  isUserDisplayNameValid,
+  isUserRoleValid,
+  isUserUsernameValid,
+  isUserVideoQuotaDailyValid,
+  isUserVideoQuotaValid
+} from '@server/helpers/custom-validators/users'
 import { logger } from '@server/helpers/logger'
 import { generateRandomString } from '@server/helpers/utils'
 import { PLUGIN_EXTERNAL_AUTH_TOKEN_LIFETIME } from '@server/initializers/constants'
 import { PluginManager } from '@server/lib/plugins/plugin-manager'
 import { OAuthTokenModel } from '@server/models/oauth/oauth-token'
+import { MUser } from '@server/types/models'
 import {
   RegisterServerAuthenticatedResult,
   RegisterServerAuthPassOptions,
   RegisterServerExternalAuthenticatedResult
 } from '@server/types/plugins/register-server-auth.model'
-import { UserRole } from '@shared/models'
+import { UserAdminFlag, UserRole } from '@shared/models'
+
+export type ExternalUser =
+  Pick<MUser, 'username' | 'email' | 'role' | 'adminFlags' | 'videoQuotaDaily' | 'videoQuota'> &
+  { displayName: string }
 
 // Token is the key, expiration date is the value
 const authBypassTokens = new Map<string, {
   expires: Date
-  user: {
-    username: string
-    email: string
-    displayName: string
-    role: UserRole
-  }
+  user: ExternalUser
   authName: string
   npmName: string
 }>()
@@ -172,30 +179,20 @@ function getBypassFromExternalAuth (username: string, externalAuthToken: string)
 }
 
 function isAuthResultValid (npmName: string, authName: string, result: RegisterServerAuthenticatedResult) {
-  if (!isUserUsernameValid(result.username)) {
-    logger.error('Auth method %s of plugin %s did not provide a valid username.', authName, npmName, { username: result.username })
+  const returnError = (field: string) => {
+    logger.error('Auth method %s of plugin %s did not provide a valid %s.', authName, npmName, field, { [field]: result[field] })
     return false
   }
 
-  if (!result.email) {
-    logger.error('Auth method %s of plugin %s did not provide a valid email.', authName, npmName, { email: result.email })
-    return false
-  }
+  if (!isUserUsernameValid(result.username)) return returnError('username')
+  if (!result.email) return returnError('email')
 
-  // role is optional
-  if (result.role && !isUserRoleValid(result.role)) {
-    logger.error('Auth method %s of plugin %s did not provide a valid role.', authName, npmName, { role: result.role })
-    return false
-  }
-
-  // display name is optional
-  if (result.displayName && !isUserDisplayNameValid(result.displayName)) {
-    logger.error(
-      'Auth method %s of plugin %s did not provide a valid display name.',
-      authName, npmName, { displayName: result.displayName }
-    )
-    return false
-  }
+  // Following fields are optional
+  if (result.role && !isUserRoleValid(result.role)) return returnError('role')
+  if (result.displayName && !isUserDisplayNameValid(result.displayName)) return returnError('displayName')
+  if (result.adminFlags && !isUserAdminFlagsValid(result.adminFlags)) return returnError('adminFlags')
+  if (result.videoQuota && !isUserVideoQuotaValid(result.videoQuota + '')) return returnError('videoQuota')
+  if (result.videoQuotaDaily && !isUserVideoQuotaDailyValid(result.videoQuotaDaily + '')) return returnError('videoQuotaDaily')
 
   return true
 }
@@ -205,7 +202,12 @@ function buildUserResult (pluginResult: RegisterServerAuthenticatedResult) {
     username: pluginResult.username,
     email: pluginResult.email,
     role: pluginResult.role ?? UserRole.USER,
-    displayName: pluginResult.displayName || pluginResult.username
+    displayName: pluginResult.displayName || pluginResult.username,
+
+    adminFlags: pluginResult.adminFlags ?? UserAdminFlag.NONE,
+
+    videoQuota: pluginResult.videoQuota,
+    videoQuotaDaily: pluginResult.videoQuotaDaily
   }
 }
 
index 322b69e3a9feea712138b355310f0c5becfee354..603cc0f5f541b473f137d047a9f75dc118ceeb17 100644 (file)
@@ -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
index c65b8d3a8f618af61d92712a947fc348549966ec..cdbaf11ac3486aeaaa7be97c912e9b125bc65172 100644 (file)
@@ -33,7 +33,10 @@ async function register ({
           username: 'kefka',
           email: 'kefka@example.com',
           role: 0,
-          displayName: 'Kefka Palazzo'
+          displayName: 'Kefka Palazzo',
+          adminFlags: 1,
+          videoQuota: 42000,
+          videoQuotaDaily: 42100
         })
       },
       hookTokenValidity: (options) => {
index 437777e90e7a2dfb72f4a975f3809b074319a228..ee78ae5aa230e407cfc63c39d0d2500d3fd59830 100644 (file)
@@ -2,7 +2,7 @@
 
 import { expect } from 'chai'
 import { wait } from '@shared/core-utils'
-import { HttpStatusCode, UserRole } from '@shared/models'
+import { HttpStatusCode, UserAdminFlag, UserRole } from '@shared/models'
 import {
   cleanupTests,
   createSingleServer,
@@ -156,6 +156,9 @@ describe('Test external auth plugins', function () {
       expect(body.account.displayName).to.equal('cyan')
       expect(body.email).to.equal('cyan@example.com')
       expect(body.role.id).to.equal(UserRole.USER)
+      expect(body.adminFlags).to.equal(UserAdminFlag.NONE)
+      expect(body.videoQuota).to.equal(5242880)
+      expect(body.videoQuotaDaily).to.equal(-1)
     }
   })
 
@@ -178,6 +181,9 @@ describe('Test external auth plugins', function () {
       expect(body.account.displayName).to.equal('Kefka Palazzo')
       expect(body.email).to.equal('kefka@example.com')
       expect(body.role.id).to.equal(UserRole.ADMINISTRATOR)
+      expect(body.adminFlags).to.equal(UserAdminFlag.BYPASS_VIDEO_AUTO_BLACKLIST)
+      expect(body.videoQuota).to.equal(42000)
+      expect(body.videoQuotaDaily).to.equal(42100)
     }
   })
 
index 79c18c406c93c4c69629689bba9d0010cbf37ca1..a17fc4b0fca7367344ccb1bb38a59351ed13a34d 100644 (file)
@@ -1,5 +1,5 @@
 import express from 'express'
-import { UserRole } from '@shared/models'
+import { UserAdminFlag, UserRole } from '@shared/models'
 import { MOAuthToken, MUser } from '../models'
 
 export type RegisterServerAuthOptions = RegisterServerAuthPassOptions | RegisterServerAuthExternalOptions
@@ -9,6 +9,11 @@ export interface RegisterServerAuthenticatedResult {
   email: string
   role?: UserRole
   displayName?: string
+
+  adminFlags?: UserAdminFlag
+
+  videoQuota?: number
+  videoQuotaDaily?: number
 }
 
 export interface RegisterServerExternalAuthenticatedResult extends RegisterServerAuthenticatedResult {