aboutsummaryrefslogtreecommitdiffhomepage
path: root/server
diff options
context:
space:
mode:
authorChocobozzz <me@florianbigard.com>2019-06-07 16:59:53 +0200
committerChocobozzz <me@florianbigard.com>2019-06-07 17:05:42 +0200
commit1f20622f2b087eaf8738d60fae00a44b9c558ca3 (patch)
tree1c8554623665ca96b8a1e6f2a6bcb8c1b5a83c2e /server
parent1a03bea0c42fa1064ce4770157b4fd2e3edd5565 (diff)
downloadPeerTube-1f20622f2b087eaf8738d60fae00a44b9c558ca3.tar.gz
PeerTube-1f20622f2b087eaf8738d60fae00a44b9c558ca3.tar.zst
PeerTube-1f20622f2b087eaf8738d60fae00a44b9c558ca3.zip
Improve registration
* Add ability to set the user display name * Use display name to guess the username/channel name * Add explanations about what is the purpose of a username/channel name * Add a loader at the "done" step
Diffstat (limited to 'server')
-rw-r--r--server/controllers/api/users/index.ts8
-rw-r--r--server/initializers/installer.ts2
-rw-r--r--server/initializers/migrations/0100-activitypub.ts9
-rw-r--r--server/lib/user.ts41
-rw-r--r--server/middlewares/validators/users.ts12
-rw-r--r--server/tests/api/check-params/users.ts7
-rw-r--r--server/tests/api/users/users.ts15
-rw-r--r--server/tests/api/videos/video-playlists.ts1
8 files changed, 73 insertions, 22 deletions
diff --git a/server/controllers/api/users/index.ts b/server/controllers/api/users/index.ts
index 48a6c63b8..99f51a648 100644
--- a/server/controllers/api/users/index.ts
+++ b/server/controllers/api/users/index.ts
@@ -184,7 +184,7 @@ async function createUser (req: express.Request, res: express.Response) {
184 adminFlags: body.adminFlags || UserAdminFlag.NONE 184 adminFlags: body.adminFlags || UserAdminFlag.NONE
185 }) 185 })
186 186
187 const { user, account } = await createUserAccountAndChannelAndPlaylist(userToCreate) 187 const { user, account } = await createUserAccountAndChannelAndPlaylist({ userToCreate: userToCreate })
188 188
189 auditLogger.create(getAuditIdFromRes(res), new UserAuditView(user.toFormattedJSON())) 189 auditLogger.create(getAuditIdFromRes(res), new UserAuditView(user.toFormattedJSON()))
190 logger.info('User %s with its channel and account created.', body.username) 190 logger.info('User %s with its channel and account created.', body.username)
@@ -214,7 +214,11 @@ async function registerUser (req: express.Request, res: express.Response) {
214 emailVerified: CONFIG.SIGNUP.REQUIRES_EMAIL_VERIFICATION ? false : null 214 emailVerified: CONFIG.SIGNUP.REQUIRES_EMAIL_VERIFICATION ? false : null
215 }) 215 })
216 216
217 const { user } = await createUserAccountAndChannelAndPlaylist(userToCreate, body.channel) 217 const { user } = await createUserAccountAndChannelAndPlaylist({
218 userToCreate: userToCreate,
219 userDisplayName: body.displayName || undefined,
220 channelNames: body.channel
221 })
218 222
219 auditLogger.create(body.username, new UserAuditView(user.toFormattedJSON())) 223 auditLogger.create(body.username, new UserAuditView(user.toFormattedJSON()))
220 logger.info('User %s with its channel and account registered.', body.username) 224 logger.info('User %s with its channel and account registered.', body.username)
diff --git a/server/initializers/installer.ts b/server/initializers/installer.ts
index e14554ede..cb58454cb 100644
--- a/server/initializers/installer.ts
+++ b/server/initializers/installer.ts
@@ -146,7 +146,7 @@ async function createOAuthAdminIfNotExist () {
146 } 146 }
147 const user = new UserModel(userData) 147 const user = new UserModel(userData)
148 148
149 await createUserAccountAndChannelAndPlaylist(user, undefined, validatePassword) 149 await createUserAccountAndChannelAndPlaylist({ userToCreate: user, channelNames: undefined, validateUser: validatePassword })
150 logger.info('Username: ' + username) 150 logger.info('Username: ' + username)
151 logger.info('User password: ' + password) 151 logger.info('User password: ' + password)
152} 152}
diff --git a/server/initializers/migrations/0100-activitypub.ts b/server/initializers/migrations/0100-activitypub.ts
index 2880a97d9..96d44a7ce 100644
--- a/server/initializers/migrations/0100-activitypub.ts
+++ b/server/initializers/migrations/0100-activitypub.ts
@@ -65,7 +65,12 @@ async function up (utils: {
65 // Create application account 65 // Create application account
66 { 66 {
67 const applicationInstance = await ApplicationModel.findOne() 67 const applicationInstance = await ApplicationModel.findOne()
68 const accountCreated = await createLocalAccountWithoutKeys(SERVER_ACTOR_NAME, null, applicationInstance.id, undefined) 68 const accountCreated = await createLocalAccountWithoutKeys({
69 name: SERVER_ACTOR_NAME,
70 userId: null,
71 applicationId: applicationInstance.id,
72 t: undefined
73 })
69 74
70 const { publicKey, privateKey } = await createPrivateAndPublicKeys() 75 const { publicKey, privateKey } = await createPrivateAndPublicKeys()
71 accountCreated.Actor.publicKey = publicKey 76 accountCreated.Actor.publicKey = publicKey
@@ -83,7 +88,7 @@ async function up (utils: {
83 // Recreate accounts for each user 88 // Recreate accounts for each user
84 const users = await db.User.findAll() 89 const users = await db.User.findAll()
85 for (const user of users) { 90 for (const user of users) {
86 const account = await createLocalAccountWithoutKeys(user.username, user.id, null, undefined) 91 const account = await createLocalAccountWithoutKeys({ name: user.username, userId: user.id, applicationId: null, t: undefined })
87 92
88 const { publicKey, privateKey } = await createPrivateAndPublicKeys() 93 const { publicKey, privateKey } = await createPrivateAndPublicKeys()
89 account.Actor.publicKey = publicKey 94 account.Actor.publicKey = publicKey
diff --git a/server/lib/user.ts b/server/lib/user.ts
index d9fd89e15..b50b09d72 100644
--- a/server/lib/user.ts
+++ b/server/lib/user.ts
@@ -1,4 +1,3 @@
1import * as Sequelize from 'sequelize'
2import * as uuidv4 from 'uuid/v4' 1import * as uuidv4 from 'uuid/v4'
3import { ActivityPubActorType } from '../../shared/models/activitypub' 2import { ActivityPubActorType } from '../../shared/models/activitypub'
4import { SERVER_ACTOR_NAME } from '../initializers/constants' 3import { SERVER_ACTOR_NAME } from '../initializers/constants'
@@ -12,9 +11,17 @@ import { UserNotificationSettingModel } from '../models/account/user-notificatio
12import { UserNotificationSetting, UserNotificationSettingValue } from '../../shared/models/users' 11import { UserNotificationSetting, UserNotificationSettingValue } from '../../shared/models/users'
13import { createWatchLaterPlaylist } from './video-playlist' 12import { createWatchLaterPlaylist } from './video-playlist'
14import { sequelizeTypescript } from '../initializers/database' 13import { sequelizeTypescript } from '../initializers/database'
14import { Transaction } from 'sequelize/types'
15 15
16type ChannelNames = { name: string, displayName: string } 16type ChannelNames = { name: string, displayName: string }
17async function createUserAccountAndChannelAndPlaylist (userToCreate: UserModel, channelNames?: ChannelNames, validateUser = true) { 17async function createUserAccountAndChannelAndPlaylist (parameters: {
18 userToCreate: UserModel,
19 userDisplayName?: string,
20 channelNames?: ChannelNames,
21 validateUser?: boolean
22}) {
23 const { userToCreate, userDisplayName, channelNames, validateUser = true } = parameters
24
18 const { user, account, videoChannel } = await sequelizeTypescript.transaction(async t => { 25 const { user, account, videoChannel } = await sequelizeTypescript.transaction(async t => {
19 const userOptions = { 26 const userOptions = {
20 transaction: t, 27 transaction: t,
@@ -24,7 +31,13 @@ async function createUserAccountAndChannelAndPlaylist (userToCreate: UserModel,
24 const userCreated = await userToCreate.save(userOptions) 31 const userCreated = await userToCreate.save(userOptions)
25 userCreated.NotificationSetting = await createDefaultUserNotificationSettings(userCreated, t) 32 userCreated.NotificationSetting = await createDefaultUserNotificationSettings(userCreated, t)
26 33
27 const accountCreated = await createLocalAccountWithoutKeys(userCreated.username, userCreated.id, null, t) 34 const accountCreated = await createLocalAccountWithoutKeys({
35 name: userCreated.username,
36 displayName: userDisplayName,
37 userId: userCreated.id,
38 applicationId: null,
39 t: t
40 })
28 userCreated.Account = accountCreated 41 userCreated.Account = accountCreated
29 42
30 const channelAttributes = await buildChannelAttributes(userCreated, channelNames) 43 const channelAttributes = await buildChannelAttributes(userCreated, channelNames)
@@ -46,20 +59,22 @@ async function createUserAccountAndChannelAndPlaylist (userToCreate: UserModel,
46 return { user, account, videoChannel } as { user: UserModel, account: AccountModel, videoChannel: VideoChannelModel } 59 return { user, account, videoChannel } as { user: UserModel, account: AccountModel, videoChannel: VideoChannelModel }
47} 60}
48 61
49async function createLocalAccountWithoutKeys ( 62async function createLocalAccountWithoutKeys (parameters: {
50 name: string, 63 name: string,
64 displayName?: string,
51 userId: number | null, 65 userId: number | null,
52 applicationId: number | null, 66 applicationId: number | null,
53 t: Sequelize.Transaction | undefined, 67 t: Transaction | undefined,
54 type: ActivityPubActorType= 'Person' 68 type?: ActivityPubActorType
55) { 69}) {
70 const { name, displayName, userId, applicationId, t, type = 'Person' } = parameters
56 const url = getAccountActivityPubUrl(name) 71 const url = getAccountActivityPubUrl(name)
57 72
58 const actorInstance = buildActorInstance(type, url, name) 73 const actorInstance = buildActorInstance(type, url, name)
59 const actorInstanceCreated = await actorInstance.save({ transaction: t }) 74 const actorInstanceCreated = await actorInstance.save({ transaction: t })
60 75
61 const accountInstance = new AccountModel({ 76 const accountInstance = new AccountModel({
62 name, 77 name: displayName || name,
63 userId, 78 userId,
64 applicationId, 79 applicationId,
65 actorId: actorInstanceCreated.id 80 actorId: actorInstanceCreated.id
@@ -72,7 +87,13 @@ async function createLocalAccountWithoutKeys (
72} 87}
73 88
74async function createApplicationActor (applicationId: number) { 89async function createApplicationActor (applicationId: number) {
75 const accountCreated = await createLocalAccountWithoutKeys(SERVER_ACTOR_NAME, null, applicationId, undefined, 'Application') 90 const accountCreated = await createLocalAccountWithoutKeys({
91 name: SERVER_ACTOR_NAME,
92 userId: null,
93 applicationId: applicationId,
94 t: undefined,
95 type: 'Application'
96 })
76 97
77 accountCreated.Actor = await setAsyncActorKeys(accountCreated.Actor) 98 accountCreated.Actor = await setAsyncActorKeys(accountCreated.Actor)
78 99
@@ -89,7 +110,7 @@ export {
89 110
90// --------------------------------------------------------------------------- 111// ---------------------------------------------------------------------------
91 112
92function createDefaultUserNotificationSettings (user: UserModel, t: Sequelize.Transaction | undefined) { 113function createDefaultUserNotificationSettings (user: UserModel, t: Transaction | undefined) {
93 const values: UserNotificationSetting & { userId: number } = { 114 const values: UserNotificationSetting & { userId: number } = {
94 userId: user.id, 115 userId: user.id,
95 newVideoFromSubscription: UserNotificationSettingValue.WEB, 116 newVideoFromSubscription: UserNotificationSettingValue.WEB,
diff --git a/server/middlewares/validators/users.ts b/server/middlewares/validators/users.ts
index 7a081af33..b4e09c9b7 100644
--- a/server/middlewares/validators/users.ts
+++ b/server/middlewares/validators/users.ts
@@ -53,8 +53,16 @@ const usersRegisterValidator = [
53 body('username').custom(isUserUsernameValid).withMessage('Should have a valid username'), 53 body('username').custom(isUserUsernameValid).withMessage('Should have a valid username'),
54 body('password').custom(isUserPasswordValid).withMessage('Should have a valid password'), 54 body('password').custom(isUserPasswordValid).withMessage('Should have a valid password'),
55 body('email').isEmail().withMessage('Should have a valid email'), 55 body('email').isEmail().withMessage('Should have a valid email'),
56 body('channel.name').optional().custom(isActorPreferredUsernameValid).withMessage('Should have a valid channel name'), 56 body('displayName')
57 body('channel.displayName').optional().custom(isVideoChannelNameValid).withMessage('Should have a valid display name'), 57 .optional()
58 .custom(isUserDisplayNameValid).withMessage('Should have a valid display name'),
59
60 body('channel.name')
61 .optional()
62 .custom(isActorPreferredUsernameValid).withMessage('Should have a valid channel name'),
63 body('channel.displayName')
64 .optional()
65 .custom(isVideoChannelNameValid).withMessage('Should have a valid display name'),
58 66
59 async (req: express.Request, res: express.Response, next: express.NextFunction) => { 67 async (req: express.Request, res: express.Response, next: express.NextFunction) => {
60 logger.debug('Checking usersRegister parameters', { parameters: omit(req.body, 'password') }) 68 logger.debug('Checking usersRegister parameters', { parameters: omit(req.body, 'password') })
diff --git a/server/tests/api/check-params/users.ts b/server/tests/api/check-params/users.ts
index 95097817b..3268f8c90 100644
--- a/server/tests/api/check-params/users.ts
+++ b/server/tests/api/check-params/users.ts
@@ -643,6 +643,7 @@ describe('Test users API validators', function () {
643 const registrationPath = path + '/register' 643 const registrationPath = path + '/register'
644 const baseCorrectParams = { 644 const baseCorrectParams = {
645 username: 'user3', 645 username: 'user3',
646 displayName: 'super user',
646 email: 'test3@example.com', 647 email: 'test3@example.com',
647 password: 'my super password' 648 password: 'my super password'
648 } 649 }
@@ -725,6 +726,12 @@ describe('Test users API validators', function () {
725 }) 726 })
726 }) 727 })
727 728
729 it('Should fail with a bad display name', async function () {
730 const fields = immutableAssign(baseCorrectParams, { displayName: 'a'.repeat(150) })
731
732 await makePostBodyRequest({ url: server.url, path: registrationPath, token: server.accessToken, fields })
733 })
734
728 it('Should fail with a bad channel name', async function () { 735 it('Should fail with a bad channel name', async function () {
729 const fields = immutableAssign(baseCorrectParams, { channel: { name: '[]azf', displayName: 'toto' } }) 736 const fields = immutableAssign(baseCorrectParams, { channel: { name: '[]azf', displayName: 'toto' } })
730 737
diff --git a/server/tests/api/users/users.ts b/server/tests/api/users/users.ts
index 9d2ef786f..b1f214fe2 100644
--- a/server/tests/api/users/users.ts
+++ b/server/tests/api/users/users.ts
@@ -17,11 +17,12 @@ import {
17 getUserInformation, 17 getUserInformation,
18 getUsersList, 18 getUsersList,
19 getUsersListPaginationAndSort, 19 getUsersListPaginationAndSort,
20 getVideoChannel,
20 getVideosList, 21 getVideosList,
21 login, 22 login,
22 makePutBodyRequest, 23 makePutBodyRequest,
23 rateVideo, 24 rateVideo,
24 registerUser, 25 registerUserWithChannel,
25 removeUser, 26 removeUser,
26 removeVideo, 27 removeVideo,
27 ServerInfo, 28 ServerInfo,
@@ -31,8 +32,7 @@ import {
31 updateMyUser, 32 updateMyUser,
32 updateUser, 33 updateUser,
33 uploadVideo, 34 uploadVideo,
34 userLogin, 35 userLogin
35 registerUserWithChannel, getVideoChannel
36} from '../../../../shared/extra-utils' 36} from '../../../../shared/extra-utils'
37import { follow } from '../../../../shared/extra-utils/server/follows' 37import { follow } from '../../../../shared/extra-utils/server/follows'
38import { setAccessTokensToServers } from '../../../../shared/extra-utils/users/login' 38import { setAccessTokensToServers } from '../../../../shared/extra-utils/users/login'
@@ -618,7 +618,7 @@ describe('Test users', function () {
618 618
619 describe('Registering a new user', function () { 619 describe('Registering a new user', function () {
620 it('Should register a new user', async function () { 620 it('Should register a new user', async function () {
621 const user = { username: 'user_15', password: 'my super password' } 621 const user = { displayName: 'super user 15', username: 'user_15', password: 'my super password' }
622 const channel = { name: 'my_user_15_channel', displayName: 'my channel rocks' } 622 const channel = { name: 'my_user_15_channel', displayName: 'my channel rocks' }
623 623
624 await registerUserWithChannel({ url: server.url, user, channel }) 624 await registerUserWithChannel({ url: server.url, user, channel })
@@ -633,6 +633,13 @@ describe('Test users', function () {
633 accessToken = await userLogin(server, user15) 633 accessToken = await userLogin(server, user15)
634 }) 634 })
635 635
636 it('Should have the correct display name', async function () {
637 const res = await getMyUserInformation(server.url, accessToken)
638 const user: User = res.body
639
640 expect(user.account.displayName).to.equal('super user 15')
641 })
642
636 it('Should have the correct video quota', async function () { 643 it('Should have the correct video quota', async function () {
637 const res = await getMyUserInformation(server.url, accessToken) 644 const res = await getMyUserInformation(server.url, accessToken)
638 const user = res.body 645 const user = res.body
diff --git a/server/tests/api/videos/video-playlists.ts b/server/tests/api/videos/video-playlists.ts
index 8690327c4..f82c8cbce 100644
--- a/server/tests/api/videos/video-playlists.ts
+++ b/server/tests/api/videos/video-playlists.ts
@@ -754,7 +754,6 @@ describe('Test video playlists', function () {
754 } 754 }
755 }) 755 })
756 756
757
758 it('Should be able to create a public playlist, and set it to private', async function () { 757 it('Should be able to create a public playlist, and set it to private', async function () {
759 this.timeout(30000) 758 this.timeout(30000)
760 759