aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--client/src/app/+admin/users/user-edit/user-edit.component.html11
-rw-r--r--client/src/app/+admin/users/user-edit/user-edit.ts5
-rw-r--r--client/src/app/+admin/users/user-edit/user-update.component.ts4
-rw-r--r--server/controllers/api/users/index.ts1
-rw-r--r--server/middlewares/validators/users.ts3
-rw-r--r--server/tests/api/users/users.ts14
-rw-r--r--shared/extra-utils/users/users.ts2
-rw-r--r--shared/models/users/user-update.model.ts1
-rw-r--r--support/doc/api/openapi.yaml29
9 files changed, 62 insertions, 8 deletions
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 @@
174 </div> 174 </div>
175 </div> 175 </div>
176 176
177 <div class="form-group" *ngIf="!isCreation() && getAuthPlugins().length !== 0">
178 <label i18n for="pluginAuth">Auth plugin</label>
179
180 <div class="peertube-select-container">
181 <select id="pluginAuth" formControlName="pluginAuth" class="form-control">
182 <option [value]="null" i18n>None (local authentication)</option>
183 <option *ngFor="let authPlugin of getAuthPlugins()" [value]="authPlugin">{{ authPlugin }}</option>
184 </select>
185 </div>
186 </div>
187
177 <div class="form-group"> 188 <div class="form-group">
178 <my-peertube-checkbox 189 <my-peertube-checkbox
179 inputName="byPassAutoBlock" formControlName="byPassAutoBlock" 190 inputName="byPassAutoBlock" formControlName="byPassAutoBlock"
diff --git a/client/src/app/+admin/users/user-edit/user-edit.ts b/client/src/app/+admin/users/user-edit/user-edit.ts
index 1613bb0d1..faa2f5ad8 100644
--- a/client/src/app/+admin/users/user-edit/user-edit.ts
+++ b/client/src/app/+admin/users/user-edit/user-edit.ts
@@ -42,6 +42,11 @@ export abstract class UserEdit extends FormReactive implements OnInit {
42 return forAccount + forChannels 42 return forAccount + forChannels
43 } 43 }
44 44
45 getAuthPlugins () {
46 return this.serverConfig.plugin.registeredIdAndPassAuths.map(p => p.npmName)
47 .concat(this.serverConfig.plugin.registeredExternalAuths.map(p => p.npmName))
48 }
49
45 isInBigView () { 50 isInBigView () {
46 return this.screenService.getWindowInnerWidth() > 1600 51 return this.screenService.getWindowInnerWidth() > 1600
47 } 52 }
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 {
53 role: USER_ROLE_VALIDATOR, 53 role: USER_ROLE_VALIDATOR,
54 videoQuota: USER_VIDEO_QUOTA_VALIDATOR, 54 videoQuota: USER_VIDEO_QUOTA_VALIDATOR,
55 videoQuotaDaily: USER_VIDEO_QUOTA_DAILY_VALIDATOR, 55 videoQuotaDaily: USER_VIDEO_QUOTA_DAILY_VALIDATOR,
56 byPassAutoBlock: null 56 byPassAutoBlock: null,
57 pluginAuth: null
57 }, defaultValues) 58 }, defaultValues)
58 59
59 this.paramsSub = this.route.params.subscribe(routeParams => { 60 this.paramsSub = this.route.params.subscribe(routeParams => {
@@ -120,6 +121,7 @@ export class UserUpdateComponent extends UserEdit implements OnInit, OnDestroy {
120 role: userJson.role.toString(), 121 role: userJson.role.toString(),
121 videoQuota: userJson.videoQuota, 122 videoQuota: userJson.videoQuota,
122 videoQuotaDaily: userJson.videoQuotaDaily, 123 videoQuotaDaily: userJson.videoQuotaDaily,
124 pluginAuth: userJson.pluginAuth,
123 byPassAutoBlock: userJson.adminFlags & UserAdminFlag.BYPASS_VIDEO_AUTO_BLACKLIST 125 byPassAutoBlock: userJson.adminFlags & UserAdminFlag.BYPASS_VIDEO_AUTO_BLACKLIST
124 }) 126 })
125 } 127 }
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) {
327 if (body.videoQuotaDaily !== undefined) userToUpdate.videoQuotaDaily = body.videoQuotaDaily 327 if (body.videoQuotaDaily !== undefined) userToUpdate.videoQuotaDaily = body.videoQuotaDaily
328 if (body.role !== undefined) userToUpdate.role = body.role 328 if (body.role !== undefined) userToUpdate.role = body.role
329 if (body.adminFlags !== undefined) userToUpdate.adminFlags = body.adminFlags 329 if (body.adminFlags !== undefined) userToUpdate.adminFlags = body.adminFlags
330 if (body.pluginAuth !== undefined) userToUpdate.pluginAuth = body.pluginAuth
330 331
331 const user = await userToUpdate.save() 332 const user = await userToUpdate.save()
332 333
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
7import { UserRole } from '../../../shared/models/users' 7import { UserRole } from '../../../shared/models/users'
8import { UserRegister } from '../../../shared/models/users/user-register.model' 8import { UserRegister } from '../../../shared/models/users/user-register.model'
9import { isActorPreferredUsernameValid } from '../../helpers/custom-validators/activitypub/actor' 9import { isActorPreferredUsernameValid } from '../../helpers/custom-validators/activitypub/actor'
10import { isIdOrUUIDValid, toBooleanOrNull, toIntOrNull } from '../../helpers/custom-validators/misc' 10import { exists, isIdOrUUIDValid, toBooleanOrNull, toIntOrNull } from '../../helpers/custom-validators/misc'
11import { isThemeNameValid } from '../../helpers/custom-validators/plugins' 11import { isThemeNameValid } from '../../helpers/custom-validators/plugins'
12import { 12import {
13 isNoInstanceConfigWarningModal, 13 isNoInstanceConfigWarningModal,
@@ -201,6 +201,7 @@ const usersUpdateValidator = [
201 body('emailVerified').optional().isBoolean().withMessage('Should have a valid email verified attribute'), 201 body('emailVerified').optional().isBoolean().withMessage('Should have a valid email verified attribute'),
202 body('videoQuota').optional().custom(isUserVideoQuotaValid).withMessage('Should have a valid user quota'), 202 body('videoQuota').optional().custom(isUserVideoQuotaValid).withMessage('Should have a valid user quota'),
203 body('videoQuotaDaily').optional().custom(isUserVideoQuotaDailyValid).withMessage('Should have a valid daily user quota'), 203 body('videoQuotaDaily').optional().custom(isUserVideoQuotaDailyValid).withMessage('Should have a valid daily user quota'),
204 body('pluginAuth').optional(),
204 body('role') 205 body('role')
205 .optional() 206 .optional()
206 .customSanitizer(toIntOrNull) 207 .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 () {
716 emailVerified: true, 716 emailVerified: true,
717 videoQuota: 42, 717 videoQuota: 42,
718 role: UserRole.MODERATOR, 718 role: UserRole.MODERATOR,
719 adminFlags: UserAdminFlag.NONE 719 adminFlags: UserAdminFlag.NONE,
720 pluginAuth: 'toto'
720 }) 721 })
721 722
722 const res = await getUserInformation(server.url, accessToken, userId) 723 const res = await getUserInformation(server.url, accessToken, userId)
723 const user = res.body 724 const user = res.body as User
724 725
725 expect(user.username).to.equal('user_1') 726 expect(user.username).to.equal('user_1')
726 expect(user.email).to.equal('updated2@example.com') 727 expect(user.email).to.equal('updated2@example.com')
@@ -730,6 +731,15 @@ describe('Test users', function () {
730 expect(user.roleLabel).to.equal('Moderator') 731 expect(user.roleLabel).to.equal('Moderator')
731 expect(user.id).to.be.a('number') 732 expect(user.id).to.be.a('number')
732 expect(user.adminFlags).to.equal(UserAdminFlag.NONE) 733 expect(user.adminFlags).to.equal(UserAdminFlag.NONE)
734 expect(user.pluginAuth).to.equal('toto')
735 })
736
737 it('Should reset the auth plugin', async function () {
738 await updateUser({ url: server.url, userId, accessToken, pluginAuth: null })
739
740 const res = await getUserInformation(server.url, accessToken, userId)
741 const user = res.body as User
742 expect(user.pluginAuth).to.be.null
733 }) 743 })
734 744
735 it('Should have removed the user token', async function () { 745 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: {
288 videoQuotaDaily?: number 288 videoQuotaDaily?: number
289 password?: string 289 password?: string
290 adminFlags?: UserAdminFlag 290 adminFlags?: UserAdminFlag
291 pluginAuth?: string
291 role?: UserRole 292 role?: UserRole
292}) { 293}) {
293 const path = '/api/v1/users/' + options.userId 294 const path = '/api/v1/users/' + options.userId
@@ -300,6 +301,7 @@ function updateUser (options: {
300 if (options.videoQuotaDaily !== undefined && options.videoQuotaDaily !== null) toSend['videoQuotaDaily'] = options.videoQuotaDaily 301 if (options.videoQuotaDaily !== undefined && options.videoQuotaDaily !== null) toSend['videoQuotaDaily'] = options.videoQuotaDaily
301 if (options.role !== undefined && options.role !== null) toSend['role'] = options.role 302 if (options.role !== undefined && options.role !== null) toSend['role'] = options.role
302 if (options.adminFlags !== undefined && options.adminFlags !== null) toSend['adminFlags'] = options.adminFlags 303 if (options.adminFlags !== undefined && options.adminFlags !== null) toSend['adminFlags'] = options.adminFlags
304 if (options.pluginAuth !== undefined) toSend['pluginAuth'] = options.pluginAuth
303 305
304 return makePutBodyRequest({ 306 return makePutBodyRequest({
305 url: options.url, 307 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 {
9 videoQuotaDaily?: number 9 videoQuotaDaily?: number
10 role?: UserRole 10 role?: UserRole
11 adminFlags?: UserAdminFlag 11 adminFlags?: UserAdminFlag
12 pluginAuth?: string
12} 13}
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:
3898 - 2 3898 - 2
3899 description: 'The user role (Admin = `0`, Moderator = `1`, User = `2`)' 3899 description: 'The user role (Admin = `0`, Moderator = `1`, User = `2`)'
3900 example: 2 3900 example: 2
3901 UserAdminFlags:
3902 type: integer
3903 enum:
3904 - 0
3905 - 1
3906 description: 'Admin flags for the user (None = `0`, Bypass video blacklist = `1`)'
3907 example: 1
3901 3908
3902 VideoStateConstant: 3909 VideoStateConstant:
3903 properties: 3910 properties:
@@ -5022,6 +5029,9 @@ components:
5022 type: string 5029 type: string
5023 format: email 5030 format: email
5024 description: The user email 5031 description: The user email
5032 pluginAuth:
5033 type: string
5034 description: Auth plugin to use to authenticate the user
5025 theme: 5035 theme:
5026 type: string 5036 type: string
5027 description: Theme enabled by this user 5037 description: Theme enabled by this user
@@ -5099,8 +5109,13 @@ components:
5099 videoQuotaDaily: 5109 videoQuotaDaily:
5100 type: integer 5110 type: integer
5101 description: The user daily video quota 5111 description: The user daily video quota
5112 channelName:
5113 type: string
5114 description: The user default channel username
5102 role: 5115 role:
5103 $ref: '#/components/schemas/UserRole' 5116 $ref: '#/components/schemas/UserRole'
5117 adminFlags:
5118 $ref: '#/components/schemas/UserAdminFlags'
5104 required: 5119 required:
5105 - username 5120 - username
5106 - password 5121 - password
@@ -5117,20 +5132,26 @@ components:
5117 type: string 5132 type: string
5118 format: email 5133 format: email
5119 description: The updated email of the user 5134 description: The updated email of the user
5135 emailVerified:
5136 type: boolean
5137 description: Set the email as verified
5120 videoQuota: 5138 videoQuota:
5121 type: integer 5139 type: integer
5122 description: The updated video quota of the user 5140 description: The updated video quota of the user
5123 videoQuotaDaily: 5141 videoQuotaDaily:
5124 type: integer 5142 type: integer
5125 description: The updated daily video quota of the user 5143 description: The updated daily video quota of the user
5144 pluginAuth:
5145 type: string
5146 nullable: true
5147 description: The auth plugin to use to authenticate the user
5148 example: 'peertube-plugin-auth-saml2'
5126 role: 5149 role:
5127 $ref: '#/components/schemas/UserRole' 5150 $ref: '#/components/schemas/UserRole'
5151 adminFlags:
5152 $ref: '#/components/schemas/UserAdminFlags'
5128 required: 5153 required:
5129 - id 5154 - id
5130 - email
5131 - videoQuota
5132 - videoQuotaDaily
5133 - role
5134 UpdateMe: 5155 UpdateMe:
5135 properties: 5156 properties:
5136 password: 5157 password: