diff options
Diffstat (limited to 'server')
29 files changed, 474 insertions, 300 deletions
diff --git a/server/controllers/api/videos/index.ts b/server/controllers/api/videos/index.ts index e2798830e..63de662a7 100644 --- a/server/controllers/api/videos/index.ts +++ b/server/controllers/api/videos/index.ts | |||
@@ -15,6 +15,7 @@ import { getServerAccount } from '../../../helpers/utils' | |||
15 | import { CONFIG, VIDEO_CATEGORIES, VIDEO_LANGUAGES, VIDEO_LICENCES, VIDEO_MIMETYPE_EXT, VIDEO_PRIVACIES } from '../../../initializers' | 15 | import { CONFIG, VIDEO_CATEGORIES, VIDEO_LANGUAGES, VIDEO_LICENCES, VIDEO_MIMETYPE_EXT, VIDEO_PRIVACIES } from '../../../initializers' |
16 | import { database as db } from '../../../initializers/database' | 16 | import { database as db } from '../../../initializers/database' |
17 | import { sendAddVideo } from '../../../lib/activitypub/send/send-add' | 17 | import { sendAddVideo } from '../../../lib/activitypub/send/send-add' |
18 | import { sendCreateViewToOrigin } from '../../../lib/activitypub/send/send-create' | ||
18 | import { sendUpdateVideo } from '../../../lib/activitypub/send/send-update' | 19 | import { sendUpdateVideo } from '../../../lib/activitypub/send/send-update' |
19 | import { shareVideoByServer } from '../../../lib/activitypub/share' | 20 | import { shareVideoByServer } from '../../../lib/activitypub/share' |
20 | import { getVideoActivityPubUrl } from '../../../lib/activitypub/url' | 21 | import { getVideoActivityPubUrl } from '../../../lib/activitypub/url' |
@@ -26,7 +27,6 @@ import { | |||
26 | authenticate, | 27 | authenticate, |
27 | paginationValidator, | 28 | paginationValidator, |
28 | setPagination, | 29 | setPagination, |
29 | setVideosSearch, | ||
30 | setVideosSort, | 30 | setVideosSort, |
31 | videosAddValidator, | 31 | videosAddValidator, |
32 | videosGetValidator, | 32 | videosGetValidator, |
@@ -40,7 +40,6 @@ import { abuseVideoRouter } from './abuse' | |||
40 | import { blacklistRouter } from './blacklist' | 40 | import { blacklistRouter } from './blacklist' |
41 | import { videoChannelRouter } from './channel' | 41 | import { videoChannelRouter } from './channel' |
42 | import { rateVideoRouter } from './rate' | 42 | import { rateVideoRouter } from './rate' |
43 | import { sendCreateViewToOrigin } from '../../../lib/activitypub/send/send-create' | ||
44 | 43 | ||
45 | const videosRouter = express.Router() | 44 | const videosRouter = express.Router() |
46 | 45 | ||
@@ -84,6 +83,14 @@ videosRouter.get('/', | |||
84 | setPagination, | 83 | setPagination, |
85 | asyncMiddleware(listVideos) | 84 | asyncMiddleware(listVideos) |
86 | ) | 85 | ) |
86 | videosRouter.get('/search', | ||
87 | videosSearchValidator, | ||
88 | paginationValidator, | ||
89 | videosSortValidator, | ||
90 | setVideosSort, | ||
91 | setPagination, | ||
92 | asyncMiddleware(searchVideos) | ||
93 | ) | ||
87 | videosRouter.put('/:id', | 94 | videosRouter.put('/:id', |
88 | authenticate, | 95 | authenticate, |
89 | asyncMiddleware(videosUpdateValidator), | 96 | asyncMiddleware(videosUpdateValidator), |
@@ -115,16 +122,6 @@ videosRouter.delete('/:id', | |||
115 | asyncMiddleware(removeVideoRetryWrapper) | 122 | asyncMiddleware(removeVideoRetryWrapper) |
116 | ) | 123 | ) |
117 | 124 | ||
118 | videosRouter.get('/search/:value', | ||
119 | videosSearchValidator, | ||
120 | paginationValidator, | ||
121 | videosSortValidator, | ||
122 | setVideosSort, | ||
123 | setPagination, | ||
124 | setVideosSearch, | ||
125 | asyncMiddleware(searchVideos) | ||
126 | ) | ||
127 | |||
128 | // --------------------------------------------------------------------------- | 125 | // --------------------------------------------------------------------------- |
129 | 126 | ||
130 | export { | 127 | export { |
@@ -157,59 +154,64 @@ async function addVideoRetryWrapper (req: express.Request, res: express.Response | |||
157 | errorMessage: 'Cannot insert the video with many retries.' | 154 | errorMessage: 'Cannot insert the video with many retries.' |
158 | } | 155 | } |
159 | 156 | ||
160 | await retryTransactionWrapper(addVideo, options) | 157 | const video = await retryTransactionWrapper(addVideo, options) |
161 | 158 | ||
162 | // TODO : include Location of the new video -> 201 | 159 | res.json({ |
163 | res.type('json').status(204).end() | 160 | video: { |
161 | id: video.id, | ||
162 | uuid: video.uuid | ||
163 | } | ||
164 | }).end() | ||
164 | } | 165 | } |
165 | 166 | ||
166 | async function addVideo (req: express.Request, res: express.Response, videoPhysicalFile: Express.Multer.File) { | 167 | async function addVideo (req: express.Request, res: express.Response, videoPhysicalFile: Express.Multer.File) { |
167 | const videoInfo: VideoCreate = req.body | 168 | const videoInfo: VideoCreate = req.body |
168 | let videoUUID = '' | ||
169 | 169 | ||
170 | await db.sequelize.transaction(async t => { | 170 | // Prepare data so we don't block the transaction |
171 | const sequelizeOptions = { transaction: t } | 171 | const videoData = { |
172 | name: videoInfo.name, | ||
173 | remote: false, | ||
174 | extname: extname(videoPhysicalFile.filename), | ||
175 | category: videoInfo.category, | ||
176 | licence: videoInfo.licence, | ||
177 | language: videoInfo.language, | ||
178 | nsfw: videoInfo.nsfw, | ||
179 | description: videoInfo.description, | ||
180 | privacy: videoInfo.privacy, | ||
181 | duration: videoPhysicalFile['duration'], // duration was added by a previous middleware | ||
182 | channelId: res.locals.videoChannel.id | ||
183 | } | ||
184 | const video = db.Video.build(videoData) | ||
185 | video.url = getVideoActivityPubUrl(video) | ||
172 | 186 | ||
173 | const videoData = { | 187 | const videoFilePath = join(CONFIG.STORAGE.VIDEOS_DIR, videoPhysicalFile.filename) |
174 | name: videoInfo.name, | 188 | const videoFileHeight = await getVideoFileHeight(videoFilePath) |
175 | remote: false, | ||
176 | extname: extname(videoPhysicalFile.filename), | ||
177 | category: videoInfo.category, | ||
178 | licence: videoInfo.licence, | ||
179 | language: videoInfo.language, | ||
180 | nsfw: videoInfo.nsfw, | ||
181 | description: videoInfo.description, | ||
182 | privacy: videoInfo.privacy, | ||
183 | duration: videoPhysicalFile['duration'], // duration was added by a previous middleware | ||
184 | channelId: res.locals.videoChannel.id | ||
185 | } | ||
186 | const video = db.Video.build(videoData) | ||
187 | video.url = getVideoActivityPubUrl(video) | ||
188 | 189 | ||
189 | const videoFilePath = join(CONFIG.STORAGE.VIDEOS_DIR, videoPhysicalFile.filename) | 190 | const videoFileData = { |
190 | const videoFileHeight = await getVideoFileHeight(videoFilePath) | 191 | extname: extname(videoPhysicalFile.filename), |
192 | resolution: videoFileHeight, | ||
193 | size: videoPhysicalFile.size | ||
194 | } | ||
195 | const videoFile = db.VideoFile.build(videoFileData) | ||
196 | const videoDir = CONFIG.STORAGE.VIDEOS_DIR | ||
197 | const source = join(videoDir, videoPhysicalFile.filename) | ||
198 | const destination = join(videoDir, video.getVideoFilename(videoFile)) | ||
191 | 199 | ||
192 | const videoFileData = { | 200 | await renamePromise(source, destination) |
193 | extname: extname(videoPhysicalFile.filename), | 201 | // This is important in case if there is another attempt in the retry process |
194 | resolution: videoFileHeight, | 202 | videoPhysicalFile.filename = video.getVideoFilename(videoFile) |
195 | size: videoPhysicalFile.size | ||
196 | } | ||
197 | const videoFile = db.VideoFile.build(videoFileData) | ||
198 | const videoDir = CONFIG.STORAGE.VIDEOS_DIR | ||
199 | const source = join(videoDir, videoPhysicalFile.filename) | ||
200 | const destination = join(videoDir, video.getVideoFilename(videoFile)) | ||
201 | 203 | ||
202 | await renamePromise(source, destination) | 204 | const tasks = [] |
203 | // This is important in case if there is another attempt in the retry process | ||
204 | videoPhysicalFile.filename = video.getVideoFilename(videoFile) | ||
205 | 205 | ||
206 | const tasks = [] | 206 | tasks.push( |
207 | video.createTorrentAndSetInfoHash(videoFile), | ||
208 | video.createThumbnail(videoFile), | ||
209 | video.createPreview(videoFile) | ||
210 | ) | ||
211 | await Promise.all(tasks) | ||
207 | 212 | ||
208 | tasks.push( | 213 | return db.sequelize.transaction(async t => { |
209 | video.createTorrentAndSetInfoHash(videoFile), | 214 | const sequelizeOptions = { transaction: t } |
210 | video.createThumbnail(videoFile), | ||
211 | video.createPreview(videoFile) | ||
212 | ) | ||
213 | 215 | ||
214 | if (CONFIG.TRANSCODING.ENABLED === true) { | 216 | if (CONFIG.TRANSCODING.ENABLED === true) { |
215 | // Put uuid because we don't have id auto incremented for now | 217 | // Put uuid because we don't have id auto incremented for now |
@@ -217,21 +219,17 @@ async function addVideo (req: express.Request, res: express.Response, videoPhysi | |||
217 | videoUUID: video.uuid | 219 | videoUUID: video.uuid |
218 | } | 220 | } |
219 | 221 | ||
220 | tasks.push( | 222 | await transcodingJobScheduler.createJob(t, 'videoFileOptimizer', dataInput) |
221 | transcodingJobScheduler.createJob(t, 'videoFileOptimizer', dataInput) | ||
222 | ) | ||
223 | } | 223 | } |
224 | await Promise.all(tasks) | ||
225 | 224 | ||
226 | const videoCreated = await video.save(sequelizeOptions) | 225 | const videoCreated = await video.save(sequelizeOptions) |
227 | // Do not forget to add video channel information to the created video | 226 | // Do not forget to add video channel information to the created video |
228 | videoCreated.VideoChannel = res.locals.videoChannel | 227 | videoCreated.VideoChannel = res.locals.videoChannel |
229 | videoUUID = videoCreated.uuid | ||
230 | 228 | ||
231 | videoFile.videoId = video.id | 229 | videoFile.videoId = video.id |
232 | |||
233 | await videoFile.save(sequelizeOptions) | 230 | await videoFile.save(sequelizeOptions) |
234 | video.VideoFiles = [videoFile] | 231 | |
232 | video.VideoFiles = [ videoFile ] | ||
235 | 233 | ||
236 | if (videoInfo.tags) { | 234 | if (videoInfo.tags) { |
237 | const tagInstances = await db.Tag.findOrCreateTags(videoInfo.tags, t) | 235 | const tagInstances = await db.Tag.findOrCreateTags(videoInfo.tags, t) |
@@ -241,15 +239,17 @@ async function addVideo (req: express.Request, res: express.Response, videoPhysi | |||
241 | } | 239 | } |
242 | 240 | ||
243 | // Let transcoding job send the video to friends because the video file extension might change | 241 | // Let transcoding job send the video to friends because the video file extension might change |
244 | if (CONFIG.TRANSCODING.ENABLED === true) return undefined | 242 | if (CONFIG.TRANSCODING.ENABLED === true) return videoCreated |
245 | // Don't send video to remote servers, it is private | 243 | // Don't send video to remote servers, it is private |
246 | if (video.privacy === VideoPrivacy.PRIVATE) return undefined | 244 | if (video.privacy === VideoPrivacy.PRIVATE) return videoCreated |
247 | 245 | ||
248 | await sendAddVideo(video, t) | 246 | await sendAddVideo(video, t) |
249 | await shareVideoByServer(video, t) | 247 | await shareVideoByServer(video, t) |
250 | }) | ||
251 | 248 | ||
252 | logger.info('Video with name %s and uuid %s created.', videoInfo.name, videoUUID) | 249 | logger.info('Video with name %s and uuid %s created.', videoInfo.name, videoCreated.uuid) |
250 | |||
251 | return videoCreated | ||
252 | }) | ||
253 | } | 253 | } |
254 | 254 | ||
255 | async function updateVideoRetryWrapper (req: express.Request, res: express.Response, next: express.NextFunction) { | 255 | async function updateVideoRetryWrapper (req: express.Request, res: express.Response, next: express.NextFunction) { |
@@ -280,7 +280,7 @@ async function updateVideo (req: express.Request, res: express.Response) { | |||
280 | if (videoInfoToUpdate.licence !== undefined) videoInstance.set('licence', videoInfoToUpdate.licence) | 280 | if (videoInfoToUpdate.licence !== undefined) videoInstance.set('licence', videoInfoToUpdate.licence) |
281 | if (videoInfoToUpdate.language !== undefined) videoInstance.set('language', videoInfoToUpdate.language) | 281 | if (videoInfoToUpdate.language !== undefined) videoInstance.set('language', videoInfoToUpdate.language) |
282 | if (videoInfoToUpdate.nsfw !== undefined) videoInstance.set('nsfw', videoInfoToUpdate.nsfw) | 282 | if (videoInfoToUpdate.nsfw !== undefined) videoInstance.set('nsfw', videoInfoToUpdate.nsfw) |
283 | if (videoInfoToUpdate.privacy !== undefined) videoInstance.set('privacy', videoInfoToUpdate.privacy) | 283 | if (videoInfoToUpdate.privacy !== undefined) videoInstance.set('privacy', parseInt(videoInfoToUpdate.privacy.toString(), 10)) |
284 | if (videoInfoToUpdate.description !== undefined) videoInstance.set('description', videoInfoToUpdate.description) | 284 | if (videoInfoToUpdate.description !== undefined) videoInstance.set('description', videoInfoToUpdate.description) |
285 | 285 | ||
286 | const videoInstanceUpdated = await videoInstance.save(sequelizeOptions) | 286 | const videoInstanceUpdated = await videoInstance.save(sequelizeOptions) |
@@ -298,9 +298,9 @@ async function updateVideo (req: express.Request, res: express.Response) { | |||
298 | } | 298 | } |
299 | 299 | ||
300 | // Video is not private anymore, send a create action to remote servers | 300 | // Video is not private anymore, send a create action to remote servers |
301 | if (wasPrivateVideo === true && videoInstance.privacy !== VideoPrivacy.PRIVATE) { | 301 | if (wasPrivateVideo === true && videoInstanceUpdated.privacy !== VideoPrivacy.PRIVATE) { |
302 | await sendAddVideo(videoInstance, t) | 302 | await sendAddVideo(videoInstanceUpdated, t) |
303 | await shareVideoByServer(videoInstance, t) | 303 | await shareVideoByServer(videoInstanceUpdated, t) |
304 | } | 304 | } |
305 | }) | 305 | }) |
306 | 306 | ||
@@ -378,8 +378,7 @@ async function removeVideo (req: express.Request, res: express.Response) { | |||
378 | 378 | ||
379 | async function searchVideos (req: express.Request, res: express.Response, next: express.NextFunction) { | 379 | async function searchVideos (req: express.Request, res: express.Response, next: express.NextFunction) { |
380 | const resultList = await db.Video.searchAndPopulateAccountAndServerAndTags( | 380 | const resultList = await db.Video.searchAndPopulateAccountAndServerAndTags( |
381 | req.params.value, | 381 | req.query.search, |
382 | req.query.field, | ||
383 | req.query.start, | 382 | req.query.start, |
384 | req.query.count, | 383 | req.query.count, |
385 | req.query.sort | 384 | req.query.sort |
diff --git a/server/controllers/client.ts b/server/controllers/client.ts index 64e5829ca..f474c4282 100644 --- a/server/controllers/client.ts +++ b/server/controllers/client.ts | |||
@@ -18,6 +18,7 @@ import { VideoInstance } from '../models' | |||
18 | const clientsRouter = express.Router() | 18 | const clientsRouter = express.Router() |
19 | 19 | ||
20 | const distPath = join(root(), 'client', 'dist') | 20 | const distPath = join(root(), 'client', 'dist') |
21 | const assetsImagesPath = join(root(), 'client', 'dist', 'assets', 'images') | ||
21 | const embedPath = join(distPath, 'standalone', 'videos', 'embed.html') | 22 | const embedPath = join(distPath, 'standalone', 'videos', 'embed.html') |
22 | const indexPath = join(distPath, 'index.html') | 23 | const indexPath = join(distPath, 'index.html') |
23 | 24 | ||
@@ -33,6 +34,7 @@ clientsRouter.use('/videos/embed', (req: express.Request, res: express.Response, | |||
33 | 34 | ||
34 | // Static HTML/CSS/JS client files | 35 | // Static HTML/CSS/JS client files |
35 | clientsRouter.use('/client', express.static(distPath, { maxAge: STATIC_MAX_AGE })) | 36 | clientsRouter.use('/client', express.static(distPath, { maxAge: STATIC_MAX_AGE })) |
37 | clientsRouter.use('/client/assets/images', express.static(assetsImagesPath, { maxAge: STATIC_MAX_AGE })) | ||
36 | 38 | ||
37 | // 404 for static files not found | 39 | // 404 for static files not found |
38 | clientsRouter.use('/client/*', (req: express.Request, res: express.Response, next: express.NextFunction) => { | 40 | clientsRouter.use('/client/*', (req: express.Request, res: express.Response, next: express.NextFunction) => { |
diff --git a/server/helpers/custom-validators/activitypub/videos.ts b/server/helpers/custom-validators/activitypub/videos.ts index 12c672fd2..2ed2988f5 100644 --- a/server/helpers/custom-validators/activitypub/videos.ts +++ b/server/helpers/custom-validators/activitypub/videos.ts | |||
@@ -49,14 +49,14 @@ function isVideoTorrentObjectValid (video: any) { | |||
49 | isActivityPubVideoDurationValid(video.duration) && | 49 | isActivityPubVideoDurationValid(video.duration) && |
50 | isUUIDValid(video.uuid) && | 50 | isUUIDValid(video.uuid) && |
51 | setValidRemoteTags(video) && | 51 | setValidRemoteTags(video) && |
52 | isRemoteIdentifierValid(video.category) && | 52 | (!video.category || isRemoteIdentifierValid(video.category)) && |
53 | isRemoteIdentifierValid(video.licence) && | 53 | (!video.licence || isRemoteIdentifierValid(video.licence)) && |
54 | (!video.language || isRemoteIdentifierValid(video.language)) && | 54 | (!video.language || isRemoteIdentifierValid(video.language)) && |
55 | isVideoViewsValid(video.views) && | 55 | isVideoViewsValid(video.views) && |
56 | isVideoNSFWValid(video.nsfw) && | 56 | isVideoNSFWValid(video.nsfw) && |
57 | isDateValid(video.published) && | 57 | isDateValid(video.published) && |
58 | isDateValid(video.updated) && | 58 | isDateValid(video.updated) && |
59 | isRemoteVideoContentValid(video.mediaType, video.content) && | 59 | (!video.content || isRemoteVideoContentValid(video.mediaType, video.content)) && |
60 | isRemoteVideoIconValid(video.icon) && | 60 | isRemoteVideoIconValid(video.icon) && |
61 | setValidRemoteVideoUrls(video) && | 61 | setValidRemoteVideoUrls(video) && |
62 | video.url.length !== 0 | 62 | video.url.length !== 0 |
diff --git a/server/helpers/custom-validators/videos.ts b/server/helpers/custom-validators/videos.ts index f13178c54..37fa8b08a 100644 --- a/server/helpers/custom-validators/videos.ts +++ b/server/helpers/custom-validators/videos.ts | |||
@@ -14,11 +14,11 @@ const VIDEOS_CONSTRAINTS_FIELDS = CONSTRAINTS_FIELDS.VIDEOS | |||
14 | const VIDEO_ABUSES_CONSTRAINTS_FIELDS = CONSTRAINTS_FIELDS.VIDEO_ABUSES | 14 | const VIDEO_ABUSES_CONSTRAINTS_FIELDS = CONSTRAINTS_FIELDS.VIDEO_ABUSES |
15 | 15 | ||
16 | function isVideoCategoryValid (value: number) { | 16 | function isVideoCategoryValid (value: number) { |
17 | return VIDEO_CATEGORIES[value] !== undefined | 17 | return value === null || VIDEO_CATEGORIES[value] !== undefined |
18 | } | 18 | } |
19 | 19 | ||
20 | function isVideoLicenceValid (value: number) { | 20 | function isVideoLicenceValid (value: number) { |
21 | return VIDEO_LICENCES[value] !== undefined | 21 | return value === null || VIDEO_LICENCES[value] !== undefined |
22 | } | 22 | } |
23 | 23 | ||
24 | function isVideoLanguageValid (value: number) { | 24 | function isVideoLanguageValid (value: number) { |
@@ -38,7 +38,7 @@ function isVideoTruncatedDescriptionValid (value: string) { | |||
38 | } | 38 | } |
39 | 39 | ||
40 | function isVideoDescriptionValid (value: string) { | 40 | function isVideoDescriptionValid (value: string) { |
41 | return exists(value) && validator.isLength(value, VIDEOS_CONSTRAINTS_FIELDS.DESCRIPTION) | 41 | return value === null || (exists(value) && validator.isLength(value, VIDEOS_CONSTRAINTS_FIELDS.DESCRIPTION)) |
42 | } | 42 | } |
43 | 43 | ||
44 | function isVideoNameValid (value: string) { | 44 | function isVideoNameValid (value: string) { |
@@ -84,7 +84,7 @@ function isVideoFile (files: { [ fieldname: string ]: Express.Multer.File[] } | | |||
84 | } | 84 | } |
85 | 85 | ||
86 | function isVideoPrivacyValid (value: string) { | 86 | function isVideoPrivacyValid (value: string) { |
87 | return VIDEO_PRIVACIES[value] !== undefined | 87 | return validator.isInt(value + '') && VIDEO_PRIVACIES[value] !== undefined |
88 | } | 88 | } |
89 | 89 | ||
90 | function isVideoFileInfoHashValid (value: string) { | 90 | function isVideoFileInfoHashValid (value: string) { |
diff --git a/server/initializers/constants.ts b/server/initializers/constants.ts index e3d779456..7be7a5f95 100644 --- a/server/initializers/constants.ts +++ b/server/initializers/constants.ts | |||
@@ -14,7 +14,7 @@ import { FollowState } from '../../shared/models/accounts/follow.model' | |||
14 | 14 | ||
15 | // --------------------------------------------------------------------------- | 15 | // --------------------------------------------------------------------------- |
16 | 16 | ||
17 | const LAST_MIGRATION_VERSION = 110 | 17 | const LAST_MIGRATION_VERSION = 120 |
18 | 18 | ||
19 | // --------------------------------------------------------------------------- | 19 | // --------------------------------------------------------------------------- |
20 | 20 | ||
@@ -25,11 +25,6 @@ const API_VERSION = 'v1' | |||
25 | const PAGINATION_COUNT_DEFAULT = 15 | 25 | const PAGINATION_COUNT_DEFAULT = 15 |
26 | 26 | ||
27 | // Sortable columns per schema | 27 | // Sortable columns per schema |
28 | const SEARCHABLE_COLUMNS = { | ||
29 | VIDEOS: [ 'name', 'magnetUri', 'host', 'account', 'tags' ] | ||
30 | } | ||
31 | |||
32 | // Sortable columns per schema | ||
33 | const SORTABLE_COLUMNS = { | 28 | const SORTABLE_COLUMNS = { |
34 | USERS: [ 'id', 'username', 'createdAt' ], | 29 | USERS: [ 'id', 'username', 'createdAt' ], |
35 | JOBS: [ 'id', 'createdAt' ], | 30 | JOBS: [ 'id', 'createdAt' ], |
@@ -60,6 +55,7 @@ const CONFIG = { | |||
60 | PASSWORD: config.get<string>('database.password') | 55 | PASSWORD: config.get<string>('database.password') |
61 | }, | 56 | }, |
62 | STORAGE: { | 57 | STORAGE: { |
58 | AVATARS_DIR: join(root(), config.get<string>('storage.avatars')), | ||
63 | LOG_DIR: join(root(), config.get<string>('storage.logs')), | 59 | LOG_DIR: join(root(), config.get<string>('storage.logs')), |
64 | VIDEOS_DIR: join(root(), config.get<string>('storage.videos')), | 60 | VIDEOS_DIR: join(root(), config.get<string>('storage.videos')), |
65 | THUMBNAILS_DIR: join(root(), config.get<string>('storage.thumbnails')), | 61 | THUMBNAILS_DIR: join(root(), config.get<string>('storage.thumbnails')), |
@@ -105,6 +101,9 @@ const CONFIG = { | |||
105 | CONFIG.WEBSERVER.URL = CONFIG.WEBSERVER.SCHEME + '://' + CONFIG.WEBSERVER.HOSTNAME + ':' + CONFIG.WEBSERVER.PORT | 101 | CONFIG.WEBSERVER.URL = CONFIG.WEBSERVER.SCHEME + '://' + CONFIG.WEBSERVER.HOSTNAME + ':' + CONFIG.WEBSERVER.PORT |
106 | CONFIG.WEBSERVER.HOST = CONFIG.WEBSERVER.HOSTNAME + ':' + CONFIG.WEBSERVER.PORT | 102 | CONFIG.WEBSERVER.HOST = CONFIG.WEBSERVER.HOSTNAME + ':' + CONFIG.WEBSERVER.PORT |
107 | 103 | ||
104 | const AVATARS_DIR = { | ||
105 | ACCOUNT: join(CONFIG.STORAGE.AVATARS_DIR, 'account') | ||
106 | } | ||
108 | // --------------------------------------------------------------------------- | 107 | // --------------------------------------------------------------------------- |
109 | 108 | ||
110 | const CONSTRAINTS_FIELDS = { | 109 | const CONSTRAINTS_FIELDS = { |
@@ -356,7 +355,7 @@ export { | |||
356 | PREVIEWS_SIZE, | 355 | PREVIEWS_SIZE, |
357 | REMOTE_SCHEME, | 356 | REMOTE_SCHEME, |
358 | FOLLOW_STATES, | 357 | FOLLOW_STATES, |
359 | SEARCHABLE_COLUMNS, | 358 | AVATARS_DIR, |
360 | SERVER_ACCOUNT_NAME, | 359 | SERVER_ACCOUNT_NAME, |
361 | PRIVATE_RSA_KEY_SIZE, | 360 | PRIVATE_RSA_KEY_SIZE, |
362 | SORTABLE_COLUMNS, | 361 | SORTABLE_COLUMNS, |
diff --git a/server/initializers/database.ts b/server/initializers/database.ts index 90dbba5b9..bb95992e1 100644 --- a/server/initializers/database.ts +++ b/server/initializers/database.ts | |||
@@ -2,6 +2,7 @@ import { join } from 'path' | |||
2 | import { flattenDepth } from 'lodash' | 2 | import { flattenDepth } from 'lodash' |
3 | require('pg').defaults.parseInt8 = true // Avoid BIGINT to be converted to string | 3 | require('pg').defaults.parseInt8 = true // Avoid BIGINT to be converted to string |
4 | import * as Sequelize from 'sequelize' | 4 | import * as Sequelize from 'sequelize' |
5 | import { AvatarModel } from '../models/avatar' | ||
5 | 6 | ||
6 | import { CONFIG } from './constants' | 7 | import { CONFIG } from './constants' |
7 | // Do not use barrel, we need to load database first | 8 | // Do not use barrel, we need to load database first |
@@ -36,6 +37,7 @@ export type PeerTubeDatabase = { | |||
36 | init?: (silent: boolean) => Promise<void>, | 37 | init?: (silent: boolean) => Promise<void>, |
37 | 38 | ||
38 | Application?: ApplicationModel, | 39 | Application?: ApplicationModel, |
40 | Avatar?: AvatarModel, | ||
39 | Account?: AccountModel, | 41 | Account?: AccountModel, |
40 | Job?: JobModel, | 42 | Job?: JobModel, |
41 | OAuthClient?: OAuthClientModel, | 43 | OAuthClient?: OAuthClientModel, |
diff --git a/server/initializers/migrations/0115-account-avatar.ts b/server/initializers/migrations/0115-account-avatar.ts new file mode 100644 index 000000000..2b947ceda --- /dev/null +++ b/server/initializers/migrations/0115-account-avatar.ts | |||
@@ -0,0 +1,31 @@ | |||
1 | import * as Sequelize from 'sequelize' | ||
2 | import { PeerTubeDatabase } from '../database' | ||
3 | |||
4 | async function up (utils: { | ||
5 | transaction: Sequelize.Transaction, | ||
6 | queryInterface: Sequelize.QueryInterface, | ||
7 | sequelize: Sequelize.Sequelize, | ||
8 | db: PeerTubeDatabase | ||
9 | }): Promise<void> { | ||
10 | await utils.db.Avatar.sync() | ||
11 | |||
12 | const data = { | ||
13 | type: Sequelize.INTEGER, | ||
14 | allowNull: true, | ||
15 | references: { | ||
16 | model: 'Avatars', | ||
17 | key: 'id' | ||
18 | }, | ||
19 | onDelete: 'CASCADE' | ||
20 | } | ||
21 | await utils.queryInterface.addColumn('Accounts', 'avatarId', data) | ||
22 | } | ||
23 | |||
24 | function down (options) { | ||
25 | throw new Error('Not implemented.') | ||
26 | } | ||
27 | |||
28 | export { | ||
29 | up, | ||
30 | down | ||
31 | } | ||
diff --git a/server/initializers/migrations/0120-video-null.ts b/server/initializers/migrations/0120-video-null.ts new file mode 100644 index 000000000..9130d10ee --- /dev/null +++ b/server/initializers/migrations/0120-video-null.ts | |||
@@ -0,0 +1,47 @@ | |||
1 | import * as Sequelize from 'sequelize' | ||
2 | import { CONSTRAINTS_FIELDS } from '../constants' | ||
3 | import { PeerTubeDatabase } from '../database' | ||
4 | |||
5 | async function up (utils: { | ||
6 | transaction: Sequelize.Transaction, | ||
7 | queryInterface: Sequelize.QueryInterface, | ||
8 | sequelize: Sequelize.Sequelize, | ||
9 | db: PeerTubeDatabase | ||
10 | }): Promise<void> { | ||
11 | |||
12 | { | ||
13 | const data = { | ||
14 | type: Sequelize.INTEGER, | ||
15 | allowNull: true, | ||
16 | defaultValue: null | ||
17 | } | ||
18 | await utils.queryInterface.changeColumn('Videos', 'licence', data) | ||
19 | } | ||
20 | |||
21 | { | ||
22 | const data = { | ||
23 | type: Sequelize.INTEGER, | ||
24 | allowNull: true, | ||
25 | defaultValue: null | ||
26 | } | ||
27 | await utils.queryInterface.changeColumn('Videos', 'category', data) | ||
28 | } | ||
29 | |||
30 | { | ||
31 | const data = { | ||
32 | type: Sequelize.STRING(CONSTRAINTS_FIELDS.VIDEOS.DESCRIPTION.max), | ||
33 | allowNull: true, | ||
34 | defaultValue: null | ||
35 | } | ||
36 | await utils.queryInterface.changeColumn('Videos', 'description', data) | ||
37 | } | ||
38 | } | ||
39 | |||
40 | function down (options) { | ||
41 | throw new Error('Not implemented.') | ||
42 | } | ||
43 | |||
44 | export { | ||
45 | up, | ||
46 | down | ||
47 | } | ||
diff --git a/server/lib/activitypub/process/misc.ts b/server/lib/activitypub/process/misc.ts index f20e588ab..0baa22c26 100644 --- a/server/lib/activitypub/process/misc.ts +++ b/server/lib/activitypub/process/misc.ts | |||
@@ -41,15 +41,30 @@ async function videoActivityObjectToDBAttributes ( | |||
41 | language = parseInt(videoObject.language.identifier, 10) | 41 | language = parseInt(videoObject.language.identifier, 10) |
42 | } | 42 | } |
43 | 43 | ||
44 | let category = null | ||
45 | if (videoObject.category) { | ||
46 | category = parseInt(videoObject.category.identifier, 10) | ||
47 | } | ||
48 | |||
49 | let licence = null | ||
50 | if (videoObject.licence) { | ||
51 | licence = parseInt(videoObject.licence.identifier, 10) | ||
52 | } | ||
53 | |||
54 | let description = null | ||
55 | if (videoObject.content) { | ||
56 | description = videoObject.content | ||
57 | } | ||
58 | |||
44 | const videoData: VideoAttributes = { | 59 | const videoData: VideoAttributes = { |
45 | name: videoObject.name, | 60 | name: videoObject.name, |
46 | uuid: videoObject.uuid, | 61 | uuid: videoObject.uuid, |
47 | url: videoObject.id, | 62 | url: videoObject.id, |
48 | category: parseInt(videoObject.category.identifier, 10), | 63 | category, |
49 | licence: parseInt(videoObject.licence.identifier, 10), | 64 | licence, |
50 | language, | 65 | language, |
66 | description, | ||
51 | nsfw: videoObject.nsfw, | 67 | nsfw: videoObject.nsfw, |
52 | description: videoObject.content, | ||
53 | channelId: videoChannel.id, | 68 | channelId: videoChannel.id, |
54 | duration: parseInt(duration, 10), | 69 | duration: parseInt(duration, 10), |
55 | createdAt: new Date(videoObject.published), | 70 | createdAt: new Date(videoObject.published), |
diff --git a/server/middlewares/index.ts b/server/middlewares/index.ts index aafcad2d9..0cef26953 100644 --- a/server/middlewares/index.ts +++ b/server/middlewares/index.ts | |||
@@ -4,6 +4,5 @@ export * from './async' | |||
4 | export * from './oauth' | 4 | export * from './oauth' |
5 | export * from './pagination' | 5 | export * from './pagination' |
6 | export * from './servers' | 6 | export * from './servers' |
7 | export * from './search' | ||
8 | export * from './sort' | 7 | export * from './sort' |
9 | export * from './user-right' | 8 | export * from './user-right' |
diff --git a/server/middlewares/search.ts b/server/middlewares/search.ts deleted file mode 100644 index 6fe83d25b..000000000 --- a/server/middlewares/search.ts +++ /dev/null | |||
@@ -1,14 +0,0 @@ | |||
1 | import 'express-validator' | ||
2 | import * as express from 'express' | ||
3 | |||
4 | function setVideosSearch (req: express.Request, res: express.Response, next: express.NextFunction) { | ||
5 | if (!req.query.field) req.query.field = 'name' | ||
6 | |||
7 | return next() | ||
8 | } | ||
9 | |||
10 | // --------------------------------------------------------------------------- | ||
11 | |||
12 | export { | ||
13 | setVideosSearch | ||
14 | } | ||
diff --git a/server/middlewares/validators/videos.ts b/server/middlewares/validators/videos.ts index f21680aa0..10625e41d 100644 --- a/server/middlewares/validators/videos.ts +++ b/server/middlewares/validators/videos.ts | |||
@@ -18,7 +18,7 @@ import { | |||
18 | } from '../../helpers/custom-validators/videos' | 18 | } from '../../helpers/custom-validators/videos' |
19 | import { getDurationFromVideoFile } from '../../helpers/ffmpeg-utils' | 19 | import { getDurationFromVideoFile } from '../../helpers/ffmpeg-utils' |
20 | import { logger } from '../../helpers/logger' | 20 | import { logger } from '../../helpers/logger' |
21 | import { CONSTRAINTS_FIELDS, SEARCHABLE_COLUMNS } from '../../initializers' | 21 | import { CONSTRAINTS_FIELDS } from '../../initializers' |
22 | import { database as db } from '../../initializers/database' | 22 | import { database as db } from '../../initializers/database' |
23 | import { UserInstance } from '../../models/account/user-interface' | 23 | import { UserInstance } from '../../models/account/user-interface' |
24 | import { VideoInstance } from '../../models/video/video-interface' | 24 | import { VideoInstance } from '../../models/video/video-interface' |
@@ -31,11 +31,11 @@ const videosAddValidator = [ | |||
31 | + CONSTRAINTS_FIELDS.VIDEOS.EXTNAME.join(', ') | 31 | + CONSTRAINTS_FIELDS.VIDEOS.EXTNAME.join(', ') |
32 | ), | 32 | ), |
33 | body('name').custom(isVideoNameValid).withMessage('Should have a valid name'), | 33 | body('name').custom(isVideoNameValid).withMessage('Should have a valid name'), |
34 | body('category').custom(isVideoCategoryValid).withMessage('Should have a valid category'), | 34 | body('category').optional().custom(isVideoCategoryValid).withMessage('Should have a valid category'), |
35 | body('licence').custom(isVideoLicenceValid).withMessage('Should have a valid licence'), | 35 | body('licence').optional().custom(isVideoLicenceValid).withMessage('Should have a valid licence'), |
36 | body('language').optional().custom(isVideoLanguageValid).withMessage('Should have a valid language'), | 36 | body('language').optional().custom(isVideoLanguageValid).withMessage('Should have a valid language'), |
37 | body('nsfw').custom(isVideoNSFWValid).withMessage('Should have a valid NSFW attribute'), | 37 | body('nsfw').custom(isVideoNSFWValid).withMessage('Should have a valid NSFW attribute'), |
38 | body('description').custom(isVideoDescriptionValid).withMessage('Should have a valid description'), | 38 | body('description').optional().custom(isVideoDescriptionValid).withMessage('Should have a valid description'), |
39 | body('channelId').custom(isIdValid).withMessage('Should have correct video channel id'), | 39 | body('channelId').custom(isIdValid).withMessage('Should have correct video channel id'), |
40 | body('privacy').custom(isVideoPrivacyValid).withMessage('Should have correct video privacy'), | 40 | body('privacy').custom(isVideoPrivacyValid).withMessage('Should have correct video privacy'), |
41 | body('tags').optional().custom(isVideoTagsValid).withMessage('Should have correct tags'), | 41 | body('tags').optional().custom(isVideoTagsValid).withMessage('Should have correct tags'), |
@@ -172,8 +172,7 @@ const videosRemoveValidator = [ | |||
172 | ] | 172 | ] |
173 | 173 | ||
174 | const videosSearchValidator = [ | 174 | const videosSearchValidator = [ |
175 | param('value').not().isEmpty().withMessage('Should have a valid search'), | 175 | query('search').not().isEmpty().withMessage('Should have a valid search'), |
176 | query('field').optional().isIn(SEARCHABLE_COLUMNS.VIDEOS).withMessage('Should have correct searchable column'), | ||
177 | 176 | ||
178 | (req: express.Request, res: express.Response, next: express.NextFunction) => { | 177 | (req: express.Request, res: express.Response, next: express.NextFunction) => { |
179 | logger.debug('Checking videosSearch parameters', { parameters: req.params }) | 178 | logger.debug('Checking videosSearch parameters', { parameters: req.params }) |
diff --git a/server/models/account/account-interface.ts b/server/models/account/account-interface.ts index b369766dc..46fe068e3 100644 --- a/server/models/account/account-interface.ts +++ b/server/models/account/account-interface.ts | |||
@@ -1,6 +1,7 @@ | |||
1 | import * as Bluebird from 'bluebird' | 1 | import * as Bluebird from 'bluebird' |
2 | import * as Sequelize from 'sequelize' | 2 | import * as Sequelize from 'sequelize' |
3 | import { Account as FormattedAccount, ActivityPubActor } from '../../../shared' | 3 | import { Account as FormattedAccount, ActivityPubActor } from '../../../shared' |
4 | import { AvatarInstance } from '../avatar' | ||
4 | import { ServerInstance } from '../server/server-interface' | 5 | import { ServerInstance } from '../server/server-interface' |
5 | import { VideoChannelInstance } from '../video/video-channel-interface' | 6 | import { VideoChannelInstance } from '../video/video-channel-interface' |
6 | 7 | ||
@@ -51,6 +52,7 @@ export interface AccountAttributes { | |||
51 | serverId?: number | 52 | serverId?: number |
52 | userId?: number | 53 | userId?: number |
53 | applicationId?: number | 54 | applicationId?: number |
55 | avatarId?: number | ||
54 | } | 56 | } |
55 | 57 | ||
56 | export interface AccountInstance extends AccountClass, AccountAttributes, Sequelize.Instance<AccountAttributes> { | 58 | export interface AccountInstance extends AccountClass, AccountAttributes, Sequelize.Instance<AccountAttributes> { |
@@ -68,6 +70,7 @@ export interface AccountInstance extends AccountClass, AccountAttributes, Sequel | |||
68 | 70 | ||
69 | Server: ServerInstance | 71 | Server: ServerInstance |
70 | VideoChannels: VideoChannelInstance[] | 72 | VideoChannels: VideoChannelInstance[] |
73 | Avatar: AvatarInstance | ||
71 | } | 74 | } |
72 | 75 | ||
73 | export interface AccountModel extends AccountClass, Sequelize.Model<AccountInstance, AccountAttributes> {} | 76 | export interface AccountModel extends AccountClass, Sequelize.Model<AccountInstance, AccountAttributes> {} |
diff --git a/server/models/account/account.ts b/server/models/account/account.ts index 61a88524c..8b0819f39 100644 --- a/server/models/account/account.ts +++ b/server/models/account/account.ts | |||
@@ -1,4 +1,6 @@ | |||
1 | import { join } from 'path' | ||
1 | import * as Sequelize from 'sequelize' | 2 | import * as Sequelize from 'sequelize' |
3 | import { Avatar } from '../../../shared/models/avatars/avatar.model' | ||
2 | import { | 4 | import { |
3 | activityPubContextify, | 5 | activityPubContextify, |
4 | isAccountFollowersCountValid, | 6 | isAccountFollowersCountValid, |
@@ -8,6 +10,7 @@ import { | |||
8 | isUserUsernameValid | 10 | isUserUsernameValid |
9 | } from '../../helpers' | 11 | } from '../../helpers' |
10 | import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub/misc' | 12 | import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub/misc' |
13 | import { AVATARS_DIR } from '../../initializers' | ||
11 | import { CONFIG, CONSTRAINTS_FIELDS } from '../../initializers/constants' | 14 | import { CONFIG, CONSTRAINTS_FIELDS } from '../../initializers/constants' |
12 | import { sendDeleteAccount } from '../../lib/activitypub/send/send-delete' | 15 | import { sendDeleteAccount } from '../../lib/activitypub/send/send-delete' |
13 | import { addMethodsToModel } from '../utils' | 16 | import { addMethodsToModel } from '../utils' |
@@ -252,6 +255,14 @@ function associate (models) { | |||
252 | as: 'followers', | 255 | as: 'followers', |
253 | onDelete: 'cascade' | 256 | onDelete: 'cascade' |
254 | }) | 257 | }) |
258 | |||
259 | Account.hasOne(models.Avatar, { | ||
260 | foreignKey: { | ||
261 | name: 'avatarId', | ||
262 | allowNull: true | ||
263 | }, | ||
264 | onDelete: 'cascade' | ||
265 | }) | ||
255 | } | 266 | } |
256 | 267 | ||
257 | function afterDestroy (account: AccountInstance) { | 268 | function afterDestroy (account: AccountInstance) { |
@@ -265,6 +276,15 @@ function afterDestroy (account: AccountInstance) { | |||
265 | toFormattedJSON = function (this: AccountInstance) { | 276 | toFormattedJSON = function (this: AccountInstance) { |
266 | let host = CONFIG.WEBSERVER.HOST | 277 | let host = CONFIG.WEBSERVER.HOST |
267 | let score: number | 278 | let score: number |
279 | let avatar: Avatar = null | ||
280 | |||
281 | if (this.Avatar) { | ||
282 | avatar = { | ||
283 | path: join(AVATARS_DIR.ACCOUNT, this.Avatar.filename), | ||
284 | createdAt: this.Avatar.createdAt, | ||
285 | updatedAt: this.Avatar.updatedAt | ||
286 | } | ||
287 | } | ||
268 | 288 | ||
269 | if (this.Server) { | 289 | if (this.Server) { |
270 | host = this.Server.host | 290 | host = this.Server.host |
@@ -273,11 +293,15 @@ toFormattedJSON = function (this: AccountInstance) { | |||
273 | 293 | ||
274 | const json = { | 294 | const json = { |
275 | id: this.id, | 295 | id: this.id, |
296 | uuid: this.uuid, | ||
276 | host, | 297 | host, |
277 | score, | 298 | score, |
278 | name: this.name, | 299 | name: this.name, |
300 | followingCount: this.followingCount, | ||
301 | followersCount: this.followersCount, | ||
279 | createdAt: this.createdAt, | 302 | createdAt: this.createdAt, |
280 | updatedAt: this.updatedAt | 303 | updatedAt: this.updatedAt, |
304 | avatar | ||
281 | } | 305 | } |
282 | 306 | ||
283 | return json | 307 | return json |
diff --git a/server/models/account/user.ts b/server/models/account/user.ts index 8f7c9b013..3705947c0 100644 --- a/server/models/account/user.ts +++ b/server/models/account/user.ts | |||
@@ -157,10 +157,7 @@ toFormattedJSON = function (this: UserInstance) { | |||
157 | roleLabel: USER_ROLE_LABELS[this.role], | 157 | roleLabel: USER_ROLE_LABELS[this.role], |
158 | videoQuota: this.videoQuota, | 158 | videoQuota: this.videoQuota, |
159 | createdAt: this.createdAt, | 159 | createdAt: this.createdAt, |
160 | account: { | 160 | account: this.Account.toFormattedJSON() |
161 | id: this.Account.id, | ||
162 | uuid: this.Account.uuid | ||
163 | } | ||
164 | } | 161 | } |
165 | 162 | ||
166 | if (Array.isArray(this.Account.VideoChannels) === true) { | 163 | if (Array.isArray(this.Account.VideoChannels) === true) { |
diff --git a/server/models/avatar/avatar-interface.ts b/server/models/avatar/avatar-interface.ts new file mode 100644 index 000000000..4af2b87b7 --- /dev/null +++ b/server/models/avatar/avatar-interface.ts | |||
@@ -0,0 +1,16 @@ | |||
1 | import * as Sequelize from 'sequelize' | ||
2 | |||
3 | export namespace AvatarMethods {} | ||
4 | |||
5 | export interface AvatarClass {} | ||
6 | |||
7 | export interface AvatarAttributes { | ||
8 | filename: string | ||
9 | } | ||
10 | |||
11 | export interface AvatarInstance extends AvatarClass, AvatarAttributes, Sequelize.Instance<AvatarAttributes> { | ||
12 | createdAt: Date | ||
13 | updatedAt: Date | ||
14 | } | ||
15 | |||
16 | export interface AvatarModel extends AvatarClass, Sequelize.Model<AvatarInstance, AvatarAttributes> {} | ||
diff --git a/server/models/avatar/avatar.ts b/server/models/avatar/avatar.ts new file mode 100644 index 000000000..96308fd5f --- /dev/null +++ b/server/models/avatar/avatar.ts | |||
@@ -0,0 +1,24 @@ | |||
1 | import * as Sequelize from 'sequelize' | ||
2 | import { addMethodsToModel } from '../utils' | ||
3 | import { AvatarAttributes, AvatarInstance } from './avatar-interface' | ||
4 | |||
5 | let Avatar: Sequelize.Model<AvatarInstance, AvatarAttributes> | ||
6 | |||
7 | export default function (sequelize: Sequelize.Sequelize, DataTypes: Sequelize.DataTypes) { | ||
8 | Avatar = sequelize.define<AvatarInstance, AvatarAttributes>('Avatar', | ||
9 | { | ||
10 | filename: { | ||
11 | type: DataTypes.STRING, | ||
12 | allowNull: false | ||
13 | } | ||
14 | }, | ||
15 | {} | ||
16 | ) | ||
17 | |||
18 | const classMethods = [] | ||
19 | addMethodsToModel(Avatar, classMethods) | ||
20 | |||
21 | return Avatar | ||
22 | } | ||
23 | |||
24 | // ------------------------------ Statics ------------------------------ | ||
diff --git a/server/models/avatar/index.ts b/server/models/avatar/index.ts new file mode 100644 index 000000000..877aed1ce --- /dev/null +++ b/server/models/avatar/index.ts | |||
@@ -0,0 +1 @@ | |||
export * from './avatar-interface' | |||
diff --git a/server/models/index.ts b/server/models/index.ts index 65faa5294..fedd97dd1 100644 --- a/server/models/index.ts +++ b/server/models/index.ts | |||
@@ -1,4 +1,5 @@ | |||
1 | export * from './application' | 1 | export * from './application' |
2 | export * from './avatar' | ||
2 | export * from './job' | 3 | export * from './job' |
3 | export * from './oauth' | 4 | export * from './oauth' |
4 | export * from './server' | 5 | export * from './server' |
diff --git a/server/models/video/video-interface.ts b/server/models/video/video-interface.ts index be140de86..2a63350af 100644 --- a/server/models/video/video-interface.ts +++ b/server/models/video/video-interface.ts | |||
@@ -50,7 +50,6 @@ export namespace VideoMethods { | |||
50 | export type ListUserVideosForApi = (userId: number, start: number, count: number, sort: string) => Bluebird< ResultList<VideoInstance> > | 50 | export type ListUserVideosForApi = (userId: number, start: number, count: number, sort: string) => Bluebird< ResultList<VideoInstance> > |
51 | export type SearchAndPopulateAccountAndServerAndTags = ( | 51 | export type SearchAndPopulateAccountAndServerAndTags = ( |
52 | value: string, | 52 | value: string, |
53 | field: string, | ||
54 | start: number, | 53 | start: number, |
55 | count: number, | 54 | count: number, |
56 | sort: string | 55 | sort: string |
diff --git a/server/models/video/video.ts b/server/models/video/video.ts index f3469c1de..d46fdeebe 100644 --- a/server/models/video/video.ts +++ b/server/models/video/video.ts | |||
@@ -104,7 +104,8 @@ export default function (sequelize: Sequelize.Sequelize, DataTypes: Sequelize.Da | |||
104 | }, | 104 | }, |
105 | category: { | 105 | category: { |
106 | type: DataTypes.INTEGER, | 106 | type: DataTypes.INTEGER, |
107 | allowNull: false, | 107 | allowNull: true, |
108 | defaultValue: null, | ||
108 | validate: { | 109 | validate: { |
109 | categoryValid: value => { | 110 | categoryValid: value => { |
110 | const res = isVideoCategoryValid(value) | 111 | const res = isVideoCategoryValid(value) |
@@ -114,7 +115,7 @@ export default function (sequelize: Sequelize.Sequelize, DataTypes: Sequelize.Da | |||
114 | }, | 115 | }, |
115 | licence: { | 116 | licence: { |
116 | type: DataTypes.INTEGER, | 117 | type: DataTypes.INTEGER, |
117 | allowNull: false, | 118 | allowNull: true, |
118 | defaultValue: null, | 119 | defaultValue: null, |
119 | validate: { | 120 | validate: { |
120 | licenceValid: value => { | 121 | licenceValid: value => { |
@@ -126,6 +127,7 @@ export default function (sequelize: Sequelize.Sequelize, DataTypes: Sequelize.Da | |||
126 | language: { | 127 | language: { |
127 | type: DataTypes.INTEGER, | 128 | type: DataTypes.INTEGER, |
128 | allowNull: true, | 129 | allowNull: true, |
130 | defaultValue: null, | ||
129 | validate: { | 131 | validate: { |
130 | languageValid: value => { | 132 | languageValid: value => { |
131 | const res = isVideoLanguageValid(value) | 133 | const res = isVideoLanguageValid(value) |
@@ -155,7 +157,8 @@ export default function (sequelize: Sequelize.Sequelize, DataTypes: Sequelize.Da | |||
155 | }, | 157 | }, |
156 | description: { | 158 | description: { |
157 | type: DataTypes.STRING(CONSTRAINTS_FIELDS.VIDEOS.DESCRIPTION.max), | 159 | type: DataTypes.STRING(CONSTRAINTS_FIELDS.VIDEOS.DESCRIPTION.max), |
158 | allowNull: false, | 160 | allowNull: true, |
161 | defaultValue: null, | ||
159 | validate: { | 162 | validate: { |
160 | descriptionValid: value => { | 163 | descriptionValid: value => { |
161 | const res = isVideoDescriptionValid(value) | 164 | const res = isVideoDescriptionValid(value) |
@@ -486,7 +489,7 @@ toFormattedJSON = function (this: VideoInstance) { | |||
486 | description: this.getTruncatedDescription(), | 489 | description: this.getTruncatedDescription(), |
487 | serverHost, | 490 | serverHost, |
488 | isLocal: this.isOwned(), | 491 | isLocal: this.isOwned(), |
489 | account: this.VideoChannel.Account.name, | 492 | accountName: this.VideoChannel.Account.name, |
490 | duration: this.duration, | 493 | duration: this.duration, |
491 | views: this.views, | 494 | views: this.views, |
492 | likes: this.likes, | 495 | likes: this.likes, |
@@ -514,6 +517,7 @@ toFormattedDetailsJSON = function (this: VideoInstance) { | |||
514 | privacy: this.privacy, | 517 | privacy: this.privacy, |
515 | descriptionPath: this.getDescriptionPath(), | 518 | descriptionPath: this.getDescriptionPath(), |
516 | channel: this.VideoChannel.toFormattedJSON(), | 519 | channel: this.VideoChannel.toFormattedJSON(), |
520 | account: this.VideoChannel.Account.toFormattedJSON(), | ||
517 | files: [] | 521 | files: [] |
518 | } | 522 | } |
519 | 523 | ||
@@ -560,6 +564,22 @@ toActivityPubObject = function (this: VideoInstance) { | |||
560 | } | 564 | } |
561 | } | 565 | } |
562 | 566 | ||
567 | let category | ||
568 | if (this.category) { | ||
569 | category = { | ||
570 | identifier: this.category + '', | ||
571 | name: this.getCategoryLabel() | ||
572 | } | ||
573 | } | ||
574 | |||
575 | let licence | ||
576 | if (this.licence) { | ||
577 | licence = { | ||
578 | identifier: this.licence + '', | ||
579 | name: this.getLicenceLabel() | ||
580 | } | ||
581 | } | ||
582 | |||
563 | let likesObject | 583 | let likesObject |
564 | let dislikesObject | 584 | let dislikesObject |
565 | 585 | ||
@@ -631,14 +651,8 @@ toActivityPubObject = function (this: VideoInstance) { | |||
631 | duration: 'PT' + this.duration + 'S', | 651 | duration: 'PT' + this.duration + 'S', |
632 | uuid: this.uuid, | 652 | uuid: this.uuid, |
633 | tag, | 653 | tag, |
634 | category: { | 654 | category, |
635 | identifier: this.category + '', | 655 | licence, |
636 | name: this.getCategoryLabel() | ||
637 | }, | ||
638 | licence: { | ||
639 | identifier: this.licence + '', | ||
640 | name: this.getLicenceLabel() | ||
641 | }, | ||
642 | language, | 656 | language, |
643 | views: this.views, | 657 | views: this.views, |
644 | nsfw: this.nsfw, | 658 | nsfw: this.nsfw, |
@@ -663,6 +677,8 @@ toActivityPubObject = function (this: VideoInstance) { | |||
663 | } | 677 | } |
664 | 678 | ||
665 | getTruncatedDescription = function (this: VideoInstance) { | 679 | getTruncatedDescription = function (this: VideoInstance) { |
680 | if (!this.description) return null | ||
681 | |||
666 | const options = { | 682 | const options = { |
667 | length: CONSTRAINTS_FIELDS.VIDEOS.TRUNCATED_DESCRIPTION.max | 683 | length: CONSTRAINTS_FIELDS.VIDEOS.TRUNCATED_DESCRIPTION.max |
668 | } | 684 | } |
@@ -753,8 +769,6 @@ getDescriptionPath = function (this: VideoInstance) { | |||
753 | 769 | ||
754 | getCategoryLabel = function (this: VideoInstance) { | 770 | getCategoryLabel = function (this: VideoInstance) { |
755 | let categoryLabel = VIDEO_CATEGORIES[this.category] | 771 | let categoryLabel = VIDEO_CATEGORIES[this.category] |
756 | |||
757 | // Maybe our server is not up to date and there are new categories since our version | ||
758 | if (!categoryLabel) categoryLabel = 'Misc' | 772 | if (!categoryLabel) categoryLabel = 'Misc' |
759 | 773 | ||
760 | return categoryLabel | 774 | return categoryLabel |
@@ -762,15 +776,12 @@ getCategoryLabel = function (this: VideoInstance) { | |||
762 | 776 | ||
763 | getLicenceLabel = function (this: VideoInstance) { | 777 | getLicenceLabel = function (this: VideoInstance) { |
764 | let licenceLabel = VIDEO_LICENCES[this.licence] | 778 | let licenceLabel = VIDEO_LICENCES[this.licence] |
765 | |||
766 | // Maybe our server is not up to date and there are new licences since our version | ||
767 | if (!licenceLabel) licenceLabel = 'Unknown' | 779 | if (!licenceLabel) licenceLabel = 'Unknown' |
768 | 780 | ||
769 | return licenceLabel | 781 | return licenceLabel |
770 | } | 782 | } |
771 | 783 | ||
772 | getLanguageLabel = function (this: VideoInstance) { | 784 | getLanguageLabel = function (this: VideoInstance) { |
773 | // Language is an optional attribute | ||
774 | let languageLabel = VIDEO_LANGUAGES[this.language] | 785 | let languageLabel = VIDEO_LANGUAGES[this.language] |
775 | if (!languageLabel) languageLabel = 'Unknown' | 786 | if (!languageLabel) languageLabel = 'Unknown' |
776 | 787 | ||
@@ -1070,7 +1081,7 @@ loadByUUIDAndPopulateAccountAndServerAndTags = function (uuid: string) { | |||
1070 | return Video.findOne(options) | 1081 | return Video.findOne(options) |
1071 | } | 1082 | } |
1072 | 1083 | ||
1073 | searchAndPopulateAccountAndServerAndTags = function (value: string, field: string, start: number, count: number, sort: string) { | 1084 | searchAndPopulateAccountAndServerAndTags = function (value: string, start: number, count: number, sort: string) { |
1074 | const serverInclude: Sequelize.IncludeOptions = { | 1085 | const serverInclude: Sequelize.IncludeOptions = { |
1075 | model: Video['sequelize'].models.Server, | 1086 | model: Video['sequelize'].models.Server, |
1076 | required: false | 1087 | required: false |
@@ -1099,33 +1110,24 @@ searchAndPopulateAccountAndServerAndTags = function (value: string, field: strin | |||
1099 | order: [ getSort(sort), [ Video['sequelize'].models.Tag, 'name', 'ASC' ] ] | 1110 | order: [ getSort(sort), [ Video['sequelize'].models.Tag, 'name', 'ASC' ] ] |
1100 | } | 1111 | } |
1101 | 1112 | ||
1102 | if (field === 'tags') { | 1113 | // TODO: search on tags too |
1103 | const escapedValue = Video['sequelize'].escape('%' + value + '%') | 1114 | // const escapedValue = Video['sequelize'].escape('%' + value + '%') |
1104 | query.where['id'][Sequelize.Op.in] = Video['sequelize'].literal( | 1115 | // query.where['id'][Sequelize.Op.in] = Video['sequelize'].literal( |
1105 | `(SELECT "VideoTags"."videoId" | 1116 | // `(SELECT "VideoTags"."videoId" |
1106 | FROM "Tags" | 1117 | // FROM "Tags" |
1107 | INNER JOIN "VideoTags" ON "Tags"."id" = "VideoTags"."tagId" | 1118 | // INNER JOIN "VideoTags" ON "Tags"."id" = "VideoTags"."tagId" |
1108 | WHERE name ILIKE ${escapedValue} | 1119 | // WHERE name ILIKE ${escapedValue} |
1109 | )` | 1120 | // )` |
1110 | ) | 1121 | // ) |
1111 | } else if (field === 'host') { | 1122 | |
1112 | // FIXME: Include our server? (not stored in the database) | 1123 | // TODO: search on account too |
1113 | serverInclude.where = { | 1124 | // accountInclude.where = { |
1114 | host: { | 1125 | // name: { |
1115 | [Sequelize.Op.iLike]: '%' + value + '%' | 1126 | // [Sequelize.Op.iLike]: '%' + value + '%' |
1116 | } | 1127 | // } |
1117 | } | 1128 | // } |
1118 | serverInclude.required = true | 1129 | query.where['name'] = { |
1119 | } else if (field === 'account') { | 1130 | [Sequelize.Op.iLike]: '%' + value + '%' |
1120 | accountInclude.where = { | ||
1121 | name: { | ||
1122 | [Sequelize.Op.iLike]: '%' + value + '%' | ||
1123 | } | ||
1124 | } | ||
1125 | } else { | ||
1126 | query.where[field] = { | ||
1127 | [Sequelize.Op.iLike]: '%' + value + '%' | ||
1128 | } | ||
1129 | } | 1131 | } |
1130 | 1132 | ||
1131 | query.include = [ | 1133 | query.include = [ |
diff --git a/server/tests/api/check-params/videos.ts b/server/tests/api/check-params/videos.ts index 2962f5640..0aaa6e7c9 100644 --- a/server/tests/api/check-params/videos.ts +++ b/server/tests/api/check-params/videos.ts | |||
@@ -189,14 +189,6 @@ describe('Test videos API validator', function () { | |||
189 | await makePostUploadRequest({ url: server.url, path: path + '/upload', token: server.accessToken, fields, attaches }) | 189 | await makePostUploadRequest({ url: server.url, path: path + '/upload', token: server.accessToken, fields, attaches }) |
190 | }) | 190 | }) |
191 | 191 | ||
192 | it('Should fail without a category', async function () { | ||
193 | const fields = getCompleteVideoUploadAttributes() | ||
194 | delete fields.category | ||
195 | |||
196 | const attaches = getVideoUploadAttaches | ||
197 | await makePostUploadRequest({ url: server.url, path: path + '/upload', token: server.accessToken, fields, attaches }) | ||
198 | }) | ||
199 | |||
200 | it('Should fail with a bad category', async function () { | 192 | it('Should fail with a bad category', async function () { |
201 | const fields = getCompleteVideoUploadAttributes() | 193 | const fields = getCompleteVideoUploadAttributes() |
202 | fields.category = 125 | 194 | fields.category = 125 |
@@ -205,14 +197,6 @@ describe('Test videos API validator', function () { | |||
205 | await makePostUploadRequest({ url: server.url, path: path + '/upload', token: server.accessToken, fields, attaches }) | 197 | await makePostUploadRequest({ url: server.url, path: path + '/upload', token: server.accessToken, fields, attaches }) |
206 | }) | 198 | }) |
207 | 199 | ||
208 | it('Should fail without a licence', async function () { | ||
209 | const fields = getCompleteVideoUploadAttributes() | ||
210 | delete fields.licence | ||
211 | |||
212 | const attaches = getVideoUploadAttaches() | ||
213 | await makePostUploadRequest({ url: server.url, path: path + '/upload', token: server.accessToken, fields, attaches }) | ||
214 | }) | ||
215 | |||
216 | it('Should fail with a bad licence', async function () { | 200 | it('Should fail with a bad licence', async function () { |
217 | const fields = getCompleteVideoUploadAttributes() | 201 | const fields = getCompleteVideoUploadAttributes() |
218 | fields.licence = 125 | 202 | fields.licence = 125 |
@@ -245,14 +229,6 @@ describe('Test videos API validator', function () { | |||
245 | await makePostUploadRequest({ url: server.url, path: path + '/upload', token: server.accessToken, fields, attaches }) | 229 | await makePostUploadRequest({ url: server.url, path: path + '/upload', token: server.accessToken, fields, attaches }) |
246 | }) | 230 | }) |
247 | 231 | ||
248 | it('Should fail without description', async function () { | ||
249 | const fields = getCompleteVideoUploadAttributes() | ||
250 | delete fields.description | ||
251 | |||
252 | const attaches = getVideoUploadAttaches() | ||
253 | await makePostUploadRequest({ url: server.url, path: path + '/upload', token: server.accessToken, fields, attaches }) | ||
254 | }) | ||
255 | |||
256 | it('Should fail with a long description', async function () { | 232 | it('Should fail with a long description', async function () { |
257 | const fields = getCompleteVideoUploadAttributes() | 233 | const fields = getCompleteVideoUploadAttributes() |
258 | fields.description = 'my super description which is very very very very very very very very very very very very long'.repeat(35) | 234 | fields.description = 'my super description which is very very very very very very very very very very very very long'.repeat(35) |
@@ -345,7 +321,7 @@ describe('Test videos API validator', function () { | |||
345 | token: server.accessToken, | 321 | token: server.accessToken, |
346 | fields, | 322 | fields, |
347 | attaches, | 323 | attaches, |
348 | statusCodeExpected: 204 | 324 | statusCodeExpected: 200 |
349 | }) | 325 | }) |
350 | 326 | ||
351 | attaches.videofile = join(__dirname, '..', 'fixtures', 'video_short.mp4') | 327 | attaches.videofile = join(__dirname, '..', 'fixtures', 'video_short.mp4') |
@@ -355,7 +331,7 @@ describe('Test videos API validator', function () { | |||
355 | token: server.accessToken, | 331 | token: server.accessToken, |
356 | fields, | 332 | fields, |
357 | attaches, | 333 | attaches, |
358 | statusCodeExpected: 204 | 334 | statusCodeExpected: 200 |
359 | }) | 335 | }) |
360 | 336 | ||
361 | attaches.videofile = join(__dirname, '..', 'fixtures', 'video_short.ogv') | 337 | attaches.videofile = join(__dirname, '..', 'fixtures', 'video_short.ogv') |
@@ -365,7 +341,7 @@ describe('Test videos API validator', function () { | |||
365 | token: server.accessToken, | 341 | token: server.accessToken, |
366 | fields, | 342 | fields, |
367 | attaches, | 343 | attaches, |
368 | statusCodeExpected: 204 | 344 | statusCodeExpected: 200 |
369 | }) | 345 | }) |
370 | }) | 346 | }) |
371 | }) | 347 | }) |
diff --git a/server/tests/api/follows.ts b/server/tests/api/follows.ts index aadae3cce..dcb4c8bd9 100644 --- a/server/tests/api/follows.ts +++ b/server/tests/api/follows.ts | |||
@@ -227,7 +227,7 @@ describe('Test follows', function () { | |||
227 | expect(videoDetails.nsfw).to.be.ok | 227 | expect(videoDetails.nsfw).to.be.ok |
228 | expect(videoDetails.description).to.equal('my super description') | 228 | expect(videoDetails.description).to.equal('my super description') |
229 | expect(videoDetails.serverHost).to.equal('localhost:9003') | 229 | expect(videoDetails.serverHost).to.equal('localhost:9003') |
230 | expect(videoDetails.account).to.equal('root') | 230 | expect(videoDetails.accountName).to.equal('root') |
231 | expect(videoDetails.likes).to.equal(1) | 231 | expect(videoDetails.likes).to.equal(1) |
232 | expect(videoDetails.dislikes).to.equal(1) | 232 | expect(videoDetails.dislikes).to.equal(1) |
233 | expect(videoDetails.isLocal).to.be.false | 233 | expect(videoDetails.isLocal).to.be.false |
diff --git a/server/tests/api/multiple-servers.ts b/server/tests/api/multiple-servers.ts index c80ded862..2f17f017a 100644 --- a/server/tests/api/multiple-servers.ts +++ b/server/tests/api/multiple-servers.ts | |||
@@ -2,6 +2,8 @@ | |||
2 | 2 | ||
3 | import 'mocha' | 3 | import 'mocha' |
4 | import * as chai from 'chai' | 4 | import * as chai from 'chai' |
5 | import { join } from 'path' | ||
6 | import * as request from 'supertest' | ||
5 | 7 | ||
6 | import { | 8 | import { |
7 | dateIsValid, | 9 | dateIsValid, |
@@ -111,13 +113,14 @@ describe('Test multiple servers', function () { | |||
111 | expect(video.tags).to.deep.equal([ 'tag1p1', 'tag2p1' ]) | 113 | expect(video.tags).to.deep.equal([ 'tag1p1', 'tag2p1' ]) |
112 | expect(dateIsValid(video.createdAt)).to.be.true | 114 | expect(dateIsValid(video.createdAt)).to.be.true |
113 | expect(dateIsValid(video.updatedAt)).to.be.true | 115 | expect(dateIsValid(video.updatedAt)).to.be.true |
114 | expect(video.account).to.equal('root') | 116 | expect(video.accountName).to.equal('root') |
115 | 117 | ||
116 | const res2 = await getVideo(server.url, video.uuid) | 118 | const res2 = await getVideo(server.url, video.uuid) |
117 | const videoDetails = res2.body | 119 | const videoDetails = res2.body |
118 | 120 | ||
119 | expect(videoDetails.channel.name).to.equal('my channel') | 121 | expect(videoDetails.channel.name).to.equal('my channel') |
120 | expect(videoDetails.channel.description).to.equal('super channel') | 122 | expect(videoDetails.channel.description).to.equal('super channel') |
123 | expect(videoDetails.account.name).to.equal('root') | ||
121 | expect(dateIsValid(videoDetails.channel.createdAt)).to.be.true | 124 | expect(dateIsValid(videoDetails.channel.createdAt)).to.be.true |
122 | expect(dateIsValid(videoDetails.channel.updatedAt)).to.be.true | 125 | expect(dateIsValid(videoDetails.channel.updatedAt)).to.be.true |
123 | expect(videoDetails.files).to.have.lengthOf(1) | 126 | expect(videoDetails.files).to.have.lengthOf(1) |
@@ -201,7 +204,7 @@ describe('Test multiple servers', function () { | |||
201 | expect(video.tags).to.deep.equal([ 'tag1p2', 'tag2p2', 'tag3p2' ]) | 204 | expect(video.tags).to.deep.equal([ 'tag1p2', 'tag2p2', 'tag3p2' ]) |
202 | expect(dateIsValid(video.createdAt)).to.be.true | 205 | expect(dateIsValid(video.createdAt)).to.be.true |
203 | expect(dateIsValid(video.updatedAt)).to.be.true | 206 | expect(dateIsValid(video.updatedAt)).to.be.true |
204 | expect(video.account).to.equal('user1') | 207 | expect(video.accountName).to.equal('user1') |
205 | 208 | ||
206 | if (server.url !== 'http://localhost:9002') { | 209 | if (server.url !== 'http://localhost:9002') { |
207 | expect(video.isLocal).to.be.false | 210 | expect(video.isLocal).to.be.false |
@@ -316,7 +319,7 @@ describe('Test multiple servers', function () { | |||
316 | expect(video1.serverHost).to.equal('localhost:9003') | 319 | expect(video1.serverHost).to.equal('localhost:9003') |
317 | expect(video1.duration).to.equal(5) | 320 | expect(video1.duration).to.equal(5) |
318 | expect(video1.tags).to.deep.equal([ 'tag1p3' ]) | 321 | expect(video1.tags).to.deep.equal([ 'tag1p3' ]) |
319 | expect(video1.account).to.equal('root') | 322 | expect(video1.accountName).to.equal('root') |
320 | expect(dateIsValid(video1.createdAt)).to.be.true | 323 | expect(dateIsValid(video1.createdAt)).to.be.true |
321 | expect(dateIsValid(video1.updatedAt)).to.be.true | 324 | expect(dateIsValid(video1.updatedAt)).to.be.true |
322 | 325 | ||
@@ -342,7 +345,7 @@ describe('Test multiple servers', function () { | |||
342 | expect(video2.serverHost).to.equal('localhost:9003') | 345 | expect(video2.serverHost).to.equal('localhost:9003') |
343 | expect(video2.duration).to.equal(5) | 346 | expect(video2.duration).to.equal(5) |
344 | expect(video2.tags).to.deep.equal([ 'tag2p3', 'tag3p3', 'tag4p3' ]) | 347 | expect(video2.tags).to.deep.equal([ 'tag2p3', 'tag3p3', 'tag4p3' ]) |
345 | expect(video2.account).to.equal('root') | 348 | expect(video2.accountName).to.equal('root') |
346 | expect(dateIsValid(video2.createdAt)).to.be.true | 349 | expect(dateIsValid(video2.createdAt)).to.be.true |
347 | expect(dateIsValid(video2.updatedAt)).to.be.true | 350 | expect(dateIsValid(video2.updatedAt)).to.be.true |
348 | 351 | ||
@@ -690,7 +693,7 @@ describe('Test multiple servers', function () { | |||
690 | expect(baseVideo.licence).to.equal(video.licence) | 693 | expect(baseVideo.licence).to.equal(video.licence) |
691 | expect(baseVideo.category).to.equal(video.category) | 694 | expect(baseVideo.category).to.equal(video.category) |
692 | expect(baseVideo.nsfw).to.equal(video.nsfw) | 695 | expect(baseVideo.nsfw).to.equal(video.nsfw) |
693 | expect(baseVideo.account).to.equal(video.account) | 696 | expect(baseVideo.accountName).to.equal(video.accountName) |
694 | expect(baseVideo.tags).to.deep.equal(video.tags) | 697 | expect(baseVideo.tags).to.deep.equal(video.tags) |
695 | } | 698 | } |
696 | }) | 699 | }) |
@@ -706,6 +709,50 @@ describe('Test multiple servers', function () { | |||
706 | }) | 709 | }) |
707 | }) | 710 | }) |
708 | 711 | ||
712 | describe('With minimum parameters', function () { | ||
713 | it('Should upload and propagate the video', async function () { | ||
714 | this.timeout(50000) | ||
715 | |||
716 | const path = '/api/v1/videos/upload' | ||
717 | |||
718 | const req = request(servers[1].url) | ||
719 | .post(path) | ||
720 | .set('Accept', 'application/json') | ||
721 | .set('Authorization', 'Bearer ' + servers[1].accessToken) | ||
722 | .field('name', 'minimum parameters') | ||
723 | .field('privacy', '1') | ||
724 | .field('nsfw', 'false') | ||
725 | .field('channelId', '1') | ||
726 | |||
727 | const filePath = join(__dirname, '..', 'api', 'fixtures', 'video_short.webm') | ||
728 | |||
729 | await req.attach('videofile', filePath) | ||
730 | .expect(200) | ||
731 | |||
732 | await wait(25000) | ||
733 | |||
734 | for (const server of servers) { | ||
735 | const res = await getVideosList(server.url) | ||
736 | const video = res.body.data.find(v => v.name === 'minimum parameters') | ||
737 | |||
738 | expect(video.name).to.equal('minimum parameters') | ||
739 | expect(video.category).to.equal(null) | ||
740 | expect(video.categoryLabel).to.equal('Misc') | ||
741 | expect(video.licence).to.equal(null) | ||
742 | expect(video.licenceLabel).to.equal('Unknown') | ||
743 | expect(video.language).to.equal(null) | ||
744 | expect(video.languageLabel).to.equal('Unknown') | ||
745 | expect(video.nsfw).to.not.be.ok | ||
746 | expect(video.description).to.equal(null) | ||
747 | expect(video.serverHost).to.equal('localhost:9002') | ||
748 | expect(video.accountName).to.equal('root') | ||
749 | expect(video.tags).to.deep.equal([ ]) | ||
750 | expect(dateIsValid(video.createdAt)).to.be.true | ||
751 | expect(dateIsValid(video.updatedAt)).to.be.true | ||
752 | } | ||
753 | }) | ||
754 | }) | ||
755 | |||
709 | after(async function () { | 756 | after(async function () { |
710 | killallServers(servers) | 757 | killallServers(servers) |
711 | 758 | ||
diff --git a/server/tests/api/services.ts b/server/tests/api/services.ts index 8d96ccc5e..4d480c305 100644 --- a/server/tests/api/services.ts +++ b/server/tests/api/services.ts | |||
@@ -46,7 +46,7 @@ describe('Test services', function () { | |||
46 | 46 | ||
47 | expect(res.body.html).to.equal(expectedHtml) | 47 | expect(res.body.html).to.equal(expectedHtml) |
48 | expect(res.body.title).to.equal(server.video.name) | 48 | expect(res.body.title).to.equal(server.video.name) |
49 | expect(res.body.author_name).to.equal(server.video.account) | 49 | expect(res.body.author_name).to.equal(server.video.accountName) |
50 | expect(res.body.width).to.equal(560) | 50 | expect(res.body.width).to.equal(560) |
51 | expect(res.body.height).to.equal(315) | 51 | expect(res.body.height).to.equal(315) |
52 | expect(res.body.thumbnail_url).to.equal(expectedThumbnailUrl) | 52 | expect(res.body.thumbnail_url).to.equal(expectedThumbnailUrl) |
@@ -66,7 +66,7 @@ describe('Test services', function () { | |||
66 | 66 | ||
67 | expect(res.body.html).to.equal(expectedHtml) | 67 | expect(res.body.html).to.equal(expectedHtml) |
68 | expect(res.body.title).to.equal(server.video.name) | 68 | expect(res.body.title).to.equal(server.video.name) |
69 | expect(res.body.author_name).to.equal(server.video.account) | 69 | expect(res.body.author_name).to.equal(server.video.accountName) |
70 | expect(res.body.height).to.equal(50) | 70 | expect(res.body.height).to.equal(50) |
71 | expect(res.body.width).to.equal(50) | 71 | expect(res.body.width).to.equal(50) |
72 | expect(res.body).to.not.have.property('thumbnail_url') | 72 | expect(res.body).to.not.have.property('thumbnail_url') |
diff --git a/server/tests/api/single-server.ts b/server/tests/api/single-server.ts index 041d13225..174fb480d 100644 --- a/server/tests/api/single-server.ts +++ b/server/tests/api/single-server.ts | |||
@@ -1,40 +1,40 @@ | |||
1 | /* tslint:disable:no-unused-expression */ | 1 | /* tslint:disable:no-unused-expression */ |
2 | 2 | ||
3 | import * as chai from 'chai' | ||
3 | import { keyBy } from 'lodash' | 4 | import { keyBy } from 'lodash' |
4 | import { join } from 'path' | ||
5 | import 'mocha' | 5 | import 'mocha' |
6 | import * as chai from 'chai' | 6 | import { join } from 'path' |
7 | const expect = chai.expect | ||
8 | |||
9 | import { | 7 | import { |
10 | ServerInfo, | ||
11 | flushTests, | ||
12 | runServer, | ||
13 | uploadVideo, | ||
14 | getVideosList, | ||
15 | rateVideo, | ||
16 | removeVideo, | ||
17 | wait, | ||
18 | setAccessTokensToServers, | ||
19 | searchVideo, | ||
20 | killallServers, | ||
21 | dateIsValid, | 8 | dateIsValid, |
9 | flushTests, | ||
10 | getVideo, | ||
22 | getVideoCategories, | 11 | getVideoCategories, |
23 | getVideoLicences, | ||
24 | getVideoLanguages, | 12 | getVideoLanguages, |
13 | getVideoLicences, | ||
25 | getVideoPrivacies, | 14 | getVideoPrivacies, |
26 | testVideoImage, | 15 | getVideosList, |
27 | webtorrentAdd, | ||
28 | getVideo, | ||
29 | readdirPromise, | ||
30 | getVideosListPagination, | 16 | getVideosListPagination, |
31 | searchVideoWithPagination, | ||
32 | getVideosListSort, | 17 | getVideosListSort, |
18 | killallServers, | ||
19 | rateVideo, | ||
20 | readdirPromise, | ||
21 | removeVideo, | ||
22 | runServer, | ||
23 | searchVideo, | ||
24 | searchVideoWithPagination, | ||
33 | searchVideoWithSort, | 25 | searchVideoWithSort, |
34 | updateVideo | 26 | ServerInfo, |
27 | setAccessTokensToServers, | ||
28 | testVideoImage, | ||
29 | updateVideo, | ||
30 | uploadVideo, | ||
31 | wait, | ||
32 | webtorrentAdd | ||
35 | } from '../utils' | 33 | } from '../utils' |
36 | import { viewVideo } from '../utils/videos' | 34 | import { viewVideo } from '../utils/videos' |
37 | 35 | ||
36 | const expect = chai.expect | ||
37 | |||
38 | describe('Test a single server', function () { | 38 | describe('Test a single server', function () { |
39 | let server: ServerInfo = null | 39 | let server: ServerInfo = null |
40 | let videoId = -1 | 40 | let videoId = -1 |
@@ -103,7 +103,10 @@ describe('Test a single server', function () { | |||
103 | licence: 6, | 103 | licence: 6, |
104 | tags: [ 'tag1', 'tag2', 'tag3' ] | 104 | tags: [ 'tag1', 'tag2', 'tag3' ] |
105 | } | 105 | } |
106 | await uploadVideo(server.url, server.accessToken, videoAttributes) | 106 | const res = await uploadVideo(server.url, server.accessToken, videoAttributes) |
107 | expect(res.body.video).to.not.be.undefined | ||
108 | expect(res.body.video.id).to.equal(1) | ||
109 | expect(res.body.video.uuid).to.have.length.above(5) | ||
107 | }) | 110 | }) |
108 | 111 | ||
109 | it('Should seed the uploaded video', async function () { | 112 | it('Should seed the uploaded video', async function () { |
@@ -127,7 +130,7 @@ describe('Test a single server', function () { | |||
127 | expect(video.nsfw).to.be.ok | 130 | expect(video.nsfw).to.be.ok |
128 | expect(video.description).to.equal('my super description') | 131 | expect(video.description).to.equal('my super description') |
129 | expect(video.serverHost).to.equal('localhost:9001') | 132 | expect(video.serverHost).to.equal('localhost:9001') |
130 | expect(video.account).to.equal('root') | 133 | expect(video.accountName).to.equal('root') |
131 | expect(video.isLocal).to.be.true | 134 | expect(video.isLocal).to.be.true |
132 | expect(video.tags).to.deep.equal([ 'tag1', 'tag2', 'tag3' ]) | 135 | expect(video.tags).to.deep.equal([ 'tag1', 'tag2', 'tag3' ]) |
133 | expect(dateIsValid(video.createdAt)).to.be.true | 136 | expect(dateIsValid(video.createdAt)).to.be.true |
@@ -176,7 +179,7 @@ describe('Test a single server', function () { | |||
176 | expect(video.nsfw).to.be.ok | 179 | expect(video.nsfw).to.be.ok |
177 | expect(video.description).to.equal('my super description') | 180 | expect(video.description).to.equal('my super description') |
178 | expect(video.serverHost).to.equal('localhost:9001') | 181 | expect(video.serverHost).to.equal('localhost:9001') |
179 | expect(video.account).to.equal('root') | 182 | expect(video.accountName).to.equal('root') |
180 | expect(video.isLocal).to.be.true | 183 | expect(video.isLocal).to.be.true |
181 | expect(video.tags).to.deep.equal([ 'tag1', 'tag2', 'tag3' ]) | 184 | expect(video.tags).to.deep.equal([ 'tag1', 'tag2', 'tag3' ]) |
182 | expect(dateIsValid(video.createdAt)).to.be.true | 185 | expect(dateIsValid(video.createdAt)).to.be.true |
@@ -225,7 +228,7 @@ describe('Test a single server', function () { | |||
225 | expect(video.views).to.equal(3) | 228 | expect(video.views).to.equal(3) |
226 | }) | 229 | }) |
227 | 230 | ||
228 | it('Should search the video by name by default', async function () { | 231 | it('Should search the video by name', async function () { |
229 | const res = await searchVideo(server.url, 'my') | 232 | const res = await searchVideo(server.url, 'my') |
230 | 233 | ||
231 | expect(res.body.total).to.equal(1) | 234 | expect(res.body.total).to.equal(1) |
@@ -243,7 +246,7 @@ describe('Test a single server', function () { | |||
243 | expect(video.nsfw).to.be.ok | 246 | expect(video.nsfw).to.be.ok |
244 | expect(video.description).to.equal('my super description') | 247 | expect(video.description).to.equal('my super description') |
245 | expect(video.serverHost).to.equal('localhost:9001') | 248 | expect(video.serverHost).to.equal('localhost:9001') |
246 | expect(video.account).to.equal('root') | 249 | expect(video.accountName).to.equal('root') |
247 | expect(video.isLocal).to.be.true | 250 | expect(video.isLocal).to.be.true |
248 | expect(video.tags).to.deep.equal([ 'tag1', 'tag2', 'tag3' ]) | 251 | expect(video.tags).to.deep.equal([ 'tag1', 'tag2', 'tag3' ]) |
249 | expect(dateIsValid(video.createdAt)).to.be.true | 252 | expect(dateIsValid(video.createdAt)).to.be.true |
@@ -279,35 +282,36 @@ describe('Test a single server', function () { | |||
279 | // }) | 282 | // }) |
280 | // }) | 283 | // }) |
281 | 284 | ||
282 | it('Should search the video by tag', async function () { | 285 | // Not implemented yet |
283 | const res = await searchVideo(server.url, 'tag1', 'tags') | 286 | // it('Should search the video by tag', async function () { |
284 | 287 | // const res = await searchVideo(server.url, 'tag1') | |
285 | expect(res.body.total).to.equal(1) | 288 | // |
286 | expect(res.body.data).to.be.an('array') | 289 | // expect(res.body.total).to.equal(1) |
287 | expect(res.body.data.length).to.equal(1) | 290 | // expect(res.body.data).to.be.an('array') |
288 | 291 | // expect(res.body.data.length).to.equal(1) | |
289 | const video = res.body.data[0] | 292 | // |
290 | expect(video.name).to.equal('my super name') | 293 | // const video = res.body.data[0] |
291 | expect(video.category).to.equal(2) | 294 | // expect(video.name).to.equal('my super name') |
292 | expect(video.categoryLabel).to.equal('Films') | 295 | // expect(video.category).to.equal(2) |
293 | expect(video.licence).to.equal(6) | 296 | // expect(video.categoryLabel).to.equal('Films') |
294 | expect(video.licenceLabel).to.equal('Attribution - Non Commercial - No Derivatives') | 297 | // expect(video.licence).to.equal(6) |
295 | expect(video.language).to.equal(3) | 298 | // expect(video.licenceLabel).to.equal('Attribution - Non Commercial - No Derivatives') |
296 | expect(video.languageLabel).to.equal('Mandarin') | 299 | // expect(video.language).to.equal(3) |
297 | expect(video.nsfw).to.be.ok | 300 | // expect(video.languageLabel).to.equal('Mandarin') |
298 | expect(video.description).to.equal('my super description') | 301 | // expect(video.nsfw).to.be.ok |
299 | expect(video.serverHost).to.equal('localhost:9001') | 302 | // expect(video.description).to.equal('my super description') |
300 | expect(video.account).to.equal('root') | 303 | // expect(video.serverHost).to.equal('localhost:9001') |
301 | expect(video.isLocal).to.be.true | 304 | // expect(video.accountName).to.equal('root') |
302 | expect(video.tags).to.deep.equal([ 'tag1', 'tag2', 'tag3' ]) | 305 | // expect(video.isLocal).to.be.true |
303 | expect(dateIsValid(video.createdAt)).to.be.true | 306 | // expect(video.tags).to.deep.equal([ 'tag1', 'tag2', 'tag3' ]) |
304 | expect(dateIsValid(video.updatedAt)).to.be.true | 307 | // expect(dateIsValid(video.createdAt)).to.be.true |
305 | 308 | // expect(dateIsValid(video.updatedAt)).to.be.true | |
306 | const test = await testVideoImage(server.url, 'video_short.webm', video.thumbnailPath) | 309 | // |
307 | expect(test).to.equal(true) | 310 | // const test = await testVideoImage(server.url, 'video_short.webm', video.thumbnailPath) |
308 | }) | 311 | // expect(test).to.equal(true) |
312 | // }) | ||
309 | 313 | ||
310 | it('Should not find a search by name by default', async function () { | 314 | it('Should not find a search by name', async function () { |
311 | const res = await searchVideo(server.url, 'hello') | 315 | const res = await searchVideo(server.url, 'hello') |
312 | 316 | ||
313 | expect(res.body.total).to.equal(0) | 317 | expect(res.body.total).to.equal(0) |
@@ -315,21 +319,23 @@ describe('Test a single server', function () { | |||
315 | expect(res.body.data.length).to.equal(0) | 319 | expect(res.body.data.length).to.equal(0) |
316 | }) | 320 | }) |
317 | 321 | ||
318 | it('Should not find a search by author', async function () { | 322 | // Not implemented yet |
319 | const res = await searchVideo(server.url, 'hello', 'account') | 323 | // it('Should not find a search by author', async function () { |
320 | 324 | // const res = await searchVideo(server.url, 'hello') | |
321 | expect(res.body.total).to.equal(0) | 325 | // |
322 | expect(res.body.data).to.be.an('array') | 326 | // expect(res.body.total).to.equal(0) |
323 | expect(res.body.data.length).to.equal(0) | 327 | // expect(res.body.data).to.be.an('array') |
324 | }) | 328 | // expect(res.body.data.length).to.equal(0) |
325 | 329 | // }) | |
326 | it('Should not find a search by tag', async function () { | 330 | // |
327 | const res = await searchVideo(server.url, 'hello', 'tags') | 331 | // Not implemented yet |
328 | 332 | // it('Should not find a search by tag', async function () { | |
329 | expect(res.body.total).to.equal(0) | 333 | // const res = await searchVideo(server.url, 'hello') |
330 | expect(res.body.data).to.be.an('array') | 334 | // |
331 | expect(res.body.data.length).to.equal(0) | 335 | // expect(res.body.total).to.equal(0) |
332 | }) | 336 | // expect(res.body.data).to.be.an('array') |
337 | // expect(res.body.data.length).to.equal(0) | ||
338 | // }) | ||
333 | 339 | ||
334 | it('Should remove the video', async function () { | 340 | it('Should remove the video', async function () { |
335 | await removeVideo(server.url, server.accessToken, videoId) | 341 | await removeVideo(server.url, server.accessToken, videoId) |
@@ -357,7 +363,7 @@ describe('Test a single server', function () { | |||
357 | 'video_short1.webm', 'video_short2.webm', 'video_short3.webm' | 363 | 'video_short1.webm', 'video_short2.webm', 'video_short3.webm' |
358 | ] | 364 | ] |
359 | 365 | ||
360 | // const tasks: Promise<any>[] = [] | 366 | const tasks: Promise<any>[] = [] |
361 | for (const video of videos) { | 367 | for (const video of videos) { |
362 | const videoAttributes = { | 368 | const videoAttributes = { |
363 | name: video + ' name', | 369 | name: video + ' name', |
@@ -371,13 +377,10 @@ describe('Test a single server', function () { | |||
371 | } | 377 | } |
372 | 378 | ||
373 | const p = uploadVideo(server.url, server.accessToken, videoAttributes) | 379 | const p = uploadVideo(server.url, server.accessToken, videoAttributes) |
374 | await p | 380 | tasks.push(p) |
375 | } | 381 | } |
376 | // FIXME: concurrent uploads does not work :( | 382 | |
377 | // tasks.push(p) | 383 | await Promise.all(tasks) |
378 | // } | ||
379 | // | ||
380 | // await Promise.all(tasks) | ||
381 | }) | 384 | }) |
382 | 385 | ||
383 | it('Should have the correct durations', async function () { | 386 | it('Should have the correct durations', async function () { |
@@ -443,7 +446,7 @@ describe('Test a single server', function () { | |||
443 | }) | 446 | }) |
444 | 447 | ||
445 | it('Should search the first video', async function () { | 448 | it('Should search the first video', async function () { |
446 | const res = await searchVideoWithPagination(server.url, 'webm', 'name', 0, 1, 'name') | 449 | const res = await searchVideoWithPagination(server.url, 'webm', 0, 1, 'name') |
447 | 450 | ||
448 | const videos = res.body.data | 451 | const videos = res.body.data |
449 | expect(res.body.total).to.equal(4) | 452 | expect(res.body.total).to.equal(4) |
@@ -452,7 +455,7 @@ describe('Test a single server', function () { | |||
452 | }) | 455 | }) |
453 | 456 | ||
454 | it('Should search the last two videos', async function () { | 457 | it('Should search the last two videos', async function () { |
455 | const res = await searchVideoWithPagination(server.url, 'webm', 'name', 2, 2, 'name') | 458 | const res = await searchVideoWithPagination(server.url, 'webm', 2, 2, 'name') |
456 | 459 | ||
457 | const videos = res.body.data | 460 | const videos = res.body.data |
458 | expect(res.body.total).to.equal(4) | 461 | expect(res.body.total).to.equal(4) |
@@ -462,20 +465,21 @@ describe('Test a single server', function () { | |||
462 | }) | 465 | }) |
463 | 466 | ||
464 | it('Should search all the webm videos', async function () { | 467 | it('Should search all the webm videos', async function () { |
465 | const res = await searchVideoWithPagination(server.url, 'webm', 'name', 0, 15) | 468 | const res = await searchVideoWithPagination(server.url, 'webm', 0, 15) |
466 | 469 | ||
467 | const videos = res.body.data | 470 | const videos = res.body.data |
468 | expect(res.body.total).to.equal(4) | 471 | expect(res.body.total).to.equal(4) |
469 | expect(videos.length).to.equal(4) | 472 | expect(videos.length).to.equal(4) |
470 | }) | 473 | }) |
471 | 474 | ||
472 | it('Should search all the root author videos', async function () { | 475 | // Not implemented yet |
473 | const res = await searchVideoWithPagination(server.url, 'root', 'account', 0, 15) | 476 | // it('Should search all the root author videos', async function () { |
474 | 477 | // const res = await searchVideoWithPagination(server.url, 'root', 0, 15) | |
475 | const videos = res.body.data | 478 | // |
476 | expect(res.body.total).to.equal(6) | 479 | // const videos = res.body.data |
477 | expect(videos.length).to.equal(6) | 480 | // expect(res.body.total).to.equal(6) |
478 | }) | 481 | // expect(videos.length).to.equal(6) |
482 | // }) | ||
479 | 483 | ||
480 | // Not implemented yet | 484 | // Not implemented yet |
481 | // it('Should search all the 9001 port videos', async function () { | 485 | // it('Should search all the 9001 port videos', async function () { |
@@ -559,7 +563,8 @@ describe('Test a single server', function () { | |||
559 | expect(video.nsfw).to.be.ok | 563 | expect(video.nsfw).to.be.ok |
560 | expect(video.description).to.equal('my super description updated') | 564 | expect(video.description).to.equal('my super description updated') |
561 | expect(video.serverHost).to.equal('localhost:9001') | 565 | expect(video.serverHost).to.equal('localhost:9001') |
562 | expect(video.account).to.equal('root') | 566 | expect(video.accountName).to.equal('root') |
567 | expect(video.account.name).to.equal('root') | ||
563 | expect(video.isLocal).to.be.true | 568 | expect(video.isLocal).to.be.true |
564 | expect(video.tags).to.deep.equal([ 'tagup1', 'tagup2' ]) | 569 | expect(video.tags).to.deep.equal([ 'tagup1', 'tagup2' ]) |
565 | expect(dateIsValid(video.createdAt)).to.be.true | 570 | expect(dateIsValid(video.createdAt)).to.be.true |
@@ -608,7 +613,7 @@ describe('Test a single server', function () { | |||
608 | expect(video.nsfw).to.be.ok | 613 | expect(video.nsfw).to.be.ok |
609 | expect(video.description).to.equal('my super description updated') | 614 | expect(video.description).to.equal('my super description updated') |
610 | expect(video.serverHost).to.equal('localhost:9001') | 615 | expect(video.serverHost).to.equal('localhost:9001') |
611 | expect(video.account).to.equal('root') | 616 | expect(video.accountName).to.equal('root') |
612 | expect(video.isLocal).to.be.true | 617 | expect(video.isLocal).to.be.true |
613 | expect(video.tags).to.deep.equal([ 'supertag', 'tag1', 'tag2' ]) | 618 | expect(video.tags).to.deep.equal([ 'supertag', 'tag1', 'tag2' ]) |
614 | expect(dateIsValid(video.createdAt)).to.be.true | 619 | expect(dateIsValid(video.createdAt)).to.be.true |
@@ -648,7 +653,7 @@ describe('Test a single server', function () { | |||
648 | expect(video.nsfw).to.be.ok | 653 | expect(video.nsfw).to.be.ok |
649 | expect(video.description).to.equal('hello everybody') | 654 | expect(video.description).to.equal('hello everybody') |
650 | expect(video.serverHost).to.equal('localhost:9001') | 655 | expect(video.serverHost).to.equal('localhost:9001') |
651 | expect(video.account).to.equal('root') | 656 | expect(video.accountName).to.equal('root') |
652 | expect(video.isLocal).to.be.true | 657 | expect(video.isLocal).to.be.true |
653 | expect(video.tags).to.deep.equal([ 'supertag', 'tag1', 'tag2' ]) | 658 | expect(video.tags).to.deep.equal([ 'supertag', 'tag1', 'tag2' ]) |
654 | expect(dateIsValid(video.createdAt)).to.be.true | 659 | expect(dateIsValid(video.createdAt)).to.be.true |
diff --git a/server/tests/api/users.ts b/server/tests/api/users.ts index 33646e84f..b3163b1e1 100644 --- a/server/tests/api/users.ts +++ b/server/tests/api/users.ts | |||
@@ -113,11 +113,11 @@ describe('Test users', function () { | |||
113 | 113 | ||
114 | it('Should upload the video with the correct token', async function () { | 114 | it('Should upload the video with the correct token', async function () { |
115 | const videoAttributes = {} | 115 | const videoAttributes = {} |
116 | await uploadVideo(server.url, accessToken, videoAttributes, 204) | 116 | await uploadVideo(server.url, accessToken, videoAttributes) |
117 | const res = await getVideosList(server.url) | 117 | const res = await getVideosList(server.url) |
118 | const video = res.body.data[ 0 ] | 118 | const video = res.body.data[ 0 ] |
119 | 119 | ||
120 | expect(video.account) | 120 | expect(video.accountName) |
121 | .to | 121 | .to |
122 | .equal('root') | 122 | .equal('root') |
123 | videoId = video.id | 123 | videoId = video.id |
@@ -125,7 +125,7 @@ describe('Test users', function () { | |||
125 | 125 | ||
126 | it('Should upload the video again with the correct token', async function () { | 126 | it('Should upload the video again with the correct token', async function () { |
127 | const videoAttributes = {} | 127 | const videoAttributes = {} |
128 | await uploadVideo(server.url, accessToken, videoAttributes, 204) | 128 | await uploadVideo(server.url, accessToken, videoAttributes) |
129 | }) | 129 | }) |
130 | 130 | ||
131 | it('Should retrieve a video rating', async function () { | 131 | it('Should retrieve a video rating', async function () { |
@@ -487,7 +487,7 @@ describe('Test users', function () { | |||
487 | .equal(1) | 487 | .equal(1) |
488 | 488 | ||
489 | const video = res.body.data[ 0 ] | 489 | const video = res.body.data[ 0 ] |
490 | expect(video.account) | 490 | expect(video.accountName) |
491 | .to | 491 | .to |
492 | .equal('root') | 492 | .equal('root') |
493 | }) | 493 | }) |
diff --git a/server/tests/utils/servers.ts b/server/tests/utils/servers.ts index faa2f19ff..8340fbc18 100644 --- a/server/tests/utils/servers.ts +++ b/server/tests/utils/servers.ts | |||
@@ -24,7 +24,7 @@ interface ServerInfo { | |||
24 | id: number | 24 | id: number |
25 | uuid: string | 25 | uuid: string |
26 | name: string | 26 | name: string |
27 | account: string | 27 | accountName: string |
28 | } | 28 | } |
29 | 29 | ||
30 | remoteVideo?: { | 30 | remoteVideo?: { |
diff --git a/server/tests/utils/videos.ts b/server/tests/utils/videos.ts index 73a9f1a0a..fb758cf29 100644 --- a/server/tests/utils/videos.ts +++ b/server/tests/utils/videos.ts | |||
@@ -145,26 +145,25 @@ function removeVideo (url: string, token: string, id: number, expectedStatus = 2 | |||
145 | .expect(expectedStatus) | 145 | .expect(expectedStatus) |
146 | } | 146 | } |
147 | 147 | ||
148 | function searchVideo (url: string, search: string, field?: string) { | 148 | function searchVideo (url: string, search: string) { |
149 | const path = '/api/v1/videos' | 149 | const path = '/api/v1/videos' |
150 | const req = request(url) | 150 | const req = request(url) |
151 | .get(path + '/search/' + search) | 151 | .get(path + '/search') |
152 | .set('Accept', 'application/json') | 152 | .query({ search }) |
153 | 153 | .set('Accept', 'application/json') | |
154 | if (field) req.query({ field }) | ||
155 | 154 | ||
156 | return req.expect(200) | 155 | return req.expect(200) |
157 | .expect('Content-Type', /json/) | 156 | .expect('Content-Type', /json/) |
158 | } | 157 | } |
159 | 158 | ||
160 | function searchVideoWithPagination (url: string, search: string, field: string, start: number, count: number, sort?: string) { | 159 | function searchVideoWithPagination (url: string, search: string, start: number, count: number, sort?: string) { |
161 | const path = '/api/v1/videos' | 160 | const path = '/api/v1/videos' |
162 | 161 | ||
163 | const req = request(url) | 162 | const req = request(url) |
164 | .get(path + '/search/' + search) | 163 | .get(path + '/search') |
165 | .query({ start }) | 164 | .query({ start }) |
165 | .query({ search }) | ||
166 | .query({ count }) | 166 | .query({ count }) |
167 | .query({ field }) | ||
168 | 167 | ||
169 | if (sort) req.query({ sort }) | 168 | if (sort) req.query({ sort }) |
170 | 169 | ||
@@ -177,7 +176,8 @@ function searchVideoWithSort (url: string, search: string, sort: string) { | |||
177 | const path = '/api/v1/videos' | 176 | const path = '/api/v1/videos' |
178 | 177 | ||
179 | return request(url) | 178 | return request(url) |
180 | .get(path + '/search/' + search) | 179 | .get(path + '/search') |
180 | .query({ search }) | ||
181 | .query({ sort }) | 181 | .query({ sort }) |
182 | .set('Accept', 'application/json') | 182 | .set('Accept', 'application/json') |
183 | .expect(200) | 183 | .expect(200) |
@@ -201,7 +201,7 @@ async function testVideoImage (url: string, imageName: string, imagePath: string | |||
201 | } | 201 | } |
202 | } | 202 | } |
203 | 203 | ||
204 | async function uploadVideo (url: string, accessToken: string, videoAttributesArg: VideoAttributes, specialStatus = 204) { | 204 | async function uploadVideo (url: string, accessToken: string, videoAttributesArg: VideoAttributes, specialStatus = 200) { |
205 | const path = '/api/v1/videos/upload' | 205 | const path = '/api/v1/videos/upload' |
206 | let defaultChannelId = '1' | 206 | let defaultChannelId = '1' |
207 | 207 | ||