Handle reports from mastodon

This commit is contained in:
Chocobozzz 2019-08-30 09:40:21 +02:00
parent 4b1f1b810a
commit 0b5c385b45
No known key found for this signature in database
GPG Key ID: 583A612D890159BE
7 changed files with 70 additions and 35 deletions

View File

@ -27,7 +27,7 @@ function isActorPublicKeyValid (publicKey: string) {
validator.isLength(publicKey, CONSTRAINTS_FIELDS.ACTORS.PUBLIC_KEY)
}
const actorNameAlphabet = '[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\\-_.]'
const actorNameAlphabet = '[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\\-_.:]'
const actorNameRegExp = new RegExp(`^${actorNameAlphabet}+$`)
function isActorPreferredUsernameValid (preferredUsername: string) {
return exists(preferredUsername) && validator.matches(preferredUsername, actorNameRegExp)
@ -46,19 +46,20 @@ function isActorObjectValid (actor: any) {
return exists(actor) &&
isActivityPubUrlValid(actor.id) &&
isActorTypeValid(actor.type) &&
isActivityPubUrlValid(actor.following) &&
isActivityPubUrlValid(actor.followers) &&
isActivityPubUrlValid(actor.inbox) &&
isActivityPubUrlValid(actor.outbox) &&
isActorPreferredUsernameValid(actor.preferredUsername) &&
isActivityPubUrlValid(actor.url) &&
isActorPublicKeyObjectValid(actor.publicKey) &&
isActorEndpointsObjectValid(actor.endpoints) &&
setValidAttributedTo(actor) &&
// If this is not an account, it should be attributed to an account
(!actor.outbox || isActivityPubUrlValid(actor.outbox)) &&
(!actor.following || isActivityPubUrlValid(actor.following)) &&
(!actor.followers || isActivityPubUrlValid(actor.followers)) &&
setValidAttributedTo(actor) &&
// If this is a group (a channel), it should be attributed to an account
// In PeerTube we use this to attach a video channel to a specific account
(actor.type === 'Person' || actor.attributedTo.length !== 0)
(actor.type !== 'Group' || actor.attributedTo.length !== 0)
}
function isActorFollowingCountValid (value: string) {

View File

@ -14,7 +14,7 @@ import { CONFIG, registerConfigChangedHandler } from './config'
// ---------------------------------------------------------------------------
const LAST_MIGRATION_VERSION = 420
const LAST_MIGRATION_VERSION = 425
// ---------------------------------------------------------------------------

View File

@ -0,0 +1,26 @@
import * as Sequelize from 'sequelize'
async function up (utils: {
transaction: Sequelize.Transaction,
queryInterface: Sequelize.QueryInterface,
sequelize: Sequelize.Sequelize,
db: any
}): Promise<void> {
const data = {
type: Sequelize.STRING,
allowNull: true
}
await utils.queryInterface.changeColumn('actor', 'outboxUrl', data)
await utils.queryInterface.changeColumn('actor', 'followersUrl', data)
await utils.queryInterface.changeColumn('actor', 'followingUrl', data)
}
function down (options) {
throw new Error('Not implemented.')
}
export {
up,
down
}

View File

@ -26,28 +26,36 @@ export {
async function processCreateVideoAbuse (activity: ActivityCreate | ActivityFlag, byActor: MActorSignature) {
const flag = activity.type === 'Flag' ? activity : (activity.object as VideoAbuseObject)
logger.debug('Reporting remote abuse for video %s.', getAPId(flag.object))
const account = byActor.Account
if (!account) throw new Error('Cannot create video abuse with the non account actor ' + byActor.url)
const { video } = await getOrCreateVideoAndAccountAndChannel({ videoObject: flag.object })
const objects = Array.isArray(flag.object) ? flag.object : [ flag.object ]
const videoAbuse = await sequelizeTypescript.transaction(async t => {
const videoAbuseData = {
reporterAccountId: account.id,
reason: flag.content,
videoId: video.id,
state: VideoAbuseState.PENDING
for (const object of objects) {
try {
logger.debug('Reporting remote abuse for video %s.', getAPId(object))
const { video } = await getOrCreateVideoAndAccountAndChannel({ videoObject: object })
const videoAbuse = await sequelizeTypescript.transaction(async t => {
const videoAbuseData = {
reporterAccountId: account.id,
reason: flag.content,
videoId: video.id,
state: VideoAbuseState.PENDING
}
const videoAbuseInstance = await VideoAbuseModel.create(videoAbuseData, { transaction: t }) as MVideoAbuseVideo
videoAbuseInstance.Video = video
logger.info('Remote abuse for video uuid %s created', flag.object)
return videoAbuseInstance
})
Notifier.Instance.notifyOnNewVideoAbuse(videoAbuse)
} catch (err) {
logger.debug('Cannot process report of %s. (Maybe not a video abuse).', getAPId(object), { err })
}
const videoAbuseInstance = await VideoAbuseModel.create(videoAbuseData, { transaction: t }) as MVideoAbuseVideo
videoAbuseInstance.Video = video
logger.info('Remote abuse for video uuid %s created', flag.object)
return videoAbuseInstance
})
Notifier.Instance.notifyOnNewVideoAbuse(videoAbuse)
}
}

View File

@ -175,8 +175,8 @@ export class ActorModel extends Model<ActorModel> {
@Column(DataType.STRING(CONSTRAINTS_FIELDS.ACTORS.URL.max))
inboxUrl: string
@AllowNull(false)
@Is('ActorOutboxUrl', value => throwIfNotValid(value, isActivityPubUrlValid, 'outbox url'))
@AllowNull(true)
@Is('ActorOutboxUrl', value => throwIfNotValid(value, isActivityPubUrlValid, 'outbox url', true))
@Column(DataType.STRING(CONSTRAINTS_FIELDS.ACTORS.URL.max))
outboxUrl: string
@ -185,13 +185,13 @@ export class ActorModel extends Model<ActorModel> {
@Column(DataType.STRING(CONSTRAINTS_FIELDS.ACTORS.URL.max))
sharedInboxUrl: string
@AllowNull(false)
@Is('ActorFollowersUrl', value => throwIfNotValid(value, isActivityPubUrlValid, 'followers url'))
@AllowNull(true)
@Is('ActorFollowersUrl', value => throwIfNotValid(value, isActivityPubUrlValid, 'followers url', true))
@Column(DataType.STRING(CONSTRAINTS_FIELDS.ACTORS.URL.max))
followersUrl: string
@AllowNull(false)
@Is('ActorFollowingUrl', value => throwIfNotValid(value, isActivityPubUrlValid, 'following url'))
@AllowNull(true)
@Is('ActorFollowingUrl', value => throwIfNotValid(value, isActivityPubUrlValid, 'following url', true))
@Column(DataType.STRING(CONSTRAINTS_FIELDS.ACTORS.URL.max))
followingUrl: string

View File

@ -91,5 +91,5 @@ export interface ActivityDislike extends BaseActivity {
export interface ActivityFlag extends BaseActivity {
type: 'Flag',
content: string,
object: APObject
object: APObject | APObject[]
}

View File

@ -1,5 +1,5 @@
export interface VideoAbuseObject {
type: 'Flag',
content: string
object: string
object: string | string[]
}