diff options
-rw-r--r-- | server/helpers/activitypub.ts | 3 | ||||
-rw-r--r-- | server/helpers/custom-validators/activitypub/videos.ts | 1 | ||||
-rw-r--r-- | server/lib/activitypub/videos.ts | 2 | ||||
-rw-r--r-- | server/models/video/video-format-utils.ts | 4 | ||||
-rw-r--r-- | server/models/video/video.ts | 13 | ||||
-rw-r--r-- | server/tests/api/check-params/videos.ts | 16 | ||||
-rw-r--r-- | server/tests/api/videos/multiple-servers.ts | 6 | ||||
-rw-r--r-- | shared/utils/videos/videos.ts | 12 |
8 files changed, 49 insertions, 8 deletions
diff --git a/server/helpers/activitypub.ts b/server/helpers/activitypub.ts index 62d78373e..e850efe13 100644 --- a/server/helpers/activitypub.ts +++ b/server/helpers/activitypub.ts | |||
@@ -34,7 +34,8 @@ function activityPubContextify <T> (data: T) { | |||
34 | expires: 'sc:expires', | 34 | expires: 'sc:expires', |
35 | support: 'sc:Text', | 35 | support: 'sc:Text', |
36 | CacheFile: 'pt:CacheFile', | 36 | CacheFile: 'pt:CacheFile', |
37 | Infohash: 'pt:Infohash' | 37 | Infohash: 'pt:Infohash', |
38 | originallyPublishedAt: 'sc:DateTime' | ||
38 | }, | 39 | }, |
39 | { | 40 | { |
40 | likes: { | 41 | likes: { |
diff --git a/server/helpers/custom-validators/activitypub/videos.ts b/server/helpers/custom-validators/activitypub/videos.ts index 53ad0588d..d94333151 100644 --- a/server/helpers/custom-validators/activitypub/videos.ts +++ b/server/helpers/custom-validators/activitypub/videos.ts | |||
@@ -54,6 +54,7 @@ function sanitizeAndCheckVideoTorrentObject (video: any) { | |||
54 | isBooleanValid(video.downloadEnabled) && | 54 | isBooleanValid(video.downloadEnabled) && |
55 | isDateValid(video.published) && | 55 | isDateValid(video.published) && |
56 | isDateValid(video.updated) && | 56 | isDateValid(video.updated) && |
57 | (!video.originallyPublishedAt || isDateValid(video.originallyPublishedAt)) && | ||
57 | (!video.content || isRemoteVideoContentValid(video.mediaType, video.content)) && | 58 | (!video.content || isRemoteVideoContentValid(video.mediaType, video.content)) && |
58 | isRemoteVideoIconValid(video.icon) && | 59 | isRemoteVideoIconValid(video.icon) && |
59 | video.url.length !== 0 && | 60 | video.url.length !== 0 && |
diff --git a/server/lib/activitypub/videos.ts b/server/lib/activitypub/videos.ts index 710929aac..9ca0502a4 100644 --- a/server/lib/activitypub/videos.ts +++ b/server/lib/activitypub/videos.ts | |||
@@ -249,6 +249,7 @@ async function updateVideoFromAP (options: { | |||
249 | options.video.set('duration', videoData.duration) | 249 | options.video.set('duration', videoData.duration) |
250 | options.video.set('createdAt', videoData.createdAt) | 250 | options.video.set('createdAt', videoData.createdAt) |
251 | options.video.set('publishedAt', videoData.publishedAt) | 251 | options.video.set('publishedAt', videoData.publishedAt) |
252 | options.video.set('originallyPublishedAt', videoData.originallyPublishedAt) | ||
252 | options.video.set('privacy', videoData.privacy) | 253 | options.video.set('privacy', videoData.privacy) |
253 | options.video.set('channelId', videoData.channelId) | 254 | options.video.set('channelId', videoData.channelId) |
254 | options.video.set('views', videoData.views) | 255 | options.video.set('views', videoData.views) |
@@ -511,6 +512,7 @@ async function videoActivityObjectToDBAttributes ( | |||
511 | duration: parseInt(duration, 10), | 512 | duration: parseInt(duration, 10), |
512 | createdAt: new Date(videoObject.published), | 513 | createdAt: new Date(videoObject.published), |
513 | publishedAt: new Date(videoObject.published), | 514 | publishedAt: new Date(videoObject.published), |
515 | originallyPublishedAt: videoObject.originallyPublishedAt ? new Date(videoObject.originallyPublishedAt) : null, | ||
514 | // FIXME: updatedAt does not seems to be considered by Sequelize | 516 | // FIXME: updatedAt does not seems to be considered by Sequelize |
515 | updatedAt: new Date(videoObject.updated), | 517 | updatedAt: new Date(videoObject.updated), |
516 | views: videoObject.views, | 518 | views: videoObject.views, |
diff --git a/server/models/video/video-format-utils.ts b/server/models/video/video-format-utils.ts index c63285e25..a62335333 100644 --- a/server/models/video/video-format-utils.ts +++ b/server/models/video/video-format-utils.ts | |||
@@ -324,9 +324,7 @@ function videoModelToActivityPubObject (video: VideoModel): VideoTorrentObject { | |||
324 | commentsEnabled: video.commentsEnabled, | 324 | commentsEnabled: video.commentsEnabled, |
325 | downloadEnabled: video.downloadEnabled, | 325 | downloadEnabled: video.downloadEnabled, |
326 | published: video.publishedAt.toISOString(), | 326 | published: video.publishedAt.toISOString(), |
327 | originallyPublishedAt: video.originallyPublishedAt ? | 327 | originallyPublishedAt: video.originallyPublishedAt ? video.originallyPublishedAt.toISOString() : null, |
328 | video.originallyPublishedAt.toISOString() : | ||
329 | null, | ||
330 | updated: video.updatedAt.toISOString(), | 328 | updated: video.updatedAt.toISOString(), |
331 | mediaType: 'text/markdown', | 329 | mediaType: 'text/markdown', |
332 | content: video.getTruncatedDescription(), | 330 | content: video.getTruncatedDescription(), |
diff --git a/server/models/video/video.ts b/server/models/video/video.ts index 73626b6a0..215e26d7d 100644 --- a/server/models/video/video.ts +++ b/server/models/video/video.ts | |||
@@ -40,7 +40,7 @@ import { | |||
40 | isVideoDurationValid, | 40 | isVideoDurationValid, |
41 | isVideoLanguageValid, | 41 | isVideoLanguageValid, |
42 | isVideoLicenceValid, | 42 | isVideoLicenceValid, |
43 | isVideoNameValid, | 43 | isVideoNameValid, isVideoOriginallyPublishedAtValid, |
44 | isVideoPrivacyValid, | 44 | isVideoPrivacyValid, |
45 | isVideoStateValid, | 45 | isVideoStateValid, |
46 | isVideoSupportValid | 46 | isVideoSupportValid |
@@ -103,11 +103,18 @@ const indexes: Sequelize.DefineIndexesOptions[] = [ | |||
103 | 103 | ||
104 | { fields: [ 'createdAt' ] }, | 104 | { fields: [ 'createdAt' ] }, |
105 | { fields: [ 'publishedAt' ] }, | 105 | { fields: [ 'publishedAt' ] }, |
106 | { fields: [ 'originallyPublishedAt' ] }, | ||
107 | { fields: [ 'duration' ] }, | 106 | { fields: [ 'duration' ] }, |
108 | { fields: [ 'views' ] }, | 107 | { fields: [ 'views' ] }, |
109 | { fields: [ 'channelId' ] }, | 108 | { fields: [ 'channelId' ] }, |
110 | { | 109 | { |
110 | fields: [ 'originallyPublishedAt' ], | ||
111 | where: { | ||
112 | originallyPublishedAt: { | ||
113 | [Sequelize.Op.ne]: null | ||
114 | } | ||
115 | } | ||
116 | }, | ||
117 | { | ||
111 | fields: [ 'category' ], // We don't care videos with an unknown category | 118 | fields: [ 'category' ], // We don't care videos with an unknown category |
112 | where: { | 119 | where: { |
113 | category: { | 120 | category: { |
@@ -741,6 +748,8 @@ export class VideoModel extends Model<VideoModel> { | |||
741 | @Column | 748 | @Column |
742 | publishedAt: Date | 749 | publishedAt: Date |
743 | 750 | ||
751 | @AllowNull(true) | ||
752 | @Default(null) | ||
744 | @Column | 753 | @Column |
745 | originallyPublishedAt: Date | 754 | originallyPublishedAt: Date |
746 | 755 | ||
diff --git a/server/tests/api/check-params/videos.ts b/server/tests/api/check-params/videos.ts index 878ffe025..3eccaee44 100644 --- a/server/tests/api/check-params/videos.ts +++ b/server/tests/api/check-params/videos.ts | |||
@@ -185,7 +185,8 @@ describe('Test videos API validator', function () { | |||
185 | support: 'my super support text', | 185 | support: 'my super support text', |
186 | tags: [ 'tag1', 'tag2' ], | 186 | tags: [ 'tag1', 'tag2' ], |
187 | privacy: VideoPrivacy.PUBLIC, | 187 | privacy: VideoPrivacy.PUBLIC, |
188 | channelId: channelId | 188 | channelId: channelId, |
189 | originallyPublishedAt: new Date().toISOString() | ||
189 | } | 190 | } |
190 | }) | 191 | }) |
191 | 192 | ||
@@ -313,6 +314,13 @@ describe('Test videos API validator', function () { | |||
313 | await makeUploadRequest({ url: server.url, path: path + '/upload', token: server.accessToken, fields, attaches }) | 314 | await makeUploadRequest({ url: server.url, path: path + '/upload', token: server.accessToken, fields, attaches }) |
314 | }) | 315 | }) |
315 | 316 | ||
317 | it('Should fail with a bad originally published at attribute', async function () { | ||
318 | const fields = immutableAssign(baseCorrectParams, { 'originallyPublishedAt': 'toto' }) | ||
319 | const attaches = baseCorrectAttaches | ||
320 | |||
321 | await makeUploadRequest({ url: server.url, path: path + '/upload', token: server.accessToken, fields, attaches }) | ||
322 | }) | ||
323 | |||
316 | it('Should fail without an input file', async function () { | 324 | it('Should fail without an input file', async function () { |
317 | const fields = baseCorrectParams | 325 | const fields = baseCorrectParams |
318 | const attaches = {} | 326 | const attaches = {} |
@@ -534,6 +542,12 @@ describe('Test videos API validator', function () { | |||
534 | await makePutBodyRequest({ url: server.url, path: path + videoId, token: server.accessToken, fields }) | 542 | await makePutBodyRequest({ url: server.url, path: path + videoId, token: server.accessToken, fields }) |
535 | }) | 543 | }) |
536 | 544 | ||
545 | it('Should fail with a bad originally published at param', async function () { | ||
546 | const fields = immutableAssign(baseCorrectParams, { originallyPublishedAt: 'toto' }) | ||
547 | |||
548 | await makePutBodyRequest({ url: server.url, path: path + videoId, token: server.accessToken, fields }) | ||
549 | }) | ||
550 | |||
537 | it('Should fail with an incorrect thumbnail file', async function () { | 551 | it('Should fail with an incorrect thumbnail file', async function () { |
538 | const fields = baseCorrectParams | 552 | const fields = baseCorrectParams |
539 | const attaches = { | 553 | const attaches = { |
diff --git a/server/tests/api/videos/multiple-servers.ts b/server/tests/api/videos/multiple-servers.ts index 1b471ba79..7e2fcb630 100644 --- a/server/tests/api/videos/multiple-servers.ts +++ b/server/tests/api/videos/multiple-servers.ts | |||
@@ -98,6 +98,7 @@ describe('Test multiple servers', function () { | |||
98 | nsfw: true, | 98 | nsfw: true, |
99 | description: 'my super description for server 1', | 99 | description: 'my super description for server 1', |
100 | support: 'my super support text for server 1', | 100 | support: 'my super support text for server 1', |
101 | originallyPublishedAt: '2019-02-10T13:38:14.449Z', | ||
101 | tags: [ 'tag1p1', 'tag2p1' ], | 102 | tags: [ 'tag1p1', 'tag2p1' ], |
102 | channelId: videoChannelId, | 103 | channelId: videoChannelId, |
103 | fixture: 'video_short1.webm' | 104 | fixture: 'video_short1.webm' |
@@ -118,6 +119,7 @@ describe('Test multiple servers', function () { | |||
118 | nsfw: true, | 119 | nsfw: true, |
119 | description: 'my super description for server 1', | 120 | description: 'my super description for server 1', |
120 | support: 'my super support text for server 1', | 121 | support: 'my super support text for server 1', |
122 | originallyPublishedAt: '2019-02-10T13:38:14.449Z', | ||
121 | account: { | 123 | account: { |
122 | name: 'root', | 124 | name: 'root', |
123 | host: 'localhost:9001' | 125 | host: 'localhost:9001' |
@@ -625,6 +627,7 @@ describe('Test multiple servers', function () { | |||
625 | support: 'my super support text updated', | 627 | support: 'my super support text updated', |
626 | tags: [ 'tag_up_1', 'tag_up_2' ], | 628 | tags: [ 'tag_up_1', 'tag_up_2' ], |
627 | thumbnailfile: 'thumbnail.jpg', | 629 | thumbnailfile: 'thumbnail.jpg', |
630 | originallyPublishedAt: '2019-02-11T13:38:14.449Z', | ||
628 | previewfile: 'preview.jpg' | 631 | previewfile: 'preview.jpg' |
629 | } | 632 | } |
630 | 633 | ||
@@ -652,6 +655,7 @@ describe('Test multiple servers', function () { | |||
652 | nsfw: true, | 655 | nsfw: true, |
653 | description: 'my super description updated', | 656 | description: 'my super description updated', |
654 | support: 'my super support text updated', | 657 | support: 'my super support text updated', |
658 | originallyPublishedAt: '2019-02-11T13:38:14.449Z', | ||
655 | account: { | 659 | account: { |
656 | name: 'root', | 660 | name: 'root', |
657 | host: 'localhost:9003' | 661 | host: 'localhost:9003' |
@@ -983,7 +987,7 @@ describe('Test multiple servers', function () { | |||
983 | isLocal, | 987 | isLocal, |
984 | duration: 5, | 988 | duration: 5, |
985 | commentsEnabled: false, | 989 | commentsEnabled: false, |
986 | downloadEnabled: false, | 990 | downloadEnabled: true, |
987 | tags: [ ], | 991 | tags: [ ], |
988 | privacy: VideoPrivacy.PUBLIC, | 992 | privacy: VideoPrivacy.PUBLIC, |
989 | channel: { | 993 | channel: { |
diff --git a/shared/utils/videos/videos.ts b/shared/utils/videos/videos.ts index 39c808d1f..16ecbfe84 100644 --- a/shared/utils/videos/videos.ts +++ b/shared/utils/videos/videos.ts | |||
@@ -31,6 +31,7 @@ type VideoAttributes = { | |||
31 | downloadEnabled?: boolean | 31 | downloadEnabled?: boolean |
32 | waitTranscoding?: boolean | 32 | waitTranscoding?: boolean |
33 | description?: string | 33 | description?: string |
34 | originallyPublishedAt?: string | ||
34 | tags?: string[] | 35 | tags?: string[] |
35 | channelId?: number | 36 | channelId?: number |
36 | privacy?: VideoPrivacy | 37 | privacy?: VideoPrivacy |
@@ -349,6 +350,9 @@ async function uploadVideo (url: string, accessToken: string, videoAttributesArg | |||
349 | if (attributes.licence !== undefined) { | 350 | if (attributes.licence !== undefined) { |
350 | req.field('licence', attributes.licence.toString()) | 351 | req.field('licence', attributes.licence.toString()) |
351 | } | 352 | } |
353 | if (attributes.originallyPublishedAt !== undefined) { | ||
354 | req.field('originallyPublishedAt', attributes.originallyPublishedAt) | ||
355 | } | ||
352 | 356 | ||
353 | for (let i = 0; i < attributes.tags.length; i++) { | 357 | for (let i = 0; i < attributes.tags.length; i++) { |
354 | req.field('tags[' + i + ']', attributes.tags[i]) | 358 | req.field('tags[' + i + ']', attributes.tags[i]) |
@@ -384,6 +388,7 @@ function updateVideo (url: string, accessToken: string, id: number | string, att | |||
384 | if (attributes.nsfw !== undefined) body['nsfw'] = JSON.stringify(attributes.nsfw) | 388 | if (attributes.nsfw !== undefined) body['nsfw'] = JSON.stringify(attributes.nsfw) |
385 | if (attributes.commentsEnabled !== undefined) body['commentsEnabled'] = JSON.stringify(attributes.commentsEnabled) | 389 | if (attributes.commentsEnabled !== undefined) body['commentsEnabled'] = JSON.stringify(attributes.commentsEnabled) |
386 | if (attributes.downloadEnabled !== undefined) body['downloadEnabled'] = JSON.stringify(attributes.downloadEnabled) | 390 | if (attributes.downloadEnabled !== undefined) body['downloadEnabled'] = JSON.stringify(attributes.downloadEnabled) |
391 | if (attributes.originallyPublishedAt !== undefined) body['originallyPublishedAt'] = attributes.originallyPublishedAt | ||
387 | if (attributes.description) body['description'] = attributes.description | 392 | if (attributes.description) body['description'] = attributes.description |
388 | if (attributes.tags) body['tags'] = attributes.tags | 393 | if (attributes.tags) body['tags'] = attributes.tags |
389 | if (attributes.privacy) body['privacy'] = attributes.privacy | 394 | if (attributes.privacy) body['privacy'] = attributes.privacy |
@@ -453,6 +458,7 @@ async function completeVideoCheck ( | |||
453 | description: string | 458 | description: string |
454 | publishedAt?: string | 459 | publishedAt?: string |
455 | support: string | 460 | support: string |
461 | originallyPublishedAt?: string, | ||
456 | account: { | 462 | account: { |
457 | name: string | 463 | name: string |
458 | host: string | 464 | host: string |
@@ -510,6 +516,12 @@ async function completeVideoCheck ( | |||
510 | expect(video.publishedAt).to.equal(attributes.publishedAt) | 516 | expect(video.publishedAt).to.equal(attributes.publishedAt) |
511 | } | 517 | } |
512 | 518 | ||
519 | if (attributes.originallyPublishedAt) { | ||
520 | expect(video.originallyPublishedAt).to.equal(attributes.originallyPublishedAt) | ||
521 | } else { | ||
522 | expect(video.originallyPublishedAt).to.be.null | ||
523 | } | ||
524 | |||
513 | const res = await getVideo(url, video.uuid) | 525 | const res = await getVideo(url, video.uuid) |
514 | const videoDetails: VideoDetails = res.body | 526 | const videoDetails: VideoDetails = res.body |
515 | 527 | ||