diff options
author | Chocobozzz <me@florianbigard.com> | 2018-02-15 14:46:26 +0100 |
---|---|---|
committer | Chocobozzz <me@florianbigard.com> | 2018-02-15 15:29:07 +0100 |
commit | 2422c46b27790d94fd29a7092170cee5a1b56008 (patch) | |
tree | d5c1942ce20cadb27a551d87c789edfe92f5b105 /server | |
parent | 34cbef8c6cc912143a421413bdd832c4adcc556a (diff) | |
download | PeerTube-2422c46b27790d94fd29a7092170cee5a1b56008.tar.gz PeerTube-2422c46b27790d94fd29a7092170cee5a1b56008.tar.zst PeerTube-2422c46b27790d94fd29a7092170cee5a1b56008.zip |
Implement support field in video and video channel
Diffstat (limited to 'server')
37 files changed, 472 insertions, 138 deletions
diff --git a/server/controllers/api/users.ts b/server/controllers/api/users.ts index e3067584e..583376c38 100644 --- a/server/controllers/api/users.ts +++ b/server/controllers/api/users.ts | |||
@@ -9,7 +9,7 @@ import { logger } from '../../helpers/logger' | |||
9 | import { createReqFiles, getFormattedObjects } from '../../helpers/utils' | 9 | import { createReqFiles, getFormattedObjects } from '../../helpers/utils' |
10 | import { AVATARS_SIZE, CONFIG, IMAGE_MIMETYPE_EXT, sequelizeTypescript } from '../../initializers' | 10 | import { AVATARS_SIZE, CONFIG, IMAGE_MIMETYPE_EXT, sequelizeTypescript } from '../../initializers' |
11 | import { updateActorAvatarInstance } from '../../lib/activitypub' | 11 | import { updateActorAvatarInstance } from '../../lib/activitypub' |
12 | import { sendUpdateUser } from '../../lib/activitypub/send' | 12 | import { sendUpdateActor } from '../../lib/activitypub/send' |
13 | import { Emailer } from '../../lib/emailer' | 13 | import { Emailer } from '../../lib/emailer' |
14 | import { Redis } from '../../lib/redis' | 14 | import { Redis } from '../../lib/redis' |
15 | import { createUserAccountAndChannel } from '../../lib/user' | 15 | import { createUserAccountAndChannel } from '../../lib/user' |
@@ -270,15 +270,21 @@ async function removeUser (req: express.Request, res: express.Response, next: ex | |||
270 | async function updateMe (req: express.Request, res: express.Response, next: express.NextFunction) { | 270 | async function updateMe (req: express.Request, res: express.Response, next: express.NextFunction) { |
271 | const body: UserUpdateMe = req.body | 271 | const body: UserUpdateMe = req.body |
272 | 272 | ||
273 | const user = res.locals.oauth.token.user | 273 | const user: UserModel = res.locals.oauth.token.user |
274 | 274 | ||
275 | if (body.password !== undefined) user.password = body.password | 275 | if (body.password !== undefined) user.password = body.password |
276 | if (body.email !== undefined) user.email = body.email | 276 | if (body.email !== undefined) user.email = body.email |
277 | if (body.displayNSFW !== undefined) user.displayNSFW = body.displayNSFW | 277 | if (body.displayNSFW !== undefined) user.displayNSFW = body.displayNSFW |
278 | if (body.autoPlayVideo !== undefined) user.autoPlayVideo = body.autoPlayVideo | 278 | if (body.autoPlayVideo !== undefined) user.autoPlayVideo = body.autoPlayVideo |
279 | 279 | ||
280 | await user.save() | 280 | await sequelizeTypescript.transaction(async t => { |
281 | await sendUpdateUser(user, undefined) | 281 | await user.save({ transaction: t }) |
282 | |||
283 | if (body.description !== undefined) user.Account.description = body.description | ||
284 | await user.Account.save({ transaction: t }) | ||
285 | |||
286 | await sendUpdateActor(user.Account, t) | ||
287 | }) | ||
282 | 288 | ||
283 | return res.sendStatus(204) | 289 | return res.sendStatus(204) |
284 | } | 290 | } |
@@ -297,7 +303,7 @@ async function updateMyAvatar (req: express.Request, res: express.Response, next | |||
297 | const updatedActor = await updateActorAvatarInstance(actor, avatarName, t) | 303 | const updatedActor = await updateActorAvatarInstance(actor, avatarName, t) |
298 | await updatedActor.save({ transaction: t }) | 304 | await updatedActor.save({ transaction: t }) |
299 | 305 | ||
300 | await sendUpdateUser(user, t) | 306 | await sendUpdateActor(user.Account, t) |
301 | 307 | ||
302 | return updatedActor.Avatar | 308 | return updatedActor.Avatar |
303 | }) | 309 | }) |
diff --git a/server/controllers/api/videos/channel.ts b/server/controllers/api/videos/channel.ts index 8ec53d9ae..fba5681de 100644 --- a/server/controllers/api/videos/channel.ts +++ b/server/controllers/api/videos/channel.ts | |||
@@ -5,6 +5,7 @@ import { logger } from '../../../helpers/logger' | |||
5 | import { getFormattedObjects, resetSequelizeInstance } from '../../../helpers/utils' | 5 | import { getFormattedObjects, resetSequelizeInstance } from '../../../helpers/utils' |
6 | import { sequelizeTypescript } from '../../../initializers' | 6 | import { sequelizeTypescript } from '../../../initializers' |
7 | import { setAsyncActorKeys } from '../../../lib/activitypub' | 7 | import { setAsyncActorKeys } from '../../../lib/activitypub' |
8 | import { sendUpdateActor } from '../../../lib/activitypub/send' | ||
8 | import { createVideoChannel } from '../../../lib/video-channel' | 9 | import { createVideoChannel } from '../../../lib/video-channel' |
9 | import { | 10 | import { |
10 | asyncMiddleware, authenticate, listVideoAccountChannelsValidator, paginationValidator, setDefaultSort, setDefaultPagination, | 11 | asyncMiddleware, authenticate, listVideoAccountChannelsValidator, paginationValidator, setDefaultSort, setDefaultPagination, |
@@ -80,23 +81,28 @@ async function addVideoChannelRetryWrapper (req: express.Request, res: express.R | |||
80 | errorMessage: 'Cannot insert the video video channel with many retries.' | 81 | errorMessage: 'Cannot insert the video video channel with many retries.' |
81 | } | 82 | } |
82 | 83 | ||
83 | await retryTransactionWrapper(addVideoChannel, options) | 84 | const videoChannel = await retryTransactionWrapper(addVideoChannel, options) |
84 | 85 | return res.json({ | |
85 | // TODO : include Location of the new video channel -> 201 | 86 | videoChannel: { |
86 | return res.type('json').status(204).end() | 87 | id: videoChannel.id |
88 | } | ||
89 | }).end() | ||
87 | } | 90 | } |
88 | 91 | ||
89 | async function addVideoChannel (req: express.Request, res: express.Response) { | 92 | async function addVideoChannel (req: express.Request, res: express.Response) { |
90 | const videoChannelInfo: VideoChannelCreate = req.body | 93 | const videoChannelInfo: VideoChannelCreate = req.body |
91 | const account: AccountModel = res.locals.oauth.token.User.Account | 94 | const account: AccountModel = res.locals.oauth.token.User.Account |
92 | 95 | ||
93 | const videoChannelCreated = await sequelizeTypescript.transaction(async t => { | 96 | const videoChannelCreated: VideoChannelModel = await sequelizeTypescript.transaction(async t => { |
94 | return createVideoChannel(videoChannelInfo, account, t) | 97 | return createVideoChannel(videoChannelInfo, account, t) |
95 | }) | 98 | }) |
96 | 99 | ||
97 | setAsyncActorKeys(videoChannelCreated.Actor) | 100 | setAsyncActorKeys(videoChannelCreated.Actor) |
101 | .catch(err => logger.error('Cannot set async actor keys for account %s.', videoChannelCreated.Actor.uuid, err)) | ||
98 | 102 | ||
99 | logger.info('Video channel with uuid %s created.', videoChannelCreated.Actor.uuid) | 103 | logger.info('Video channel with uuid %s created.', videoChannelCreated.Actor.uuid) |
104 | |||
105 | return videoChannelCreated | ||
100 | } | 106 | } |
101 | 107 | ||
102 | async function updateVideoChannelRetryWrapper (req: express.Request, res: express.Response, next: express.NextFunction) { | 108 | async function updateVideoChannelRetryWrapper (req: express.Request, res: express.Response, next: express.NextFunction) { |
@@ -123,11 +129,10 @@ async function updateVideoChannel (req: express.Request, res: express.Response) | |||
123 | 129 | ||
124 | if (videoChannelInfoToUpdate.name !== undefined) videoChannelInstance.set('name', videoChannelInfoToUpdate.name) | 130 | if (videoChannelInfoToUpdate.name !== undefined) videoChannelInstance.set('name', videoChannelInfoToUpdate.name) |
125 | if (videoChannelInfoToUpdate.description !== undefined) videoChannelInstance.set('description', videoChannelInfoToUpdate.description) | 131 | if (videoChannelInfoToUpdate.description !== undefined) videoChannelInstance.set('description', videoChannelInfoToUpdate.description) |
132 | if (videoChannelInfoToUpdate.support !== undefined) videoChannelInstance.set('support', videoChannelInfoToUpdate.support) | ||
126 | 133 | ||
127 | await videoChannelInstance.save(sequelizeOptions) | 134 | const videoChannelInstanceUpdated = await videoChannelInstance.save(sequelizeOptions) |
128 | 135 | await sendUpdateActor(videoChannelInstanceUpdated, t) | |
129 | // TODO | ||
130 | // await sendUpdateVideoChannel(videoChannelInstanceUpdated, t) | ||
131 | }) | 136 | }) |
132 | 137 | ||
133 | logger.info('Video channel with name %s and uuid %s updated.', videoChannelInstance.name, videoChannelInstance.Actor.uuid) | 138 | logger.info('Video channel with name %s and uuid %s updated.', videoChannelInstance.name, videoChannelInstance.Actor.uuid) |
diff --git a/server/controllers/api/videos/index.ts b/server/controllers/api/videos/index.ts index 564ccd3f8..c9334676e 100644 --- a/server/controllers/api/videos/index.ts +++ b/server/controllers/api/videos/index.ts | |||
@@ -178,6 +178,7 @@ async function addVideo (req: express.Request, res: express.Response, videoPhysi | |||
178 | commentsEnabled: videoInfo.commentsEnabled, | 178 | commentsEnabled: videoInfo.commentsEnabled, |
179 | nsfw: videoInfo.nsfw, | 179 | nsfw: videoInfo.nsfw, |
180 | description: videoInfo.description, | 180 | description: videoInfo.description, |
181 | support: videoInfo.support, | ||
181 | privacy: videoInfo.privacy, | 182 | privacy: videoInfo.privacy, |
182 | duration: videoPhysicalFile['duration'], // duration was added by a previous middleware | 183 | duration: videoPhysicalFile['duration'], // duration was added by a previous middleware |
183 | channelId: res.locals.videoChannel.id | 184 | channelId: res.locals.videoChannel.id |
@@ -306,6 +307,7 @@ async function updateVideo (req: express.Request, res: express.Response) { | |||
306 | if (videoInfoToUpdate.language !== undefined) videoInstance.set('language', videoInfoToUpdate.language) | 307 | if (videoInfoToUpdate.language !== undefined) videoInstance.set('language', videoInfoToUpdate.language) |
307 | if (videoInfoToUpdate.nsfw !== undefined) videoInstance.set('nsfw', videoInfoToUpdate.nsfw) | 308 | if (videoInfoToUpdate.nsfw !== undefined) videoInstance.set('nsfw', videoInfoToUpdate.nsfw) |
308 | if (videoInfoToUpdate.privacy !== undefined) videoInstance.set('privacy', parseInt(videoInfoToUpdate.privacy.toString(), 10)) | 309 | if (videoInfoToUpdate.privacy !== undefined) videoInstance.set('privacy', parseInt(videoInfoToUpdate.privacy.toString(), 10)) |
310 | if (videoInfoToUpdate.support !== undefined) videoInstance.set('support', videoInfoToUpdate.support) | ||
309 | if (videoInfoToUpdate.description !== undefined) videoInstance.set('description', videoInfoToUpdate.description) | 311 | if (videoInfoToUpdate.description !== undefined) videoInstance.set('description', videoInfoToUpdate.description) |
310 | if (videoInfoToUpdate.commentsEnabled !== undefined) videoInstance.set('commentsEnabled', videoInfoToUpdate.commentsEnabled) | 312 | if (videoInfoToUpdate.commentsEnabled !== undefined) videoInstance.set('commentsEnabled', videoInfoToUpdate.commentsEnabled) |
311 | 313 | ||
diff --git a/server/helpers/activitypub.ts b/server/helpers/activitypub.ts index eaee324eb..d64a6dd78 100644 --- a/server/helpers/activitypub.ts +++ b/server/helpers/activitypub.ts | |||
@@ -19,7 +19,8 @@ function activityPubContextify <T> (data: T) { | |||
19 | 'language': 'http://schema.org/inLanguage', | 19 | 'language': 'http://schema.org/inLanguage', |
20 | 'views': 'http://schema.org/Number', | 20 | 'views': 'http://schema.org/Number', |
21 | 'size': 'http://schema.org/Number', | 21 | 'size': 'http://schema.org/Number', |
22 | 'commentsEnabled': 'http://schema.org/Boolean' | 22 | 'commentsEnabled': 'http://schema.org/Boolean', |
23 | 'support': 'http://schema.org/Text' | ||
23 | }, | 24 | }, |
24 | { | 25 | { |
25 | likes: { | 26 | likes: { |
diff --git a/server/helpers/custom-validators/accounts.ts b/server/helpers/custom-validators/accounts.ts index 8dc5d1f0d..a46ffc162 100644 --- a/server/helpers/custom-validators/accounts.ts +++ b/server/helpers/custom-validators/accounts.ts | |||
@@ -3,12 +3,16 @@ import { Response } from 'express' | |||
3 | import 'express-validator' | 3 | import 'express-validator' |
4 | import * as validator from 'validator' | 4 | import * as validator from 'validator' |
5 | import { AccountModel } from '../../models/account/account' | 5 | import { AccountModel } from '../../models/account/account' |
6 | import { isUserUsernameValid } from './users' | 6 | import { isUserDescriptionValid, isUserUsernameValid } from './users' |
7 | 7 | ||
8 | function isAccountNameValid (value: string) { | 8 | function isAccountNameValid (value: string) { |
9 | return isUserUsernameValid(value) | 9 | return isUserUsernameValid(value) |
10 | } | 10 | } |
11 | 11 | ||
12 | function isAccountDescriptionValid (value: string) { | ||
13 | return isUserDescriptionValid(value) | ||
14 | } | ||
15 | |||
12 | function isAccountIdExist (id: number | string, res: Response) { | 16 | function isAccountIdExist (id: number | string, res: Response) { |
13 | let promise: Bluebird<AccountModel> | 17 | let promise: Bluebird<AccountModel> |
14 | 18 | ||
@@ -48,5 +52,6 @@ async function isAccountExist (p: Bluebird<AccountModel>, res: Response) { | |||
48 | export { | 52 | export { |
49 | isAccountIdExist, | 53 | isAccountIdExist, |
50 | isLocalAccountNameExist, | 54 | isLocalAccountNameExist, |
55 | isAccountDescriptionValid, | ||
51 | isAccountNameValid | 56 | isAccountNameValid |
52 | } | 57 | } |
diff --git a/server/helpers/custom-validators/users.ts b/server/helpers/custom-validators/users.ts index e805313f8..bbc7cc199 100644 --- a/server/helpers/custom-validators/users.ts +++ b/server/helpers/custom-validators/users.ts | |||
@@ -21,6 +21,10 @@ function isUserUsernameValid (value: string) { | |||
21 | return exists(value) && validator.matches(value, new RegExp(`^[a-z0-9._]{${min},${max}}$`)) | 21 | return exists(value) && validator.matches(value, new RegExp(`^[a-z0-9._]{${min},${max}}$`)) |
22 | } | 22 | } |
23 | 23 | ||
24 | function isUserDescriptionValid (value: string) { | ||
25 | return value === null || (exists(value) && validator.isLength(value, CONSTRAINTS_FIELDS.USERS.DESCRIPTION)) | ||
26 | } | ||
27 | |||
24 | function isBoolean (value: any) { | 28 | function isBoolean (value: any) { |
25 | return typeof value === 'boolean' || (typeof value === 'string' && validator.isBoolean(value)) | 29 | return typeof value === 'boolean' || (typeof value === 'string' && validator.isBoolean(value)) |
26 | } | 30 | } |
@@ -54,5 +58,6 @@ export { | |||
54 | isUserUsernameValid, | 58 | isUserUsernameValid, |
55 | isUserDisplayNSFWValid, | 59 | isUserDisplayNSFWValid, |
56 | isUserAutoPlayVideoValid, | 60 | isUserAutoPlayVideoValid, |
61 | isUserDescriptionValid, | ||
57 | isAvatarFile | 62 | isAvatarFile |
58 | } | 63 | } |
diff --git a/server/helpers/custom-validators/video-channels.ts b/server/helpers/custom-validators/video-channels.ts index 6bc96bf51..2a6f56840 100644 --- a/server/helpers/custom-validators/video-channels.ts +++ b/server/helpers/custom-validators/video-channels.ts | |||
@@ -16,6 +16,10 @@ function isVideoChannelNameValid (value: string) { | |||
16 | return exists(value) && validator.isLength(value, VIDEO_CHANNELS_CONSTRAINTS_FIELDS.NAME) | 16 | return exists(value) && validator.isLength(value, VIDEO_CHANNELS_CONSTRAINTS_FIELDS.NAME) |
17 | } | 17 | } |
18 | 18 | ||
19 | function isVideoChannelSupportValid (value: string) { | ||
20 | return value === null || (exists(value) && validator.isLength(value, VIDEO_CHANNELS_CONSTRAINTS_FIELDS.SUPPORT)) | ||
21 | } | ||
22 | |||
19 | async function isVideoChannelExist (id: string, res: express.Response) { | 23 | async function isVideoChannelExist (id: string, res: express.Response) { |
20 | let videoChannel: VideoChannelModel | 24 | let videoChannel: VideoChannelModel |
21 | if (validator.isInt(id)) { | 25 | if (validator.isInt(id)) { |
@@ -41,5 +45,6 @@ async function isVideoChannelExist (id: string, res: express.Response) { | |||
41 | export { | 45 | export { |
42 | isVideoChannelDescriptionValid, | 46 | isVideoChannelDescriptionValid, |
43 | isVideoChannelNameValid, | 47 | isVideoChannelNameValid, |
48 | isVideoChannelSupportValid, | ||
44 | isVideoChannelExist | 49 | isVideoChannelExist |
45 | } | 50 | } |
diff --git a/server/helpers/custom-validators/videos.ts b/server/helpers/custom-validators/videos.ts index 8ef3a3c64..a46d715ba 100644 --- a/server/helpers/custom-validators/videos.ts +++ b/server/helpers/custom-validators/videos.ts | |||
@@ -42,6 +42,10 @@ function isVideoDescriptionValid (value: string) { | |||
42 | return value === null || (exists(value) && validator.isLength(value, VIDEOS_CONSTRAINTS_FIELDS.DESCRIPTION)) | 42 | return value === null || (exists(value) && validator.isLength(value, VIDEOS_CONSTRAINTS_FIELDS.DESCRIPTION)) |
43 | } | 43 | } |
44 | 44 | ||
45 | function isVideoSupportValid (value: string) { | ||
46 | return value === null || (exists(value) && validator.isLength(value, VIDEOS_CONSTRAINTS_FIELDS.SUPPORT)) | ||
47 | } | ||
48 | |||
45 | function isVideoNameValid (value: string) { | 49 | function isVideoNameValid (value: string) { |
46 | return exists(value) && validator.isLength(value, VIDEOS_CONSTRAINTS_FIELDS.NAME) | 50 | return exists(value) && validator.isLength(value, VIDEOS_CONSTRAINTS_FIELDS.NAME) |
47 | } | 51 | } |
@@ -140,5 +144,6 @@ export { | |||
140 | isVideoFileResolutionValid, | 144 | isVideoFileResolutionValid, |
141 | isVideoFileSizeValid, | 145 | isVideoFileSizeValid, |
142 | isVideoExist, | 146 | isVideoExist, |
143 | isVideoImage | 147 | isVideoImage, |
148 | isVideoSupportValid | ||
144 | } | 149 | } |
diff --git a/server/initializers/constants.ts b/server/initializers/constants.ts index 91fbbde75..ac001bbc7 100644 --- a/server/initializers/constants.ts +++ b/server/initializers/constants.ts | |||
@@ -12,7 +12,7 @@ let config: IConfig = require('config') | |||
12 | 12 | ||
13 | // --------------------------------------------------------------------------- | 13 | // --------------------------------------------------------------------------- |
14 | 14 | ||
15 | const LAST_MIGRATION_VERSION = 190 | 15 | const LAST_MIGRATION_VERSION = 195 |
16 | 16 | ||
17 | // --------------------------------------------------------------------------- | 17 | // --------------------------------------------------------------------------- |
18 | 18 | ||
@@ -168,6 +168,7 @@ const CONSTRAINTS_FIELDS = { | |||
168 | USERS: { | 168 | USERS: { |
169 | USERNAME: { min: 3, max: 20 }, // Length | 169 | USERNAME: { min: 3, max: 20 }, // Length |
170 | PASSWORD: { min: 6, max: 255 }, // Length | 170 | PASSWORD: { min: 6, max: 255 }, // Length |
171 | DESCRIPTION: { min: 3, max: 250 }, // Length | ||
171 | VIDEO_QUOTA: { min: -1 } | 172 | VIDEO_QUOTA: { min: -1 } |
172 | }, | 173 | }, |
173 | VIDEO_ABUSES: { | 174 | VIDEO_ABUSES: { |
@@ -176,12 +177,14 @@ const CONSTRAINTS_FIELDS = { | |||
176 | VIDEO_CHANNELS: { | 177 | VIDEO_CHANNELS: { |
177 | NAME: { min: 3, max: 120 }, // Length | 178 | NAME: { min: 3, max: 120 }, // Length |
178 | DESCRIPTION: { min: 3, max: 250 }, // Length | 179 | DESCRIPTION: { min: 3, max: 250 }, // Length |
180 | SUPPORT: { min: 3, max: 300 }, // Length | ||
179 | URL: { min: 3, max: 2000 } // Length | 181 | URL: { min: 3, max: 2000 } // Length |
180 | }, | 182 | }, |
181 | VIDEOS: { | 183 | VIDEOS: { |
182 | NAME: { min: 3, max: 120 }, // Length | 184 | NAME: { min: 3, max: 120 }, // Length |
183 | TRUNCATED_DESCRIPTION: { min: 3, max: 250 }, // Length | 185 | TRUNCATED_DESCRIPTION: { min: 3, max: 250 }, // Length |
184 | DESCRIPTION: { min: 3, max: 3000 }, // Length | 186 | DESCRIPTION: { min: 3, max: 10000 }, // Length |
187 | SUPPORT: { min: 3, max: 300 }, // Length | ||
185 | IMAGE: { | 188 | IMAGE: { |
186 | EXTNAME: [ '.jpg', '.jpeg' ], | 189 | EXTNAME: [ '.jpg', '.jpeg' ], |
187 | FILE_SIZE: { | 190 | FILE_SIZE: { |
diff --git a/server/initializers/migrations/0195-support.ts b/server/initializers/migrations/0195-support.ts new file mode 100644 index 000000000..8722a5f22 --- /dev/null +++ b/server/initializers/migrations/0195-support.ts | |||
@@ -0,0 +1,53 @@ | |||
1 | import * as Sequelize from 'sequelize' | ||
2 | import { CONSTRAINTS_FIELDS } from '../index' | ||
3 | |||
4 | async function up (utils: { | ||
5 | transaction: Sequelize.Transaction, | ||
6 | queryInterface: Sequelize.QueryInterface, | ||
7 | sequelize: Sequelize.Sequelize | ||
8 | }): Promise<void> { | ||
9 | { | ||
10 | const data = { | ||
11 | type: Sequelize.STRING(CONSTRAINTS_FIELDS.VIDEOS.SUPPORT.max), | ||
12 | allowNull: true, | ||
13 | defaultValue: null | ||
14 | } | ||
15 | await utils.queryInterface.addColumn('video', 'support', data) | ||
16 | } | ||
17 | |||
18 | { | ||
19 | const data = { | ||
20 | type: Sequelize.STRING(CONSTRAINTS_FIELDS.VIDEO_CHANNELS.SUPPORT.max), | ||
21 | allowNull: true, | ||
22 | defaultValue: null | ||
23 | } | ||
24 | await utils.queryInterface.addColumn('videoChannel', 'support', data) | ||
25 | } | ||
26 | |||
27 | { | ||
28 | const data = { | ||
29 | type: Sequelize.STRING(CONSTRAINTS_FIELDS.USERS.DESCRIPTION.max), | ||
30 | allowNull: true, | ||
31 | defaultValue: null | ||
32 | } | ||
33 | await utils.queryInterface.addColumn('account', 'description', data) | ||
34 | } | ||
35 | |||
36 | { | ||
37 | const data = { | ||
38 | type: Sequelize.STRING(CONSTRAINTS_FIELDS.VIDEOS.DESCRIPTION.max), | ||
39 | allowNull: true, | ||
40 | defaultValue: null | ||
41 | } | ||
42 | await utils.queryInterface.changeColumn('video', 'description', data) | ||
43 | } | ||
44 | } | ||
45 | |||
46 | function down (options) { | ||
47 | throw new Error('Not implemented.') | ||
48 | } | ||
49 | |||
50 | export { | ||
51 | up, | ||
52 | down | ||
53 | } | ||
diff --git a/server/lib/activitypub/actor.ts b/server/lib/activitypub/actor.ts index c3255d8ca..897acee85 100644 --- a/server/lib/activitypub/actor.ts +++ b/server/lib/activitypub/actor.ts | |||
@@ -225,12 +225,10 @@ function saveActorAndServerAndModelIfNotExist ( | |||
225 | }) | 225 | }) |
226 | 226 | ||
227 | if (actorCreated.type === 'Person' || actorCreated.type === 'Application') { | 227 | if (actorCreated.type === 'Person' || actorCreated.type === 'Application') { |
228 | const account = await saveAccount(actorCreated, result, t) | 228 | actorCreated.Account = await saveAccount(actorCreated, result, t) |
229 | actorCreated.Account = account | ||
230 | actorCreated.Account.Actor = actorCreated | 229 | actorCreated.Account.Actor = actorCreated |
231 | } else if (actorCreated.type === 'Group') { // Video channel | 230 | } else if (actorCreated.type === 'Group') { // Video channel |
232 | const videoChannel = await saveVideoChannel(actorCreated, result, ownerActor, t) | 231 | actorCreated.VideoChannel = await saveVideoChannel(actorCreated, result, ownerActor, t) |
233 | actorCreated.VideoChannel = videoChannel | ||
234 | actorCreated.VideoChannel.Actor = actorCreated | 232 | actorCreated.VideoChannel.Actor = actorCreated |
235 | } | 233 | } |
236 | 234 | ||
@@ -242,6 +240,7 @@ type FetchRemoteActorResult = { | |||
242 | actor: ActorModel | 240 | actor: ActorModel |
243 | name: string | 241 | name: string |
244 | summary: string | 242 | summary: string |
243 | support?: string | ||
245 | avatarName?: string | 244 | avatarName?: string |
246 | attributedTo: ActivityPubAttributedTo[] | 245 | attributedTo: ActivityPubAttributedTo[] |
247 | } | 246 | } |
@@ -290,6 +289,7 @@ async function fetchRemoteActor (actorUrl: string): Promise<FetchRemoteActorResu | |||
290 | name, | 289 | name, |
291 | avatarName, | 290 | avatarName, |
292 | summary: actorJSON.summary, | 291 | summary: actorJSON.summary, |
292 | support: actorJSON.support, | ||
293 | attributedTo: actorJSON.attributedTo | 293 | attributedTo: actorJSON.attributedTo |
294 | } | 294 | } |
295 | } | 295 | } |
@@ -298,6 +298,7 @@ async function saveAccount (actor: ActorModel, result: FetchRemoteActorResult, t | |||
298 | const [ accountCreated ] = await AccountModel.findOrCreate({ | 298 | const [ accountCreated ] = await AccountModel.findOrCreate({ |
299 | defaults: { | 299 | defaults: { |
300 | name: result.name, | 300 | name: result.name, |
301 | description: result.summary, | ||
301 | actorId: actor.id | 302 | actorId: actor.id |
302 | }, | 303 | }, |
303 | where: { | 304 | where: { |
@@ -314,6 +315,7 @@ async function saveVideoChannel (actor: ActorModel, result: FetchRemoteActorResu | |||
314 | defaults: { | 315 | defaults: { |
315 | name: result.name, | 316 | name: result.name, |
316 | description: result.summary, | 317 | description: result.summary, |
318 | support: result.support, | ||
317 | actorId: actor.id, | 319 | actorId: actor.id, |
318 | accountId: ownerActor.Account.id | 320 | accountId: ownerActor.Account.id |
319 | }, | 321 | }, |
@@ -352,11 +354,14 @@ async function refreshActorIfNeeded (actor: ActorModel) { | |||
352 | await actor.save({ transaction: t }) | 354 | await actor.save({ transaction: t }) |
353 | 355 | ||
354 | actor.Account.set('name', result.name) | 356 | actor.Account.set('name', result.name) |
357 | actor.Account.set('description', result.summary) | ||
355 | await actor.Account.save({ transaction: t }) | 358 | await actor.Account.save({ transaction: t }) |
356 | } else if (actor.VideoChannel) { | 359 | } else if (actor.VideoChannel) { |
357 | await actor.save({ transaction: t }) | 360 | await actor.save({ transaction: t }) |
358 | 361 | ||
359 | actor.VideoChannel.set('name', result.name) | 362 | actor.VideoChannel.set('name', result.name) |
363 | actor.VideoChannel.set('description', result.summary) | ||
364 | actor.VideoChannel.set('support', result.support) | ||
360 | await actor.VideoChannel.save({ transaction: t }) | 365 | await actor.VideoChannel.save({ transaction: t }) |
361 | } | 366 | } |
362 | 367 | ||
diff --git a/server/lib/activitypub/process/process-update.ts b/server/lib/activitypub/process/process-update.ts index c7ad412bc..566e5938b 100644 --- a/server/lib/activitypub/process/process-update.ts +++ b/server/lib/activitypub/process/process-update.ts | |||
@@ -9,20 +9,24 @@ import { sequelizeTypescript } from '../../../initializers' | |||
9 | import { AccountModel } from '../../../models/account/account' | 9 | import { AccountModel } from '../../../models/account/account' |
10 | import { ActorModel } from '../../../models/activitypub/actor' | 10 | import { ActorModel } from '../../../models/activitypub/actor' |
11 | import { TagModel } from '../../../models/video/tag' | 11 | import { TagModel } from '../../../models/video/tag' |
12 | import { VideoChannelModel } from '../../../models/video/video-channel' | ||
12 | import { VideoFileModel } from '../../../models/video/video-file' | 13 | import { VideoFileModel } from '../../../models/video/video-file' |
13 | import { fetchAvatarIfExists, getOrCreateActorAndServerAndModel, updateActorAvatarInstance, updateActorInstance } from '../actor' | 14 | import { fetchAvatarIfExists, getOrCreateActorAndServerAndModel, updateActorAvatarInstance, updateActorInstance } from '../actor' |
14 | import { | 15 | import { |
15 | generateThumbnailFromUrl, getOrCreateAccountAndVideoAndChannel, videoActivityObjectToDBAttributes, | 16 | generateThumbnailFromUrl, |
17 | getOrCreateAccountAndVideoAndChannel, | ||
18 | videoActivityObjectToDBAttributes, | ||
16 | videoFileActivityUrlToDBAttributes | 19 | videoFileActivityUrlToDBAttributes |
17 | } from '../videos' | 20 | } from '../videos' |
18 | 21 | ||
19 | async function processUpdateActivity (activity: ActivityUpdate) { | 22 | async function processUpdateActivity (activity: ActivityUpdate) { |
20 | const actor = await getOrCreateActorAndServerAndModel(activity.actor) | 23 | const actor = await getOrCreateActorAndServerAndModel(activity.actor) |
24 | const objectType = activity.object.type | ||
21 | 25 | ||
22 | if (activity.object.type === 'Video') { | 26 | if (objectType === 'Video') { |
23 | return processUpdateVideo(actor, activity) | 27 | return processUpdateVideo(actor, activity) |
24 | } else if (activity.object.type === 'Person') { | 28 | } else if (objectType === 'Person' || objectType === 'Application' || objectType === 'Group') { |
25 | return processUpdateAccount(actor, activity) | 29 | return processUpdateActor(actor, activity) |
26 | } | 30 | } |
27 | 31 | ||
28 | return | 32 | return |
@@ -75,6 +79,7 @@ async function updateRemoteVideo (actor: ActorModel, activity: ActivityUpdate) { | |||
75 | videoInstance.set('licence', videoData.licence) | 79 | videoInstance.set('licence', videoData.licence) |
76 | videoInstance.set('language', videoData.language) | 80 | videoInstance.set('language', videoData.language) |
77 | videoInstance.set('description', videoData.description) | 81 | videoInstance.set('description', videoData.description) |
82 | videoInstance.set('support', videoData.support) | ||
78 | videoInstance.set('nsfw', videoData.nsfw) | 83 | videoInstance.set('nsfw', videoData.nsfw) |
79 | videoInstance.set('commentsEnabled', videoData.commentsEnabled) | 84 | videoInstance.set('commentsEnabled', videoData.commentsEnabled) |
80 | videoInstance.set('duration', videoData.duration) | 85 | videoInstance.set('duration', videoData.duration) |
@@ -117,33 +122,36 @@ async function updateRemoteVideo (actor: ActorModel, activity: ActivityUpdate) { | |||
117 | } | 122 | } |
118 | } | 123 | } |
119 | 124 | ||
120 | function processUpdateAccount (actor: ActorModel, activity: ActivityUpdate) { | 125 | function processUpdateActor (actor: ActorModel, activity: ActivityUpdate) { |
121 | const options = { | 126 | const options = { |
122 | arguments: [ actor, activity ], | 127 | arguments: [ actor, activity ], |
123 | errorMessage: 'Cannot update the remote account with many retries' | 128 | errorMessage: 'Cannot update the remote actor with many retries' |
124 | } | 129 | } |
125 | 130 | ||
126 | return retryTransactionWrapper(updateRemoteAccount, options) | 131 | return retryTransactionWrapper(updateRemoteActor, options) |
127 | } | 132 | } |
128 | 133 | ||
129 | async function updateRemoteAccount (actor: ActorModel, activity: ActivityUpdate) { | 134 | async function updateRemoteActor (actor: ActorModel, activity: ActivityUpdate) { |
130 | const accountAttributesToUpdate = activity.object as ActivityPubActor | 135 | const actorAttributesToUpdate = activity.object as ActivityPubActor |
131 | 136 | ||
132 | logger.debug('Updating remote account "%s".', accountAttributesToUpdate.uuid) | 137 | logger.debug('Updating remote account "%s".', actorAttributesToUpdate.uuid) |
133 | let accountInstance: AccountModel | 138 | let accountOrChannelInstance: AccountModel | VideoChannelModel |
134 | let actorFieldsSave: object | 139 | let actorFieldsSave: object |
135 | let accountFieldsSave: object | 140 | let accountOrChannelFieldsSave: object |
136 | 141 | ||
137 | // Fetch icon? | 142 | // Fetch icon? |
138 | const avatarName = await fetchAvatarIfExists(accountAttributesToUpdate) | 143 | const avatarName = await fetchAvatarIfExists(actorAttributesToUpdate) |
139 | 144 | ||
140 | try { | 145 | try { |
141 | await sequelizeTypescript.transaction(async t => { | 146 | await sequelizeTypescript.transaction(async t => { |
142 | actorFieldsSave = actor.toJSON() | 147 | actorFieldsSave = actor.toJSON() |
143 | accountInstance = actor.Account | ||
144 | accountFieldsSave = actor.Account.toJSON() | ||
145 | 148 | ||
146 | await updateActorInstance(actor, accountAttributesToUpdate) | 149 | if (actorAttributesToUpdate.type === 'Group') accountOrChannelInstance = actor.VideoChannel |
150 | else accountOrChannelInstance = actor.Account | ||
151 | |||
152 | accountOrChannelFieldsSave = accountOrChannelInstance.toJSON() | ||
153 | |||
154 | await updateActorInstance(actor, actorAttributesToUpdate) | ||
147 | 155 | ||
148 | if (avatarName !== undefined) { | 156 | if (avatarName !== undefined) { |
149 | await updateActorAvatarInstance(actor, avatarName, t) | 157 | await updateActorAvatarInstance(actor, avatarName, t) |
@@ -151,18 +159,20 @@ async function updateRemoteAccount (actor: ActorModel, activity: ActivityUpdate) | |||
151 | 159 | ||
152 | await actor.save({ transaction: t }) | 160 | await actor.save({ transaction: t }) |
153 | 161 | ||
154 | actor.Account.set('name', accountAttributesToUpdate.name || accountAttributesToUpdate.preferredUsername) | 162 | accountOrChannelInstance.set('name', actorAttributesToUpdate.name || actorAttributesToUpdate.preferredUsername) |
155 | await actor.Account.save({ transaction: t }) | 163 | accountOrChannelInstance.set('description', actorAttributesToUpdate.summary) |
164 | accountOrChannelInstance.set('support', actorAttributesToUpdate.support) | ||
165 | await accountOrChannelInstance.save({ transaction: t }) | ||
156 | }) | 166 | }) |
157 | 167 | ||
158 | logger.info('Remote account with uuid %s updated', accountAttributesToUpdate.uuid) | 168 | logger.info('Remote account with uuid %s updated', actorAttributesToUpdate.uuid) |
159 | } catch (err) { | 169 | } catch (err) { |
160 | if (actor !== undefined && actorFieldsSave !== undefined) { | 170 | if (actor !== undefined && actorFieldsSave !== undefined) { |
161 | resetSequelizeInstance(actor, actorFieldsSave) | 171 | resetSequelizeInstance(actor, actorFieldsSave) |
162 | } | 172 | } |
163 | 173 | ||
164 | if (accountInstance !== undefined && accountFieldsSave !== undefined) { | 174 | if (accountOrChannelInstance !== undefined && accountOrChannelFieldsSave !== undefined) { |
165 | resetSequelizeInstance(accountInstance, accountFieldsSave) | 175 | resetSequelizeInstance(accountOrChannelInstance, accountOrChannelFieldsSave) |
166 | } | 176 | } |
167 | 177 | ||
168 | // This is just a debug because we will retry the insert | 178 | // This is just a debug because we will retry the insert |
diff --git a/server/lib/activitypub/send/send-update.ts b/server/lib/activitypub/send/send-update.ts index e8f11edd0..622648308 100644 --- a/server/lib/activitypub/send/send-update.ts +++ b/server/lib/activitypub/send/send-update.ts | |||
@@ -1,9 +1,10 @@ | |||
1 | import { Transaction } from 'sequelize' | 1 | import { Transaction } from 'sequelize' |
2 | import { ActivityAudience, ActivityUpdate } from '../../../../shared/models/activitypub' | 2 | import { ActivityAudience, ActivityUpdate } from '../../../../shared/models/activitypub' |
3 | import { VideoPrivacy } from '../../../../shared/models/videos' | 3 | import { VideoPrivacy } from '../../../../shared/models/videos' |
4 | import { UserModel } from '../../../models/account/user' | 4 | import { AccountModel } from '../../../models/account/account' |
5 | import { ActorModel } from '../../../models/activitypub/actor' | 5 | import { ActorModel } from '../../../models/activitypub/actor' |
6 | import { VideoModel } from '../../../models/video/video' | 6 | import { VideoModel } from '../../../models/video/video' |
7 | import { VideoChannelModel } from '../../../models/video/video-channel' | ||
7 | import { VideoShareModel } from '../../../models/video/video-share' | 8 | import { VideoShareModel } from '../../../models/video/video-share' |
8 | import { getUpdateActivityPubUrl } from '../url' | 9 | import { getUpdateActivityPubUrl } from '../url' |
9 | import { audiencify, broadcastToFollowers, getAudience } from './misc' | 10 | import { audiencify, broadcastToFollowers, getAudience } from './misc' |
@@ -23,15 +24,23 @@ async function sendUpdateVideo (video: VideoModel, t: Transaction) { | |||
23 | return broadcastToFollowers(data, byActor, actorsInvolved, t) | 24 | return broadcastToFollowers(data, byActor, actorsInvolved, t) |
24 | } | 25 | } |
25 | 26 | ||
26 | async function sendUpdateUser (user: UserModel, t: Transaction) { | 27 | async function sendUpdateActor (accountOrChannel: AccountModel | VideoChannelModel, t: Transaction) { |
27 | const byActor = user.Account.Actor | 28 | const byActor = accountOrChannel.Actor |
28 | 29 | ||
29 | const url = getUpdateActivityPubUrl(byActor.url, byActor.updatedAt.toISOString()) | 30 | const url = getUpdateActivityPubUrl(byActor.url, byActor.updatedAt.toISOString()) |
30 | const accountObject = user.Account.toActivityPubObject() | 31 | const accountOrChannelObject = accountOrChannel.toActivityPubObject() |
31 | const audience = await getAudience(byActor, t) | 32 | const audience = await getAudience(byActor, t) |
32 | const data = await updateActivityData(url, byActor, accountObject, t, audience) | 33 | const data = await updateActivityData(url, byActor, accountOrChannelObject, t, audience) |
34 | |||
35 | let actorsInvolved: ActorModel[] | ||
36 | if (accountOrChannel instanceof AccountModel) { | ||
37 | // Actors that shared my videos are involved too | ||
38 | actorsInvolved = await VideoShareModel.loadActorsByVideoOwner(byActor.id, t) | ||
39 | } else { | ||
40 | // Actors that shared videos of my channel are involved too | ||
41 | actorsInvolved = await VideoShareModel.loadActorsByVideoChannel(accountOrChannel.id, t) | ||
42 | } | ||
33 | 43 | ||
34 | const actorsInvolved = await VideoShareModel.loadActorsByVideoOwner(byActor.id, t) | ||
35 | actorsInvolved.push(byActor) | 44 | actorsInvolved.push(byActor) |
36 | 45 | ||
37 | return broadcastToFollowers(data, byActor, actorsInvolved, t) | 46 | return broadcastToFollowers(data, byActor, actorsInvolved, t) |
@@ -40,7 +49,7 @@ async function sendUpdateUser (user: UserModel, t: Transaction) { | |||
40 | // --------------------------------------------------------------------------- | 49 | // --------------------------------------------------------------------------- |
41 | 50 | ||
42 | export { | 51 | export { |
43 | sendUpdateUser, | 52 | sendUpdateActor, |
44 | sendUpdateVideo | 53 | sendUpdateVideo |
45 | } | 54 | } |
46 | 55 | ||
diff --git a/server/lib/activitypub/videos.ts b/server/lib/activitypub/videos.ts index 40e9318e3..e65362190 100644 --- a/server/lib/activitypub/videos.ts +++ b/server/lib/activitypub/videos.ts | |||
@@ -83,6 +83,11 @@ async function videoActivityObjectToDBAttributes (videoChannel: VideoChannelMode | |||
83 | description = videoObject.content | 83 | description = videoObject.content |
84 | } | 84 | } |
85 | 85 | ||
86 | let support = null | ||
87 | if (videoObject.support) { | ||
88 | support = videoObject.support | ||
89 | } | ||
90 | |||
86 | return { | 91 | return { |
87 | name: videoObject.name, | 92 | name: videoObject.name, |
88 | uuid: videoObject.uuid, | 93 | uuid: videoObject.uuid, |
@@ -91,6 +96,7 @@ async function videoActivityObjectToDBAttributes (videoChannel: VideoChannelMode | |||
91 | licence, | 96 | licence, |
92 | language, | 97 | language, |
93 | description, | 98 | description, |
99 | support, | ||
94 | nsfw: videoObject.sensitive, | 100 | nsfw: videoObject.sensitive, |
95 | commentsEnabled: videoObject.commentsEnabled, | 101 | commentsEnabled: videoObject.commentsEnabled, |
96 | channelId: videoChannel.id, | 102 | channelId: videoChannel.id, |
diff --git a/server/lib/video-channel.ts b/server/lib/video-channel.ts index 569b8f29d..9f7ed9297 100644 --- a/server/lib/video-channel.ts +++ b/server/lib/video-channel.ts | |||
@@ -16,6 +16,7 @@ async function createVideoChannel (videoChannelInfo: VideoChannelCreate, account | |||
16 | const videoChannelData = { | 16 | const videoChannelData = { |
17 | name: videoChannelInfo.name, | 17 | name: videoChannelInfo.name, |
18 | description: videoChannelInfo.description, | 18 | description: videoChannelInfo.description, |
19 | support: videoChannelInfo.support, | ||
19 | accountId: account.id, | 20 | accountId: account.id, |
20 | actorId: actorInstanceCreated.id | 21 | actorId: actorInstanceCreated.id |
21 | } | 22 | } |
diff --git a/server/middlewares/validators/users.ts b/server/middlewares/validators/users.ts index cba15c8d3..49bc0bb56 100644 --- a/server/middlewares/validators/users.ts +++ b/server/middlewares/validators/users.ts | |||
@@ -7,6 +7,7 @@ import { isIdOrUUIDValid } from '../../helpers/custom-validators/misc' | |||
7 | import { | 7 | import { |
8 | isAvatarFile, | 8 | isAvatarFile, |
9 | isUserAutoPlayVideoValid, | 9 | isUserAutoPlayVideoValid, |
10 | isUserDescriptionValid, | ||
10 | isUserDisplayNSFWValid, | 11 | isUserDisplayNSFWValid, |
11 | isUserPasswordValid, | 12 | isUserPasswordValid, |
12 | isUserRoleValid, | 13 | isUserRoleValid, |
@@ -97,6 +98,7 @@ const usersUpdateValidator = [ | |||
97 | ] | 98 | ] |
98 | 99 | ||
99 | const usersUpdateMeValidator = [ | 100 | const usersUpdateMeValidator = [ |
101 | body('description').optional().custom(isUserDescriptionValid).withMessage('Should have a valid description'), | ||
100 | body('password').optional().custom(isUserPasswordValid).withMessage('Should have a valid password'), | 102 | body('password').optional().custom(isUserPasswordValid).withMessage('Should have a valid password'), |
101 | body('email').optional().isEmail().withMessage('Should have a valid email attribute'), | 103 | body('email').optional().isEmail().withMessage('Should have a valid email attribute'), |
102 | body('displayNSFW').optional().custom(isUserDisplayNSFWValid).withMessage('Should have a valid display Not Safe For Work attribute'), | 104 | body('displayNSFW').optional().custom(isUserDisplayNSFWValid).withMessage('Should have a valid display Not Safe For Work attribute'), |
diff --git a/server/middlewares/validators/video-channels.ts b/server/middlewares/validators/video-channels.ts index 86bddde82..fe42105e8 100644 --- a/server/middlewares/validators/video-channels.ts +++ b/server/middlewares/validators/video-channels.ts | |||
@@ -5,7 +5,7 @@ import { isAccountIdExist } from '../../helpers/custom-validators/accounts' | |||
5 | import { isIdOrUUIDValid } from '../../helpers/custom-validators/misc' | 5 | import { isIdOrUUIDValid } from '../../helpers/custom-validators/misc' |
6 | import { | 6 | import { |
7 | isVideoChannelDescriptionValid, isVideoChannelExist, | 7 | isVideoChannelDescriptionValid, isVideoChannelExist, |
8 | isVideoChannelNameValid | 8 | isVideoChannelNameValid, isVideoChannelSupportValid |
9 | } from '../../helpers/custom-validators/video-channels' | 9 | } from '../../helpers/custom-validators/video-channels' |
10 | import { logger } from '../../helpers/logger' | 10 | import { logger } from '../../helpers/logger' |
11 | import { UserModel } from '../../models/account/user' | 11 | import { UserModel } from '../../models/account/user' |
@@ -27,7 +27,8 @@ const listVideoAccountChannelsValidator = [ | |||
27 | 27 | ||
28 | const videoChannelsAddValidator = [ | 28 | const videoChannelsAddValidator = [ |
29 | body('name').custom(isVideoChannelNameValid).withMessage('Should have a valid name'), | 29 | body('name').custom(isVideoChannelNameValid).withMessage('Should have a valid name'), |
30 | body('description').custom(isVideoChannelDescriptionValid).withMessage('Should have a valid description'), | 30 | body('description').optional().custom(isVideoChannelDescriptionValid).withMessage('Should have a valid description'), |
31 | body('support').optional().custom(isVideoChannelSupportValid).withMessage('Should have a valid support text'), | ||
31 | 32 | ||
32 | (req: express.Request, res: express.Response, next: express.NextFunction) => { | 33 | (req: express.Request, res: express.Response, next: express.NextFunction) => { |
33 | logger.debug('Checking videoChannelsAdd parameters', { parameters: req.body }) | 34 | logger.debug('Checking videoChannelsAdd parameters', { parameters: req.body }) |
@@ -42,6 +43,7 @@ const videoChannelsUpdateValidator = [ | |||
42 | param('id').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid id'), | 43 | param('id').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid id'), |
43 | body('name').optional().custom(isVideoChannelNameValid).withMessage('Should have a valid name'), | 44 | body('name').optional().custom(isVideoChannelNameValid).withMessage('Should have a valid name'), |
44 | body('description').optional().custom(isVideoChannelDescriptionValid).withMessage('Should have a valid description'), | 45 | body('description').optional().custom(isVideoChannelDescriptionValid).withMessage('Should have a valid description'), |
46 | body('support').optional().custom(isVideoChannelSupportValid).withMessage('Should have a valid support text'), | ||
45 | 47 | ||
46 | async (req: express.Request, res: express.Response, next: express.NextFunction) => { | 48 | async (req: express.Request, res: express.Response, next: express.NextFunction) => { |
47 | logger.debug('Checking videoChannelsUpdate parameters', { parameters: req.body }) | 49 | logger.debug('Checking videoChannelsUpdate parameters', { parameters: req.body }) |
diff --git a/server/middlewares/validators/videos.ts b/server/middlewares/validators/videos.ts index 6d4fb907b..e91739f81 100644 --- a/server/middlewares/validators/videos.ts +++ b/server/middlewares/validators/videos.ts | |||
@@ -14,7 +14,7 @@ import { | |||
14 | isVideoLicenceValid, | 14 | isVideoLicenceValid, |
15 | isVideoNameValid, | 15 | isVideoNameValid, |
16 | isVideoPrivacyValid, | 16 | isVideoPrivacyValid, |
17 | isVideoRatingTypeValid, | 17 | isVideoRatingTypeValid, isVideoSupportValid, |
18 | isVideoTagsValid | 18 | isVideoTagsValid |
19 | } from '../../helpers/custom-validators/videos' | 19 | } from '../../helpers/custom-validators/videos' |
20 | import { getDurationFromVideoFile } from '../../helpers/ffmpeg-utils' | 20 | import { getDurationFromVideoFile } from '../../helpers/ffmpeg-utils' |
@@ -46,6 +46,7 @@ const videosAddValidator = [ | |||
46 | body('language').optional().custom(isVideoLanguageValid).withMessage('Should have a valid language'), | 46 | body('language').optional().custom(isVideoLanguageValid).withMessage('Should have a valid language'), |
47 | body('nsfw').custom(isBooleanValid).withMessage('Should have a valid NSFW attribute'), | 47 | body('nsfw').custom(isBooleanValid).withMessage('Should have a valid NSFW attribute'), |
48 | body('description').optional().custom(isVideoDescriptionValid).withMessage('Should have a valid description'), | 48 | body('description').optional().custom(isVideoDescriptionValid).withMessage('Should have a valid description'), |
49 | body('support').optional().custom(isVideoSupportValid).withMessage('Should have a valid support text'), | ||
49 | body('channelId').custom(isIdValid).withMessage('Should have correct video channel id'), | 50 | body('channelId').custom(isIdValid).withMessage('Should have correct video channel id'), |
50 | body('privacy').custom(isVideoPrivacyValid).withMessage('Should have correct video privacy'), | 51 | body('privacy').custom(isVideoPrivacyValid).withMessage('Should have correct video privacy'), |
51 | body('tags').optional().custom(isVideoTagsValid).withMessage('Should have correct tags'), | 52 | body('tags').optional().custom(isVideoTagsValid).withMessage('Should have correct tags'), |
@@ -116,6 +117,7 @@ const videosUpdateValidator = [ | |||
116 | body('nsfw').optional().custom(isBooleanValid).withMessage('Should have a valid NSFW attribute'), | 117 | body('nsfw').optional().custom(isBooleanValid).withMessage('Should have a valid NSFW attribute'), |
117 | body('privacy').optional().custom(isVideoPrivacyValid).withMessage('Should have correct video privacy'), | 118 | body('privacy').optional().custom(isVideoPrivacyValid).withMessage('Should have correct video privacy'), |
118 | body('description').optional().custom(isVideoDescriptionValid).withMessage('Should have a valid description'), | 119 | body('description').optional().custom(isVideoDescriptionValid).withMessage('Should have a valid description'), |
120 | body('support').optional().custom(isVideoSupportValid).withMessage('Should have a valid support text'), | ||
119 | body('tags').optional().custom(isVideoTagsValid).withMessage('Should have correct tags'), | 121 | body('tags').optional().custom(isVideoTagsValid).withMessage('Should have correct tags'), |
120 | body('commentsEnabled').optional().custom(isBooleanValid).withMessage('Should have comments enabled boolean'), | 122 | body('commentsEnabled').optional().custom(isBooleanValid).withMessage('Should have comments enabled boolean'), |
121 | 123 | ||
diff --git a/server/models/account/account.ts b/server/models/account/account.ts index 20724ae0c..d8f305c37 100644 --- a/server/models/account/account.ts +++ b/server/models/account/account.ts | |||
@@ -1,16 +1,28 @@ | |||
1 | import * as Sequelize from 'sequelize' | 1 | import * as Sequelize from 'sequelize' |
2 | import { | 2 | import { |
3 | AllowNull, BeforeDestroy, BelongsTo, Column, CreatedAt, DefaultScope, ForeignKey, HasMany, Model, Table, | 3 | AllowNull, |
4 | BeforeDestroy, | ||
5 | BelongsTo, | ||
6 | Column, | ||
7 | CreatedAt, | ||
8 | Default, | ||
9 | DefaultScope, | ||
10 | ForeignKey, | ||
11 | HasMany, | ||
12 | Is, | ||
13 | Model, | ||
14 | Table, | ||
4 | UpdatedAt | 15 | UpdatedAt |
5 | } from 'sequelize-typescript' | 16 | } from 'sequelize-typescript' |
6 | import { Account } from '../../../shared/models/actors' | 17 | import { Account } from '../../../shared/models/actors' |
18 | import { isAccountDescriptionValid } from '../../helpers/custom-validators/accounts' | ||
7 | import { logger } from '../../helpers/logger' | 19 | import { logger } from '../../helpers/logger' |
8 | import { sendDeleteActor } from '../../lib/activitypub/send' | 20 | import { sendDeleteActor } from '../../lib/activitypub/send' |
9 | import { ActorModel } from '../activitypub/actor' | 21 | import { ActorModel } from '../activitypub/actor' |
10 | import { ApplicationModel } from '../application/application' | 22 | import { ApplicationModel } from '../application/application' |
11 | import { AvatarModel } from '../avatar/avatar' | 23 | import { AvatarModel } from '../avatar/avatar' |
12 | import { ServerModel } from '../server/server' | 24 | import { ServerModel } from '../server/server' |
13 | import { getSort } from '../utils' | 25 | import { getSort, throwIfNotValid } from '../utils' |
14 | import { VideoChannelModel } from '../video/video-channel' | 26 | import { VideoChannelModel } from '../video/video-channel' |
15 | import { VideoCommentModel } from '../video/video-comment' | 27 | import { VideoCommentModel } from '../video/video-comment' |
16 | import { UserModel } from './user' | 28 | import { UserModel } from './user' |
@@ -42,6 +54,12 @@ export class AccountModel extends Model<AccountModel> { | |||
42 | @Column | 54 | @Column |
43 | name: string | 55 | name: string |
44 | 56 | ||
57 | @AllowNull(true) | ||
58 | @Default(null) | ||
59 | @Is('AccountDescription', value => throwIfNotValid(value, isAccountDescriptionValid, 'description')) | ||
60 | @Column | ||
61 | description: string | ||
62 | |||
45 | @CreatedAt | 63 | @CreatedAt |
46 | createdAt: Date | 64 | createdAt: Date |
47 | 65 | ||
@@ -196,6 +214,7 @@ export class AccountModel extends Model<AccountModel> { | |||
196 | const account = { | 214 | const account = { |
197 | id: this.id, | 215 | id: this.id, |
198 | displayName: this.name, | 216 | displayName: this.name, |
217 | description: this.description, | ||
199 | createdAt: this.createdAt, | 218 | createdAt: this.createdAt, |
200 | updatedAt: this.updatedAt | 219 | updatedAt: this.updatedAt |
201 | } | 220 | } |
@@ -204,7 +223,11 @@ export class AccountModel extends Model<AccountModel> { | |||
204 | } | 223 | } |
205 | 224 | ||
206 | toActivityPubObject () { | 225 | toActivityPubObject () { |
207 | return this.Actor.toActivityPubObject(this.name, 'Account') | 226 | const obj = this.Actor.toActivityPubObject(this.name, 'Account') |
227 | |||
228 | return Object.assign(obj, { | ||
229 | summary: this.description | ||
230 | }) | ||
208 | } | 231 | } |
209 | 232 | ||
210 | isOwned () { | 233 | isOwned () { |
diff --git a/server/models/activitypub/actor.ts b/server/models/activitypub/actor.ts index c79bba96b..1d0e54ee3 100644 --- a/server/models/activitypub/actor.ts +++ b/server/models/activitypub/actor.ts | |||
@@ -2,14 +2,31 @@ import { values } from 'lodash' | |||
2 | import { extname } from 'path' | 2 | import { extname } from 'path' |
3 | import * as Sequelize from 'sequelize' | 3 | import * as Sequelize from 'sequelize' |
4 | import { | 4 | import { |
5 | AllowNull, BelongsTo, Column, CreatedAt, DataType, Default, DefaultScope, ForeignKey, HasMany, HasOne, Is, IsUUID, Model, Scopes, | 5 | AllowNull, |
6 | Table, UpdatedAt | 6 | BelongsTo, |
7 | Column, | ||
8 | CreatedAt, | ||
9 | DataType, | ||
10 | Default, | ||
11 | DefaultScope, | ||
12 | ForeignKey, | ||
13 | HasMany, | ||
14 | HasOne, | ||
15 | Is, | ||
16 | IsUUID, | ||
17 | Model, | ||
18 | Scopes, | ||
19 | Table, | ||
20 | UpdatedAt | ||
7 | } from 'sequelize-typescript' | 21 | } from 'sequelize-typescript' |
8 | import { ActivityPubActorType } from '../../../shared/models/activitypub' | 22 | import { ActivityPubActorType } from '../../../shared/models/activitypub' |
9 | import { Avatar } from '../../../shared/models/avatars/avatar.model' | 23 | import { Avatar } from '../../../shared/models/avatars/avatar.model' |
10 | import { activityPubContextify } from '../../helpers/activitypub' | 24 | import { activityPubContextify } from '../../helpers/activitypub' |
11 | import { | 25 | import { |
12 | isActorFollowersCountValid, isActorFollowingCountValid, isActorPreferredUsernameValid, isActorPrivateKeyValid, | 26 | isActorFollowersCountValid, |
27 | isActorFollowingCountValid, | ||
28 | isActorPreferredUsernameValid, | ||
29 | isActorPrivateKeyValid, | ||
13 | isActorPublicKeyValid | 30 | isActorPublicKeyValid |
14 | } from '../../helpers/custom-validators/activitypub/actor' | 31 | } from '../../helpers/custom-validators/activitypub/actor' |
15 | import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub/misc' | 32 | import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub/misc' |
diff --git a/server/models/video/video-channel.ts b/server/models/video/video-channel.ts index 7c161c864..289775a0f 100644 --- a/server/models/video/video-channel.ts +++ b/server/models/video/video-channel.ts | |||
@@ -1,9 +1,13 @@ | |||
1 | import { | 1 | import { |
2 | AllowNull, BeforeDestroy, BelongsTo, Column, CreatedAt, DefaultScope, ForeignKey, HasMany, Is, Model, Scopes, Table, | 2 | AllowNull, BeforeDestroy, BelongsTo, Column, CreatedAt, DefaultScope, ForeignKey, HasMany, Is, Model, Scopes, Table, |
3 | UpdatedAt | 3 | UpdatedAt, Default |
4 | } from 'sequelize-typescript' | 4 | } from 'sequelize-typescript' |
5 | import { ActivityPubActor } from '../../../shared/models/activitypub' | 5 | import { ActivityPubActor } from '../../../shared/models/activitypub' |
6 | import { isVideoChannelDescriptionValid, isVideoChannelNameValid } from '../../helpers/custom-validators/video-channels' | 6 | import { VideoChannel } from '../../../shared/models/videos' |
7 | import { | ||
8 | isVideoChannelDescriptionValid, isVideoChannelNameValid, | ||
9 | isVideoChannelSupportValid | ||
10 | } from '../../helpers/custom-validators/video-channels' | ||
7 | import { logger } from '../../helpers/logger' | 11 | import { logger } from '../../helpers/logger' |
8 | import { sendDeleteActor } from '../../lib/activitypub/send' | 12 | import { sendDeleteActor } from '../../lib/activitypub/send' |
9 | import { AccountModel } from '../account/account' | 13 | import { AccountModel } from '../account/account' |
@@ -67,10 +71,17 @@ export class VideoChannelModel extends Model<VideoChannelModel> { | |||
67 | name: string | 71 | name: string |
68 | 72 | ||
69 | @AllowNull(true) | 73 | @AllowNull(true) |
74 | @Default(null) | ||
70 | @Is('VideoChannelDescription', value => throwIfNotValid(value, isVideoChannelDescriptionValid, 'description')) | 75 | @Is('VideoChannelDescription', value => throwIfNotValid(value, isVideoChannelDescriptionValid, 'description')) |
71 | @Column | 76 | @Column |
72 | description: string | 77 | description: string |
73 | 78 | ||
79 | @AllowNull(true) | ||
80 | @Default(null) | ||
81 | @Is('VideoChannelSupport', value => throwIfNotValid(value, isVideoChannelSupportValid, 'support')) | ||
82 | @Column | ||
83 | support: string | ||
84 | |||
74 | @CreatedAt | 85 | @CreatedAt |
75 | createdAt: Date | 86 | createdAt: Date |
76 | 87 | ||
@@ -221,12 +232,13 @@ export class VideoChannelModel extends Model<VideoChannelModel> { | |||
221 | .findById(id, options) | 232 | .findById(id, options) |
222 | } | 233 | } |
223 | 234 | ||
224 | toFormattedJSON () { | 235 | toFormattedJSON (): VideoChannel { |
225 | const actor = this.Actor.toFormattedJSON() | 236 | const actor = this.Actor.toFormattedJSON() |
226 | const account = { | 237 | const account = { |
227 | id: this.id, | 238 | id: this.id, |
228 | displayName: this.name, | 239 | displayName: this.name, |
229 | description: this.description, | 240 | description: this.description, |
241 | support: this.support, | ||
230 | isLocal: this.Actor.isOwned(), | 242 | isLocal: this.Actor.isOwned(), |
231 | createdAt: this.createdAt, | 243 | createdAt: this.createdAt, |
232 | updatedAt: this.updatedAt | 244 | updatedAt: this.updatedAt |
@@ -240,6 +252,7 @@ export class VideoChannelModel extends Model<VideoChannelModel> { | |||
240 | 252 | ||
241 | return Object.assign(obj, { | 253 | return Object.assign(obj, { |
242 | summary: this.description, | 254 | summary: this.description, |
255 | support: this.support, | ||
243 | attributedTo: [ | 256 | attributedTo: [ |
244 | { | 257 | { |
245 | type: 'Person' as 'Person', | 258 | type: 'Person' as 'Person', |
diff --git a/server/models/video/video-share.ts b/server/models/video/video-share.ts index 48ba68a4a..6f770957f 100644 --- a/server/models/video/video-share.ts +++ b/server/models/video/video-share.ts | |||
@@ -1,4 +1,5 @@ | |||
1 | import * as Sequelize from 'sequelize' | 1 | import * as Sequelize from 'sequelize' |
2 | import * as Bluebird from 'bluebird' | ||
2 | import { AllowNull, BelongsTo, Column, CreatedAt, DataType, ForeignKey, Is, Model, Scopes, Table, UpdatedAt } from 'sequelize-typescript' | 3 | import { AllowNull, BelongsTo, Column, CreatedAt, DataType, ForeignKey, Is, Model, Scopes, Table, UpdatedAt } from 'sequelize-typescript' |
3 | import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub/misc' | 4 | import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub/misc' |
4 | import { CONSTRAINTS_FIELDS } from '../../initializers' | 5 | import { CONSTRAINTS_FIELDS } from '../../initializers' |
@@ -115,7 +116,7 @@ export class VideoShareModel extends Model<VideoShareModel> { | |||
115 | .then(res => res.map(r => r.Actor)) | 116 | .then(res => res.map(r => r.Actor)) |
116 | } | 117 | } |
117 | 118 | ||
118 | static loadActorsByVideoOwner (actorOwnerId: number, t: Sequelize.Transaction) { | 119 | static loadActorsByVideoOwner (actorOwnerId: number, t: Sequelize.Transaction): Bluebird<ActorModel[]> { |
119 | const query = { | 120 | const query = { |
120 | attributes: [], | 121 | attributes: [], |
121 | include: [ | 122 | include: [ |
@@ -152,4 +153,29 @@ export class VideoShareModel extends Model<VideoShareModel> { | |||
152 | return VideoShareModel.scope(ScopeNames.FULL).findAll(query) | 153 | return VideoShareModel.scope(ScopeNames.FULL).findAll(query) |
153 | .then(res => res.map(r => r.Actor)) | 154 | .then(res => res.map(r => r.Actor)) |
154 | } | 155 | } |
156 | |||
157 | static loadActorsByVideoChannel (videoChannelId: number, t: Sequelize.Transaction): Bluebird<ActorModel[]> { | ||
158 | const query = { | ||
159 | attributes: [], | ||
160 | include: [ | ||
161 | { | ||
162 | model: ActorModel, | ||
163 | required: true | ||
164 | }, | ||
165 | { | ||
166 | attributes: [], | ||
167 | model: VideoModel, | ||
168 | required: true, | ||
169 | where: { | ||
170 | channelId: videoChannelId | ||
171 | } | ||
172 | } | ||
173 | ], | ||
174 | transaction: t | ||
175 | } | ||
176 | |||
177 | return VideoShareModel.scope(ScopeNames.FULL) | ||
178 | .findAll(query) | ||
179 | .then(res => res.map(r => r.Actor)) | ||
180 | } | ||
155 | } | 181 | } |
diff --git a/server/models/video/video.ts b/server/models/video/video.ts index ff82fb3b2..d748e81bd 100644 --- a/server/models/video/video.ts +++ b/server/models/video/video.ts | |||
@@ -40,7 +40,7 @@ import { | |||
40 | isVideoLanguageValid, | 40 | isVideoLanguageValid, |
41 | isVideoLicenceValid, | 41 | isVideoLicenceValid, |
42 | isVideoNameValid, | 42 | isVideoNameValid, |
43 | isVideoPrivacyValid | 43 | isVideoPrivacyValid, isVideoSupportValid |
44 | } from '../../helpers/custom-validators/videos' | 44 | } from '../../helpers/custom-validators/videos' |
45 | import { generateImageFromVideoFile, getVideoFileHeight, transcode } from '../../helpers/ffmpeg-utils' | 45 | import { generateImageFromVideoFile, getVideoFileHeight, transcode } from '../../helpers/ffmpeg-utils' |
46 | import { logger } from '../../helpers/logger' | 46 | import { logger } from '../../helpers/logger' |
@@ -299,6 +299,12 @@ export class VideoModel extends Model<VideoModel> { | |||
299 | @Column(DataType.STRING(CONSTRAINTS_FIELDS.VIDEOS.DESCRIPTION.max)) | 299 | @Column(DataType.STRING(CONSTRAINTS_FIELDS.VIDEOS.DESCRIPTION.max)) |
300 | description: string | 300 | description: string |
301 | 301 | ||
302 | @AllowNull(true) | ||
303 | @Default(null) | ||
304 | @Is('VideoSupport', value => throwIfNotValid(value, isVideoSupportValid, 'support')) | ||
305 | @Column(DataType.STRING(CONSTRAINTS_FIELDS.VIDEOS.SUPPORT.max)) | ||
306 | support: string | ||
307 | |||
302 | @AllowNull(false) | 308 | @AllowNull(false) |
303 | @Is('VideoDuration', value => throwIfNotValid(value, isVideoDurationValid, 'duration')) | 309 | @Is('VideoDuration', value => throwIfNotValid(value, isVideoDurationValid, 'duration')) |
304 | @Column | 310 | @Column |
@@ -841,7 +847,7 @@ export class VideoModel extends Model<VideoModel> { | |||
841 | return join(STATIC_PATHS.PREVIEWS, this.getPreviewName()) | 847 | return join(STATIC_PATHS.PREVIEWS, this.getPreviewName()) |
842 | } | 848 | } |
843 | 849 | ||
844 | toFormattedJSON () { | 850 | toFormattedJSON (): Video { |
845 | let serverHost | 851 | let serverHost |
846 | 852 | ||
847 | if (this.VideoChannel.Account.Actor.Server) { | 853 | if (this.VideoChannel.Account.Actor.Server) { |
@@ -875,10 +881,10 @@ export class VideoModel extends Model<VideoModel> { | |||
875 | embedPath: this.getEmbedPath(), | 881 | embedPath: this.getEmbedPath(), |
876 | createdAt: this.createdAt, | 882 | createdAt: this.createdAt, |
877 | updatedAt: this.updatedAt | 883 | updatedAt: this.updatedAt |
878 | } as Video | 884 | } |
879 | } | 885 | } |
880 | 886 | ||
881 | toFormattedDetailsJSON () { | 887 | toFormattedDetailsJSON (): VideoDetails { |
882 | const formattedJson = this.toFormattedJSON() | 888 | const formattedJson = this.toFormattedJSON() |
883 | 889 | ||
884 | // Maybe our server is not up to date and there are new privacy settings since our version | 890 | // Maybe our server is not up to date and there are new privacy settings since our version |
@@ -888,6 +894,7 @@ export class VideoModel extends Model<VideoModel> { | |||
888 | const detailsJson = { | 894 | const detailsJson = { |
889 | privacyLabel, | 895 | privacyLabel, |
890 | privacy: this.privacy, | 896 | privacy: this.privacy, |
897 | support: this.support, | ||
891 | descriptionPath: this.getDescriptionPath(), | 898 | descriptionPath: this.getDescriptionPath(), |
892 | channel: this.VideoChannel.toFormattedJSON(), | 899 | channel: this.VideoChannel.toFormattedJSON(), |
893 | account: this.VideoChannel.Account.toFormattedJSON(), | 900 | account: this.VideoChannel.Account.toFormattedJSON(), |
@@ -917,7 +924,7 @@ export class VideoModel extends Model<VideoModel> { | |||
917 | return -1 | 924 | return -1 |
918 | }) | 925 | }) |
919 | 926 | ||
920 | return Object.assign(formattedJson, detailsJson) as VideoDetails | 927 | return Object.assign(formattedJson, detailsJson) |
921 | } | 928 | } |
922 | 929 | ||
923 | toActivityPubObject (): VideoTorrentObject { | 930 | toActivityPubObject (): VideoTorrentObject { |
@@ -957,17 +964,6 @@ export class VideoModel extends Model<VideoModel> { | |||
957 | let dislikesObject | 964 | let dislikesObject |
958 | 965 | ||
959 | if (Array.isArray(this.AccountVideoRates)) { | 966 | if (Array.isArray(this.AccountVideoRates)) { |
960 | const likes: string[] = [] | ||
961 | const dislikes: string[] = [] | ||
962 | |||
963 | for (const rate of this.AccountVideoRates) { | ||
964 | if (rate.type === 'like') { | ||
965 | likes.push(rate.Account.Actor.url) | ||
966 | } else if (rate.type === 'dislike') { | ||
967 | dislikes.push(rate.Account.Actor.url) | ||
968 | } | ||
969 | } | ||
970 | |||
971 | const res = this.toRatesActivityPubObjects() | 967 | const res = this.toRatesActivityPubObjects() |
972 | likesObject = res.likesObject | 968 | likesObject = res.likesObject |
973 | dislikesObject = res.dislikesObject | 969 | dislikesObject = res.dislikesObject |
@@ -1032,6 +1028,7 @@ export class VideoModel extends Model<VideoModel> { | |||
1032 | updated: this.updatedAt.toISOString(), | 1028 | updated: this.updatedAt.toISOString(), |
1033 | mediaType: 'text/markdown', | 1029 | mediaType: 'text/markdown', |
1034 | content: this.getTruncatedDescription(), | 1030 | content: this.getTruncatedDescription(), |
1031 | support: this.support, | ||
1035 | icon: { | 1032 | icon: { |
1036 | type: 'Image', | 1033 | type: 'Image', |
1037 | url: this.getThumbnailUrl(baseUrlHttp), | 1034 | url: this.getThumbnailUrl(baseUrlHttp), |
diff --git a/server/tests/api/check-params/users.ts b/server/tests/api/check-params/users.ts index d9dea0713..ee591d620 100644 --- a/server/tests/api/check-params/users.ts +++ b/server/tests/api/check-params/users.ts | |||
@@ -255,6 +255,14 @@ describe('Test users API validators', function () { | |||
255 | await makePutBodyRequest({ url: server.url, path: path + 'me', token: 'super token', fields, statusCodeExpected: 401 }) | 255 | await makePutBodyRequest({ url: server.url, path: path + 'me', token: 'super token', fields, statusCodeExpected: 401 }) |
256 | }) | 256 | }) |
257 | 257 | ||
258 | it('Should fail with a too long description', async function () { | ||
259 | const fields = { | ||
260 | description: 'super'.repeat(60) | ||
261 | } | ||
262 | |||
263 | await makePutBodyRequest({ url: server.url, path: path + 'me', token: userAccessToken, fields }) | ||
264 | }) | ||
265 | |||
258 | it('Should succeed with the correct params', async function () { | 266 | it('Should succeed with the correct params', async function () { |
259 | const fields = { | 267 | const fields = { |
260 | password: 'my super password', | 268 | password: 'my super password', |
diff --git a/server/tests/api/check-params/video-channels.ts b/server/tests/api/check-params/video-channels.ts index d073e28f0..43c5462ee 100644 --- a/server/tests/api/check-params/video-channels.ts +++ b/server/tests/api/check-params/video-channels.ts | |||
@@ -62,7 +62,8 @@ describe('Test videos API validator', function () { | |||
62 | describe('When adding a video channel', function () { | 62 | describe('When adding a video channel', function () { |
63 | const baseCorrectParams = { | 63 | const baseCorrectParams = { |
64 | name: 'hello', | 64 | name: 'hello', |
65 | description: 'super description' | 65 | description: 'super description', |
66 | support: 'super support text' | ||
66 | } | 67 | } |
67 | 68 | ||
68 | it('Should fail with a non authenticated user', async function () { | 69 | it('Should fail with a non authenticated user', async function () { |
@@ -89,13 +90,18 @@ describe('Test videos API validator', function () { | |||
89 | await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields }) | 90 | await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields }) |
90 | }) | 91 | }) |
91 | 92 | ||
93 | it('Should fail with a long support text', async function () { | ||
94 | const fields = immutableAssign(baseCorrectParams, { support: 'super'.repeat(70) }) | ||
95 | await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields }) | ||
96 | }) | ||
97 | |||
92 | it('Should succeed with the correct parameters', async function () { | 98 | it('Should succeed with the correct parameters', async function () { |
93 | await makePostBodyRequest({ | 99 | await makePostBodyRequest({ |
94 | url: server.url, | 100 | url: server.url, |
95 | path, | 101 | path, |
96 | token: server.accessToken, | 102 | token: server.accessToken, |
97 | fields: baseCorrectParams, | 103 | fields: baseCorrectParams, |
98 | statusCodeExpected: 204 | 104 | statusCodeExpected: 200 |
99 | }) | 105 | }) |
100 | }) | 106 | }) |
101 | }) | 107 | }) |
@@ -143,6 +149,11 @@ describe('Test videos API validator', function () { | |||
143 | await makePutBodyRequest({ url: server.url, path: path + '/' + videoChannelId, token: server.accessToken, fields }) | 149 | await makePutBodyRequest({ url: server.url, path: path + '/' + videoChannelId, token: server.accessToken, fields }) |
144 | }) | 150 | }) |
145 | 151 | ||
152 | it('Should fail with a long support text', async function () { | ||
153 | const fields = immutableAssign(baseCorrectParams, { support: 'super'.repeat(70) }) | ||
154 | await makePutBodyRequest({ url: server.url, path: path + '/' + videoChannelId, token: server.accessToken, fields }) | ||
155 | }) | ||
156 | |||
146 | it('Should succeed with the correct parameters', async function () { | 157 | it('Should succeed with the correct parameters', async function () { |
147 | await makePutBodyRequest({ | 158 | await makePutBodyRequest({ |
148 | url: server.url, | 159 | url: server.url, |
diff --git a/server/tests/api/check-params/videos.ts b/server/tests/api/check-params/videos.ts index aa30b721b..1d5c8543d 100644 --- a/server/tests/api/check-params/videos.ts +++ b/server/tests/api/check-params/videos.ts | |||
@@ -102,6 +102,7 @@ describe('Test videos API validator', function () { | |||
102 | nsfw: false, | 102 | nsfw: false, |
103 | commentsEnabled: true, | 103 | commentsEnabled: true, |
104 | description: 'my super description', | 104 | description: 'my super description', |
105 | support: 'my super support text', | ||
105 | tags: [ 'tag1', 'tag2' ], | 106 | tags: [ 'tag1', 'tag2' ], |
106 | privacy: VideoPrivacy.PUBLIC, | 107 | privacy: VideoPrivacy.PUBLIC, |
107 | channelId | 108 | channelId |
@@ -178,7 +179,14 @@ describe('Test videos API validator', function () { | |||
178 | }) | 179 | }) |
179 | 180 | ||
180 | it('Should fail with a long description', async function () { | 181 | it('Should fail with a long description', async function () { |
181 | const fields = immutableAssign(baseCorrectParams, { description: 'super'.repeat(1500) }) | 182 | const fields = immutableAssign(baseCorrectParams, { description: 'super'.repeat(2500) }) |
183 | const attaches = baseCorrectAttaches | ||
184 | |||
185 | await makeUploadRequest({ url: server.url, path: path + '/upload', token: server.accessToken, fields, attaches }) | ||
186 | }) | ||
187 | |||
188 | it('Should fail with a long support text', async function () { | ||
189 | const fields = immutableAssign(baseCorrectParams, { support: 'super'.repeat(70) }) | ||
182 | const attaches = baseCorrectAttaches | 190 | const attaches = baseCorrectAttaches |
183 | 191 | ||
184 | await makeUploadRequest({ url: server.url, path: path + '/upload', token: server.accessToken, fields, attaches }) | 192 | await makeUploadRequest({ url: server.url, path: path + '/upload', token: server.accessToken, fields, attaches }) |
@@ -417,7 +425,13 @@ describe('Test videos API validator', function () { | |||
417 | }) | 425 | }) |
418 | 426 | ||
419 | it('Should fail with a long description', async function () { | 427 | it('Should fail with a long description', async function () { |
420 | const fields = immutableAssign(baseCorrectParams, { description: 'super'.repeat(1500) }) | 428 | const fields = immutableAssign(baseCorrectParams, { description: 'super'.repeat(2500) }) |
429 | |||
430 | await makePutBodyRequest({ url: server.url, path: path + videoId, token: server.accessToken, fields }) | ||
431 | }) | ||
432 | |||
433 | it('Should fail with a long support text', async function () { | ||
434 | const fields = immutableAssign(baseCorrectParams, { support: 'super'.repeat(70) }) | ||
421 | 435 | ||
422 | await makePutBodyRequest({ url: server.url, path: path + videoId, token: server.accessToken, fields }) | 436 | await makePutBodyRequest({ url: server.url, path: path + videoId, token: server.accessToken, fields }) |
423 | }) | 437 | }) |
diff --git a/server/tests/api/server/follows.ts b/server/tests/api/server/follows.ts index 46ad4879e..19b843861 100644 --- a/server/tests/api/server/follows.ts +++ b/server/tests/api/server/follows.ts | |||
@@ -280,6 +280,7 @@ describe('Test follows', function () { | |||
280 | language: 3, | 280 | language: 3, |
281 | nsfw: true, | 281 | nsfw: true, |
282 | description: 'my super description', | 282 | description: 'my super description', |
283 | support: 'my super support text', | ||
283 | host: 'localhost:9003', | 284 | host: 'localhost:9003', |
284 | account: 'root', | 285 | account: 'root', |
285 | isLocal, | 286 | isLocal, |
diff --git a/server/tests/api/server/handle-down.ts b/server/tests/api/server/handle-down.ts index 4cedeb89e..84153b097 100644 --- a/server/tests/api/server/handle-down.ts +++ b/server/tests/api/server/handle-down.ts | |||
@@ -36,6 +36,7 @@ describe('Test handle downs', function () { | |||
36 | nsfw: true, | 36 | nsfw: true, |
37 | privacy: VideoPrivacy.PUBLIC, | 37 | privacy: VideoPrivacy.PUBLIC, |
38 | description: 'my super description for server 1', | 38 | description: 'my super description for server 1', |
39 | support: 'my super support text for server 1', | ||
39 | tags: [ 'tag1p1', 'tag2p1' ], | 40 | tags: [ 'tag1p1', 'tag2p1' ], |
40 | fixture: 'video_short1.webm' | 41 | fixture: 'video_short1.webm' |
41 | } | 42 | } |
@@ -51,6 +52,7 @@ describe('Test handle downs', function () { | |||
51 | language: 9, | 52 | language: 9, |
52 | nsfw: true, | 53 | nsfw: true, |
53 | description: 'my super description for server 1', | 54 | description: 'my super description for server 1', |
55 | support: 'my super support text for server 1', | ||
54 | host: 'localhost:9001', | 56 | host: 'localhost:9001', |
55 | account: 'root', | 57 | account: 'root', |
56 | isLocal: false, | 58 | isLocal: false, |
diff --git a/server/tests/api/users/users-multiple-servers.ts b/server/tests/api/users/users-multiple-servers.ts index 3c4eaff14..bb458f7a5 100644 --- a/server/tests/api/users/users-multiple-servers.ts +++ b/server/tests/api/users/users-multiple-servers.ts | |||
@@ -3,7 +3,10 @@ | |||
3 | import * as chai from 'chai' | 3 | import * as chai from 'chai' |
4 | import 'mocha' | 4 | import 'mocha' |
5 | import { Account } from '../../../../shared/models/actors' | 5 | import { Account } from '../../../../shared/models/actors' |
6 | import { checkVideoFilesWereRemoved, createUser, doubleFollow, flushAndRunMultipleServers, removeUser, userLogin, wait } from '../../utils' | 6 | import { |
7 | checkVideoFilesWereRemoved, createUser, doubleFollow, flushAndRunMultipleServers, removeUser, updateMyUser, userLogin, | ||
8 | wait | ||
9 | } from '../../utils' | ||
7 | import { flushTests, getMyUserInformation, killallServers, ServerInfo, testImage, updateMyAvatar, uploadVideo } from '../../utils/index' | 10 | import { flushTests, getMyUserInformation, killallServers, ServerInfo, testImage, updateMyAvatar, uploadVideo } from '../../utils/index' |
8 | import { checkActorFilesWereRemoved, getAccount, getAccountsList } from '../../utils/users/accounts' | 11 | import { checkActorFilesWereRemoved, getAccount, getAccountsList } from '../../utils/users/accounts' |
9 | import { setAccessTokensToServers } from '../../utils/users/login' | 12 | import { setAccessTokensToServers } from '../../utils/users/login' |
@@ -51,6 +54,22 @@ describe('Test users with multiple servers', function () { | |||
51 | await wait(5000) | 54 | await wait(5000) |
52 | }) | 55 | }) |
53 | 56 | ||
57 | it('Should be able to update my description', async function () { | ||
58 | this.timeout(10000) | ||
59 | |||
60 | await updateMyUser({ | ||
61 | url: servers[0].url, | ||
62 | accessToken: servers[0].accessToken, | ||
63 | description: 'my super description updated' | ||
64 | }) | ||
65 | |||
66 | const res = await getMyUserInformation(servers[0].url, servers[0].accessToken) | ||
67 | user = res.body | ||
68 | expect(user.account.description).to.equal('my super description updated') | ||
69 | |||
70 | await wait(5000) | ||
71 | }) | ||
72 | |||
54 | it('Should be able to update my avatar', async function () { | 73 | it('Should be able to update my avatar', async function () { |
55 | this.timeout(10000) | 74 | this.timeout(10000) |
56 | 75 | ||
@@ -70,7 +89,7 @@ describe('Test users with multiple servers', function () { | |||
70 | await wait(5000) | 89 | await wait(5000) |
71 | }) | 90 | }) |
72 | 91 | ||
73 | it('Should have updated my avatar on other servers too', async function () { | 92 | it('Should have updated my avatar and my description on other servers too', async function () { |
74 | for (const server of servers) { | 93 | for (const server of servers) { |
75 | const resAccounts = await getAccountsList(server.url, '-createdAt') | 94 | const resAccounts = await getAccountsList(server.url, '-createdAt') |
76 | 95 | ||
@@ -81,6 +100,7 @@ describe('Test users with multiple servers', function () { | |||
81 | const rootServer1Get = resAccount.body as Account | 100 | const rootServer1Get = resAccount.body as Account |
82 | expect(rootServer1Get.name).to.equal('root') | 101 | expect(rootServer1Get.name).to.equal('root') |
83 | expect(rootServer1Get.host).to.equal('localhost:9001') | 102 | expect(rootServer1Get.host).to.equal('localhost:9001') |
103 | expect(rootServer1Get.description).to.equal('my super description updated') | ||
84 | 104 | ||
85 | await testImage(server.url, 'avatar2-resized', rootServer1Get.avatar.path, '.png') | 105 | await testImage(server.url, 'avatar2-resized', rootServer1Get.avatar.path, '.png') |
86 | } | 106 | } |
diff --git a/server/tests/api/users/users.ts b/server/tests/api/users/users.ts index ac167d4f9..c650a74f5 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.description).to.be.null | ||
175 | }) | 176 | }) |
176 | 177 | ||
177 | it('Should be able to upload a video with this user', async function () { | 178 | it('Should be able to upload a video with this user', async function () { |
@@ -315,6 +316,7 @@ describe('Test users', function () { | |||
315 | expect(user.displayNSFW).to.be.ok | 316 | expect(user.displayNSFW).to.be.ok |
316 | expect(user.videoQuota).to.equal(2 * 1024 * 1024) | 317 | expect(user.videoQuota).to.equal(2 * 1024 * 1024) |
317 | expect(user.id).to.be.a('number') | 318 | expect(user.id).to.be.a('number') |
319 | expect(user.account.description).to.be.null | ||
318 | }) | 320 | }) |
319 | 321 | ||
320 | it('Should be able to change the autoPlayVideo attribute', async function () { | 322 | it('Should be able to change the autoPlayVideo attribute', async function () { |
@@ -345,6 +347,7 @@ describe('Test users', function () { | |||
345 | expect(user.displayNSFW).to.be.ok | 347 | expect(user.displayNSFW).to.be.ok |
346 | expect(user.videoQuota).to.equal(2 * 1024 * 1024) | 348 | expect(user.videoQuota).to.equal(2 * 1024 * 1024) |
347 | expect(user.id).to.be.a('number') | 349 | expect(user.id).to.be.a('number') |
350 | expect(user.account.description).to.be.null | ||
348 | }) | 351 | }) |
349 | 352 | ||
350 | it('Should be able to update my avatar', async function () { | 353 | it('Should be able to update my avatar', async function () { |
@@ -362,6 +365,24 @@ describe('Test users', function () { | |||
362 | await testImage(server.url, 'avatar-resized', user.account.avatar.path, '.png') | 365 | await testImage(server.url, 'avatar-resized', user.account.avatar.path, '.png') |
363 | }) | 366 | }) |
364 | 367 | ||
368 | it('Should be able to update my description', async function () { | ||
369 | await updateMyUser({ | ||
370 | url: server.url, | ||
371 | accessToken: accessTokenUser, | ||
372 | description: 'my super description updated' | ||
373 | }) | ||
374 | |||
375 | const res = await getMyUserInformation(server.url, accessTokenUser) | ||
376 | const user = res.body | ||
377 | |||
378 | expect(user.username).to.equal('user_1') | ||
379 | expect(user.email).to.equal('updated@example.com') | ||
380 | expect(user.displayNSFW).to.be.ok | ||
381 | expect(user.videoQuota).to.equal(2 * 1024 * 1024) | ||
382 | expect(user.id).to.be.a('number') | ||
383 | expect(user.account.description).to.equal('my super description updated') | ||
384 | }) | ||
385 | |||
365 | it('Should be able to update another user', async function () { | 386 | it('Should be able to update another user', async function () { |
366 | await updateUser({ | 387 | await updateUser({ |
367 | url: server.url, | 388 | url: server.url, |
diff --git a/server/tests/api/videos/multiple-servers.ts b/server/tests/api/videos/multiple-servers.ts index 85d158d61..c82ac1348 100644 --- a/server/tests/api/videos/multiple-servers.ts +++ b/server/tests/api/videos/multiple-servers.ts | |||
@@ -70,6 +70,7 @@ describe('Test multiple servers', function () { | |||
70 | language: 9, | 70 | language: 9, |
71 | nsfw: true, | 71 | nsfw: true, |
72 | description: 'my super description for server 1', | 72 | description: 'my super description for server 1', |
73 | support: 'my super support text for server 1', | ||
73 | tags: [ 'tag1p1', 'tag2p1' ], | 74 | tags: [ 'tag1p1', 'tag2p1' ], |
74 | channelId: videoChannelId, | 75 | channelId: videoChannelId, |
75 | fixture: 'video_short1.webm' | 76 | fixture: 'video_short1.webm' |
@@ -88,6 +89,7 @@ describe('Test multiple servers', function () { | |||
88 | language: 9, | 89 | language: 9, |
89 | nsfw: true, | 90 | nsfw: true, |
90 | description: 'my super description for server 1', | 91 | description: 'my super description for server 1', |
92 | support: 'my super support text for server 1', | ||
91 | host: 'localhost:9001', | 93 | host: 'localhost:9001', |
92 | account: 'root', | 94 | account: 'root', |
93 | isLocal, | 95 | isLocal, |
@@ -136,6 +138,7 @@ describe('Test multiple servers', function () { | |||
136 | language: 11, | 138 | language: 11, |
137 | nsfw: true, | 139 | nsfw: true, |
138 | description: 'my super description for server 2', | 140 | description: 'my super description for server 2', |
141 | support: 'my super support text for server 2', | ||
139 | tags: [ 'tag1p2', 'tag2p2', 'tag3p2' ], | 142 | tags: [ 'tag1p2', 'tag2p2', 'tag3p2' ], |
140 | fixture: 'video_short2.webm', | 143 | fixture: 'video_short2.webm', |
141 | thumbnailfile: 'thumbnail.jpg', | 144 | thumbnailfile: 'thumbnail.jpg', |
@@ -156,6 +159,7 @@ describe('Test multiple servers', function () { | |||
156 | language: 11, | 159 | language: 11, |
157 | nsfw: true, | 160 | nsfw: true, |
158 | description: 'my super description for server 2', | 161 | description: 'my super description for server 2', |
162 | support: 'my super support text for server 2', | ||
159 | host: 'localhost:9002', | 163 | host: 'localhost:9002', |
160 | account: 'user1', | 164 | account: 'user1', |
161 | isLocal, | 165 | isLocal, |
@@ -211,6 +215,7 @@ describe('Test multiple servers', function () { | |||
211 | language: 11, | 215 | language: 11, |
212 | nsfw: true, | 216 | nsfw: true, |
213 | description: 'my super description for server 3', | 217 | description: 'my super description for server 3', |
218 | support: 'my super support text for server 3', | ||
214 | tags: [ 'tag1p3' ], | 219 | tags: [ 'tag1p3' ], |
215 | fixture: 'video_short3.webm' | 220 | fixture: 'video_short3.webm' |
216 | } | 221 | } |
@@ -223,6 +228,7 @@ describe('Test multiple servers', function () { | |||
223 | language: 12, | 228 | language: 12, |
224 | nsfw: false, | 229 | nsfw: false, |
225 | description: 'my super description for server 3-2', | 230 | description: 'my super description for server 3-2', |
231 | support: 'my super support text for server 3-2', | ||
226 | tags: [ 'tag2p3', 'tag3p3', 'tag4p3' ], | 232 | tags: [ 'tag2p3', 'tag3p3', 'tag4p3' ], |
227 | fixture: 'video_short.webm' | 233 | fixture: 'video_short.webm' |
228 | } | 234 | } |
@@ -257,6 +263,7 @@ describe('Test multiple servers', function () { | |||
257 | language: 11, | 263 | language: 11, |
258 | nsfw: true, | 264 | nsfw: true, |
259 | description: 'my super description for server 3', | 265 | description: 'my super description for server 3', |
266 | support: 'my super support text for server 3', | ||
260 | host: 'localhost:9003', | 267 | host: 'localhost:9003', |
261 | account: 'root', | 268 | account: 'root', |
262 | isLocal, | 269 | isLocal, |
@@ -286,6 +293,7 @@ describe('Test multiple servers', function () { | |||
286 | language: 12, | 293 | language: 12, |
287 | nsfw: false, | 294 | nsfw: false, |
288 | description: 'my super description for server 3-2', | 295 | description: 'my super description for server 3-2', |
296 | support: 'my super support text for server 3-2', | ||
289 | host: 'localhost:9003', | 297 | host: 'localhost:9003', |
290 | account: 'root', | 298 | account: 'root', |
291 | commentsEnabled: true, | 299 | commentsEnabled: true, |
@@ -525,6 +533,7 @@ describe('Test multiple servers', function () { | |||
525 | language: 13, | 533 | language: 13, |
526 | nsfw: true, | 534 | nsfw: true, |
527 | description: 'my super description updated', | 535 | description: 'my super description updated', |
536 | support: 'my super support text updated', | ||
528 | tags: [ 'tag_up_1', 'tag_up_2' ], | 537 | tags: [ 'tag_up_1', 'tag_up_2' ], |
529 | thumbnailfile: 'thumbnail.jpg', | 538 | thumbnailfile: 'thumbnail.jpg', |
530 | previewfile: 'preview.jpg' | 539 | previewfile: 'preview.jpg' |
@@ -553,6 +562,7 @@ describe('Test multiple servers', function () { | |||
553 | language: 13, | 562 | language: 13, |
554 | nsfw: true, | 563 | nsfw: true, |
555 | description: 'my super description updated', | 564 | description: 'my super description updated', |
565 | support: 'my super support text updated', | ||
556 | host: 'localhost:9003', | 566 | host: 'localhost:9003', |
557 | account: 'root', | 567 | account: 'root', |
558 | isLocal, | 568 | isLocal, |
@@ -841,6 +851,7 @@ describe('Test multiple servers', function () { | |||
841 | language: null, | 851 | language: null, |
842 | nsfw: false, | 852 | nsfw: false, |
843 | description: null, | 853 | description: null, |
854 | support: null, | ||
844 | host: 'localhost:9002', | 855 | host: 'localhost:9002', |
845 | account: 'root', | 856 | account: 'root', |
846 | isLocal, | 857 | isLocal, |
diff --git a/server/tests/api/videos/single-server.ts b/server/tests/api/videos/single-server.ts index 8f55075fb..83b6a0e9a 100644 --- a/server/tests/api/videos/single-server.ts +++ b/server/tests/api/videos/single-server.ts | |||
@@ -26,6 +26,7 @@ describe('Test a single server', function () { | |||
26 | language: 3, | 26 | language: 3, |
27 | nsfw: true, | 27 | nsfw: true, |
28 | description: 'my super description', | 28 | description: 'my super description', |
29 | support: 'my super support text', | ||
29 | host: 'localhost:9001', | 30 | host: 'localhost:9001', |
30 | account: 'root', | 31 | account: 'root', |
31 | isLocal: true, | 32 | isLocal: true, |
@@ -54,6 +55,7 @@ describe('Test a single server', function () { | |||
54 | language: 5, | 55 | language: 5, |
55 | nsfw: false, | 56 | nsfw: false, |
56 | description: 'my super description updated', | 57 | description: 'my super description updated', |
58 | support: 'my super support text updated', | ||
57 | host: 'localhost:9001', | 59 | host: 'localhost:9001', |
58 | account: 'root', | 60 | account: 'root', |
59 | isLocal: true, | 61 | isLocal: true, |
diff --git a/server/tests/api/videos/video-channels.ts b/server/tests/api/videos/video-channels.ts index 25b7ad6ab..b9c9bbf3c 100644 --- a/server/tests/api/videos/video-channels.ts +++ b/server/tests/api/videos/video-channels.ts | |||
@@ -1,27 +1,27 @@ | |||
1 | /* tslint:disable:no-unused-expression */ | 1 | /* tslint:disable:no-unused-expression */ |
2 | 2 | ||
3 | import 'mocha' | ||
4 | import * as chai from 'chai' | 3 | import * as chai from 'chai' |
5 | const expect = chai.expect | 4 | import 'mocha' |
6 | 5 | import { User } from '../../../../shared/index' | |
6 | import { doubleFollow, flushAndRunMultipleServers, uploadVideo, wait } from '../../utils' | ||
7 | import { | 7 | import { |
8 | ServerInfo, | 8 | addVideoChannel, |
9 | deleteVideoChannel, | ||
9 | flushTests, | 10 | flushTests, |
10 | runServer, | 11 | getAccountVideoChannelsList, |
11 | setAccessTokensToServers, | ||
12 | killallServers, | ||
13 | getMyUserInformation, | 12 | getMyUserInformation, |
13 | getVideoChannel, | ||
14 | getVideoChannelsList, | 14 | getVideoChannelsList, |
15 | addVideoChannel, | 15 | killallServers, |
16 | getAccountVideoChannelsList, | 16 | ServerInfo, |
17 | updateVideoChannel, | 17 | setAccessTokensToServers, |
18 | deleteVideoChannel, | 18 | updateVideoChannel |
19 | getVideoChannel | ||
20 | } from '../../utils/index' | 19 | } from '../../utils/index' |
21 | import { User } from '../../../../shared/index' | ||
22 | 20 | ||
23 | describe('Test a video channels', function () { | 21 | const expect = chai.expect |
24 | let server: ServerInfo | 22 | |
23 | describe('Test video channels', function () { | ||
24 | let servers: ServerInfo[] | ||
25 | let userInfo: User | 25 | let userInfo: User |
26 | let videoChannelId: number | 26 | let videoChannelId: number |
27 | 27 | ||
@@ -30,29 +30,41 @@ describe('Test a video channels', function () { | |||
30 | 30 | ||
31 | await flushTests() | 31 | await flushTests() |
32 | 32 | ||
33 | server = await runServer(1) | 33 | servers = await flushAndRunMultipleServers(2) |
34 | |||
35 | await setAccessTokensToServers(servers) | ||
36 | await doubleFollow(servers[0], servers[1]) | ||
34 | 37 | ||
35 | await setAccessTokensToServers([ server ]) | 38 | await wait(5000) |
36 | }) | 39 | }) |
37 | 40 | ||
38 | it('Should have one video channel (created with root)', async () => { | 41 | it('Should have one video channel (created with root)', async () => { |
39 | const res = await getVideoChannelsList(server.url, 0, 2) | 42 | const res = await getVideoChannelsList(servers[0].url, 0, 2) |
40 | 43 | ||
41 | expect(res.body.total).to.equal(1) | 44 | expect(res.body.total).to.equal(1) |
42 | expect(res.body.data).to.be.an('array') | 45 | expect(res.body.data).to.be.an('array') |
43 | expect(res.body.data).to.have.lengthOf(1) | 46 | expect(res.body.data).to.have.lengthOf(1) |
44 | }) | 47 | }) |
45 | 48 | ||
46 | it('Should create another video channel', async () => { | 49 | it('Should create another video channel', async function () { |
50 | this.timeout(10000) | ||
51 | |||
47 | const videoChannel = { | 52 | const videoChannel = { |
48 | name: 'second video channel', | 53 | name: 'second video channel', |
49 | description: 'super video channel description' | 54 | description: 'super video channel description', |
55 | support: 'super video channel support text' | ||
50 | } | 56 | } |
51 | await addVideoChannel(server.url, server.accessToken, videoChannel) | 57 | const res = await addVideoChannel(servers[0].url, servers[0].accessToken, videoChannel) |
58 | videoChannelId = res.body.videoChannel.id | ||
59 | |||
60 | // The channel is 1 is propagated to servers 2 | ||
61 | await uploadVideo(servers[0].url, servers[0].accessToken, { channelId: videoChannelId }) | ||
62 | |||
63 | await wait(3000) | ||
52 | }) | 64 | }) |
53 | 65 | ||
54 | it('Should have two video channels when getting my information', async () => { | 66 | it('Should have two video channels when getting my information', async () => { |
55 | const res = await getMyUserInformation(server.url, server.accessToken) | 67 | const res = await getMyUserInformation(servers[0].url, servers[0].accessToken) |
56 | userInfo = res.body | 68 | userInfo = res.body |
57 | 69 | ||
58 | expect(userInfo.videoChannels).to.be.an('array') | 70 | expect(userInfo.videoChannels).to.be.an('array') |
@@ -62,11 +74,11 @@ describe('Test a video channels', function () { | |||
62 | expect(videoChannels[0].displayName).to.equal('Default root channel') | 74 | expect(videoChannels[0].displayName).to.equal('Default root channel') |
63 | expect(videoChannels[1].displayName).to.equal('second video channel') | 75 | expect(videoChannels[1].displayName).to.equal('second video channel') |
64 | expect(videoChannels[1].description).to.equal('super video channel description') | 76 | expect(videoChannels[1].description).to.equal('super video channel description') |
77 | expect(videoChannels[1].support).to.equal('super video channel support text') | ||
65 | }) | 78 | }) |
66 | 79 | ||
67 | it('Should have two video channels when getting account channels', async () => { | 80 | it('Should have two video channels when getting account channels on server 1', async function () { |
68 | const res = await getAccountVideoChannelsList(server.url, userInfo.account.uuid) | 81 | const res = await getAccountVideoChannelsList(servers[0].url, userInfo.account.uuid) |
69 | |||
70 | expect(res.body.total).to.equal(2) | 82 | expect(res.body.total).to.equal(2) |
71 | expect(res.body.data).to.be.an('array') | 83 | expect(res.body.data).to.be.an('array') |
72 | expect(res.body.data).to.have.lengthOf(2) | 84 | expect(res.body.data).to.have.lengthOf(2) |
@@ -75,12 +87,23 @@ describe('Test a video channels', function () { | |||
75 | expect(videoChannels[0].displayName).to.equal('Default root channel') | 87 | expect(videoChannels[0].displayName).to.equal('Default root channel') |
76 | expect(videoChannels[1].displayName).to.equal('second video channel') | 88 | expect(videoChannels[1].displayName).to.equal('second video channel') |
77 | expect(videoChannels[1].description).to.equal('super video channel description') | 89 | expect(videoChannels[1].description).to.equal('super video channel description') |
90 | expect(videoChannels[1].support).to.equal('super video channel support text') | ||
91 | }) | ||
92 | |||
93 | it('Should have one video channel when getting account channels on server 2', async function () { | ||
94 | const res = await getAccountVideoChannelsList(servers[1].url, userInfo.account.uuid) | ||
95 | expect(res.body.total).to.equal(1) | ||
96 | expect(res.body.data).to.be.an('array') | ||
97 | expect(res.body.data).to.have.lengthOf(1) | ||
78 | 98 | ||
79 | videoChannelId = videoChannels[1].id | 99 | const videoChannels = res.body.data |
100 | expect(videoChannels[0].displayName).to.equal('second video channel') | ||
101 | expect(videoChannels[0].description).to.equal('super video channel description') | ||
102 | expect(videoChannels[0].support).to.equal('super video channel support text') | ||
80 | }) | 103 | }) |
81 | 104 | ||
82 | it('Should list video channels', async () => { | 105 | it('Should list video channels', async function () { |
83 | const res = await getVideoChannelsList(server.url, 1, 1, '-name') | 106 | const res = await getVideoChannelsList(servers[0].url, 1, 1, '-name') |
84 | 107 | ||
85 | expect(res.body.total).to.equal(2) | 108 | expect(res.body.total).to.equal(2) |
86 | expect(res.body.data).to.be.an('array') | 109 | expect(res.body.data).to.be.an('array') |
@@ -88,39 +111,48 @@ describe('Test a video channels', function () { | |||
88 | expect(res.body.data[0].displayName).to.equal('Default root channel') | 111 | expect(res.body.data[0].displayName).to.equal('Default root channel') |
89 | }) | 112 | }) |
90 | 113 | ||
91 | it('Should update video channel', async () => { | 114 | it('Should update video channel', async function () { |
115 | this.timeout(5000) | ||
116 | |||
92 | const videoChannelAttributes = { | 117 | const videoChannelAttributes = { |
93 | name: 'video channel updated', | 118 | name: 'video channel updated', |
94 | description: 'video channel description updated' | 119 | description: 'video channel description updated', |
120 | support: 'video channel support text updated' | ||
95 | } | 121 | } |
96 | 122 | ||
97 | await updateVideoChannel(server.url, server.accessToken, videoChannelId, videoChannelAttributes) | 123 | await updateVideoChannel(servers[0].url, servers[0].accessToken, videoChannelId, videoChannelAttributes) |
124 | |||
125 | await wait(3000) | ||
98 | }) | 126 | }) |
99 | 127 | ||
100 | it('Should have video channel updated', async () => { | 128 | it('Should have video channel updated', async function () { |
101 | const res = await getVideoChannelsList(server.url, 0, 1, '-name') | 129 | for (const server of servers) { |
130 | const res = await getVideoChannelsList(server.url, 0, 1, '-name') | ||
102 | 131 | ||
103 | expect(res.body.total).to.equal(2) | 132 | expect(res.body.total).to.equal(2) |
104 | expect(res.body.data).to.be.an('array') | 133 | expect(res.body.data).to.be.an('array') |
105 | expect(res.body.data).to.have.lengthOf(1) | 134 | expect(res.body.data).to.have.lengthOf(1) |
106 | expect(res.body.data[0].displayName).to.equal('video channel updated') | 135 | expect(res.body.data[0].displayName).to.equal('video channel updated') |
107 | expect(res.body.data[0].description).to.equal('video channel description updated') | 136 | expect(res.body.data[0].description).to.equal('video channel description updated') |
137 | expect(res.body.data[0].support).to.equal('video channel support text updated') | ||
138 | } | ||
108 | }) | 139 | }) |
109 | 140 | ||
110 | it('Should get video channel', async () => { | 141 | it('Should get video channel', async function () { |
111 | const res = await getVideoChannel(server.url, videoChannelId) | 142 | const res = await getVideoChannel(servers[0].url, videoChannelId) |
112 | 143 | ||
113 | const videoChannel = res.body | 144 | const videoChannel = res.body |
114 | expect(videoChannel.displayName).to.equal('video channel updated') | 145 | expect(videoChannel.displayName).to.equal('video channel updated') |
115 | expect(videoChannel.description).to.equal('video channel description updated') | 146 | expect(videoChannel.description).to.equal('video channel description updated') |
147 | expect(videoChannel.support).to.equal('video channel support text updated') | ||
116 | }) | 148 | }) |
117 | 149 | ||
118 | it('Should delete video channel', async () => { | 150 | it('Should delete video channel', async function () { |
119 | await deleteVideoChannel(server.url, server.accessToken, videoChannelId) | 151 | await deleteVideoChannel(servers[0].url, servers[0].accessToken, videoChannelId) |
120 | }) | 152 | }) |
121 | 153 | ||
122 | it('Should have video channel deleted', async () => { | 154 | it('Should have video channel deleted', async function () { |
123 | const res = await getVideoChannelsList(server.url, 0, 10) | 155 | const res = await getVideoChannelsList(servers[0].url, 0, 10) |
124 | 156 | ||
125 | expect(res.body.total).to.equal(1) | 157 | expect(res.body.total).to.equal(1) |
126 | expect(res.body.data).to.be.an('array') | 158 | expect(res.body.data).to.be.an('array') |
@@ -129,7 +161,7 @@ describe('Test a video channels', function () { | |||
129 | }) | 161 | }) |
130 | 162 | ||
131 | after(async function () { | 163 | after(async function () { |
132 | killallServers([ server ]) | 164 | killallServers(servers) |
133 | 165 | ||
134 | // Keep the logs if the test failed | 166 | // Keep the logs if the test failed |
135 | if (this['ok']) { | 167 | if (this['ok']) { |
diff --git a/server/tests/utils/users/users.ts b/server/tests/utils/users/users.ts index 3c9d46246..daf731a14 100644 --- a/server/tests/utils/users/users.ts +++ b/server/tests/utils/users/users.ts | |||
@@ -131,6 +131,7 @@ function updateMyUser (options: { | |||
131 | displayNSFW?: boolean, | 131 | displayNSFW?: boolean, |
132 | email?: string, | 132 | email?: string, |
133 | autoPlayVideo?: boolean | 133 | autoPlayVideo?: boolean |
134 | description?: string | ||
134 | }) { | 135 | }) { |
135 | const path = '/api/v1/users/me' | 136 | const path = '/api/v1/users/me' |
136 | 137 | ||
@@ -139,6 +140,7 @@ function updateMyUser (options: { | |||
139 | if (options.displayNSFW !== undefined && options.displayNSFW !== null) toSend['displayNSFW'] = options.displayNSFW | 140 | if (options.displayNSFW !== undefined && options.displayNSFW !== null) toSend['displayNSFW'] = options.displayNSFW |
140 | if (options.autoPlayVideo !== undefined && options.autoPlayVideo !== null) toSend['autoPlayVideo'] = options.autoPlayVideo | 141 | if (options.autoPlayVideo !== undefined && options.autoPlayVideo !== null) toSend['autoPlayVideo'] = options.autoPlayVideo |
141 | if (options.email !== undefined && options.email !== null) toSend['email'] = options.email | 142 | if (options.email !== undefined && options.email !== null) toSend['email'] = options.email |
143 | if (options.description !== undefined && options.description !== null) toSend['description'] = options.description | ||
142 | 144 | ||
143 | return makePutBodyRequest({ | 145 | return makePutBodyRequest({ |
144 | url: options.url, | 146 | url: options.url, |
diff --git a/server/tests/utils/videos/video-channels.ts b/server/tests/utils/videos/video-channels.ts index 062ca8f4d..2d095d8ab 100644 --- a/server/tests/utils/videos/video-channels.ts +++ b/server/tests/utils/videos/video-channels.ts | |||
@@ -3,6 +3,7 @@ import * as request from 'supertest' | |||
3 | type VideoChannelAttributes = { | 3 | type VideoChannelAttributes = { |
4 | name?: string | 4 | name?: string |
5 | description?: string | 5 | description?: string |
6 | support?: string | ||
6 | } | 7 | } |
7 | 8 | ||
8 | function getVideoChannelsList (url: string, start: number, count: number, sort?: string) { | 9 | function getVideoChannelsList (url: string, start: number, count: number, sort?: string) { |
@@ -30,13 +31,14 @@ function getAccountVideoChannelsList (url: string, accountId: number | string, s | |||
30 | .expect('Content-Type', /json/) | 31 | .expect('Content-Type', /json/) |
31 | } | 32 | } |
32 | 33 | ||
33 | function addVideoChannel (url: string, token: string, videoChannelAttributesArg: VideoChannelAttributes, expectedStatus = 204) { | 34 | function addVideoChannel (url: string, token: string, videoChannelAttributesArg: VideoChannelAttributes, expectedStatus = 200) { |
34 | const path = '/api/v1/videos/channels' | 35 | const path = '/api/v1/videos/channels' |
35 | 36 | ||
36 | // Default attributes | 37 | // Default attributes |
37 | let attributes = { | 38 | let attributes = { |
38 | name: 'my super video channel', | 39 | name: 'my super video channel', |
39 | description: 'my super channel description' | 40 | description: 'my super channel description', |
41 | support: 'my super channel support' | ||
40 | } | 42 | } |
41 | attributes = Object.assign(attributes, videoChannelAttributesArg) | 43 | attributes = Object.assign(attributes, videoChannelAttributesArg) |
42 | 44 | ||
@@ -54,6 +56,7 @@ function updateVideoChannel (url: string, token: string, channelId: number, attr | |||
54 | 56 | ||
55 | if (attributes.name) body['name'] = attributes.name | 57 | if (attributes.name) body['name'] = attributes.name |
56 | if (attributes.description) body['description'] = attributes.description | 58 | if (attributes.description) body['description'] = attributes.description |
59 | if (attributes.support) body['support'] = attributes.support | ||
57 | 60 | ||
58 | return request(url) | 61 | return request(url) |
59 | .put(path) | 62 | .put(path) |
diff --git a/server/tests/utils/videos/videos.ts b/server/tests/utils/videos/videos.ts index 9a4af0b9f..a06078d40 100644 --- a/server/tests/utils/videos/videos.ts +++ b/server/tests/utils/videos/videos.ts | |||
@@ -248,6 +248,7 @@ async function uploadVideo (url: string, accessToken: string, videoAttributesArg | |||
248 | channelId: defaultChannelId, | 248 | channelId: defaultChannelId, |
249 | nsfw: true, | 249 | nsfw: true, |
250 | description: 'my super description', | 250 | description: 'my super description', |
251 | support: 'my super support text', | ||
251 | tags: [ 'tag' ], | 252 | tags: [ 'tag' ], |
252 | privacy: VideoPrivacy.PUBLIC, | 253 | privacy: VideoPrivacy.PUBLIC, |
253 | commentsEnabled: true, | 254 | commentsEnabled: true, |
@@ -277,6 +278,10 @@ async function uploadVideo (url: string, accessToken: string, videoAttributesArg | |||
277 | req.field('licence', attributes.licence.toString()) | 278 | req.field('licence', attributes.licence.toString()) |
278 | } | 279 | } |
279 | 280 | ||
281 | for (let i = 0; i < attributes.tags.length; i++) { | ||
282 | req.field('tags[' + i + ']', attributes.tags[i]) | ||
283 | } | ||
284 | |||
280 | if (attributes.thumbnailfile !== undefined) { | 285 | if (attributes.thumbnailfile !== undefined) { |
281 | req.attach('thumbnailfile', buildAbsoluteFixturePath(attributes.thumbnailfile)) | 286 | req.attach('thumbnailfile', buildAbsoluteFixturePath(attributes.thumbnailfile)) |
282 | } | 287 | } |
@@ -284,10 +289,6 @@ async function uploadVideo (url: string, accessToken: string, videoAttributesArg | |||
284 | req.attach('previewfile', buildAbsoluteFixturePath(attributes.previewfile)) | 289 | req.attach('previewfile', buildAbsoluteFixturePath(attributes.previewfile)) |
285 | } | 290 | } |
286 | 291 | ||
287 | for (let i = 0; i < attributes.tags.length; i++) { | ||
288 | req.field('tags[' + i + ']', attributes.tags[i]) | ||
289 | } | ||
290 | |||
291 | return req.attach('videofile', buildAbsoluteFixturePath(attributes.fixture)) | 292 | return req.attach('videofile', buildAbsoluteFixturePath(attributes.fixture)) |
292 | .expect(specialStatus) | 293 | .expect(specialStatus) |
293 | } | 294 | } |
@@ -366,6 +367,7 @@ async function completeVideoCheck ( | |||
366 | nsfw: boolean | 367 | nsfw: boolean |
367 | commentsEnabled: boolean | 368 | commentsEnabled: boolean |
368 | description: string | 369 | description: string |
370 | support: string | ||
369 | host: string | 371 | host: string |
370 | account: string | 372 | account: string |
371 | isLocal: boolean, | 373 | isLocal: boolean, |
diff --git a/server/tools/upload.ts b/server/tools/upload.ts index 3bf9dd65e..de8ff8d26 100644 --- a/server/tools/upload.ts +++ b/server/tools/upload.ts | |||
@@ -19,6 +19,7 @@ program | |||
19 | .option('-L, --language <language number>', 'Language number') | 19 | .option('-L, --language <language number>', 'Language number') |
20 | .option('-d, --video-description <description>', 'Video description') | 20 | .option('-d, --video-description <description>', 'Video description') |
21 | .option('-t, --tags <tags>', 'Video tags', list) | 21 | .option('-t, --tags <tags>', 'Video tags', list) |
22 | .option('-b, --thumbnail <thumbnailPath>', 'Thumbnail path') | ||
22 | .option('-f, --file <file>', 'Video absolute file path') | 23 | .option('-f, --file <file>', 'Video absolute file path') |
23 | .parse(process.argv) | 24 | .parse(process.argv) |
24 | 25 | ||
@@ -72,7 +73,8 @@ async function run () { | |||
72 | description: program['videoDescription'], | 73 | description: program['videoDescription'], |
73 | tags: program['tags'], | 74 | tags: program['tags'], |
74 | commentsEnabled: program['commentsEnabled'], | 75 | commentsEnabled: program['commentsEnabled'], |
75 | fixture: program['file'] | 76 | fixture: program['file'], |
77 | thumbnailfile: program['thumbnailPath'] | ||
76 | } | 78 | } |
77 | 79 | ||
78 | await uploadVideo(program['url'], accessToken, videoAttributes) | 80 | await uploadVideo(program['url'], accessToken, videoAttributes) |