diff --git a/client/src/app/+admin/users/user-edit/user-edit.component.html b/client/src/app/+admin/users/user-edit/user-edit.component.html
index 78c92227f..fb34d6b22 100644
--- a/client/src/app/+admin/users/user-edit/user-edit.component.html
+++ b/client/src/app/+admin/users/user-edit/user-edit.component.html
@@ -174,6 +174,17 @@
+
+
p.npmName)
+ .concat(this.serverConfig.plugin.registeredExternalAuths.map(p => p.npmName))
+ }
+
isInBigView () {
return this.screenService.getWindowInnerWidth() > 1600
}
diff --git a/client/src/app/+admin/users/user-edit/user-update.component.ts b/client/src/app/+admin/users/user-edit/user-update.component.ts
index e16f66a2b..281c3dcef 100644
--- a/client/src/app/+admin/users/user-edit/user-update.component.ts
+++ b/client/src/app/+admin/users/user-edit/user-update.component.ts
@@ -53,7 +53,8 @@ export class UserUpdateComponent extends UserEdit implements OnInit, OnDestroy {
role: USER_ROLE_VALIDATOR,
videoQuota: USER_VIDEO_QUOTA_VALIDATOR,
videoQuotaDaily: USER_VIDEO_QUOTA_DAILY_VALIDATOR,
- byPassAutoBlock: null
+ byPassAutoBlock: null,
+ pluginAuth: null
}, defaultValues)
this.paramsSub = this.route.params.subscribe(routeParams => {
@@ -120,6 +121,7 @@ export class UserUpdateComponent extends UserEdit implements OnInit, OnDestroy {
role: userJson.role.toString(),
videoQuota: userJson.videoQuota,
videoQuotaDaily: userJson.videoQuotaDaily,
+ pluginAuth: userJson.pluginAuth,
byPassAutoBlock: userJson.adminFlags & UserAdminFlag.BYPASS_VIDEO_AUTO_BLACKLIST
})
}
diff --git a/server/controllers/api/users/index.ts b/server/controllers/api/users/index.ts
index c3190e731..5911d1a0f 100644
--- a/server/controllers/api/users/index.ts
+++ b/server/controllers/api/users/index.ts
@@ -327,6 +327,7 @@ async function updateUser (req: express.Request, res: express.Response) {
if (body.videoQuotaDaily !== undefined) userToUpdate.videoQuotaDaily = body.videoQuotaDaily
if (body.role !== undefined) userToUpdate.role = body.role
if (body.adminFlags !== undefined) userToUpdate.adminFlags = body.adminFlags
+ if (body.pluginAuth !== undefined) userToUpdate.pluginAuth = body.pluginAuth
const user = await userToUpdate.save()
diff --git a/server/middlewares/validators/users.ts b/server/middlewares/validators/users.ts
index 6b6e6c2df..345571e83 100644
--- a/server/middlewares/validators/users.ts
+++ b/server/middlewares/validators/users.ts
@@ -7,7 +7,7 @@ import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-code
import { UserRole } from '../../../shared/models/users'
import { UserRegister } from '../../../shared/models/users/user-register.model'
import { isActorPreferredUsernameValid } from '../../helpers/custom-validators/activitypub/actor'
-import { isIdOrUUIDValid, toBooleanOrNull, toIntOrNull } from '../../helpers/custom-validators/misc'
+import { exists, isIdOrUUIDValid, toBooleanOrNull, toIntOrNull } from '../../helpers/custom-validators/misc'
import { isThemeNameValid } from '../../helpers/custom-validators/plugins'
import {
isNoInstanceConfigWarningModal,
@@ -201,6 +201,7 @@ const usersUpdateValidator = [
body('emailVerified').optional().isBoolean().withMessage('Should have a valid email verified attribute'),
body('videoQuota').optional().custom(isUserVideoQuotaValid).withMessage('Should have a valid user quota'),
body('videoQuotaDaily').optional().custom(isUserVideoQuotaDailyValid).withMessage('Should have a valid daily user quota'),
+ body('pluginAuth').optional(),
body('role')
.optional()
.customSanitizer(toIntOrNull)
diff --git a/server/tests/api/users/users.ts b/server/tests/api/users/users.ts
index cd928b980..62a59033f 100644
--- a/server/tests/api/users/users.ts
+++ b/server/tests/api/users/users.ts
@@ -716,11 +716,12 @@ describe('Test users', function () {
emailVerified: true,
videoQuota: 42,
role: UserRole.MODERATOR,
- adminFlags: UserAdminFlag.NONE
+ adminFlags: UserAdminFlag.NONE,
+ pluginAuth: 'toto'
})
const res = await getUserInformation(server.url, accessToken, userId)
- const user = res.body
+ const user = res.body as User
expect(user.username).to.equal('user_1')
expect(user.email).to.equal('updated2@example.com')
@@ -730,6 +731,15 @@ describe('Test users', function () {
expect(user.roleLabel).to.equal('Moderator')
expect(user.id).to.be.a('number')
expect(user.adminFlags).to.equal(UserAdminFlag.NONE)
+ expect(user.pluginAuth).to.equal('toto')
+ })
+
+ it('Should reset the auth plugin', async function () {
+ await updateUser({ url: server.url, userId, accessToken, pluginAuth: null })
+
+ const res = await getUserInformation(server.url, accessToken, userId)
+ const user = res.body as User
+ expect(user.pluginAuth).to.be.null
})
it('Should have removed the user token', async function () {
diff --git a/shared/extra-utils/users/users.ts b/shared/extra-utils/users/users.ts
index c683dcdd1..db532dbb0 100644
--- a/shared/extra-utils/users/users.ts
+++ b/shared/extra-utils/users/users.ts
@@ -288,6 +288,7 @@ function updateUser (options: {
videoQuotaDaily?: number
password?: string
adminFlags?: UserAdminFlag
+ pluginAuth?: string
role?: UserRole
}) {
const path = '/api/v1/users/' + options.userId
@@ -300,6 +301,7 @@ function updateUser (options: {
if (options.videoQuotaDaily !== undefined && options.videoQuotaDaily !== null) toSend['videoQuotaDaily'] = options.videoQuotaDaily
if (options.role !== undefined && options.role !== null) toSend['role'] = options.role
if (options.adminFlags !== undefined && options.adminFlags !== null) toSend['adminFlags'] = options.adminFlags
+ if (options.pluginAuth !== undefined) toSend['pluginAuth'] = options.pluginAuth
return makePutBodyRequest({
url: options.url,
diff --git a/shared/models/users/user-update.model.ts b/shared/models/users/user-update.model.ts
index fa43487ac..158738545 100644
--- a/shared/models/users/user-update.model.ts
+++ b/shared/models/users/user-update.model.ts
@@ -9,4 +9,5 @@ export interface UserUpdate {
videoQuotaDaily?: number
role?: UserRole
adminFlags?: UserAdminFlag
+ pluginAuth?: string
}
diff --git a/support/doc/api/openapi.yaml b/support/doc/api/openapi.yaml
index b05a113ca..49616bcaa 100644
--- a/support/doc/api/openapi.yaml
+++ b/support/doc/api/openapi.yaml
@@ -3898,6 +3898,13 @@ components:
- 2
description: 'The user role (Admin = `0`, Moderator = `1`, User = `2`)'
example: 2
+ UserAdminFlags:
+ type: integer
+ enum:
+ - 0
+ - 1
+ description: 'Admin flags for the user (None = `0`, Bypass video blacklist = `1`)'
+ example: 1
VideoStateConstant:
properties:
@@ -5022,6 +5029,9 @@ components:
type: string
format: email
description: The user email
+ pluginAuth:
+ type: string
+ description: Auth plugin to use to authenticate the user
theme:
type: string
description: Theme enabled by this user
@@ -5099,8 +5109,13 @@ components:
videoQuotaDaily:
type: integer
description: The user daily video quota
+ channelName:
+ type: string
+ description: The user default channel username
role:
$ref: '#/components/schemas/UserRole'
+ adminFlags:
+ $ref: '#/components/schemas/UserAdminFlags'
required:
- username
- password
@@ -5117,20 +5132,26 @@ components:
type: string
format: email
description: The updated email of the user
+ emailVerified:
+ type: boolean
+ description: Set the email as verified
videoQuota:
type: integer
description: The updated video quota of the user
videoQuotaDaily:
type: integer
description: The updated daily video quota of the user
+ pluginAuth:
+ type: string
+ nullable: true
+ description: The auth plugin to use to authenticate the user
+ example: 'peertube-plugin-auth-saml2'
role:
$ref: '#/components/schemas/UserRole'
+ adminFlags:
+ $ref: '#/components/schemas/UserAdminFlags'
required:
- id
- - email
- - videoQuota
- - videoQuotaDaily
- - role
UpdateMe:
properties:
password: