aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--client/src/app/menu/menu.component.html6
-rw-r--r--client/src/app/my-account/my-account-settings/my-account-details/index.ts1
-rw-r--r--client/src/app/my-account/my-account-settings/my-account-profile/index.ts1
-rw-r--r--client/src/app/my-account/my-account-settings/my-account-profile/my-account-profile.component.html24
-rw-r--r--client/src/app/my-account/my-account-settings/my-account-profile/my-account-profile.component.scss23
-rw-r--r--client/src/app/my-account/my-account-settings/my-account-profile/my-account-profile.component.ts65
-rw-r--r--client/src/app/my-account/my-account-settings/my-account-settings.component.html9
-rw-r--r--client/src/app/my-account/my-account-settings/my-account-video-settings/index.ts1
-rw-r--r--client/src/app/my-account/my-account-settings/my-account-video-settings/my-account-video-settings.component.html (renamed from client/src/app/my-account/my-account-settings/my-account-details/my-account-details.component.html)0
-rw-r--r--client/src/app/my-account/my-account-settings/my-account-video-settings/my-account-video-settings.component.scss (renamed from client/src/app/my-account/my-account-settings/my-account-details/my-account-details.component.scss)0
-rw-r--r--client/src/app/my-account/my-account-settings/my-account-video-settings/my-account-video-settings.component.ts (renamed from client/src/app/my-account/my-account-settings/my-account-details/my-account-details.component.ts)10
-rw-r--r--client/src/app/my-account/my-account.component.html2
-rw-r--r--client/src/app/my-account/my-account.module.ts6
-rw-r--r--client/src/app/shared/forms/form-validators/user.ts24
-rw-r--r--client/src/app/shared/users/user.service.ts4
-rw-r--r--server/controllers/api/users.ts1
-rw-r--r--server/helpers/custom-validators/users.ts5
-rw-r--r--server/initializers/constants.ts3
-rw-r--r--server/middlewares/validators/users.ts3
-rw-r--r--server/tests/api/users/users-multiple-servers.ts20
-rw-r--r--server/tests/api/users/users.ts23
-rw-r--r--server/tests/utils/users/users.ts2
-rw-r--r--shared/models/users/user-update-me.model.ts1
23 files changed, 215 insertions, 19 deletions
diff --git a/client/src/app/menu/menu.component.html b/client/src/app/menu/menu.component.html
index 6e8189371..d1488ec3c 100644
--- a/client/src/app/menu/menu.component.html
+++ b/client/src/app/menu/menu.component.html
@@ -5,7 +5,7 @@
5 </a> 5 </a>
6 6
7 <div class="logged-in-info"> 7 <div class="logged-in-info">
8 <a routerLink="/my-account/settings" class="logged-in-username">{{ user.username }}</a> 8 <a routerLink="/my-account/settings" class="logged-in-username">{{ user.account?.displayName }}</a>
9 <div class="logged-in-email">{{ user.email }}</div> 9 <div class="logged-in-email">{{ user.email }}</div>
10 </div> 10 </div>
11 11
@@ -14,8 +14,8 @@
14 14
15 <ul *dropdownMenu class="dropdown-menu"> 15 <ul *dropdownMenu class="dropdown-menu">
16 <li> 16 <li>
17 <a i18n routerLink="/my-account/settings" class="dropdown-item" title="My account"> 17 <a routerLink="/my-account/settings" class="dropdown-item" title="My settings">
18 My account 18 My settings
19 </a> 19 </a>
20 20
21 <a (click)="logout($event)" class="dropdown-item" title="Log out" href="#"> 21 <a (click)="logout($event)" class="dropdown-item" title="Log out" href="#">
diff --git a/client/src/app/my-account/my-account-settings/my-account-details/index.ts b/client/src/app/my-account/my-account-settings/my-account-details/index.ts
deleted file mode 100644
index b7f58e329..000000000
--- a/client/src/app/my-account/my-account-settings/my-account-details/index.ts
+++ /dev/null
@@ -1 +0,0 @@
1export * from './my-account-details.component'
diff --git a/client/src/app/my-account/my-account-settings/my-account-profile/index.ts b/client/src/app/my-account/my-account-settings/my-account-profile/index.ts
new file mode 100644
index 000000000..3cc049f8f
--- /dev/null
+++ b/client/src/app/my-account/my-account-settings/my-account-profile/index.ts
@@ -0,0 +1 @@
export * from './my-account-profile.component'
diff --git a/client/src/app/my-account/my-account-settings/my-account-profile/my-account-profile.component.html b/client/src/app/my-account/my-account-settings/my-account-profile/my-account-profile.component.html
new file mode 100644
index 000000000..306f3a12c
--- /dev/null
+++ b/client/src/app/my-account/my-account-settings/my-account-profile/my-account-profile.component.html
@@ -0,0 +1,24 @@
1<div *ngIf="error" class="alert alert-danger">{{ error }}</div>
2
3<form role="form" (ngSubmit)="updateMyProfile()" [formGroup]="form">
4
5 <label for="display-name">Display name</label>
6 <input
7 type="text" id="display-name"
8 formControlName="display-name" [ngClass]="{ 'input-error': formErrors['display-name'] }"
9 >
10 <div *ngIf="formErrors['display-name']" class="form-error">
11 {{ formErrors['display-name'] }}
12 </div>
13
14 <label for="description">Description</label>
15 <textarea
16 id="description" formControlName="description"
17 [ngClass]="{ 'input-error': formErrors['description'] }"
18 ></textarea>
19 <div *ngIf="formErrors.description" class="form-error">
20 {{ formErrors.description }}
21 </div>
22
23 <input type="submit" value="Update my profile" [disabled]="!form.valid">
24</form>
diff --git a/client/src/app/my-account/my-account-settings/my-account-profile/my-account-profile.component.scss b/client/src/app/my-account/my-account-settings/my-account-profile/my-account-profile.component.scss
new file mode 100644
index 000000000..fc2b92c89
--- /dev/null
+++ b/client/src/app/my-account/my-account-settings/my-account-profile/my-account-profile.component.scss
@@ -0,0 +1,23 @@
1@import '_variables';
2@import '_mixins';
3
4input[type=text] {
5 @include peertube-input-text(340px);
6
7 display: block;
8 margin-bottom: 15px;
9}
10
11textarea {
12 @include peertube-textarea(500px, 150px);
13
14 display: block;
15}
16
17input[type=submit] {
18 @include peertube-button;
19 @include orange-button;
20
21 margin-top: 15px;
22}
23
diff --git a/client/src/app/my-account/my-account-settings/my-account-profile/my-account-profile.component.ts b/client/src/app/my-account/my-account-settings/my-account-profile/my-account-profile.component.ts
new file mode 100644
index 000000000..2b7ba353c
--- /dev/null
+++ b/client/src/app/my-account/my-account-settings/my-account-profile/my-account-profile.component.ts
@@ -0,0 +1,65 @@
1import { Component, Input, OnInit } from '@angular/core'
2import { FormBuilder, FormGroup } from '@angular/forms'
3import { NotificationsService } from 'angular2-notifications'
4import { FormReactive, USER_DESCRIPTION, USER_DISPLAY_NAME, UserService } from '../../../shared'
5import { User } from '@app/shared'
6
7@Component({
8 selector: 'my-account-profile',
9 templateUrl: './my-account-profile.component.html',
10 styleUrls: [ './my-account-profile.component.scss' ]
11})
12export class MyAccountProfileComponent extends FormReactive implements OnInit {
13 @Input() user: User = null
14
15 error: string = null
16
17 form: FormGroup
18 formErrors = {
19 'display-name': '',
20 'description': ''
21 }
22 validationMessages = {
23 'display-name': USER_DISPLAY_NAME.MESSAGES,
24 'description': USER_DESCRIPTION.MESSAGES
25 }
26
27 constructor (
28 private formBuilder: FormBuilder,
29 private notificationsService: NotificationsService,
30 private userService: UserService
31 ) {
32 super()
33 }
34
35 buildForm () {
36 this.form = this.formBuilder.group({
37 'display-name': [ this.user.account.displayName, USER_DISPLAY_NAME.VALIDATORS ],
38 'description': [ this.user.account.description, USER_DESCRIPTION.VALIDATORS ]
39 })
40
41 this.form.valueChanges.subscribe(data => this.onValueChanged(data))
42 }
43
44 ngOnInit () {
45 this.buildForm()
46 }
47
48 updateMyProfile () {
49 const displayName = this.form.value['display-name']
50 const description = this.form.value['description']
51
52 this.error = null
53
54 this.userService.updateMyProfile({ displayName, description }).subscribe(
55 () => {
56 this.user.account.displayName = displayName
57 this.user.account.description = description
58
59 this.notificationsService.success('Success', 'Profile updated.')
60 },
61
62 err => this.error = err.message
63 )
64 }
65}
diff --git a/client/src/app/my-account/my-account-settings/my-account-settings.component.html b/client/src/app/my-account/my-account-settings/my-account-settings.component.html
index e11d93c01..e655b9d96 100644
--- a/client/src/app/my-account/my-account-settings/my-account-settings.component.html
+++ b/client/src/app/my-account/my-account-settings/my-account-settings.component.html
@@ -17,8 +17,13 @@
17 <span class="user-quota-label">Video quota:</span> {{ userVideoQuotaUsed | bytes: 0 }} / {{ userVideoQuota }} 17 <span class="user-quota-label">Video quota:</span> {{ userVideoQuotaUsed | bytes: 0 }} / {{ userVideoQuota }}
18</div> 18</div>
19 19
20<div class="account-title">Account settings</div> 20<ng-template [ngIf]="user && user.account">
21 <div class="account-title">Profile</div>
22 <my-account-profile [user]="user"></my-account-profile>
23</ng-template>
24
25<div class="account-title">Password</div>
21<my-account-change-password></my-account-change-password> 26<my-account-change-password></my-account-change-password>
22 27
23<div class="account-title">Video settings</div> 28<div class="account-title">Video settings</div>
24<my-account-details [user]="user"></my-account-details> 29<my-account-video-settings [user]="user"></my-account-video-settings>
diff --git a/client/src/app/my-account/my-account-settings/my-account-video-settings/index.ts b/client/src/app/my-account/my-account-settings/my-account-video-settings/index.ts
new file mode 100644
index 000000000..1253bd369
--- /dev/null
+++ b/client/src/app/my-account/my-account-settings/my-account-video-settings/index.ts
@@ -0,0 +1 @@
export * from './my-account-video-settings.component'
diff --git a/client/src/app/my-account/my-account-settings/my-account-details/my-account-details.component.html b/client/src/app/my-account/my-account-settings/my-account-video-settings/my-account-video-settings.component.html
index 0e8598e9e..0e8598e9e 100644
--- a/client/src/app/my-account/my-account-settings/my-account-details/my-account-details.component.html
+++ b/client/src/app/my-account/my-account-settings/my-account-video-settings/my-account-video-settings.component.html
diff --git a/client/src/app/my-account/my-account-settings/my-account-details/my-account-details.component.scss b/client/src/app/my-account/my-account-settings/my-account-video-settings/my-account-video-settings.component.scss
index ed59e4689..ed59e4689 100644
--- a/client/src/app/my-account/my-account-settings/my-account-details/my-account-details.component.scss
+++ b/client/src/app/my-account/my-account-settings/my-account-video-settings/my-account-video-settings.component.scss
diff --git a/client/src/app/my-account/my-account-settings/my-account-details/my-account-details.component.ts b/client/src/app/my-account/my-account-settings/my-account-video-settings/my-account-video-settings.component.ts
index 4c1456541..acc70c14d 100644
--- a/client/src/app/my-account/my-account-settings/my-account-details/my-account-details.component.ts
+++ b/client/src/app/my-account/my-account-settings/my-account-video-settings/my-account-video-settings.component.ts
@@ -6,11 +6,11 @@ import { AuthService } from '../../../core'
6import { FormReactive, User, UserService } from '../../../shared' 6import { FormReactive, User, UserService } from '../../../shared'
7 7
8@Component({ 8@Component({
9 selector: 'my-account-details', 9 selector: 'my-account-video-settings',
10 templateUrl: './my-account-details.component.html', 10 templateUrl: './my-account-video-settings.component.html',
11 styleUrls: [ './my-account-details.component.scss' ] 11 styleUrls: [ './my-account-video-settings.component.scss' ]
12}) 12})
13export class MyAccountDetailsComponent extends FormReactive implements OnInit { 13export class MyAccountVideoSettingsComponent extends FormReactive implements OnInit {
14 @Input() user: User = null 14 @Input() user: User = null
15 15
16 form: FormGroup 16 form: FormGroup
@@ -47,7 +47,7 @@ export class MyAccountDetailsComponent extends FormReactive implements OnInit {
47 autoPlayVideo 47 autoPlayVideo
48 } 48 }
49 49
50 this.userService.updateMyDetails(details).subscribe( 50 this.userService.updateMyProfile(details).subscribe(
51 () => { 51 () => {
52 this.notificationsService.success('Success', 'Information updated.') 52 this.notificationsService.success('Success', 'Information updated.')
53 53
diff --git a/client/src/app/my-account/my-account.component.html b/client/src/app/my-account/my-account.component.html
index 637b2587c..41afc1e5d 100644
--- a/client/src/app/my-account/my-account.component.html
+++ b/client/src/app/my-account/my-account.component.html
@@ -1,6 +1,6 @@
1<div class="row"> 1<div class="row">
2 <div class="sub-menu"> 2 <div class="sub-menu">
3 <a routerLink="/my-account/settings" routerLinkActive="active" class="title-page">My account</a> 3 <a routerLink="/my-account/settings" routerLinkActive="active" class="title-page">My settings</a>
4 4
5 <a routerLink="/my-account/videos" routerLinkActive="active" class="title-page">My videos</a> 5 <a routerLink="/my-account/videos" routerLinkActive="active" class="title-page">My videos</a>
6 </div> 6 </div>
diff --git a/client/src/app/my-account/my-account.module.ts b/client/src/app/my-account/my-account.module.ts
index 317277304..981d3c697 100644
--- a/client/src/app/my-account/my-account.module.ts
+++ b/client/src/app/my-account/my-account.module.ts
@@ -2,10 +2,11 @@ import { NgModule } from '@angular/core'
2import { SharedModule } from '../shared' 2import { SharedModule } from '../shared'
3import { MyAccountRoutingModule } from './my-account-routing.module' 3import { MyAccountRoutingModule } from './my-account-routing.module'
4import { MyAccountChangePasswordComponent } from './my-account-settings/my-account-change-password/my-account-change-password.component' 4import { MyAccountChangePasswordComponent } from './my-account-settings/my-account-change-password/my-account-change-password.component'
5import { MyAccountDetailsComponent } from './my-account-settings/my-account-details/my-account-details.component' 5import { MyAccountVideoSettingsComponent } from './my-account-settings/my-account-video-settings/my-account-video-settings.component'
6import { MyAccountSettingsComponent } from './my-account-settings/my-account-settings.component' 6import { MyAccountSettingsComponent } from './my-account-settings/my-account-settings.component'
7import { MyAccountComponent } from './my-account.component' 7import { MyAccountComponent } from './my-account.component'
8import { MyAccountVideosComponent } from './my-account-videos/my-account-videos.component' 8import { MyAccountVideosComponent } from './my-account-videos/my-account-videos.component'
9import { MyAccountProfileComponent } from '@app/my-account/my-account-settings/my-account-profile/my-account-profile.component'
9 10
10@NgModule({ 11@NgModule({
11 imports: [ 12 imports: [
@@ -17,7 +18,8 @@ import { MyAccountVideosComponent } from './my-account-videos/my-account-videos.
17 MyAccountComponent, 18 MyAccountComponent,
18 MyAccountSettingsComponent, 19 MyAccountSettingsComponent,
19 MyAccountChangePasswordComponent, 20 MyAccountChangePasswordComponent,
20 MyAccountDetailsComponent, 21 MyAccountVideoSettingsComponent,
22 MyAccountProfileComponent,
21 MyAccountVideosComponent 23 MyAccountVideosComponent
22 ], 24 ],
23 25
diff --git a/client/src/app/shared/forms/form-validators/user.ts b/client/src/app/shared/forms/form-validators/user.ts
index d2a28a272..095b534c0 100644
--- a/client/src/app/shared/forms/form-validators/user.ts
+++ b/client/src/app/shared/forms/form-validators/user.ts
@@ -46,3 +46,27 @@ export const USER_ROLE = {
46 'required': 'User role is required.' 46 'required': 'User role is required.'
47 } 47 }
48} 48}
49export const USER_DISPLAY_NAME = {
50 VALIDATORS: [
51 Validators.required,
52 Validators.minLength(3),
53 Validators.maxLength(120)
54 ],
55 MESSAGES: {
56 'required': 'Display name is required.',
57 'minlength': 'Display name must be at least 3 characters long.',
58 'maxlength': 'Display name cannot be more than 120 characters long.'
59 }
60}
61export const USER_DESCRIPTION = {
62 VALIDATORS: [
63 Validators.required,
64 Validators.minLength(3),
65 Validators.maxLength(250)
66 ],
67 MESSAGES: {
68 'required': 'Display name is required.',
69 'minlength': 'Display name must be at least 3 characters long.',
70 'maxlength': 'Display name cannot be more than 250 characters long.'
71 }
72}
diff --git a/client/src/app/shared/users/user.service.ts b/client/src/app/shared/users/user.service.ts
index da7b583f4..adb840cec 100644
--- a/client/src/app/shared/users/user.service.ts
+++ b/client/src/app/shared/users/user.service.ts
@@ -26,10 +26,10 @@ export class UserService {
26 .catch(res => this.restExtractor.handleError(res)) 26 .catch(res => this.restExtractor.handleError(res))
27 } 27 }
28 28
29 updateMyDetails (details: UserUpdateMe) { 29 updateMyProfile (profile: UserUpdateMe) {
30 const url = UserService.BASE_USERS_URL + 'me' 30 const url = UserService.BASE_USERS_URL + 'me'
31 31
32 return this.authHttp.put(url, details) 32 return this.authHttp.put(url, profile)
33 .map(this.restExtractor.extractDataBool) 33 .map(this.restExtractor.extractDataBool)
34 .catch(res => this.restExtractor.handleError(res)) 34 .catch(res => this.restExtractor.handleError(res))
35 } 35 }
diff --git a/server/controllers/api/users.ts b/server/controllers/api/users.ts
index dcc4ef196..2342c23dd 100644
--- a/server/controllers/api/users.ts
+++ b/server/controllers/api/users.ts
@@ -303,6 +303,7 @@ async function updateMe (req: express.Request, res: express.Response, next: expr
303 await sequelizeTypescript.transaction(async t => { 303 await sequelizeTypescript.transaction(async t => {
304 await user.save({ transaction: t }) 304 await user.save({ transaction: t })
305 305
306 if (body.displayName !== undefined) user.Account.name = body.displayName
306 if (body.description !== undefined) user.Account.description = body.description 307 if (body.description !== undefined) user.Account.description = body.description
307 await user.Account.save({ transaction: t }) 308 await user.Account.save({ transaction: t })
308 309
diff --git a/server/helpers/custom-validators/users.ts b/server/helpers/custom-validators/users.ts
index c0acb8218..b59b766de 100644
--- a/server/helpers/custom-validators/users.ts
+++ b/server/helpers/custom-validators/users.ts
@@ -22,6 +22,10 @@ function isUserUsernameValid (value: string) {
22 return exists(value) && validator.matches(value, new RegExp(`^[a-z0-9._]{${min},${max}}$`)) 22 return exists(value) && validator.matches(value, new RegExp(`^[a-z0-9._]{${min},${max}}$`))
23} 23}
24 24
25function isUserDisplayNameValid (value: string) {
26 return value === null || (exists(value) && validator.isLength(value, CONSTRAINTS_FIELDS.USERS.NAME))
27}
28
25function isUserDescriptionValid (value: string) { 29function isUserDescriptionValid (value: string) {
26 return value === null || (exists(value) && validator.isLength(value, CONSTRAINTS_FIELDS.USERS.DESCRIPTION)) 30 return value === null || (exists(value) && validator.isLength(value, CONSTRAINTS_FIELDS.USERS.DESCRIPTION))
27} 31}
@@ -60,6 +64,7 @@ export {
60 isUserUsernameValid, 64 isUserUsernameValid,
61 isUserNSFWPolicyValid, 65 isUserNSFWPolicyValid,
62 isUserAutoPlayVideoValid, 66 isUserAutoPlayVideoValid,
67 isUserDisplayNameValid,
63 isUserDescriptionValid, 68 isUserDescriptionValid,
64 isAvatarFile 69 isAvatarFile
65} 70}
diff --git a/server/initializers/constants.ts b/server/initializers/constants.ts
index 9c9c3afc0..365b8617d 100644
--- a/server/initializers/constants.ts
+++ b/server/initializers/constants.ts
@@ -180,9 +180,10 @@ const CONFIG = {
180 180
181const CONSTRAINTS_FIELDS = { 181const CONSTRAINTS_FIELDS = {
182 USERS: { 182 USERS: {
183 NAME: { min: 3, max: 120 }, // Length
184 DESCRIPTION: { min: 3, max: 250 }, // Length
183 USERNAME: { min: 3, max: 20 }, // Length 185 USERNAME: { min: 3, max: 20 }, // Length
184 PASSWORD: { min: 6, max: 255 }, // Length 186 PASSWORD: { min: 6, max: 255 }, // Length
185 DESCRIPTION: { min: 3, max: 250 }, // Length
186 VIDEO_QUOTA: { min: -1 } 187 VIDEO_QUOTA: { min: -1 }
187 }, 188 },
188 VIDEO_ABUSES: { 189 VIDEO_ABUSES: {
diff --git a/server/middlewares/validators/users.ts b/server/middlewares/validators/users.ts
index 5dd8caa3f..247b704c4 100644
--- a/server/middlewares/validators/users.ts
+++ b/server/middlewares/validators/users.ts
@@ -7,7 +7,7 @@ import { isIdOrUUIDValid } from '../../helpers/custom-validators/misc'
7import { 7import {
8 isAvatarFile, 8 isAvatarFile,
9 isUserAutoPlayVideoValid, 9 isUserAutoPlayVideoValid,
10 isUserDescriptionValid, 10 isUserDescriptionValid, isUserDisplayNameValid,
11 isUserNSFWPolicyValid, 11 isUserNSFWPolicyValid,
12 isUserPasswordValid, 12 isUserPasswordValid,
13 isUserRoleValid, 13 isUserRoleValid,
@@ -98,6 +98,7 @@ const usersUpdateValidator = [
98] 98]
99 99
100const usersUpdateMeValidator = [ 100const usersUpdateMeValidator = [
101 body('displayName').optional().custom(isUserDisplayNameValid).withMessage('Should have a valid display name'),
101 body('description').optional().custom(isUserDescriptionValid).withMessage('Should have a valid description'), 102 body('description').optional().custom(isUserDescriptionValid).withMessage('Should have a valid description'),
102 body('password').optional().custom(isUserPasswordValid).withMessage('Should have a valid password'), 103 body('password').optional().custom(isUserPasswordValid).withMessage('Should have a valid password'),
103 body('email').optional().isEmail().withMessage('Should have a valid email attribute'), 104 body('email').optional().isEmail().withMessage('Should have a valid email attribute'),
diff --git a/server/tests/api/users/users-multiple-servers.ts b/server/tests/api/users/users-multiple-servers.ts
index a7f3aa8d3..8b9b63348 100644
--- a/server/tests/api/users/users-multiple-servers.ts
+++ b/server/tests/api/users/users-multiple-servers.ts
@@ -76,6 +76,22 @@ describe('Test users with multiple servers', function () {
76 await wait(5000) 76 await wait(5000)
77 }) 77 })
78 78
79 it('Should be able to update my display name', async function () {
80 this.timeout(10000)
81
82 await updateMyUser({
83 url: servers[0].url,
84 accessToken: servers[0].accessToken,
85 displayName: 'my super display name'
86 })
87
88 const res = await getMyUserInformation(servers[0].url, servers[0].accessToken)
89 user = res.body
90 expect(user.account.displayName).to.equal('my super display name')
91
92 await wait(5000)
93 })
94
79 it('Should be able to update my description', async function () { 95 it('Should be able to update my description', async function () {
80 this.timeout(10000) 96 this.timeout(10000)
81 97
@@ -87,6 +103,7 @@ describe('Test users with multiple servers', function () {
87 103
88 const res = await getMyUserInformation(servers[0].url, servers[0].accessToken) 104 const res = await getMyUserInformation(servers[0].url, servers[0].accessToken)
89 user = res.body 105 user = res.body
106 expect(user.account.displayName).to.equal('my super display name')
90 expect(user.account.description).to.equal('my super description updated') 107 expect(user.account.description).to.equal('my super description updated')
91 108
92 await wait(5000) 109 await wait(5000)
@@ -111,7 +128,7 @@ describe('Test users with multiple servers', function () {
111 await wait(5000) 128 await wait(5000)
112 }) 129 })
113 130
114 it('Should have updated my avatar and my description on other servers too', async function () { 131 it('Should have updated my profile on other servers too', async function () {
115 for (const server of servers) { 132 for (const server of servers) {
116 const resAccounts = await getAccountsList(server.url, '-createdAt') 133 const resAccounts = await getAccountsList(server.url, '-createdAt')
117 134
@@ -122,6 +139,7 @@ describe('Test users with multiple servers', function () {
122 const rootServer1Get = resAccount.body as Account 139 const rootServer1Get = resAccount.body as Account
123 expect(rootServer1Get.name).to.equal('root') 140 expect(rootServer1Get.name).to.equal('root')
124 expect(rootServer1Get.host).to.equal('localhost:9001') 141 expect(rootServer1Get.host).to.equal('localhost:9001')
142 expect(rootServer1Get.displayName).to.equal('my super display name')
125 expect(rootServer1Get.description).to.equal('my super description updated') 143 expect(rootServer1Get.description).to.equal('my super description updated')
126 144
127 await testImage(server.url, 'avatar2-resized', rootServer1Get.avatar.path, '.png') 145 await testImage(server.url, 'avatar2-resized', rootServer1Get.avatar.path, '.png')
diff --git a/server/tests/api/users/users.ts b/server/tests/api/users/users.ts
index 1192ef9e4..1ea599859 100644
--- a/server/tests/api/users/users.ts
+++ b/server/tests/api/users/users.ts
@@ -172,6 +172,7 @@ describe('Test users', function () {
172 expect(user.videoQuota).to.equal(2 * 1024 * 1024) 172 expect(user.videoQuota).to.equal(2 * 1024 * 1024)
173 expect(user.roleLabel).to.equal('User') 173 expect(user.roleLabel).to.equal('User')
174 expect(user.id).to.be.a('number') 174 expect(user.id).to.be.a('number')
175 expect(user.account.displayName).to.equal('user_1')
175 expect(user.account.description).to.be.null 176 expect(user.account.description).to.be.null
176 }) 177 })
177 178
@@ -316,6 +317,7 @@ describe('Test users', function () {
316 expect(user.nsfwPolicy).to.equal('do_not_list') 317 expect(user.nsfwPolicy).to.equal('do_not_list')
317 expect(user.videoQuota).to.equal(2 * 1024 * 1024) 318 expect(user.videoQuota).to.equal(2 * 1024 * 1024)
318 expect(user.id).to.be.a('number') 319 expect(user.id).to.be.a('number')
320 expect(user.account.displayName).to.equal('user_1')
319 expect(user.account.description).to.be.null 321 expect(user.account.description).to.be.null
320 }) 322 })
321 323
@@ -347,6 +349,7 @@ describe('Test users', function () {
347 expect(user.nsfwPolicy).to.equal('do_not_list') 349 expect(user.nsfwPolicy).to.equal('do_not_list')
348 expect(user.videoQuota).to.equal(2 * 1024 * 1024) 350 expect(user.videoQuota).to.equal(2 * 1024 * 1024)
349 expect(user.id).to.be.a('number') 351 expect(user.id).to.be.a('number')
352 expect(user.account.displayName).to.equal('user_1')
350 expect(user.account.description).to.be.null 353 expect(user.account.description).to.be.null
351 }) 354 })
352 355
@@ -365,6 +368,25 @@ describe('Test users', function () {
365 await testImage(server.url, 'avatar-resized', user.account.avatar.path, '.png') 368 await testImage(server.url, 'avatar-resized', user.account.avatar.path, '.png')
366 }) 369 })
367 370
371 it('Should be able to update my display name', async function () {
372 await updateMyUser({
373 url: server.url,
374 accessToken: accessTokenUser,
375 displayName: 'new display name'
376 })
377
378 const res = await getMyUserInformation(server.url, accessTokenUser)
379 const user = res.body
380
381 expect(user.username).to.equal('user_1')
382 expect(user.email).to.equal('updated@example.com')
383 expect(user.nsfwPolicy).to.equal('do_not_list')
384 expect(user.videoQuota).to.equal(2 * 1024 * 1024)
385 expect(user.id).to.be.a('number')
386 expect(user.account.displayName).to.equal('new display name')
387 expect(user.account.description).to.be.null
388 })
389
368 it('Should be able to update my description', async function () { 390 it('Should be able to update my description', async function () {
369 await updateMyUser({ 391 await updateMyUser({
370 url: server.url, 392 url: server.url,
@@ -380,6 +402,7 @@ describe('Test users', function () {
380 expect(user.nsfwPolicy).to.equal('do_not_list') 402 expect(user.nsfwPolicy).to.equal('do_not_list')
381 expect(user.videoQuota).to.equal(2 * 1024 * 1024) 403 expect(user.videoQuota).to.equal(2 * 1024 * 1024)
382 expect(user.id).to.be.a('number') 404 expect(user.id).to.be.a('number')
405 expect(user.account.displayName).to.equal('new display name')
383 expect(user.account.description).to.equal('my super description updated') 406 expect(user.account.description).to.equal('my super description updated')
384 }) 407 })
385 408
diff --git a/server/tests/utils/users/users.ts b/server/tests/utils/users/users.ts
index fc6b26c50..d31e57a25 100644
--- a/server/tests/utils/users/users.ts
+++ b/server/tests/utils/users/users.ts
@@ -132,6 +132,7 @@ function updateMyUser (options: {
132 nsfwPolicy?: NSFWPolicyType, 132 nsfwPolicy?: NSFWPolicyType,
133 email?: string, 133 email?: string,
134 autoPlayVideo?: boolean 134 autoPlayVideo?: boolean
135 displayName?: string,
135 description?: string 136 description?: string
136}) { 137}) {
137 const path = '/api/v1/users/me' 138 const path = '/api/v1/users/me'
@@ -142,6 +143,7 @@ function updateMyUser (options: {
142 if (options.autoPlayVideo !== undefined && options.autoPlayVideo !== null) toSend['autoPlayVideo'] = options.autoPlayVideo 143 if (options.autoPlayVideo !== undefined && options.autoPlayVideo !== null) toSend['autoPlayVideo'] = options.autoPlayVideo
143 if (options.email !== undefined && options.email !== null) toSend['email'] = options.email 144 if (options.email !== undefined && options.email !== null) toSend['email'] = options.email
144 if (options.description !== undefined && options.description !== null) toSend['description'] = options.description 145 if (options.description !== undefined && options.description !== null) toSend['description'] = options.description
146 if (options.displayName !== undefined && options.displayName !== null) toSend['displayName'] = options.displayName
145 147
146 return makePutBodyRequest({ 148 return makePutBodyRequest({
147 url: options.url, 149 url: options.url,
diff --git a/shared/models/users/user-update-me.model.ts b/shared/models/users/user-update-me.model.ts
index 0a73879ed..ddab837fe 100644
--- a/shared/models/users/user-update-me.model.ts
+++ b/shared/models/users/user-update-me.model.ts
@@ -1,6 +1,7 @@
1import { NSFWPolicyType } from '../videos/nsfw-policy.type' 1import { NSFWPolicyType } from '../videos/nsfw-policy.type'
2 2
3export interface UserUpdateMe { 3export interface UserUpdateMe {
4 displayName?: string
4 description?: string 5 description?: string
5 nsfwPolicy?: NSFWPolicyType 6 nsfwPolicy?: NSFWPolicyType
6 autoPlayVideo?: boolean 7 autoPlayVideo?: boolean