Fix retrieving of deleted comments when subscribing to a new instance

pull/2302/head
Julien Maulny 2019-12-03 21:48:31 +01:00 committed by Chocobozzz
parent 69222afac8
commit b5206dfc45
5 changed files with 87 additions and 19 deletions

View File

@ -3,11 +3,28 @@ import { ACTIVITY_PUB } from '../../../initializers/constants'
import { exists, isArray, isDateValid } from '../misc'
import { isActivityPubUrlValid } from './misc'
function isTypeValid (comment: any): boolean {
if (comment.type === 'Note') return true
if (comment.type === 'Tombstone' && comment.formerType === 'Note') return true
return false
}
function sanitizeAndCheckVideoCommentObject (comment: any) {
if (!comment || comment.type !== 'Note') return false
if (!comment) return false
if (!isTypeValid(comment)) return false
normalizeComment(comment)
if (comment.type === 'Tombstone') {
return isActivityPubUrlValid(comment.id) &&
isDateValid(comment.published) &&
isDateValid(comment.deleted) &&
isActivityPubUrlValid(comment.url)
}
return isActivityPubUrlValid(comment.id) &&
isCommentContentValid(comment.content) &&
isActivityPubUrlValid(comment.inReplyTo) &&

View File

@ -131,9 +131,9 @@ async function resolveParentComment (params: ResolveThreadParams) {
}
const actorUrl = body.attributedTo
if (!actorUrl) throw new Error('Miss attributed to in comment')
if (!actorUrl && body.type !== 'Tombstone') throw new Error('Miss attributed to in comment')
if (checkUrlsSameHost(url, actorUrl) !== true) {
if (actorUrl && checkUrlsSameHost(url, actorUrl) !== true) {
throw new Error(`Actor url ${actorUrl} has not the same host than the comment url ${url}`)
}
@ -141,18 +141,19 @@ async function resolveParentComment (params: ResolveThreadParams) {
throw new Error(`Comment url ${url} host is different from the AP object id ${body.id}`)
}
const actor = await getOrCreateActorAndServerAndModel(actorUrl, 'all')
const actor = actorUrl ? await getOrCreateActorAndServerAndModel(actorUrl, 'all') : null
const comment = new VideoCommentModel({
url: body.id,
text: body.content,
text: body.content ? body.content : '',
videoId: null,
accountId: actor.Account.id,
accountId: actor ? actor.Account.id : null,
inReplyToCommentId: null,
originCommentId: null,
createdAt: new Date(body.published),
updatedAt: new Date(body.updated)
updatedAt: new Date(body.updated),
deletedAt: body.deleted ? new Date(body.deleted) : null
}) as MCommentOwner
comment.Account = actor.Account
comment.Account = actor ? actor.Account : null
return resolveThread({
url: body.inReplyTo,

View File

@ -507,17 +507,6 @@ export class VideoCommentModel extends Model<VideoCommentModel> {
}
toActivityPubObject (this: MCommentAP, threadParentComments: MCommentOwner[]): VideoCommentObject | ActivityTombstoneObject {
if (this.isDeleted()) {
return {
id: this.url,
type: 'Tombstone',
formerType: 'Note',
published: this.createdAt.toISOString(),
updated: this.updatedAt.toISOString(),
deleted: this.deletedAt.toISOString()
}
}
let inReplyTo: string
// New thread, so in AS we reply to the video
if (this.inReplyToCommentId === null) {
@ -526,8 +515,22 @@ export class VideoCommentModel extends Model<VideoCommentModel> {
inReplyTo = this.InReplyToVideoComment.url
}
if (this.isDeleted()) {
return {
id: this.url,
type: 'Tombstone',
formerType: 'Note',
inReplyTo,
published: this.createdAt.toISOString(),
updated: this.updatedAt.toISOString(),
deleted: this.deletedAt.toISOString()
}
}
const tag: ActivityTagObject[] = []
for (const parentComment of threadParentComments) {
if (!parentComment.Account) continue
const actor = parentComment.Account.Actor
tag.push({

View File

@ -15,6 +15,7 @@ import {
createUser,
dateIsValid,
doubleFollow,
flushAndRunServer,
flushAndRunMultipleServers,
getLocalVideos,
getVideo,
@ -938,7 +939,51 @@ describe('Test multiple servers', function () {
}
})
it('Should retrieve all comments when subscribing to a new server', async function () {
this.timeout(120000)
const newServer = await flushAndRunServer(4)
await setAccessTokensToServers([newServer])
await doubleFollow(newServer, servers[0])
await doubleFollow(newServer, servers[2])
await waitJobs([newServer, ...servers])
const res = await getVideoCommentThreads(newServer.url, videoUUID, 0, 5)
expect(res.body.total).to.equal(2)
expect(res.body.data).to.be.an('array')
expect(res.body.data).to.have.lengthOf(2)
{
const comment: VideoComment = res.body.data[0]
expect(comment).to.not.be.undefined
expect(comment.inReplyToCommentId).to.be.null
expect(comment.account.name).to.equal('root')
expect(comment.account.host).to.equal('localhost:' + servers[2].port)
expect(comment.totalReplies).to.equal(0)
expect(dateIsValid(comment.createdAt as string)).to.be.true
expect(dateIsValid(comment.updatedAt as string)).to.be.true
}
{
const deletedComment: VideoComment = res.body.data[1]
expect(deletedComment).to.not.be.undefined
expect(deletedComment.isDeleted).to.be.true
expect(deletedComment.deletedAt).to.not.be.null
expect(deletedComment.text).to.equal('')
expect(deletedComment.inReplyToCommentId).to.be.null
expect(deletedComment.account).to.be.null
expect(deletedComment.totalReplies).to.equal(3)
expect(dateIsValid(deletedComment.createdAt as string)).to.be.true
expect(dateIsValid(deletedComment.updatedAt as string)).to.be.true
expect(dateIsValid(deletedComment.deletedAt as string)).to.be.true
}
})
it('Should delete a remote thread by the origin server', async function () {
this.timeout(5000)
const res = await getVideoCommentThreads(servers[ 0 ].url, videoUUID, 0, 5)
const threadId = res.body.data.find(c => c.text === 'my super second comment').id
await deleteVideoComment(servers[ 0 ].url, servers[ 0 ].accessToken, videoUUID, threadId)

View File

@ -93,9 +93,11 @@ export interface ActivityPubAttributedTo {
export interface ActivityTombstoneObject {
'@context'?: any
id: string
url?: string
type: 'Tombstone'
name?: string
formerType?: string
inReplyTo?: string
published: string
updated: string
deleted: string