Skip to content

Commit

Permalink
correct VideoAbuseCreate
Browse files Browse the repository at this point in the history
  • Loading branch information
rigelk committed Jun 15, 2020
1 parent 6f595e1 commit 2774779
Show file tree
Hide file tree
Showing 14 changed files with 96 additions and 90 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -57,17 +57,17 @@
<span class="col-9 moderation-expanded-text" [innerHTML]="videoAbuse.reasonHtml"></span>
</div>

<div *ngIf="predefinedReasons" class="mt-2 d-flex">
<div *ngIf="predefinedReasons()" class="mt-2 d-flex">
<span class="col-3"></span>
<span class="col-9">
<a [routerLink]="[ '/admin/moderation/video-abuses/list' ]" [queryParams]="{ 'search': 'tag:' + reason.id }" class="chip bg-secondary text-light" *ngFor="let reason of predefinedReasons">
<a [routerLink]="[ '/admin/moderation/video-abuses/list' ]" [queryParams]="{ 'search': 'tag:' + reason.id }" class="chip bg-secondary text-light" *ngFor="let reason of predefinedReasons()">
<div>{{ reason.label }}</div>
</a>
</span>
</div>

<div *ngIf="videoAbuse.startAt" class="mt-2 d-flex">
<span class="col-3 moderation-expanded-label" i18n>Reported parts</span>
<span class="col-3 moderation-expanded-label" i18n>Reported part</span>
<span class="col-9">
{{ startAt }}<ng-container *ngIf="videoAbuse.endAt"> - {{ endAt }}</ng-container>
</span>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,6 @@ export class VideoAbuseDetailsComponent {
}
}

get predefinedReasons () {
if (!this.videoAbuse.predefinedReasons) return []
return this.videoAbuse.predefinedReasons.map(r => ({
id: r,
label: this.predefinedReasonsTranslations[r]
}))
}

get startAt () {
return durationToString(this.videoAbuse.startAt)
}
Expand All @@ -46,6 +38,14 @@ export class VideoAbuseDetailsComponent {
return durationToString(this.videoAbuse.endAt)
}

predefinedReasons () {
if (!this.videoAbuse.predefinedReasons) return []
return this.videoAbuse.predefinedReasons.map(r => ({
id: r,
label: this.predefinedReasonsTranslations[r]
}))
}

switchToDefaultAvatar ($event: Event) {
($event.target as HTMLImageElement).src = Actor.GET_DEFAULT_AVATAR_URL()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { ModerationCommentModalComponent } from './moderation-comment-modal.comp
import { Video } from '../../../shared/video/video.model'
import { MarkdownService } from '@app/shared/renderer'
import { Actor } from '@app/shared/actor/actor.model'
import { buildVideoEmbed } from 'src/assets/player/utils'
import { buildVideoEmbed, buildVideoLink } from 'src/assets/player/utils'
import { DomSanitizer } from '@angular/platform-browser'
import { BlocklistService } from '@app/shared/blocklist'
import { VideoService } from '@app/shared/video/video.service'
Expand Down Expand Up @@ -259,7 +259,15 @@ export class VideoAbuseListComponent extends RestTable implements OnInit, AfterV
}

getVideoEmbed (videoAbuse: VideoAbuse) {
return buildVideoEmbed(`${environment.embedUrl}/videos/embed/${videoAbuse.video.uuid}`)
return buildVideoEmbed(
buildVideoLink({
baseUrl: `${environment.embedUrl}/videos/embed/${videoAbuse.video.uuid}`,
title: false,
warningTitle: false,
startTime: videoAbuse.startAt,
stopTime: videoAbuse.endAt
})
)
}

switchToDefaultAvatar ($event: Event) {
Expand Down
1 change: 0 additions & 1 deletion client/src/app/shared/video-abuse/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
export * from './video-abuse.service'
export * from './video-abuse-predefined-reasons.model'

This file was deleted.

12 changes: 6 additions & 6 deletions client/src/app/shared/video-abuse/video-abuse.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ import { HttpClient, HttpParams } from '@angular/common/http'
import { Injectable } from '@angular/core'
import { SortMeta } from 'primeng/api'
import { Observable } from 'rxjs'
import { ResultList, VideoAbuse, VideoAbuseUpdate, VideoAbuseState } from '../../../../../shared'
import { ResultList, VideoAbuse, VideoAbuseCreate, VideoAbuseState, VideoAbuseUpdate } from '../../../../../shared'
import { environment } from '../../../environments/environment'
import { RestExtractor, RestPagination, RestService } from '../rest'
import { VideoAbusePredefinedReasons } from './video-abuse-predefined-reasons.model'
import { omit } from 'lodash-es'

@Injectable()
export class VideoAbuseService {
Expand Down Expand Up @@ -59,7 +59,8 @@ export class VideoAbuseService {
try {
const id = parseInt(v, 10)
return id
} catch {
} catch (e) {
console.error('Cannot parse predefinedReasonId in search.', e)
return undefined
}
}
Expand All @@ -75,11 +76,10 @@ export class VideoAbuseService {
)
}

reportVideo (parameters: { id: number, reason: string, predefinedReasons?: VideoAbusePredefinedReasons, timestamp: any }) {
reportVideo (parameters: { id: number } & VideoAbuseCreate) {
const url = VideoAbuseService.BASE_VIDEO_ABUSE_URL + parameters.id + '/abuse'

delete parameters.id
const body = { ...parameters }
const body = { ...omit(parameters, [ 'id' ]) }

return this.authHttp.post(url, body)
.pipe(
Expand Down
72 changes: 39 additions & 33 deletions client/src/app/shared/video/modals/video-report.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@ import { FormValidatorService } from '@app/shared/forms/form-validators/form-val
import { VideoAbuseValidatorsService } from '@app/shared/forms/form-validators/video-abuse-validators.service'
import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
import { NgbModalRef } from '@ng-bootstrap/ng-bootstrap/modal/modal-ref'
import { VideoAbuseService, VideoAbusePredefinedReasons, PredefinedReasons } from '@app/shared/video-abuse'
import { VideoAbuseService } from '@app/shared/video-abuse'
import { Video } from '@app/shared/video/video.model'
import { buildVideoEmbed } from 'src/assets/player/utils'
import { buildVideoEmbed, buildVideoLink } from 'src/assets/player/utils'
import { DomSanitizer, SafeHtml } from '@angular/platform-browser'
import { VideoAbusePredefinedReasonsIn } from '@shared/models/videos/abuse/video-abuse-reason.model'
import { mapValues, pickBy, keys } from 'lodash-es'

@Component({
selector: 'my-video-report',
Expand All @@ -22,7 +24,7 @@ export class VideoReportComponent extends FormReactive implements OnInit {
@ViewChild('modal', { static: true }) modal: NgbModal

error: string = null
predefinedReasons: { id: PredefinedReasons, label: string, description?: string, help?: string }[] = []
predefinedReasons: { id: keyof VideoAbusePredefinedReasonsIn, label: string, description?: string, help?: string }[] = []
embedHtml: SafeHtml

private openedModal: NgbModalRef
Expand Down Expand Up @@ -57,25 +59,20 @@ export class VideoReportComponent extends FormReactive implements OnInit {

getVideoEmbed () {
return this.sanitizer.bypassSecurityTrustHtml(
buildVideoEmbed(this.video.embedUrl)
buildVideoEmbed(
buildVideoLink({
baseUrl: this.video.embedUrl,
title: false,
warningTitle: false
})
)
)
}

ngOnInit () {
const predefinedReasons: Required<VideoAbusePredefinedReasons> = {
violentOrRepulsive: null,
hatefulOrAbusive: null,
spamOrMisleading: null,
privacy: null,
rights: null,
serverRules: null,
captions: null,
thumbnails: null
}

this.buildForm({
reason: this.videoAbuseValidatorsService.VIDEO_ABUSE_REASON,
predefinedReasons: predefinedReasons as {[key: string]: null},
predefinedReasons: mapValues(VideoAbusePredefinedReasonsIn, r => null),
timestamp: {
hasStart: null,
startAt: null,
Expand All @@ -86,42 +83,42 @@ export class VideoReportComponent extends FormReactive implements OnInit {

this.predefinedReasons = [
{
id: PredefinedReasons.violentOrRepulsive,
id: 'violentOrRepulsive',
label: this.i18n('Violent or repulsive'),
help: this.i18n('Contains offensive, violent, or coarse language or iconography.')
},
{
id: PredefinedReasons.hatefulOrAbusive,
id: 'hatefulOrAbusive',
label: this.i18n('Hateful or abusive'),
help: this.i18n('Contains abusive, racist or sexist language or iconography.')
},
{
id: PredefinedReasons.spamOrMisleading,
id: 'spamOrMisleading',
label: this.i18n('Spam, ad or false news'),
help: this.i18n('Contains marketing, spam, purposefully deceitful news, or otherwise misleading thumbnail/text/tags. Please provide reputable sources to report hoaxes.')
},
{
id: PredefinedReasons.privacy,
id: 'privacy',
label: this.i18n('Privacy breach or doxxing'),
help: this.i18n('Contains personal information that could be used to track, identify, contact or impersonate someone (e.g. name, address, phone number, email, or credit card details).')
},
{
id: PredefinedReasons.rights,
id: 'rights',
label: this.i18n('Intellectual property violation'),
help: this.i18n('Infringes my intellectual property or copyright, wrt. the regional rules with which the server must comply.')
},
{
id: PredefinedReasons.serverRules,
id: 'serverRules',
label: this.i18n('Breaks server rules'),
description: this.i18n('Anything not included in the above that breaks the terms of service, code of conduct, or general rules in place on the server.')
},
{
id: PredefinedReasons.thumbnails,
id: 'thumbnails',
label: this.i18n('Thumbnails'),
help: this.i18n('The above can only be seen in thumbnails.')
},
{
id: PredefinedReasons.captions,
id: 'captions',
label: this.i18n('Captions'),
help: this.i18n('The above can only be seen in captions (please describe which).')
}
Expand All @@ -140,15 +137,24 @@ export class VideoReportComponent extends FormReactive implements OnInit {
}

report () {
this.videoAbuseService.reportVideo({ id: this.video.id, ...this.form.value })
.subscribe(
() => {
this.notifier.success(this.i18n('Video reported.'))
this.hide()
},

err => this.notifier.error(err.message)
)
const reason = this.form.get('reason').value
const predefinedReasons = pickBy(this.form.get('predefinedReasons').value)
const { hasStart, startAt, hasEnd, endAt } = this.form.get('timestamp').value

this.videoAbuseService.reportVideo({
id: this.video.id,
reason,
predefinedReasons,
startAt: hasStart && startAt ? startAt : undefined,
endAt: hasEnd && endAt ? endAt : undefined
}).subscribe(
() => {
this.notifier.success(this.i18n('Video reported.'))
this.hide()
},

err => this.notifier.error(err.message)
)
}

isRemoteVideo () {
Expand Down
7 changes: 2 additions & 5 deletions server/controllers/api/videos/abuse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -127,18 +127,15 @@ async function reportVideoAbuse (req: express.Request, res: express.Response) {
const videoAbuseInstance = await sequelizeTypescript.transaction(async t => {
reporterAccount = await AccountModel.load(res.locals.oauth.token.User.Account.id, t)
const predefinedReasons = keys(pickBy(body.predefinedReasons)).map(r => VideoAbusePredefinedReasonsIn[r])
const timestamp = body.timestamp
const startAt = timestamp['hasStart'] && timestamp['startAt'] ? timestamp['startAt'] : undefined
const endAt = timestamp['hasEnd'] && timestamp['endAt'] ? timestamp['endAt'] : undefined

const abuseToCreate = {
reporterAccountId: reporterAccount.id,
reason: body.reason,
videoId: videoInstance.id,
state: VideoAbuseState.PENDING,
predefinedReasons,
startAt,
endAt
startAt: body.startAt,
endAt: body.endAt
}

const videoAbuseInstance: MVideoAbuseAccountVideo = await VideoAbuseModel.create(abuseToCreate, { transaction: t })
Expand Down
5 changes: 0 additions & 5 deletions server/helpers/custom-validators/video-abuses.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,6 @@ function isVideoAbusePredefinedReasonsValid (value: {}) {
return exists(value)
}

function isVideoAbuseTimestampValid (value: {}) {
return exists(value)
}

function isVideoAbuseModerationCommentValid (value: string) {
return exists(value) && validator.isLength(value, VIDEO_ABUSES_CONSTRAINTS_FIELDS.MODERATION_COMMENT)
}
Expand All @@ -38,7 +34,6 @@ function isAbuseVideoIsValid (value: VideoAbuseVideoIs) {
export {
isVideoAbuseReasonValid,
isVideoAbusePredefinedReasonsValid,
isVideoAbuseTimestampValid,
isVideoAbuseModerationCommentValid,
isVideoAbuseStateValid,
isAbuseVideoIsValid
Expand Down
4 changes: 2 additions & 2 deletions server/lib/activitypub/process/process-flag.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,9 @@ async function processCreateVideoAbuse (activity: ActivityCreate | ActivityFlag,

const { video } = await getOrCreateVideoAndAccountAndChannel({ videoObject: object })
const reporterAccount = await sequelizeTypescript.transaction(async t => AccountModel.load(account.id, t))
const predefinedReasons = flag.tag?.map(tag => parseInt(tag.name, 10)) || []
const predefinedReasons = flag.tag?.map(tag => parseInt(tag.name, 10)).filter(v => !isNaN(v)) || []
const startAt = flag.startAt
const endAt = flag.startAt
const endAt = flag.endAt

const videoAbuseInstance = await sequelizeTypescript.transaction(async t => {
const videoAbuseData = {
Expand Down
12 changes: 8 additions & 4 deletions server/middlewares/validators/videos/video-abuses.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as express from 'express'
import { body, param, query } from 'express-validator'
import { exists, isIdOrUUIDValid, isIdValid } from '../../../helpers/custom-validators/misc'
import { exists, isIdOrUUIDValid, isIdValid, toIntOrNull } from '../../../helpers/custom-validators/misc'
import {
isAbuseVideoIsValid,
isVideoAbuseModerationCommentValid,
Expand All @@ -26,10 +26,14 @@ const videoAbuseReportValidator = [
.optional()
.custom(isVideoAbusePredefinedReasonsValid)
.withMessage('Should have a valid list of predefined reasons'),
body('timestamp')
body('startAt')
.optional()
.custom(isVideoAbuseTimestampValid)
.withMessage('Should have valid timestamp definition'),
.custom(toIntOrNull)
.withMessage('Should have valid starting time value'),
body('endAt')
.optional()
.custom(toIntOrNull)
.withMessage('Should have valid ending time value'),

async (req: express.Request, res: express.Response, next: express.NextFunction) => {
logger.debug('Checking videoAbuseReport parameters', { parameters: req.body })
Expand Down
7 changes: 3 additions & 4 deletions shared/models/activitypub/objects/common-objects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,20 +70,19 @@ export type ActivityHtmlUrlObject = {
}

export interface ActivityHashTagObject {
type: 'Hashtag' | 'Mention'
type: 'Hashtag'
href?: string
name: string
}

export interface ActivityMentionObject {
type: 'Hashtag' | 'Mention'
type: 'Mention'
href?: string
name: string
}

export interface ActivityFlagReasonObject {
type: 'Hashtag' | 'Mention'
href?: string
type: 'Hashtag'
name: string
}

Expand Down
5 changes: 3 additions & 2 deletions shared/models/videos/abuse/video-abuse-create.model.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
export interface VideoAbuseCreate {
reason: string
predefinedReasons: any
timestamp: any
predefinedReasons?: {[key: string]: boolean} // see VideoAbusePredefinedReasonsIn
startAt?: number
endAt?: number
}
Loading

0 comments on commit 2774779

Please sign in to comment.