diff options
37 files changed, 269 insertions, 112 deletions
diff --git a/client/src/app/shared/video/video-details.model.ts b/client/src/app/shared/video/video-details.model.ts index 8243b9f1c..cf6b71b60 100644 --- a/client/src/app/shared/video/video-details.model.ts +++ b/client/src/app/shared/video/video-details.model.ts | |||
@@ -1,14 +1,10 @@ | |||
1 | import { Account } from '../../../../../shared/models/actors' | ||
2 | import { Video } from '../../shared/video/video.model' | ||
3 | import { AuthUser } from '../../core' | ||
4 | import { | 1 | import { |
5 | VideoDetails as VideoDetailsServerModel, | 2 | UserRight, VideoChannel, VideoDetails as VideoDetailsServerModel, VideoFile, VideoPrivacy, |
6 | VideoFile, | 3 | VideoResolution |
7 | VideoChannel, | ||
8 | VideoResolution, | ||
9 | UserRight, | ||
10 | VideoPrivacy | ||
11 | } from '../../../../../shared' | 4 | } from '../../../../../shared' |
5 | import { Account } from '../../../../../shared/models/actors' | ||
6 | import { AuthUser } from '../../core' | ||
7 | import { Video } from '../../shared/video/video.model' | ||
12 | 8 | ||
13 | export class VideoDetails extends Video implements VideoDetailsServerModel { | 9 | export class VideoDetails extends Video implements VideoDetailsServerModel { |
14 | accountName: string | 10 | accountName: string |
@@ -48,6 +44,7 @@ export class VideoDetails extends Video implements VideoDetailsServerModel { | |||
48 | account: Account | 44 | account: Account |
49 | likesPercent: number | 45 | likesPercent: number |
50 | dislikesPercent: number | 46 | dislikesPercent: number |
47 | commentsEnabled: boolean | ||
51 | 48 | ||
52 | constructor (hash: VideoDetailsServerModel) { | 49 | constructor (hash: VideoDetailsServerModel) { |
53 | super(hash) | 50 | super(hash) |
@@ -59,6 +56,7 @@ export class VideoDetails extends Video implements VideoDetailsServerModel { | |||
59 | this.channel = hash.channel | 56 | this.channel = hash.channel |
60 | this.account = hash.account | 57 | this.account = hash.account |
61 | this.tags = hash.tags | 58 | this.tags = hash.tags |
59 | this.commentsEnabled = hash.commentsEnabled | ||
62 | 60 | ||
63 | this.likesPercent = (this.likes / (this.likes + this.dislikes)) * 100 | 61 | this.likesPercent = (this.likes / (this.likes + this.dislikes)) * 100 |
64 | this.dislikesPercent = (this.dislikes / (this.likes + this.dislikes)) * 100 | 62 | this.dislikesPercent = (this.dislikes / (this.likes + this.dislikes)) * 100 |
diff --git a/client/src/app/shared/video/video-edit.model.ts b/client/src/app/shared/video/video-edit.model.ts index 47c63d976..b1c772217 100644 --- a/client/src/app/shared/video/video-edit.model.ts +++ b/client/src/app/shared/video/video-edit.model.ts | |||
@@ -9,6 +9,7 @@ export class VideoEdit { | |||
9 | name: string | 9 | name: string |
10 | tags: string[] | 10 | tags: string[] |
11 | nsfw: boolean | 11 | nsfw: boolean |
12 | commentsEnabled: boolean | ||
12 | channel: number | 13 | channel: number |
13 | privacy: VideoPrivacy | 14 | privacy: VideoPrivacy |
14 | uuid?: string | 15 | uuid?: string |
@@ -25,6 +26,7 @@ export class VideoEdit { | |||
25 | this.name = videoDetails.name | 26 | this.name = videoDetails.name |
26 | this.tags = videoDetails.tags | 27 | this.tags = videoDetails.tags |
27 | this.nsfw = videoDetails.nsfw | 28 | this.nsfw = videoDetails.nsfw |
29 | this.commentsEnabled = videoDetails.commentsEnabled | ||
28 | this.channel = videoDetails.channel.id | 30 | this.channel = videoDetails.channel.id |
29 | this.privacy = videoDetails.privacy | 31 | this.privacy = videoDetails.privacy |
30 | } | 32 | } |
@@ -45,6 +47,7 @@ export class VideoEdit { | |||
45 | name: this.name, | 47 | name: this.name, |
46 | tags: this.tags, | 48 | tags: this.tags, |
47 | nsfw: this.nsfw, | 49 | nsfw: this.nsfw, |
50 | commentsEnabled: this.commentsEnabled, | ||
48 | channelId: this.channel, | 51 | channelId: this.channel, |
49 | privacy: this.privacy | 52 | privacy: this.privacy |
50 | } | 53 | } |
diff --git a/client/src/app/shared/video/video.service.ts b/client/src/app/shared/video/video.service.ts index fc7505a51..073acb2b6 100644 --- a/client/src/app/shared/video/video.service.ts +++ b/client/src/app/shared/video/video.service.ts | |||
@@ -55,7 +55,8 @@ export class VideoService { | |||
55 | description, | 55 | description, |
56 | privacy: video.privacy, | 56 | privacy: video.privacy, |
57 | tags: video.tags, | 57 | tags: video.tags, |
58 | nsfw: video.nsfw | 58 | nsfw: video.nsfw, |
59 | commentsEnabled: video.commentsEnabled | ||
59 | } | 60 | } |
60 | 61 | ||
61 | return this.authHttp.put(VideoService.BASE_VIDEO_URL + video.id, body) | 62 | return this.authHttp.put(VideoService.BASE_VIDEO_URL + video.id, body) |
diff --git a/client/src/app/videos/+video-edit/shared/video-edit.component.html b/client/src/app/videos/+video-edit/shared/video-edit.component.html index 9acbafcb6..80377933e 100644 --- a/client/src/app/videos/+video-edit/shared/video-edit.component.html +++ b/client/src/app/videos/+video-edit/shared/video-edit.component.html | |||
@@ -99,5 +99,11 @@ | |||
99 | <label for="nsfw">This video contains mature or explicit content</label> | 99 | <label for="nsfw">This video contains mature or explicit content</label> |
100 | </div> | 100 | </div> |
101 | 101 | ||
102 | <div class="form-group form-group-checkbox"> | ||
103 | <input type="checkbox" id="commentsEnabled" formControlName="commentsEnabled" /> | ||
104 | <label for="commentsEnabled"></label> | ||
105 | <label for="commentsEnabled">Enable video comments</label> | ||
106 | </div> | ||
107 | |||
102 | </div> | 108 | </div> |
103 | </div> | 109 | </div> |
diff --git a/client/src/app/videos/+video-edit/shared/video-edit.component.ts b/client/src/app/videos/+video-edit/shared/video-edit.component.ts index 7fe265284..2b307d5fa 100644 --- a/client/src/app/videos/+video-edit/shared/video-edit.component.ts +++ b/client/src/app/videos/+video-edit/shared/video-edit.component.ts | |||
@@ -70,6 +70,7 @@ export class VideoEditComponent implements OnInit { | |||
70 | this.form.addControl('privacy', new FormControl('', VIDEO_PRIVACY.VALIDATORS)) | 70 | this.form.addControl('privacy', new FormControl('', VIDEO_PRIVACY.VALIDATORS)) |
71 | this.form.addControl('channelId', new FormControl({ value: '', disabled: true })) | 71 | this.form.addControl('channelId', new FormControl({ value: '', disabled: true })) |
72 | this.form.addControl('nsfw', new FormControl(false)) | 72 | this.form.addControl('nsfw', new FormControl(false)) |
73 | this.form.addControl('commentsEnabled', new FormControl(true)) | ||
73 | this.form.addControl('category', new FormControl('', VIDEO_CATEGORY.VALIDATORS)) | 74 | this.form.addControl('category', new FormControl('', VIDEO_CATEGORY.VALIDATORS)) |
74 | this.form.addControl('licence', new FormControl('', VIDEO_LICENCE.VALIDATORS)) | 75 | this.form.addControl('licence', new FormControl('', VIDEO_LICENCE.VALIDATORS)) |
75 | this.form.addControl('language', new FormControl('', VIDEO_LANGUAGE.VALIDATORS)) | 76 | this.form.addControl('language', new FormControl('', VIDEO_LANGUAGE.VALIDATORS)) |
diff --git a/client/src/app/videos/+video-edit/video-add.component.ts b/client/src/app/videos/+video-edit/video-add.component.ts index 9bbee58d8..843475647 100644 --- a/client/src/app/videos/+video-edit/video-add.component.ts +++ b/client/src/app/videos/+video-edit/video-add.component.ts | |||
@@ -88,6 +88,7 @@ export class VideoAddComponent extends FormReactive implements OnInit { | |||
88 | const name = videofile.name.replace(/\.[^/.]+$/, '') | 88 | const name = videofile.name.replace(/\.[^/.]+$/, '') |
89 | const privacy = this.firstStepPrivacyId.toString() | 89 | const privacy = this.firstStepPrivacyId.toString() |
90 | const nsfw = false | 90 | const nsfw = false |
91 | const commentsEnabled = true | ||
91 | const channelId = this.firstStepChannelId.toString() | 92 | const channelId = this.firstStepChannelId.toString() |
92 | 93 | ||
93 | const formData = new FormData() | 94 | const formData = new FormData() |
@@ -95,6 +96,7 @@ export class VideoAddComponent extends FormReactive implements OnInit { | |||
95 | // Put the video "private" -> we wait he validates the second step | 96 | // Put the video "private" -> we wait he validates the second step |
96 | formData.append('privacy', VideoPrivacy.PRIVATE.toString()) | 97 | formData.append('privacy', VideoPrivacy.PRIVATE.toString()) |
97 | formData.append('nsfw', '' + nsfw) | 98 | formData.append('nsfw', '' + nsfw) |
99 | formData.append('commentsEnabled', '' + commentsEnabled) | ||
98 | formData.append('channelId', '' + channelId) | 100 | formData.append('channelId', '' + channelId) |
99 | formData.append('videofile', videofile) | 101 | formData.append('videofile', videofile) |
100 | 102 | ||
diff --git a/client/src/app/videos/+video-watch/comment/video-comments.component.html b/client/src/app/videos/+video-watch/comment/video-comments.component.html index 5c6908150..078900e06 100644 --- a/client/src/app/videos/+video-watch/comment/video-comments.component.html +++ b/client/src/app/videos/+video-watch/comment/video-comments.component.html | |||
@@ -3,35 +3,43 @@ | |||
3 | Comments | 3 | Comments |
4 | </div> | 4 | </div> |
5 | 5 | ||
6 | <my-video-comment-add | 6 | <ng-template [ngIf]="video.commentsEnabled === true"> |
7 | *ngIf="isUserLoggedIn()" | 7 | <my-video-comment-add |
8 | [video]="video" | 8 | *ngIf="isUserLoggedIn()" |
9 | (commentCreated)="onCommentThreadCreated($event)" | 9 | [video]="video" |
10 | ></my-video-comment-add> | 10 | (commentCreated)="onCommentThreadCreated($event)" |
11 | ></my-video-comment-add> | ||
11 | 12 | ||
12 | <div | 13 | <div *ngIf="componentPagination.totalItems === 0 && comments.length === 0">No comments.</div> |
13 | class="comment-threads" | ||
14 | infiniteScroll | ||
15 | [infiniteScrollUpDistance]="1.5" | ||
16 | [infiniteScrollDistance]="0.5" | ||
17 | (scrolled)="onNearOfBottom()" | ||
18 | > | ||
19 | <div *ngFor="let comment of comments"> | ||
20 | <my-video-comment | ||
21 | [comment]="comment" | ||
22 | [video]="video" | ||
23 | [inReplyToCommentId]="inReplyToCommentId" | ||
24 | [commentTree]="threadComments[comment.id]" | ||
25 | (wantedToReply)="onWantedToReply($event)" | ||
26 | (resetReply)="onResetReply()" | ||
27 | ></my-video-comment> | ||
28 | 14 | ||
29 | <div *ngIf="comment.totalReplies !== 0 && !threadComments[comment.id]" (click)="viewReplies(comment)" class="view-replies"> | 15 | <div |
30 | View all {{ comment.totalReplies }} replies | 16 | class="comment-threads" |
17 | infiniteScroll | ||
18 | [infiniteScrollUpDistance]="1.5" | ||
19 | [infiniteScrollDistance]="0.5" | ||
20 | (scrolled)="onNearOfBottom()" | ||
21 | > | ||
22 | <div *ngFor="let comment of comments"> | ||
23 | <my-video-comment | ||
24 | [comment]="comment" | ||
25 | [video]="video" | ||
26 | [inReplyToCommentId]="inReplyToCommentId" | ||
27 | [commentTree]="threadComments[comment.id]" | ||
28 | (wantedToReply)="onWantedToReply($event)" | ||
29 | (resetReply)="onResetReply()" | ||
30 | ></my-video-comment> | ||
31 | 31 | ||
32 | <span *ngIf="!threadLoading[comment.id]" class="glyphicon glyphicon-menu-down"></span> | 32 | <div *ngIf="comment.totalReplies !== 0 && !threadComments[comment.id]" (click)="viewReplies(comment)" class="view-replies"> |
33 | <my-loader class="comment-thread-loading" [loading]="threadLoading[comment.id]"></my-loader> | 33 | View all {{ comment.totalReplies }} replies |
34 | |||
35 | <span *ngIf="!threadLoading[comment.id]" class="glyphicon glyphicon-menu-down"></span> | ||
36 | <my-loader class="comment-thread-loading" [loading]="threadLoading[comment.id]"></my-loader> | ||
37 | </div> | ||
34 | </div> | 38 | </div> |
35 | </div> | 39 | </div> |
40 | </ng-template> | ||
41 | |||
42 | <div *ngIf="video.commentsEnabled === false"> | ||
43 | Comments are disabled. | ||
36 | </div> | 44 | </div> |
37 | </div> | 45 | </div> |
diff --git a/client/src/app/videos/+video-watch/comment/video-comments.component.ts b/client/src/app/videos/+video-watch/comment/video-comments.component.ts index f4dda9089..4d801c970 100644 --- a/client/src/app/videos/+video-watch/comment/video-comments.component.ts +++ b/client/src/app/videos/+video-watch/comment/video-comments.component.ts | |||
@@ -5,6 +5,7 @@ import { AuthService } from '../../../core/auth' | |||
5 | import { ComponentPagination } from '../../../shared/rest/component-pagination.model' | 5 | import { ComponentPagination } from '../../../shared/rest/component-pagination.model' |
6 | import { User } from '../../../shared/users' | 6 | import { User } from '../../../shared/users' |
7 | import { SortField } from '../../../shared/video/sort-field.type' | 7 | import { SortField } from '../../../shared/video/sort-field.type' |
8 | import { VideoDetails } from '../../../shared/video/video-details.model' | ||
8 | import { Video } from '../../../shared/video/video.model' | 9 | import { Video } from '../../../shared/video/video.model' |
9 | import { VideoComment } from './video-comment.model' | 10 | import { VideoComment } from './video-comment.model' |
10 | import { VideoCommentService } from './video-comment.service' | 11 | import { VideoCommentService } from './video-comment.service' |
@@ -15,7 +16,7 @@ import { VideoCommentService } from './video-comment.service' | |||
15 | styleUrls: ['./video-comments.component.scss'] | 16 | styleUrls: ['./video-comments.component.scss'] |
16 | }) | 17 | }) |
17 | export class VideoCommentsComponent implements OnInit { | 18 | export class VideoCommentsComponent implements OnInit { |
18 | @Input() video: Video | 19 | @Input() video: VideoDetails |
19 | @Input() user: User | 20 | @Input() user: User |
20 | 21 | ||
21 | comments: VideoComment[] = [] | 22 | comments: VideoComment[] = [] |
@@ -36,7 +37,9 @@ export class VideoCommentsComponent implements OnInit { | |||
36 | ) {} | 37 | ) {} |
37 | 38 | ||
38 | ngOnInit () { | 39 | ngOnInit () { |
39 | this.loadMoreComments() | 40 | if (this.video.commentsEnabled === true) { |
41 | this.loadMoreComments() | ||
42 | } | ||
40 | } | 43 | } |
41 | 44 | ||
42 | viewReplies (comment: VideoComment) { | 45 | viewReplies (comment: VideoComment) { |
diff --git a/server/controllers/api/videos/comment.ts b/server/controllers/api/videos/comment.ts index b11da2ef7..e09b242ed 100644 --- a/server/controllers/api/videos/comment.ts +++ b/server/controllers/api/videos/comment.ts | |||
@@ -1,4 +1,5 @@ | |||
1 | import * as express from 'express' | 1 | import * as express from 'express' |
2 | import { ResultList } from '../../../../shared/models' | ||
2 | import { VideoCommentCreate } from '../../../../shared/models/videos/video-comment.model' | 3 | import { VideoCommentCreate } from '../../../../shared/models/videos/video-comment.model' |
3 | import { retryTransactionWrapper } from '../../../helpers/database-utils' | 4 | import { retryTransactionWrapper } from '../../../helpers/database-utils' |
4 | import { getFormattedObjects } from '../../../helpers/utils' | 5 | import { getFormattedObjects } from '../../../helpers/utils' |
@@ -10,6 +11,7 @@ import { | |||
10 | addVideoCommentReplyValidator, addVideoCommentThreadValidator, listVideoCommentThreadsValidator, | 11 | addVideoCommentReplyValidator, addVideoCommentThreadValidator, listVideoCommentThreadsValidator, |
11 | listVideoThreadCommentsValidator | 12 | listVideoThreadCommentsValidator |
12 | } from '../../../middlewares/validators/video-comments' | 13 | } from '../../../middlewares/validators/video-comments' |
14 | import { VideoModel } from '../../../models/video/video' | ||
13 | import { VideoCommentModel } from '../../../models/video/video-comment' | 15 | import { VideoCommentModel } from '../../../models/video/video-comment' |
14 | 16 | ||
15 | const videoCommentRouter = express.Router() | 17 | const videoCommentRouter = express.Router() |
@@ -47,13 +49,33 @@ export { | |||
47 | // --------------------------------------------------------------------------- | 49 | // --------------------------------------------------------------------------- |
48 | 50 | ||
49 | async function listVideoThreads (req: express.Request, res: express.Response, next: express.NextFunction) { | 51 | async function listVideoThreads (req: express.Request, res: express.Response, next: express.NextFunction) { |
50 | const resultList = await VideoCommentModel.listThreadsForApi(res.locals.video.id, req.query.start, req.query.count, req.query.sort) | 52 | const video = res.locals.video as VideoModel |
53 | let resultList: ResultList<VideoCommentModel> | ||
54 | |||
55 | if (video.commentsEnabled === true) { | ||
56 | resultList = await VideoCommentModel.listThreadsForApi(video.id, req.query.start, req.query.count, req.query.sort) | ||
57 | } else { | ||
58 | resultList = { | ||
59 | total: 0, | ||
60 | data: [] | ||
61 | } | ||
62 | } | ||
51 | 63 | ||
52 | return res.json(getFormattedObjects(resultList.data, resultList.total)) | 64 | return res.json(getFormattedObjects(resultList.data, resultList.total)) |
53 | } | 65 | } |
54 | 66 | ||
55 | async function listVideoThreadComments (req: express.Request, res: express.Response, next: express.NextFunction) { | 67 | async function listVideoThreadComments (req: express.Request, res: express.Response, next: express.NextFunction) { |
56 | const resultList = await VideoCommentModel.listThreadCommentsForApi(res.locals.video.id, res.locals.videoCommentThread.id) | 68 | const video = res.locals.video as VideoModel |
69 | let resultList: ResultList<VideoCommentModel> | ||
70 | |||
71 | if (video.commentsEnabled === true) { | ||
72 | resultList = await VideoCommentModel.listThreadCommentsForApi(res.locals.video.id, res.locals.videoCommentThread.id) | ||
73 | } else { | ||
74 | resultList = { | ||
75 | total: 0, | ||
76 | data: [] | ||
77 | } | ||
78 | } | ||
57 | 79 | ||
58 | return res.json(buildFormattedCommentTree(resultList)) | 80 | return res.json(buildFormattedCommentTree(resultList)) |
59 | } | 81 | } |
diff --git a/server/controllers/api/videos/index.ts b/server/controllers/api/videos/index.ts index ff0d967e1..368327914 100644 --- a/server/controllers/api/videos/index.ts +++ b/server/controllers/api/videos/index.ts | |||
@@ -1,12 +1,11 @@ | |||
1 | import * as express from 'express' | 1 | import * as express from 'express' |
2 | import * as multer from 'multer' | ||
3 | import { extname, join } from 'path' | 2 | import { extname, join } from 'path' |
4 | import { VideoCreate, VideoPrivacy, VideoUpdate } from '../../../../shared' | 3 | import { VideoCreate, VideoPrivacy, VideoUpdate } from '../../../../shared' |
5 | import { renamePromise } from '../../../helpers/core-utils' | 4 | import { renamePromise } from '../../../helpers/core-utils' |
6 | import { retryTransactionWrapper } from '../../../helpers/database-utils' | 5 | import { retryTransactionWrapper } from '../../../helpers/database-utils' |
7 | import { getVideoFileHeight } from '../../../helpers/ffmpeg-utils' | 6 | import { getVideoFileHeight } from '../../../helpers/ffmpeg-utils' |
8 | import { logger } from '../../../helpers/logger' | 7 | import { logger } from '../../../helpers/logger' |
9 | import { createReqFiles, generateRandomString, getFormattedObjects, getServerActor, resetSequelizeInstance } from '../../../helpers/utils' | 8 | import { createReqFiles, getFormattedObjects, getServerActor, resetSequelizeInstance } from '../../../helpers/utils' |
10 | import { | 9 | import { |
11 | CONFIG, sequelizeTypescript, VIDEO_CATEGORIES, VIDEO_LANGUAGES, VIDEO_LICENCES, VIDEO_MIMETYPE_EXT, | 10 | CONFIG, sequelizeTypescript, VIDEO_CATEGORIES, VIDEO_LANGUAGES, VIDEO_LICENCES, VIDEO_MIMETYPE_EXT, |
12 | VIDEO_PRIVACIES | 11 | VIDEO_PRIVACIES |
@@ -141,6 +140,7 @@ async function addVideo (req: express.Request, res: express.Response, videoPhysi | |||
141 | category: videoInfo.category, | 140 | category: videoInfo.category, |
142 | licence: videoInfo.licence, | 141 | licence: videoInfo.licence, |
143 | language: videoInfo.language, | 142 | language: videoInfo.language, |
143 | commentsEnabled: videoInfo.commentsEnabled, | ||
144 | nsfw: videoInfo.nsfw, | 144 | nsfw: videoInfo.nsfw, |
145 | description: videoInfo.description, | 145 | description: videoInfo.description, |
146 | privacy: videoInfo.privacy, | 146 | privacy: videoInfo.privacy, |
@@ -248,6 +248,7 @@ async function updateVideo (req: express.Request, res: express.Response) { | |||
248 | if (videoInfoToUpdate.nsfw !== undefined) videoInstance.set('nsfw', videoInfoToUpdate.nsfw) | 248 | if (videoInfoToUpdate.nsfw !== undefined) videoInstance.set('nsfw', videoInfoToUpdate.nsfw) |
249 | if (videoInfoToUpdate.privacy !== undefined) videoInstance.set('privacy', parseInt(videoInfoToUpdate.privacy.toString(), 10)) | 249 | if (videoInfoToUpdate.privacy !== undefined) videoInstance.set('privacy', parseInt(videoInfoToUpdate.privacy.toString(), 10)) |
250 | if (videoInfoToUpdate.description !== undefined) videoInstance.set('description', videoInfoToUpdate.description) | 250 | if (videoInfoToUpdate.description !== undefined) videoInstance.set('description', videoInfoToUpdate.description) |
251 | if (videoInfoToUpdate.commentsEnabled !== undefined) videoInstance.set('commentsEnabled', videoInfoToUpdate.commentsEnabled) | ||
251 | 252 | ||
252 | const videoInstanceUpdated = await videoInstance.save(sequelizeOptions) | 253 | const videoInstanceUpdated = await videoInstance.save(sequelizeOptions) |
253 | 254 | ||
diff --git a/server/helpers/custom-validators/activitypub/activity.ts b/server/helpers/custom-validators/activitypub/activity.ts index f2e137061..fbdde10ad 100644 --- a/server/helpers/custom-validators/activitypub/activity.ts +++ b/server/helpers/custom-validators/activitypub/activity.ts | |||
@@ -5,7 +5,6 @@ import { isAnnounceActivityValid } from './announce' | |||
5 | import { isActivityPubUrlValid } from './misc' | 5 | import { isActivityPubUrlValid } from './misc' |
6 | import { isDislikeActivityValid, isLikeActivityValid } from './rate' | 6 | import { isDislikeActivityValid, isLikeActivityValid } from './rate' |
7 | import { isUndoActivityValid } from './undo' | 7 | import { isUndoActivityValid } from './undo' |
8 | import { isVideoChannelDeleteActivityValid, isVideoChannelUpdateActivityValid } from './video-channels' | ||
9 | import { isVideoCommentCreateActivityValid } from './video-comments' | 8 | import { isVideoCommentCreateActivityValid } from './video-comments' |
10 | import { | 9 | import { |
11 | isVideoFlagValid, | 10 | isVideoFlagValid, |
@@ -65,13 +64,11 @@ function checkCreateActivity (activity: any) { | |||
65 | } | 64 | } |
66 | 65 | ||
67 | function checkUpdateActivity (activity: any) { | 66 | function checkUpdateActivity (activity: any) { |
68 | return isVideoTorrentUpdateActivityValid(activity) || | 67 | return isVideoTorrentUpdateActivityValid(activity) |
69 | isVideoChannelUpdateActivityValid(activity) | ||
70 | } | 68 | } |
71 | 69 | ||
72 | function checkDeleteActivity (activity: any) { | 70 | function checkDeleteActivity (activity: any) { |
73 | return isVideoTorrentDeleteActivityValid(activity) || | 71 | return isVideoTorrentDeleteActivityValid(activity) || |
74 | isVideoChannelDeleteActivityValid(activity) || | ||
75 | isActorDeleteActivityValid(activity) | 72 | isActorDeleteActivityValid(activity) |
76 | } | 73 | } |
77 | 74 | ||
diff --git a/server/helpers/custom-validators/activitypub/video-channels.ts b/server/helpers/custom-validators/activitypub/video-channels.ts deleted file mode 100644 index eb45c6372..000000000 --- a/server/helpers/custom-validators/activitypub/video-channels.ts +++ /dev/null | |||
@@ -1,30 +0,0 @@ | |||
1 | import { isDateValid, isUUIDValid } from '../misc' | ||
2 | import { isVideoChannelDescriptionValid, isVideoChannelNameValid } from '../video-channels' | ||
3 | import { isActivityPubUrlValid, isBaseActivityValid } from './misc' | ||
4 | |||
5 | function isVideoChannelUpdateActivityValid (activity: any) { | ||
6 | return isBaseActivityValid(activity, 'Update') && | ||
7 | isVideoChannelObjectValid(activity.object) | ||
8 | } | ||
9 | |||
10 | function isVideoChannelDeleteActivityValid (activity: any) { | ||
11 | return isBaseActivityValid(activity, 'Delete') | ||
12 | } | ||
13 | |||
14 | function isVideoChannelObjectValid (videoChannel: any) { | ||
15 | return videoChannel.type === 'VideoChannel' && | ||
16 | isActivityPubUrlValid(videoChannel.id) && | ||
17 | isVideoChannelNameValid(videoChannel.name) && | ||
18 | isVideoChannelDescriptionValid(videoChannel.content) && | ||
19 | isDateValid(videoChannel.published) && | ||
20 | isDateValid(videoChannel.updated) && | ||
21 | isUUIDValid(videoChannel.uuid) | ||
22 | } | ||
23 | |||
24 | // --------------------------------------------------------------------------- | ||
25 | |||
26 | export { | ||
27 | isVideoChannelUpdateActivityValid, | ||
28 | isVideoChannelDeleteActivityValid, | ||
29 | isVideoChannelObjectValid | ||
30 | } | ||
diff --git a/server/helpers/custom-validators/activitypub/videos.ts b/server/helpers/custom-validators/activitypub/videos.ts index ae1339611..37cd6965a 100644 --- a/server/helpers/custom-validators/activitypub/videos.ts +++ b/server/helpers/custom-validators/activitypub/videos.ts | |||
@@ -1,11 +1,10 @@ | |||
1 | import * as validator from 'validator' | 1 | import * as validator from 'validator' |
2 | import { ACTIVITY_PUB } from '../../../initializers' | 2 | import { ACTIVITY_PUB } from '../../../initializers' |
3 | import { exists, isDateValid, isUUIDValid } from '../misc' | 3 | import { exists, isBooleanValid, isDateValid, isUUIDValid } from '../misc' |
4 | import { | 4 | import { |
5 | isVideoAbuseReasonValid, | 5 | isVideoAbuseReasonValid, |
6 | isVideoDurationValid, | 6 | isVideoDurationValid, |
7 | isVideoNameValid, | 7 | isVideoNameValid, |
8 | isVideoNSFWValid, | ||
9 | isVideoTagValid, | 8 | isVideoTagValid, |
10 | isVideoTruncatedDescriptionValid, | 9 | isVideoTruncatedDescriptionValid, |
11 | isVideoViewsValid | 10 | isVideoViewsValid |
@@ -53,7 +52,8 @@ function isVideoTorrentObjectValid (video: any) { | |||
53 | (!video.licence || isRemoteIdentifierValid(video.licence)) && | 52 | (!video.licence || isRemoteIdentifierValid(video.licence)) && |
54 | (!video.language || isRemoteIdentifierValid(video.language)) && | 53 | (!video.language || isRemoteIdentifierValid(video.language)) && |
55 | isVideoViewsValid(video.views) && | 54 | isVideoViewsValid(video.views) && |
56 | isVideoNSFWValid(video.nsfw) && | 55 | isBooleanValid(video.nsfw) && |
56 | isBooleanValid(video.commentsEnabled) && | ||
57 | isDateValid(video.published) && | 57 | isDateValid(video.published) && |
58 | isDateValid(video.updated) && | 58 | isDateValid(video.updated) && |
59 | (!video.content || isRemoteVideoContentValid(video.mediaType, video.content)) && | 59 | (!video.content || isRemoteVideoContentValid(video.mediaType, video.content)) && |
diff --git a/server/helpers/custom-validators/misc.ts b/server/helpers/custom-validators/misc.ts index 160ec91f3..3903884ea 100644 --- a/server/helpers/custom-validators/misc.ts +++ b/server/helpers/custom-validators/misc.ts | |||
@@ -24,6 +24,10 @@ function isIdOrUUIDValid (value: string) { | |||
24 | return isIdValid(value) || isUUIDValid(value) | 24 | return isIdValid(value) || isUUIDValid(value) |
25 | } | 25 | } |
26 | 26 | ||
27 | function isBooleanValid (value: string) { | ||
28 | return typeof value === 'boolean' || (typeof value === 'string' && validator.isBoolean(value)) | ||
29 | } | ||
30 | |||
27 | // --------------------------------------------------------------------------- | 31 | // --------------------------------------------------------------------------- |
28 | 32 | ||
29 | export { | 33 | export { |
@@ -32,5 +36,6 @@ export { | |||
32 | isIdValid, | 36 | isIdValid, |
33 | isUUIDValid, | 37 | isUUIDValid, |
34 | isIdOrUUIDValid, | 38 | isIdOrUUIDValid, |
35 | isDateValid | 39 | isDateValid, |
40 | isBooleanValid | ||
36 | } | 41 | } |
diff --git a/server/helpers/custom-validators/videos.ts b/server/helpers/custom-validators/videos.ts index ee9d0ed19..1a5fdb887 100644 --- a/server/helpers/custom-validators/videos.ts +++ b/server/helpers/custom-validators/videos.ts | |||
@@ -30,10 +30,6 @@ function isVideoLanguageValid (value: number) { | |||
30 | return value === null || VIDEO_LANGUAGES[value] !== undefined | 30 | return value === null || VIDEO_LANGUAGES[value] !== undefined |
31 | } | 31 | } |
32 | 32 | ||
33 | function isVideoNSFWValid (value: any) { | ||
34 | return typeof value === 'boolean' || (typeof value === 'string' && validator.isBoolean(value)) | ||
35 | } | ||
36 | |||
37 | function isVideoDurationValid (value: string) { | 33 | function isVideoDurationValid (value: string) { |
38 | return exists(value) && validator.isInt(value + '', VIDEOS_CONSTRAINTS_FIELDS.DURATION) | 34 | return exists(value) && validator.isInt(value + '', VIDEOS_CONSTRAINTS_FIELDS.DURATION) |
39 | } | 35 | } |
@@ -131,7 +127,6 @@ export { | |||
131 | isVideoCategoryValid, | 127 | isVideoCategoryValid, |
132 | isVideoLicenceValid, | 128 | isVideoLicenceValid, |
133 | isVideoLanguageValid, | 129 | isVideoLanguageValid, |
134 | isVideoNSFWValid, | ||
135 | isVideoTruncatedDescriptionValid, | 130 | isVideoTruncatedDescriptionValid, |
136 | isVideoDescriptionValid, | 131 | isVideoDescriptionValid, |
137 | isVideoFileInfoHashValid, | 132 | isVideoFileInfoHashValid, |
diff --git a/server/helpers/utils.ts b/server/helpers/utils.ts index 7a32e286c..b61d6e3fa 100644 --- a/server/helpers/utils.ts +++ b/server/helpers/utils.ts | |||
@@ -3,7 +3,7 @@ import * as multer from 'multer' | |||
3 | import { Model } from 'sequelize-typescript' | 3 | import { Model } from 'sequelize-typescript' |
4 | import { ResultList } from '../../shared' | 4 | import { ResultList } from '../../shared' |
5 | import { VideoResolution } from '../../shared/models/videos' | 5 | import { VideoResolution } from '../../shared/models/videos' |
6 | import { CONFIG, REMOTE_SCHEME, VIDEO_MIMETYPE_EXT } from '../initializers' | 6 | import { CONFIG, REMOTE_SCHEME } from '../initializers' |
7 | import { UserModel } from '../models/account/user' | 7 | import { UserModel } from '../models/account/user' |
8 | import { ActorModel } from '../models/activitypub/actor' | 8 | import { ActorModel } from '../models/activitypub/actor' |
9 | import { ApplicationModel } from '../models/application/application' | 9 | import { ApplicationModel } from '../models/application/application' |
diff --git a/server/initializers/constants.ts b/server/initializers/constants.ts index 50a29dc43..31bb6c981 100644 --- a/server/initializers/constants.ts +++ b/server/initializers/constants.ts | |||
@@ -9,7 +9,7 @@ import { isTestInstance, root, sanitizeHost, sanitizeUrl } from '../helpers/core | |||
9 | 9 | ||
10 | // --------------------------------------------------------------------------- | 10 | // --------------------------------------------------------------------------- |
11 | 11 | ||
12 | const LAST_MIGRATION_VERSION = 150 | 12 | const LAST_MIGRATION_VERSION = 155 |
13 | 13 | ||
14 | // --------------------------------------------------------------------------- | 14 | // --------------------------------------------------------------------------- |
15 | 15 | ||
diff --git a/server/initializers/migrations/0155-video-comments-enabled.ts b/server/initializers/migrations/0155-video-comments-enabled.ts new file mode 100644 index 000000000..59f4110de --- /dev/null +++ b/server/initializers/migrations/0155-video-comments-enabled.ts | |||
@@ -0,0 +1,26 @@ | |||
1 | import * as Sequelize from 'sequelize' | ||
2 | |||
3 | async function up (utils: { | ||
4 | transaction: Sequelize.Transaction, | ||
5 | queryInterface: Sequelize.QueryInterface, | ||
6 | sequelize: Sequelize.Sequelize | ||
7 | }): Promise<void> { | ||
8 | const data = { | ||
9 | type: Sequelize.BOOLEAN, | ||
10 | allowNull: false, | ||
11 | defaultValue: true | ||
12 | } | ||
13 | await utils.queryInterface.addColumn('video', 'commentsEnabled', data) | ||
14 | |||
15 | data.defaultValue = null | ||
16 | return utils.queryInterface.changeColumn('video', 'commentsEnabled', data) | ||
17 | } | ||
18 | |||
19 | function down (options) { | ||
20 | throw new Error('Not implemented.') | ||
21 | } | ||
22 | |||
23 | export { | ||
24 | up, | ||
25 | down | ||
26 | } | ||
diff --git a/server/lib/activitypub/process/misc.ts b/server/lib/activitypub/process/misc.ts index f65395c99..461619ea7 100644 --- a/server/lib/activitypub/process/misc.ts +++ b/server/lib/activitypub/process/misc.ts | |||
@@ -53,6 +53,7 @@ async function videoActivityObjectToDBAttributes ( | |||
53 | language, | 53 | language, |
54 | description, | 54 | description, |
55 | nsfw: videoObject.nsfw, | 55 | nsfw: videoObject.nsfw, |
56 | commentsEnabled: videoObject.commentsEnabled, | ||
56 | channelId: videoChannel.id, | 57 | channelId: videoChannel.id, |
57 | duration: parseInt(duration, 10), | 58 | duration: parseInt(duration, 10), |
58 | createdAt: new Date(videoObject.published), | 59 | createdAt: new Date(videoObject.published), |
diff --git a/server/middlewares/validators/users.ts b/server/middlewares/validators/users.ts index 42ebddd56..7c77e9a39 100644 --- a/server/middlewares/validators/users.ts +++ b/server/middlewares/validators/users.ts | |||
@@ -3,11 +3,10 @@ import 'express-validator' | |||
3 | import { body, param } from 'express-validator/check' | 3 | import { body, param } from 'express-validator/check' |
4 | import { isIdOrUUIDValid } from '../../helpers/custom-validators/misc' | 4 | import { isIdOrUUIDValid } from '../../helpers/custom-validators/misc' |
5 | import { | 5 | import { |
6 | isAvatarFile, | 6 | isAvatarFile, isUserAutoPlayVideoValid, isUserDisplayNSFWValid, isUserPasswordValid, isUserRoleValid, isUserUsernameValid, |
7 | isUserAutoPlayVideoValid, isUserDisplayNSFWValid, isUserPasswordValid, isUserRoleValid, isUserUsernameValid, | ||
8 | isUserVideoQuotaValid | 7 | isUserVideoQuotaValid |
9 | } from '../../helpers/custom-validators/users' | 8 | } from '../../helpers/custom-validators/users' |
10 | import { isVideoExist, isVideoFile } from '../../helpers/custom-validators/videos' | 9 | import { isVideoExist } from '../../helpers/custom-validators/videos' |
11 | import { logger } from '../../helpers/logger' | 10 | import { logger } from '../../helpers/logger' |
12 | import { isSignupAllowed } from '../../helpers/utils' | 11 | import { isSignupAllowed } from '../../helpers/utils' |
13 | import { CONSTRAINTS_FIELDS } from '../../initializers' | 12 | import { CONSTRAINTS_FIELDS } from '../../initializers' |
diff --git a/server/middlewares/validators/video-comments.ts b/server/middlewares/validators/video-comments.ts index fdd092571..ade0b7b9f 100644 --- a/server/middlewares/validators/video-comments.ts +++ b/server/middlewares/validators/video-comments.ts | |||
@@ -45,6 +45,7 @@ const addVideoCommentThreadValidator = [ | |||
45 | 45 | ||
46 | if (areValidationErrors(req, res)) return | 46 | if (areValidationErrors(req, res)) return |
47 | if (!await isVideoExist(req.params.videoId, res)) return | 47 | if (!await isVideoExist(req.params.videoId, res)) return |
48 | if (!isVideoCommentsEnabled(res.locals.video, res)) return | ||
48 | 49 | ||
49 | return next() | 50 | return next() |
50 | } | 51 | } |
@@ -60,6 +61,7 @@ const addVideoCommentReplyValidator = [ | |||
60 | 61 | ||
61 | if (areValidationErrors(req, res)) return | 62 | if (areValidationErrors(req, res)) return |
62 | if (!await isVideoExist(req.params.videoId, res)) return | 63 | if (!await isVideoExist(req.params.videoId, res)) return |
64 | if (!isVideoCommentsEnabled(res.locals.video, res)) return | ||
63 | if (!await isVideoCommentExist(req.params.commentId, res.locals.video, res)) return | 65 | if (!await isVideoCommentExist(req.params.commentId, res.locals.video, res)) return |
64 | 66 | ||
65 | return next() | 67 | return next() |
@@ -146,3 +148,15 @@ async function isVideoCommentExist (id: number, video: VideoModel, res: express. | |||
146 | res.locals.videoComment = videoComment | 148 | res.locals.videoComment = videoComment |
147 | return true | 149 | return true |
148 | } | 150 | } |
151 | |||
152 | function isVideoCommentsEnabled (video: VideoModel, res: express.Response) { | ||
153 | if (video.commentsEnabled !== true) { | ||
154 | res.status(409) | ||
155 | .json({ error: 'Video comments are disabled for this video.' }) | ||
156 | .end() | ||
157 | |||
158 | return false | ||
159 | } | ||
160 | |||
161 | return true | ||
162 | } | ||
diff --git a/server/middlewares/validators/videos.ts b/server/middlewares/validators/videos.ts index bffc50322..e8cb2ae03 100644 --- a/server/middlewares/validators/videos.ts +++ b/server/middlewares/validators/videos.ts | |||
@@ -2,10 +2,10 @@ import * as express from 'express' | |||
2 | import 'express-validator' | 2 | import 'express-validator' |
3 | import { body, param, query } from 'express-validator/check' | 3 | import { body, param, query } from 'express-validator/check' |
4 | import { UserRight, VideoPrivacy } from '../../../shared' | 4 | import { UserRight, VideoPrivacy } from '../../../shared' |
5 | import { isIdOrUUIDValid, isIdValid } from '../../helpers/custom-validators/misc' | 5 | import { isBooleanValid, isIdOrUUIDValid, isIdValid } from '../../helpers/custom-validators/misc' |
6 | import { | 6 | import { |
7 | isVideoAbuseReasonValid, isVideoCategoryValid, isVideoDescriptionValid, isVideoExist, isVideoFile, isVideoLanguageValid, | 7 | isVideoAbuseReasonValid, isVideoCategoryValid, isVideoDescriptionValid, isVideoExist, isVideoFile, isVideoLanguageValid, |
8 | isVideoLicenceValid, isVideoNameValid, isVideoNSFWValid, isVideoPrivacyValid, isVideoRatingTypeValid, isVideoTagsValid | 8 | isVideoLicenceValid, isVideoNameValid, isVideoPrivacyValid, isVideoRatingTypeValid, isVideoTagsValid |
9 | } from '../../helpers/custom-validators/videos' | 9 | } from '../../helpers/custom-validators/videos' |
10 | import { getDurationFromVideoFile } from '../../helpers/ffmpeg-utils' | 10 | import { getDurationFromVideoFile } from '../../helpers/ffmpeg-utils' |
11 | import { logger } from '../../helpers/logger' | 11 | import { logger } from '../../helpers/logger' |
@@ -26,11 +26,12 @@ const videosAddValidator = [ | |||
26 | body('category').optional().custom(isVideoCategoryValid).withMessage('Should have a valid category'), | 26 | body('category').optional().custom(isVideoCategoryValid).withMessage('Should have a valid category'), |
27 | body('licence').optional().custom(isVideoLicenceValid).withMessage('Should have a valid licence'), | 27 | body('licence').optional().custom(isVideoLicenceValid).withMessage('Should have a valid licence'), |
28 | body('language').optional().custom(isVideoLanguageValid).withMessage('Should have a valid language'), | 28 | body('language').optional().custom(isVideoLanguageValid).withMessage('Should have a valid language'), |
29 | body('nsfw').custom(isVideoNSFWValid).withMessage('Should have a valid NSFW attribute'), | 29 | body('nsfw').custom(isBooleanValid).withMessage('Should have a valid NSFW attribute'), |
30 | body('description').optional().custom(isVideoDescriptionValid).withMessage('Should have a valid description'), | 30 | body('description').optional().custom(isVideoDescriptionValid).withMessage('Should have a valid description'), |
31 | body('channelId').custom(isIdValid).withMessage('Should have correct video channel id'), | 31 | body('channelId').custom(isIdValid).withMessage('Should have correct video channel id'), |
32 | body('privacy').custom(isVideoPrivacyValid).withMessage('Should have correct video privacy'), | 32 | body('privacy').custom(isVideoPrivacyValid).withMessage('Should have correct video privacy'), |
33 | body('tags').optional().custom(isVideoTagsValid).withMessage('Should have correct tags'), | 33 | body('tags').optional().custom(isVideoTagsValid).withMessage('Should have correct tags'), |
34 | body('commentsEnabled').custom(isBooleanValid).withMessage('Should have comments enabled boolean'), | ||
34 | 35 | ||
35 | async (req: express.Request, res: express.Response, next: express.NextFunction) => { | 36 | async (req: express.Request, res: express.Response, next: express.NextFunction) => { |
36 | logger.debug('Checking videosAdd parameters', { parameters: req.body, files: req.files }) | 37 | logger.debug('Checking videosAdd parameters', { parameters: req.body, files: req.files }) |
@@ -85,10 +86,11 @@ const videosUpdateValidator = [ | |||
85 | body('category').optional().custom(isVideoCategoryValid).withMessage('Should have a valid category'), | 86 | body('category').optional().custom(isVideoCategoryValid).withMessage('Should have a valid category'), |
86 | body('licence').optional().custom(isVideoLicenceValid).withMessage('Should have a valid licence'), | 87 | body('licence').optional().custom(isVideoLicenceValid).withMessage('Should have a valid licence'), |
87 | body('language').optional().custom(isVideoLanguageValid).withMessage('Should have a valid language'), | 88 | body('language').optional().custom(isVideoLanguageValid).withMessage('Should have a valid language'), |
88 | body('nsfw').optional().custom(isVideoNSFWValid).withMessage('Should have a valid NSFW attribute'), | 89 | body('nsfw').optional().custom(isBooleanValid).withMessage('Should have a valid NSFW attribute'), |
89 | body('privacy').optional().custom(isVideoPrivacyValid).withMessage('Should have correct video privacy'), | 90 | body('privacy').optional().custom(isVideoPrivacyValid).withMessage('Should have correct video privacy'), |
90 | body('description').optional().custom(isVideoDescriptionValid).withMessage('Should have a valid description'), | 91 | body('description').optional().custom(isVideoDescriptionValid).withMessage('Should have a valid description'), |
91 | body('tags').optional().custom(isVideoTagsValid).withMessage('Should have correct tags'), | 92 | body('tags').optional().custom(isVideoTagsValid).withMessage('Should have correct tags'), |
93 | body('commentsEnabled').optional().custom(isBooleanValid).withMessage('Should have comments enabled boolean'), | ||
92 | 94 | ||
93 | async (req: express.Request, res: express.Response, next: express.NextFunction) => { | 95 | async (req: express.Request, res: express.Response, next: express.NextFunction) => { |
94 | logger.debug('Checking videosUpdate parameters', { parameters: req.body }) | 96 | logger.debug('Checking videosUpdate parameters', { parameters: req.body }) |
diff --git a/server/models/activitypub/actor.ts b/server/models/activitypub/actor.ts index 8422653df..a12f3ec9e 100644 --- a/server/models/activitypub/actor.ts +++ b/server/models/activitypub/actor.ts | |||
@@ -1,5 +1,5 @@ | |||
1 | import { values } from 'lodash' | 1 | import { values } from 'lodash' |
2 | import { extname, join } from 'path' | 2 | import { extname } from 'path' |
3 | import * as Sequelize from 'sequelize' | 3 | import * as Sequelize from 'sequelize' |
4 | import { | 4 | import { |
5 | AllowNull, BelongsTo, Column, CreatedAt, DataType, Default, DefaultScope, ForeignKey, HasMany, HasOne, Is, IsUUID, Model, Scopes, | 5 | AllowNull, BelongsTo, Column, CreatedAt, DataType, Default, DefaultScope, ForeignKey, HasMany, HasOne, Is, IsUUID, Model, Scopes, |
@@ -13,7 +13,7 @@ import { | |||
13 | isActorPublicKeyValid | 13 | isActorPublicKeyValid |
14 | } from '../../helpers/custom-validators/activitypub/actor' | 14 | } from '../../helpers/custom-validators/activitypub/actor' |
15 | import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub/misc' | 15 | import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub/misc' |
16 | import { ACTIVITY_PUB_ACTOR_TYPES, AVATARS_DIR, CONFIG, CONSTRAINTS_FIELDS } from '../../initializers' | 16 | import { ACTIVITY_PUB_ACTOR_TYPES, CONFIG, CONSTRAINTS_FIELDS } from '../../initializers' |
17 | import { AccountModel } from '../account/account' | 17 | import { AccountModel } from '../account/account' |
18 | import { AvatarModel } from '../avatar/avatar' | 18 | import { AvatarModel } from '../avatar/avatar' |
19 | import { ServerModel } from '../server/server' | 19 | import { ServerModel } from '../server/server' |
diff --git a/server/models/avatar/avatar.ts b/server/models/avatar/avatar.ts index 7493c3d75..e1d4c20bc 100644 --- a/server/models/avatar/avatar.ts +++ b/server/models/avatar/avatar.ts | |||
@@ -2,9 +2,7 @@ import { join } from 'path' | |||
2 | import { AfterDestroy, AllowNull, Column, CreatedAt, Model, Table, UpdatedAt } from 'sequelize-typescript' | 2 | import { AfterDestroy, AllowNull, Column, CreatedAt, Model, Table, UpdatedAt } from 'sequelize-typescript' |
3 | import { Avatar } from '../../../shared/models/avatars/avatar.model' | 3 | import { Avatar } from '../../../shared/models/avatars/avatar.model' |
4 | import { unlinkPromise } from '../../helpers/core-utils' | 4 | import { unlinkPromise } from '../../helpers/core-utils' |
5 | import { logger } from '../../helpers/logger' | ||
6 | import { CONFIG, STATIC_PATHS } from '../../initializers' | 5 | import { CONFIG, STATIC_PATHS } from '../../initializers' |
7 | import { sendDeleteVideo } from '../../lib/activitypub/send' | ||
8 | 6 | ||
9 | @Table({ | 7 | @Table({ |
10 | tableName: 'avatar' | 8 | tableName: 'avatar' |
diff --git a/server/models/video/video.ts b/server/models/video/video.ts index 2504ae58a..c4b716cd2 100644 --- a/server/models/video/video.ts +++ b/server/models/video/video.ts | |||
@@ -15,9 +15,10 @@ import { Video, VideoDetails } from '../../../shared/models/videos' | |||
15 | import { activityPubCollection } from '../../helpers/activitypub' | 15 | import { activityPubCollection } from '../../helpers/activitypub' |
16 | import { createTorrentPromise, renamePromise, statPromise, unlinkPromise, writeFilePromise } from '../../helpers/core-utils' | 16 | import { createTorrentPromise, renamePromise, statPromise, unlinkPromise, writeFilePromise } from '../../helpers/core-utils' |
17 | import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub/misc' | 17 | import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub/misc' |
18 | import { isBooleanValid } from '../../helpers/custom-validators/misc' | ||
18 | import { | 19 | import { |
19 | isVideoCategoryValid, isVideoDescriptionValid, isVideoDurationValid, isVideoLanguageValid, isVideoLicenceValid, isVideoNameValid, | 20 | isVideoCategoryValid, isVideoDescriptionValid, isVideoDurationValid, isVideoLanguageValid, isVideoLicenceValid, isVideoNameValid, |
20 | isVideoNSFWValid, isVideoPrivacyValid | 21 | isVideoPrivacyValid |
21 | } from '../../helpers/custom-validators/videos' | 22 | } from '../../helpers/custom-validators/videos' |
22 | import { generateImageFromVideoFile, getVideoFileHeight, transcode } from '../../helpers/ffmpeg-utils' | 23 | import { generateImageFromVideoFile, getVideoFileHeight, transcode } from '../../helpers/ffmpeg-utils' |
23 | import { logger } from '../../helpers/logger' | 24 | import { logger } from '../../helpers/logger' |
@@ -185,7 +186,7 @@ export class VideoModel extends Model<VideoModel> { | |||
185 | privacy: number | 186 | privacy: number |
186 | 187 | ||
187 | @AllowNull(false) | 188 | @AllowNull(false) |
188 | @Is('VideoNSFW', value => throwIfNotValid(value, isVideoNSFWValid, 'NSFW boolean')) | 189 | @Is('VideoNSFW', value => throwIfNotValid(value, isBooleanValid, 'NSFW boolean')) |
189 | @Column | 190 | @Column |
190 | nsfw: boolean | 191 | nsfw: boolean |
191 | 192 | ||
@@ -230,6 +231,10 @@ export class VideoModel extends Model<VideoModel> { | |||
230 | @Column(DataType.STRING(CONSTRAINTS_FIELDS.VIDEOS.URL.max)) | 231 | @Column(DataType.STRING(CONSTRAINTS_FIELDS.VIDEOS.URL.max)) |
231 | url: string | 232 | url: string |
232 | 233 | ||
234 | @AllowNull(false) | ||
235 | @Column | ||
236 | commentsEnabled: boolean | ||
237 | |||
233 | @CreatedAt | 238 | @CreatedAt |
234 | createdAt: Date | 239 | createdAt: Date |
235 | 240 | ||
@@ -773,6 +778,7 @@ export class VideoModel extends Model<VideoModel> { | |||
773 | channel: this.VideoChannel.toFormattedJSON(), | 778 | channel: this.VideoChannel.toFormattedJSON(), |
774 | account: this.VideoChannel.Account.toFormattedJSON(), | 779 | account: this.VideoChannel.Account.toFormattedJSON(), |
775 | tags: map<TagModel, string>(this.Tags, 'name'), | 780 | tags: map<TagModel, string>(this.Tags, 'name'), |
781 | commentsEnabled: this.commentsEnabled, | ||
776 | files: [] | 782 | files: [] |
777 | } | 783 | } |
778 | 784 | ||
@@ -920,6 +926,7 @@ export class VideoModel extends Model<VideoModel> { | |||
920 | language, | 926 | language, |
921 | views: this.views, | 927 | views: this.views, |
922 | nsfw: this.nsfw, | 928 | nsfw: this.nsfw, |
929 | commentsEnabled: this.commentsEnabled, | ||
923 | published: this.createdAt.toISOString(), | 930 | published: this.createdAt.toISOString(), |
924 | updated: this.updatedAt.toISOString(), | 931 | updated: this.updatedAt.toISOString(), |
925 | mediaType: 'text/markdown', | 932 | mediaType: 'text/markdown', |
diff --git a/server/tests/activitypub.ts b/server/tests/activitypub.ts index 94615c63f..c8884719d 100644 --- a/server/tests/activitypub.ts +++ b/server/tests/activitypub.ts | |||
@@ -20,11 +20,11 @@ describe('Test activitypub', function () { | |||
20 | }) | 20 | }) |
21 | 21 | ||
22 | it('Should return the account object', async function () { | 22 | it('Should return the account object', async function () { |
23 | const res = await makeActivityPubGetRequest(server.url, '/account/root') | 23 | const res = await makeActivityPubGetRequest(server.url, '/accounts/root') |
24 | const object = res.body | 24 | const object = res.body |
25 | 25 | ||
26 | expect(object.type).to.equal('Person') | 26 | expect(object.type).to.equal('Person') |
27 | expect(object.id).to.equal('http://localhost:9001/account/root') | 27 | expect(object.id).to.equal('http://localhost:9001/accounts/root') |
28 | expect(object.name).to.equal('root') | 28 | expect(object.name).to.equal('root') |
29 | expect(object.preferredUsername).to.equal('root') | 29 | expect(object.preferredUsername).to.equal('root') |
30 | }) | 30 | }) |
diff --git a/server/tests/api/check-params/users.ts b/server/tests/api/check-params/users.ts index 44412ad82..33d92ac24 100644 --- a/server/tests/api/check-params/users.ts +++ b/server/tests/api/check-params/users.ts | |||
@@ -2,14 +2,13 @@ | |||
2 | 2 | ||
3 | import { omit } from 'lodash' | 3 | import { omit } from 'lodash' |
4 | import 'mocha' | 4 | import 'mocha' |
5 | import { join } from "path" | 5 | import { join } from 'path' |
6 | import { UserRole } from '../../../../shared' | 6 | import { UserRole } from '../../../../shared' |
7 | 7 | ||
8 | import { | 8 | import { |
9 | createUser, flushTests, getMyUserInformation, getMyUserVideoRating, getUsersList, immutableAssign, killallServers, makeGetRequest, | 9 | createUser, flushTests, getMyUserInformation, getMyUserVideoRating, getUsersList, immutableAssign, killallServers, makeGetRequest, |
10 | makePostBodyRequest, makePostUploadRequest, makePutBodyRequest, registerUser, removeUser, runServer, ServerInfo, setAccessTokensToServers, | 10 | makePostBodyRequest, makePostUploadRequest, makePutBodyRequest, registerUser, removeUser, runServer, ServerInfo, setAccessTokensToServers, |
11 | updateUser, | 11 | updateUser, uploadVideo, userLogin |
12 | uploadVideo, userLogin | ||
13 | } from '../../utils' | 12 | } from '../../utils' |
14 | import { checkBadCountPagination, checkBadSortPagination, checkBadStartPagination } from '../../utils/requests/check-api-params' | 13 | import { checkBadCountPagination, checkBadSortPagination, checkBadStartPagination } from '../../utils/requests/check-api-params' |
15 | 14 | ||
@@ -25,7 +24,7 @@ describe('Test users API validators', function () { | |||
25 | // --------------------------------------------------------------- | 24 | // --------------------------------------------------------------- |
26 | 25 | ||
27 | before(async function () { | 26 | before(async function () { |
28 | this.timeout(120000) | 27 | this.timeout(20000) |
29 | 28 | ||
30 | await flushTests() | 29 | await flushTests() |
31 | 30 | ||
@@ -282,7 +281,14 @@ describe('Test users API validators', function () { | |||
282 | const attaches = { | 281 | const attaches = { |
283 | 'avatarfile': join(__dirname, '..', 'fixtures', 'avatar.png') | 282 | 'avatarfile': join(__dirname, '..', 'fixtures', 'avatar.png') |
284 | } | 283 | } |
285 | await makePostUploadRequest({ url: server.url, path: path + '/me/avatar/pick', token: server.accessToken, fields, attaches }) | 284 | await makePostUploadRequest({ |
285 | url: server.url, | ||
286 | path: path + '/me/avatar/pick', | ||
287 | token: server.accessToken, | ||
288 | fields, | ||
289 | attaches, | ||
290 | statusCodeExpected: 200 | ||
291 | }) | ||
286 | }) | 292 | }) |
287 | }) | 293 | }) |
288 | 294 | ||
diff --git a/server/tests/api/check-params/video-comments.ts b/server/tests/api/check-params/video-comments.ts index cdb48a276..c11660d07 100644 --- a/server/tests/api/check-params/video-comments.ts +++ b/server/tests/api/check-params/video-comments.ts | |||
@@ -1,5 +1,6 @@ | |||
1 | /* tslint:disable:no-unused-expression */ | 1 | /* tslint:disable:no-unused-expression */ |
2 | 2 | ||
3 | import * as chai from 'chai' | ||
3 | import 'mocha' | 4 | import 'mocha' |
4 | import { | 5 | import { |
5 | flushTests, killallServers, makeGetRequest, makePostBodyRequest, runServer, ServerInfo, setAccessTokensToServers, | 6 | flushTests, killallServers, makeGetRequest, makePostBodyRequest, runServer, ServerInfo, setAccessTokensToServers, |
@@ -8,6 +9,8 @@ import { | |||
8 | import { checkBadCountPagination, checkBadSortPagination, checkBadStartPagination } from '../../utils/requests/check-api-params' | 9 | import { checkBadCountPagination, checkBadSortPagination, checkBadStartPagination } from '../../utils/requests/check-api-params' |
9 | import { addVideoCommentThread } from '../../utils/videos/video-comments' | 10 | import { addVideoCommentThread } from '../../utils/videos/video-comments' |
10 | 11 | ||
12 | const expect = chai.expect | ||
13 | |||
11 | describe('Test video comments API validator', function () { | 14 | describe('Test video comments API validator', function () { |
12 | let pathThread: string | 15 | let pathThread: string |
13 | let pathComment: string | 16 | let pathComment: string |
@@ -42,17 +45,14 @@ describe('Test video comments API validator', function () { | |||
42 | describe('When listing video comment threads', function () { | 45 | describe('When listing video comment threads', function () { |
43 | it('Should fail with a bad start pagination', async function () { | 46 | it('Should fail with a bad start pagination', async function () { |
44 | await checkBadStartPagination(server.url, pathThread, server.accessToken) | 47 | await checkBadStartPagination(server.url, pathThread, server.accessToken) |
45 | |||
46 | }) | 48 | }) |
47 | 49 | ||
48 | it('Should fail with a bad count pagination', async function () { | 50 | it('Should fail with a bad count pagination', async function () { |
49 | await checkBadCountPagination(server.url, pathThread, server.accessToken) | 51 | await checkBadCountPagination(server.url, pathThread, server.accessToken) |
50 | |||
51 | }) | 52 | }) |
52 | 53 | ||
53 | it('Should fail with an incorrect sort', async function () { | 54 | it('Should fail with an incorrect sort', async function () { |
54 | await checkBadSortPagination(server.url, pathThread, server.accessToken) | 55 | await checkBadSortPagination(server.url, pathThread, server.accessToken) |
55 | |||
56 | }) | 56 | }) |
57 | 57 | ||
58 | it('Should fail with an incorrect video', async function () { | 58 | it('Should fail with an incorrect video', async function () { |
@@ -185,6 +185,35 @@ describe('Test video comments API validator', function () { | |||
185 | }) | 185 | }) |
186 | }) | 186 | }) |
187 | 187 | ||
188 | describe('When a video has comments disabled', function () { | ||
189 | before(async function () { | ||
190 | const res = await uploadVideo(server.url, server.accessToken, { commentsEnabled: false }) | ||
191 | videoUUID = res.body.video.uuid | ||
192 | pathThread = '/api/v1/videos/' + videoUUID + '/comment-threads' | ||
193 | }) | ||
194 | |||
195 | it('Should return an empty thread list', async function () { | ||
196 | const res = await makeGetRequest({ | ||
197 | url: server.url, | ||
198 | path: pathThread, | ||
199 | statusCodeExpected: 200 | ||
200 | }) | ||
201 | expect(res.body.total).to.equal(0) | ||
202 | expect(res.body.data).to.have.lengthOf(0) | ||
203 | }) | ||
204 | |||
205 | it('Should return an thread comments list') | ||
206 | |||
207 | it('Should return conflict on thread add', async function () { | ||
208 | const fields = { | ||
209 | text: 'super comment' | ||
210 | } | ||
211 | await makePostBodyRequest({ url: server.url, path: pathThread, token: server.accessToken, fields, statusCodeExpected: 409 }) | ||
212 | }) | ||
213 | |||
214 | it('Should return conflict on comment thread add') | ||
215 | }) | ||
216 | |||
188 | after(async function () { | 217 | after(async function () { |
189 | killallServers([ server ]) | 218 | killallServers([ server ]) |
190 | 219 | ||
diff --git a/server/tests/api/check-params/videos.ts b/server/tests/api/check-params/videos.ts index b9484afc4..5c067dc96 100644 --- a/server/tests/api/check-params/videos.ts +++ b/server/tests/api/check-params/videos.ts | |||
@@ -100,6 +100,7 @@ describe('Test videos API validator', function () { | |||
100 | licence: 1, | 100 | licence: 1, |
101 | language: 6, | 101 | language: 6, |
102 | nsfw: false, | 102 | nsfw: false, |
103 | commentsEnabled: true, | ||
103 | description: 'my super description', | 104 | description: 'my super description', |
104 | tags: [ 'tag1', 'tag2' ], | 105 | tags: [ 'tag1', 'tag2' ], |
105 | privacy: VideoPrivacy.PUBLIC, | 106 | privacy: VideoPrivacy.PUBLIC, |
@@ -162,6 +163,20 @@ describe('Test videos API validator', function () { | |||
162 | await makePostUploadRequest({ url: server.url, path: path + '/upload', token: server.accessToken, fields, attaches }) | 163 | await makePostUploadRequest({ url: server.url, path: path + '/upload', token: server.accessToken, fields, attaches }) |
163 | }) | 164 | }) |
164 | 165 | ||
166 | it('Should fail without commentsEnabled attribute', async function () { | ||
167 | const fields = omit(baseCorrectParams, 'commentsEnabled') | ||
168 | const attaches = baseCorrectAttaches | ||
169 | |||
170 | await makePostUploadRequest({ url: server.url, path: path + '/upload', token: server.accessToken, fields, attaches }) | ||
171 | }) | ||
172 | |||
173 | it('Should fail with a bad commentsEnabled attribute', async function () { | ||
174 | const fields = immutableAssign(baseCorrectParams, { commentsEnabled: 2 }) | ||
175 | const attaches = baseCorrectAttaches | ||
176 | |||
177 | await makePostUploadRequest({ url: server.url, path: path + '/upload', token: server.accessToken, fields, attaches }) | ||
178 | }) | ||
179 | |||
165 | it('Should fail with a long description', async function () { | 180 | it('Should fail with a long description', async function () { |
166 | const fields = immutableAssign(baseCorrectParams, { description: 'super'.repeat(1500) }) | 181 | const fields = immutableAssign(baseCorrectParams, { description: 'super'.repeat(1500) }) |
167 | const attaches = baseCorrectAttaches | 182 | const attaches = baseCorrectAttaches |
@@ -291,6 +306,7 @@ describe('Test videos API validator', function () { | |||
291 | licence: 2, | 306 | licence: 2, |
292 | language: 6, | 307 | language: 6, |
293 | nsfw: false, | 308 | nsfw: false, |
309 | commentsEnabled: false, | ||
294 | description: 'my super description', | 310 | description: 'my super description', |
295 | privacy: VideoPrivacy.PUBLIC, | 311 | privacy: VideoPrivacy.PUBLIC, |
296 | tags: [ 'tag1', 'tag2' ] | 312 | tags: [ 'tag1', 'tag2' ] |
@@ -354,6 +370,12 @@ describe('Test videos API validator', function () { | |||
354 | await makePutBodyRequest({ url: server.url, path: path + videoId, token: server.accessToken, fields }) | 370 | await makePutBodyRequest({ url: server.url, path: path + videoId, token: server.accessToken, fields }) |
355 | }) | 371 | }) |
356 | 372 | ||
373 | it('Should fail with a bad commentsEnabled attribute', async function () { | ||
374 | const fields = immutableAssign(baseCorrectParams, { commentsEnabled: 2 }) | ||
375 | |||
376 | await makePutBodyRequest({ url: server.url, path: path + videoId, token: server.accessToken, fields }) | ||
377 | }) | ||
378 | |||
357 | it('Should fail with a long description', async function () { | 379 | it('Should fail with a long description', async function () { |
358 | const fields = immutableAssign(baseCorrectParams, { description: 'super'.repeat(1500) }) | 380 | const fields = immutableAssign(baseCorrectParams, { description: 'super'.repeat(1500) }) |
359 | 381 | ||
diff --git a/server/tests/api/server/follows.ts b/server/tests/api/server/follows.ts index fc9c5c3b6..e6dfd5f62 100644 --- a/server/tests/api/server/follows.ts +++ b/server/tests/api/server/follows.ts | |||
@@ -246,6 +246,7 @@ describe('Test follows', function () { | |||
246 | host: 'localhost:9003', | 246 | host: 'localhost:9003', |
247 | account: 'root', | 247 | account: 'root', |
248 | isLocal, | 248 | isLocal, |
249 | commentsEnabled: true, | ||
249 | duration: 5, | 250 | duration: 5, |
250 | tags: [ 'tag1', 'tag2', 'tag3' ], | 251 | tags: [ 'tag1', 'tag2', 'tag3' ], |
251 | privacy: VideoPrivacy.PUBLIC, | 252 | privacy: VideoPrivacy.PUBLIC, |
diff --git a/server/tests/api/videos/multiple-servers.ts b/server/tests/api/videos/multiple-servers.ts index abd051a30..b6dfe0d1b 100644 --- a/server/tests/api/videos/multiple-servers.ts +++ b/server/tests/api/videos/multiple-servers.ts | |||
@@ -93,6 +93,7 @@ describe('Test multiple servers', function () { | |||
93 | duration: 10, | 93 | duration: 10, |
94 | tags: [ 'tag1p1', 'tag2p1' ], | 94 | tags: [ 'tag1p1', 'tag2p1' ], |
95 | privacy: VideoPrivacy.PUBLIC, | 95 | privacy: VideoPrivacy.PUBLIC, |
96 | commentsEnabled: true, | ||
96 | channel: { | 97 | channel: { |
97 | name: 'my channel', | 98 | name: 'my channel', |
98 | description: 'super channel', | 99 | description: 'super channel', |
@@ -155,6 +156,7 @@ describe('Test multiple servers', function () { | |||
155 | host: 'localhost:9002', | 156 | host: 'localhost:9002', |
156 | account: 'user1', | 157 | account: 'user1', |
157 | isLocal, | 158 | isLocal, |
159 | commentsEnabled: true, | ||
158 | duration: 5, | 160 | duration: 5, |
159 | tags: [ 'tag1p2', 'tag2p2', 'tag3p2' ], | 161 | tags: [ 'tag1p2', 'tag2p2', 'tag3p2' ], |
160 | privacy: VideoPrivacy.PUBLIC, | 162 | privacy: VideoPrivacy.PUBLIC, |
@@ -254,6 +256,7 @@ describe('Test multiple servers', function () { | |||
254 | account: 'root', | 256 | account: 'root', |
255 | isLocal, | 257 | isLocal, |
256 | duration: 5, | 258 | duration: 5, |
259 | commentsEnabled: true, | ||
257 | tags: [ 'tag1p3' ], | 260 | tags: [ 'tag1p3' ], |
258 | privacy: VideoPrivacy.PUBLIC, | 261 | privacy: VideoPrivacy.PUBLIC, |
259 | channel: { | 262 | channel: { |
@@ -280,6 +283,7 @@ describe('Test multiple servers', function () { | |||
280 | description: 'my super description for server 3-2', | 283 | description: 'my super description for server 3-2', |
281 | host: 'localhost:9003', | 284 | host: 'localhost:9003', |
282 | account: 'root', | 285 | account: 'root', |
286 | commentsEnabled: true, | ||
283 | isLocal, | 287 | isLocal, |
284 | duration: 5, | 288 | duration: 5, |
285 | tags: [ 'tag2p3', 'tag3p3', 'tag4p3' ], | 289 | tags: [ 'tag2p3', 'tag3p3', 'tag4p3' ], |
@@ -545,6 +549,7 @@ describe('Test multiple servers', function () { | |||
545 | account: 'root', | 549 | account: 'root', |
546 | isLocal, | 550 | isLocal, |
547 | duration: 5, | 551 | duration: 5, |
552 | commentsEnabled: true, | ||
548 | tags: [ 'tag_up_1', 'tag_up_2' ], | 553 | tags: [ 'tag_up_1', 'tag_up_2' ], |
549 | privacy: VideoPrivacy.PUBLIC, | 554 | privacy: VideoPrivacy.PUBLIC, |
550 | channel: { | 555 | channel: { |
@@ -732,6 +737,26 @@ describe('Test multiple servers', function () { | |||
732 | expect(secondChild.children).to.have.lengthOf(0) | 737 | expect(secondChild.children).to.have.lengthOf(0) |
733 | } | 738 | } |
734 | }) | 739 | }) |
740 | |||
741 | it('Should disable comments', async function () { | ||
742 | this.timeout(20000) | ||
743 | |||
744 | const attributes = { | ||
745 | commentsEnabled: false | ||
746 | } | ||
747 | |||
748 | await updateVideo(servers[0].url, servers[0].accessToken, videoUUID, attributes) | ||
749 | |||
750 | await wait(5000) | ||
751 | |||
752 | for (const server of servers) { | ||
753 | const res = await getVideo(server.url, videoUUID) | ||
754 | expect(res.body.commentsEnabled).to.be.false | ||
755 | |||
756 | const text = 'my super forbidden comment' | ||
757 | await addVideoCommentThread(server.url, server.accessToken, videoUUID, text, 409) | ||
758 | } | ||
759 | }) | ||
735 | }) | 760 | }) |
736 | 761 | ||
737 | describe('With minimum parameters', function () { | 762 | describe('With minimum parameters', function () { |
@@ -748,6 +773,7 @@ describe('Test multiple servers', function () { | |||
748 | .field('privacy', '1') | 773 | .field('privacy', '1') |
749 | .field('nsfw', 'false') | 774 | .field('nsfw', 'false') |
750 | .field('channelId', '1') | 775 | .field('channelId', '1') |
776 | .field('commentsEnabled', 'true') | ||
751 | 777 | ||
752 | const filePath = join(__dirname, '..', '..', 'api', 'fixtures', 'video_short.webm') | 778 | const filePath = join(__dirname, '..', '..', 'api', 'fixtures', 'video_short.webm') |
753 | 779 | ||
@@ -772,6 +798,7 @@ describe('Test multiple servers', function () { | |||
772 | account: 'root', | 798 | account: 'root', |
773 | isLocal, | 799 | isLocal, |
774 | duration: 5, | 800 | duration: 5, |
801 | commentsEnabled: true, | ||
775 | tags: [ ], | 802 | tags: [ ], |
776 | privacy: VideoPrivacy.PUBLIC, | 803 | privacy: VideoPrivacy.PUBLIC, |
777 | channel: { | 804 | channel: { |
diff --git a/server/tests/api/videos/single-server.ts b/server/tests/api/videos/single-server.ts index 2a3126f32..0a0c95750 100644 --- a/server/tests/api/videos/single-server.ts +++ b/server/tests/api/videos/single-server.ts | |||
@@ -32,6 +32,7 @@ describe('Test a single server', function () { | |||
32 | duration: 5, | 32 | duration: 5, |
33 | tags: [ 'tag1', 'tag2', 'tag3' ], | 33 | tags: [ 'tag1', 'tag2', 'tag3' ], |
34 | privacy: VideoPrivacy.PUBLIC, | 34 | privacy: VideoPrivacy.PUBLIC, |
35 | commentsEnabled: true, | ||
35 | channel: { | 36 | channel: { |
36 | name: 'Default root channel', | 37 | name: 'Default root channel', |
37 | description: '', | 38 | description: '', |
@@ -51,7 +52,7 @@ describe('Test a single server', function () { | |||
51 | category: 4, | 52 | category: 4, |
52 | licence: 2, | 53 | licence: 2, |
53 | language: 5, | 54 | language: 5, |
54 | nsfw: true, | 55 | nsfw: false, |
55 | description: 'my super description updated', | 56 | description: 'my super description updated', |
56 | host: 'localhost:9001', | 57 | host: 'localhost:9001', |
57 | account: 'root', | 58 | account: 'root', |
@@ -59,6 +60,7 @@ describe('Test a single server', function () { | |||
59 | tags: [ 'tagup1', 'tagup2' ], | 60 | tags: [ 'tagup1', 'tagup2' ], |
60 | privacy: VideoPrivacy.PUBLIC, | 61 | privacy: VideoPrivacy.PUBLIC, |
61 | duration: 5, | 62 | duration: 5, |
63 | commentsEnabled: false, | ||
62 | channel: { | 64 | channel: { |
63 | name: 'Default root channel', | 65 | name: 'Default root channel', |
64 | description: '', | 66 | description: '', |
@@ -475,6 +477,7 @@ describe('Test a single server', function () { | |||
475 | language: 5, | 477 | language: 5, |
476 | nsfw: false, | 478 | nsfw: false, |
477 | description: 'my super description updated', | 479 | description: 'my super description updated', |
480 | commentsEnabled: false, | ||
478 | tags: [ 'tagup1', 'tagup2' ] | 481 | tags: [ 'tagup1', 'tagup2' ] |
479 | } | 482 | } |
480 | await updateVideo(server.url, server.accessToken, videoId, attributes) | 483 | await updateVideo(server.url, server.accessToken, videoId, attributes) |
diff --git a/server/tests/utils/videos/videos.ts b/server/tests/utils/videos/videos.ts index aca51ee5d..c437c21b2 100644 --- a/server/tests/utils/videos/videos.ts +++ b/server/tests/utils/videos/videos.ts | |||
@@ -16,6 +16,7 @@ type VideoAttributes = { | |||
16 | licence?: number | 16 | licence?: number |
17 | language?: number | 17 | language?: number |
18 | nsfw?: boolean | 18 | nsfw?: boolean |
19 | commentsEnabled?: boolean | ||
19 | description?: string | 20 | description?: string |
20 | tags?: string[] | 21 | tags?: string[] |
21 | channelId?: number | 22 | channelId?: number |
@@ -238,6 +239,7 @@ async function uploadVideo (url: string, accessToken: string, videoAttributesArg | |||
238 | description: 'my super description', | 239 | description: 'my super description', |
239 | tags: [ 'tag' ], | 240 | tags: [ 'tag' ], |
240 | privacy: VideoPrivacy.PUBLIC, | 241 | privacy: VideoPrivacy.PUBLIC, |
242 | commentsEnabled: true, | ||
241 | fixture: 'video_short.webm' | 243 | fixture: 'video_short.webm' |
242 | } | 244 | } |
243 | attributes = Object.assign(attributes, videoAttributesArg) | 245 | attributes = Object.assign(attributes, videoAttributesArg) |
@@ -250,6 +252,7 @@ async function uploadVideo (url: string, accessToken: string, videoAttributesArg | |||
250 | .field('category', attributes.category.toString()) | 252 | .field('category', attributes.category.toString()) |
251 | .field('licence', attributes.licence.toString()) | 253 | .field('licence', attributes.licence.toString()) |
252 | .field('nsfw', JSON.stringify(attributes.nsfw)) | 254 | .field('nsfw', JSON.stringify(attributes.nsfw)) |
255 | .field('commentsEnabled', JSON.stringify(attributes.commentsEnabled)) | ||
253 | .field('description', attributes.description) | 256 | .field('description', attributes.description) |
254 | .field('privacy', attributes.privacy.toString()) | 257 | .field('privacy', attributes.privacy.toString()) |
255 | .field('channelId', attributes.channelId) | 258 | .field('channelId', attributes.channelId) |
@@ -273,7 +276,7 @@ async function uploadVideo (url: string, accessToken: string, videoAttributesArg | |||
273 | .expect(specialStatus) | 276 | .expect(specialStatus) |
274 | } | 277 | } |
275 | 278 | ||
276 | function updateVideo (url: string, accessToken: string, id: number, attributes: VideoAttributes, specialStatus = 204) { | 279 | function updateVideo (url: string, accessToken: string, id: number | string, attributes: VideoAttributes, specialStatus = 204) { |
277 | const path = '/api/v1/videos/' + id | 280 | const path = '/api/v1/videos/' + id |
278 | const body = {} | 281 | const body = {} |
279 | 282 | ||
@@ -281,7 +284,8 @@ function updateVideo (url: string, accessToken: string, id: number, attributes: | |||
281 | if (attributes.category) body['category'] = attributes.category | 284 | if (attributes.category) body['category'] = attributes.category |
282 | if (attributes.licence) body['licence'] = attributes.licence | 285 | if (attributes.licence) body['licence'] = attributes.licence |
283 | if (attributes.language) body['language'] = attributes.language | 286 | if (attributes.language) body['language'] = attributes.language |
284 | if (attributes.nsfw) body['nsfw'] = attributes.nsfw | 287 | if (attributes.nsfw !== undefined) body['nsfw'] = JSON.stringify(attributes.nsfw) |
288 | if (attributes.commentsEnabled !== undefined) body['commentsEnabled'] = JSON.stringify(attributes.commentsEnabled) | ||
285 | if (attributes.description) body['description'] = attributes.description | 289 | if (attributes.description) body['description'] = attributes.description |
286 | if (attributes.tags) body['tags'] = attributes.tags | 290 | if (attributes.tags) body['tags'] = attributes.tags |
287 | if (attributes.privacy) body['privacy'] = attributes.privacy | 291 | if (attributes.privacy) body['privacy'] = attributes.privacy |
@@ -326,6 +330,7 @@ async function completeVideoCheck ( | |||
326 | licence: number | 330 | licence: number |
327 | language: number | 331 | language: number |
328 | nsfw: boolean | 332 | nsfw: boolean |
333 | commentsEnabled: boolean | ||
329 | description: string | 334 | description: string |
330 | host: string | 335 | host: string |
331 | account: string | 336 | account: string |
@@ -376,6 +381,7 @@ async function completeVideoCheck ( | |||
376 | expect(videoDetails.privacy).to.deep.equal(attributes.privacy) | 381 | expect(videoDetails.privacy).to.deep.equal(attributes.privacy) |
377 | expect(videoDetails.privacyLabel).to.deep.equal(VIDEO_PRIVACIES[attributes.privacy]) | 382 | expect(videoDetails.privacyLabel).to.deep.equal(VIDEO_PRIVACIES[attributes.privacy]) |
378 | expect(videoDetails.account.name).to.equal(attributes.account) | 383 | expect(videoDetails.account.name).to.equal(attributes.account) |
384 | expect(videoDetails.commentsEnabled).to.equal(attributes.commentsEnabled) | ||
379 | 385 | ||
380 | expect(videoDetails.channel.name).to.equal(attributes.channel.name) | 386 | expect(videoDetails.channel.name).to.equal(attributes.channel.name) |
381 | expect(videoDetails.channel.isLocal).to.equal(attributes.channel.isLocal) | 387 | expect(videoDetails.channel.isLocal).to.equal(attributes.channel.isLocal) |
diff --git a/shared/models/activitypub/objects/video-torrent-object.ts b/shared/models/activitypub/objects/video-torrent-object.ts index 5ccc80bcb..cf0e0ba54 100644 --- a/shared/models/activitypub/objects/video-torrent-object.ts +++ b/shared/models/activitypub/objects/video-torrent-object.ts | |||
@@ -18,6 +18,7 @@ export interface VideoTorrentObject { | |||
18 | language: ActivityIdentifierObject | 18 | language: ActivityIdentifierObject |
19 | views: number | 19 | views: number |
20 | nsfw: boolean | 20 | nsfw: boolean |
21 | commentsEnabled: boolean | ||
21 | published: string | 22 | published: string |
22 | updated: string | 23 | updated: string |
23 | mediaType: 'text/markdown' | 24 | mediaType: 'text/markdown' |
diff --git a/shared/models/videos/video-create.model.ts b/shared/models/videos/video-create.model.ts index 8bc6a6639..139c2579e 100644 --- a/shared/models/videos/video-create.model.ts +++ b/shared/models/videos/video-create.model.ts | |||
@@ -9,5 +9,6 @@ export interface VideoCreate { | |||
9 | nsfw: boolean | 9 | nsfw: boolean |
10 | name: string | 10 | name: string |
11 | tags?: string[] | 11 | tags?: string[] |
12 | commentsEnabled?: boolean | ||
12 | privacy: VideoPrivacy | 13 | privacy: VideoPrivacy |
13 | } | 14 | } |
diff --git a/shared/models/videos/video-update.model.ts b/shared/models/videos/video-update.model.ts index 0cf38fe6e..fc772f77b 100644 --- a/shared/models/videos/video-update.model.ts +++ b/shared/models/videos/video-update.model.ts | |||
@@ -8,5 +8,6 @@ export interface VideoUpdate { | |||
8 | description?: string | 8 | description?: string |
9 | privacy?: VideoPrivacy | 9 | privacy?: VideoPrivacy |
10 | tags?: string[] | 10 | tags?: string[] |
11 | commentsEnabled?: boolean | ||
11 | nsfw?: boolean | 12 | nsfw?: boolean |
12 | } | 13 | } |
diff --git a/shared/models/videos/video.model.ts b/shared/models/videos/video.model.ts index 13b9c49b3..39d1edc06 100644 --- a/shared/models/videos/video.model.ts +++ b/shared/models/videos/video.model.ts | |||
@@ -45,4 +45,5 @@ export interface VideoDetails extends Video { | |||
45 | tags: string[] | 45 | tags: string[] |
46 | files: VideoFile[] | 46 | files: VideoFile[] |
47 | account: Account | 47 | account: Account |
48 | commentsEnabled: boolean | ||
48 | } | 49 | } |