aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--server/controllers/api/videos/comment.ts8
-rw-r--r--server/lib/activitypub/process/process-delete.ts6
-rw-r--r--server/lib/activitypub/send/send-delete.ts5
-rw-r--r--server/models/video/video-comment.ts43
-rw-r--r--server/tests/api/videos/multiple-servers.ts41
5 files changed, 49 insertions, 54 deletions
diff --git a/server/controllers/api/videos/comment.ts b/server/controllers/api/videos/comment.ts
index 39d521f5f..bc6d81a7c 100644
--- a/server/controllers/api/videos/comment.ts
+++ b/server/controllers/api/videos/comment.ts
@@ -27,6 +27,10 @@ import { auditLoggerFactory, CommentAuditView, getAuditIdFromRes } from '../../.
27import { AccountModel } from '../../../models/account/account' 27import { AccountModel } from '../../../models/account/account'
28import { Notifier } from '../../../lib/notifier' 28import { Notifier } from '../../../lib/notifier'
29import { Hooks } from '../../../lib/plugins/hooks' 29import { Hooks } from '../../../lib/plugins/hooks'
30import { ActorModel } from '../../../models/activitypub/actor'
31import { VideoChannelModel } from '../../../models/video/video-channel'
32import { VideoModel } from '../../../models/video/video'
33import { sendDeleteVideoComment } from '../../../lib/activitypub/send'
30 34
31const auditLogger = auditLoggerFactory('comments') 35const auditLogger = auditLoggerFactory('comments')
32const videoCommentRouter = express.Router() 36const videoCommentRouter = express.Router()
@@ -179,6 +183,10 @@ async function removeVideoComment (req: express.Request, res: express.Response)
179 183
180 await sequelizeTypescript.transaction(async t => { 184 await sequelizeTypescript.transaction(async t => {
181 await videoCommentInstance.destroy({ transaction: t }) 185 await videoCommentInstance.destroy({ transaction: t })
186
187 if (videoCommentInstance.isOwned() || videoCommentInstance.Video.isOwned()) {
188 await sendDeleteVideoComment(videoCommentInstance, t)
189 }
182 }) 190 })
183 191
184 auditLogger.delete(getAuditIdFromRes(res), new CommentAuditView(videoCommentInstance.toFormattedJSON())) 192 auditLogger.delete(getAuditIdFromRes(res), new CommentAuditView(videoCommentInstance.toFormattedJSON()))
diff --git a/server/lib/activitypub/process/process-delete.ts b/server/lib/activitypub/process/process-delete.ts
index 845a7b249..9fcfd9e3a 100644
--- a/server/lib/activitypub/process/process-delete.ts
+++ b/server/lib/activitypub/process/process-delete.ts
@@ -34,7 +34,7 @@ async function processDeleteActivity (options: APProcessorOptions<ActivityDelete
34 } 34 }
35 35
36 { 36 {
37 const videoCommentInstance = await VideoCommentModel.loadByUrlAndPopulateAccount(objectUrl) 37 const videoCommentInstance = await VideoCommentModel.loadByUrlAndPopulateAccountAndVideo(objectUrl)
38 if (videoCommentInstance) { 38 if (videoCommentInstance) {
39 return retryTransactionWrapper(processDeleteVideoComment, byActor, videoCommentInstance, activity) 39 return retryTransactionWrapper(processDeleteVideoComment, byActor, videoCommentInstance, activity)
40 } 40 }
@@ -121,8 +121,8 @@ function processDeleteVideoComment (byActor: ActorModel, videoComment: VideoComm
121 logger.debug('Removing remote video comment "%s".', videoComment.url) 121 logger.debug('Removing remote video comment "%s".', videoComment.url)
122 122
123 return sequelizeTypescript.transaction(async t => { 123 return sequelizeTypescript.transaction(async t => {
124 if (videoComment.Account.id !== byActor.Account.id) { 124 if (byActor.Account.id !== videoComment.Account.id && byActor.Account.id !== videoComment.Video.VideoChannel.accountId) {
125 throw new Error('Account ' + byActor.url + ' does not own video comment ' + videoComment.url) 125 throw new Error(`Account ${byActor.url} does not own video comment ${videoComment.url} or video ${videoComment.Video.url}`)
126 } 126 }
127 127
128 await videoComment.destroy({ transaction: t }) 128 await videoComment.destroy({ transaction: t })
diff --git a/server/lib/activitypub/send/send-delete.ts b/server/lib/activitypub/send/send-delete.ts
index 7a1d6f0ba..6c7fb8449 100644
--- a/server/lib/activitypub/send/send-delete.ts
+++ b/server/lib/activitypub/send/send-delete.ts
@@ -48,7 +48,10 @@ async function sendDeleteVideoComment (videoComment: VideoCommentModel, t: Trans
48 const isVideoOrigin = videoComment.Video.isOwned() 48 const isVideoOrigin = videoComment.Video.isOwned()
49 49
50 const url = getDeleteActivityPubUrl(videoComment.url) 50 const url = getDeleteActivityPubUrl(videoComment.url)
51 const byActor = videoComment.Account.Actor 51 const byActor = videoComment.isOwned()
52 ? videoComment.Account.Actor
53 : videoComment.Video.VideoChannel.Account.Actor
54
52 const threadParentComments = await VideoCommentModel.listThreadParentComments(videoComment, t) 55 const threadParentComments = await VideoCommentModel.listThreadParentComments(videoComment, t)
53 56
54 const actorsInvolvedInComment = await getActorsInvolvedInVideo(videoComment.Video, t) 57 const actorsInvolvedInComment = await getActorsInvolvedInVideo(videoComment.Video, t)
diff --git a/server/models/video/video-comment.ts b/server/models/video/video-comment.ts
index 6eda32f05..58b75510d 100644
--- a/server/models/video/video-comment.ts
+++ b/server/models/video/video-comment.ts
@@ -106,6 +106,10 @@ enum ScopeNames {
106 required: true, 106 required: true,
107 include: [ 107 include: [
108 { 108 {
109 model: ActorModel,
110 required: true
111 },
112 {
109 model: AccountModel, 113 model: AccountModel,
110 required: true, 114 required: true,
111 include: [ 115 include: [
@@ -208,41 +212,6 @@ export class VideoCommentModel extends Model<VideoCommentModel> {
208 }) 212 })
209 Account: AccountModel 213 Account: AccountModel
210 214
211 @BeforeDestroy
212 static async sendDeleteIfOwned (instance: VideoCommentModel, options) {
213 if (!instance.Account || !instance.Account.Actor) {
214 instance.Account = await instance.$get('Account', {
215 include: [ ActorModel ],
216 transaction: options.transaction
217 }) as AccountModel
218 }
219
220 if (!instance.Video) {
221 instance.Video = await instance.$get('Video', {
222 include: [
223 {
224 model: VideoChannelModel,
225 include: [
226 {
227 model: AccountModel,
228 include: [
229 {
230 model: ActorModel
231 }
232 ]
233 }
234 ]
235 }
236 ],
237 transaction: options.transaction
238 }) as VideoModel
239 }
240
241 if (instance.isOwned()) {
242 await sendDeleteVideoComment(instance, options.transaction)
243 }
244 }
245
246 static loadById (id: number, t?: Transaction) { 215 static loadById (id: number, t?: Transaction) {
247 const query: FindOptions = { 216 const query: FindOptions = {
248 where: { 217 where: {
@@ -269,7 +238,7 @@ export class VideoCommentModel extends Model<VideoCommentModel> {
269 .findOne(query) 238 .findOne(query)
270 } 239 }
271 240
272 static loadByUrlAndPopulateAccount (url: string, t?: Transaction) { 241 static loadByUrlAndPopulateAccountAndVideo (url: string, t?: Transaction) {
273 const query: FindOptions = { 242 const query: FindOptions = {
274 where: { 243 where: {
275 url 244 url
@@ -278,7 +247,7 @@ export class VideoCommentModel extends Model<VideoCommentModel> {
278 247
279 if (t !== undefined) query.transaction = t 248 if (t !== undefined) query.transaction = t
280 249
281 return VideoCommentModel.scope([ ScopeNames.WITH_ACCOUNT ]).findOne(query) 250 return VideoCommentModel.scope([ ScopeNames.WITH_ACCOUNT, ScopeNames.WITH_VIDEO ]).findOne(query)
282 } 251 }
283 252
284 static loadByUrlAndPopulateReplyAndVideoUrlAndAccount (url: string, t?: Transaction) { 253 static loadByUrlAndPopulateReplyAndVideoUrlAndAccount (url: string, t?: Transaction) {
diff --git a/server/tests/api/videos/multiple-servers.ts b/server/tests/api/videos/multiple-servers.ts
index e811ccd8e..651765776 100644
--- a/server/tests/api/videos/multiple-servers.ts
+++ b/server/tests/api/videos/multiple-servers.ts
@@ -500,20 +500,18 @@ describe('Test multiple servers', function () {
500 it('Should view multiple videos on owned servers', async function () { 500 it('Should view multiple videos on owned servers', async function () {
501 this.timeout(30000) 501 this.timeout(30000)
502 502
503 const tasks: Promise<any>[] = []
504 await viewVideo(servers[2].url, localVideosServer3[0])
505 await viewVideo(servers[2].url, localVideosServer3[0])
506 await viewVideo(servers[2].url, localVideosServer3[0]) 503 await viewVideo(servers[2].url, localVideosServer3[0])
507 await viewVideo(servers[2].url, localVideosServer3[1]) 504 await wait(1000)
508
509 await Promise.all(tasks)
510 await waitJobs(servers)
511 505
512 await viewVideo(servers[2].url, localVideosServer3[0]) 506 await viewVideo(servers[2].url, localVideosServer3[0])
507 await viewVideo(servers[2].url, localVideosServer3[1])
513 508
514 await waitJobs(servers) 509 await wait(1000)
515 510
516 await viewVideo(servers[2].url, localVideosServer3[0]) 511 await Promise.all([
512 viewVideo(servers[2].url, localVideosServer3[0]),
513 viewVideo(servers[2].url, localVideosServer3[0])
514 ])
517 515
518 await waitJobs(servers) 516 await waitJobs(servers)
519 517
@@ -894,14 +892,14 @@ describe('Test multiple servers', function () {
894 it('Should delete the thread comments', async function () { 892 it('Should delete the thread comments', async function () {
895 this.timeout(10000) 893 this.timeout(10000)
896 894
897 const res1 = await getVideoCommentThreads(servers[0].url, videoUUID, 0, 5) 895 const res = await getVideoCommentThreads(servers[ 0 ].url, videoUUID, 0, 5)
898 const threadId = res1.body.data.find(c => c.text === 'my super first comment').id 896 const threadId = res.body.data.find(c => c.text === 'my super first comment').id
899 await deleteVideoComment(servers[0].url, servers[0].accessToken, videoUUID, threadId) 897 await deleteVideoComment(servers[ 0 ].url, servers[ 0 ].accessToken, videoUUID, threadId)
900 898
901 await waitJobs(servers) 899 await waitJobs(servers)
902 }) 900 })
903 901
904 it('Should have the thread comments deleted on other servers too', async function () { 902 it('Should have the threads deleted on other servers too', async function () {
905 for (const server of servers) { 903 for (const server of servers) {
906 const res = await getVideoCommentThreads(server.url, videoUUID, 0, 5) 904 const res = await getVideoCommentThreads(server.url, videoUUID, 0, 5)
907 905
@@ -922,6 +920,23 @@ describe('Test multiple servers', function () {
922 } 920 }
923 }) 921 })
924 922
923 it('Should delete a remote thread by the origin server', async function () {
924 const res = await getVideoCommentThreads(servers[ 0 ].url, videoUUID, 0, 5)
925 const threadId = res.body.data.find(c => c.text === 'my super second comment').id
926 await deleteVideoComment(servers[ 0 ].url, servers[ 0 ].accessToken, videoUUID, threadId)
927
928 await waitJobs(servers)
929 })
930
931 it('Should have the threads deleted on other servers too', async function () {
932 for (const server of servers) {
933 const res = await getVideoCommentThreads(server.url, videoUUID, 0, 5)
934
935 expect(res.body.total).to.equal(0)
936 expect(res.body.data).to.have.lengthOf(0)
937 }
938 })
939
925 it('Should disable comments and download', async function () { 940 it('Should disable comments and download', async function () {
926 this.timeout(20000) 941 this.timeout(20000)
927 942