mirror of
https://github.com/Chocobozzz/PeerTube.git
synced 2025-10-05 02:39:33 +02:00
Migrate server to ESM
Sorry for the very big commit that may lead to git log issues and merge conflicts, but it's a major step forward: * Server can be faster at startup because imports() are async and we can easily lazy import big modules * Angular doesn't seem to support ES import (with .js extension), so we had to correctly organize peertube into a monorepo: * Use yarn workspace feature * Use typescript reference projects for dependencies * Shared projects have been moved into "packages", each one is now a node module (with a dedicated package.json/tsconfig.json) * server/tools have been moved into apps/ and is now a dedicated app bundled and published on NPM so users don't have to build peertube cli tools manually * server/tests have been moved into packages/ so we don't compile them every time we want to run the server * Use isolatedModule option: * Had to move from const enum to const (https://www.typescriptlang.org/docs/handbook/enums.html#objects-vs-enums) * Had to explictely specify "type" imports when used in decorators * Prefer tsx (that uses esbuild under the hood) instead of ts-node to load typescript files (tests with mocha or scripts): * To reduce test complexity as esbuild doesn't support decorator metadata, we only test server files that do not import server models * We still build tests files into js files for a faster CI * Remove unmaintained peertube CLI import script * Removed some barrels to speed up execution (less imports)
This commit is contained in:
parent
04d1da5621
commit
3a4992633e
2196 changed files with 12690 additions and 11574 deletions
257
server/server/lib/moderation.ts
Normal file
257
server/server/lib/moderation.ts
Normal file
|
@ -0,0 +1,257 @@
|
|||
import express, { VideoUploadFile } from 'express'
|
||||
import { PathLike } from 'fs-extra/esm'
|
||||
import { Transaction } from 'sequelize'
|
||||
import { AbuseAuditView, auditLoggerFactory } from '@server/helpers/audit-logger.js'
|
||||
import { afterCommitIfTransaction } from '@server/helpers/database-utils.js'
|
||||
import { logger } from '@server/helpers/logger.js'
|
||||
import { AbuseModel } from '@server/models/abuse/abuse.js'
|
||||
import { VideoAbuseModel } from '@server/models/abuse/video-abuse.js'
|
||||
import { VideoCommentAbuseModel } from '@server/models/abuse/video-comment-abuse.js'
|
||||
import { VideoFileModel } from '@server/models/video/video-file.js'
|
||||
import { FilteredModelAttributes } from '@server/types/index.js'
|
||||
import {
|
||||
MAbuseFull,
|
||||
MAccountDefault,
|
||||
MAccountLight,
|
||||
MComment,
|
||||
MCommentAbuseAccountVideo,
|
||||
MCommentOwnerVideo,
|
||||
MUser,
|
||||
MVideoAbuseVideoFull,
|
||||
MVideoAccountLightBlacklistAllFiles
|
||||
} from '@server/types/models/index.js'
|
||||
import { LiveVideoCreate, VideoCommentCreate, VideoCreate, VideoImportCreate } from '@peertube/peertube-models'
|
||||
import { UserModel } from '../models/user/user.js'
|
||||
import { VideoCommentModel } from '../models/video/video-comment.js'
|
||||
import { VideoModel } from '../models/video/video.js'
|
||||
import { sendAbuse } from './activitypub/send/send-flag.js'
|
||||
import { Notifier } from './notifier/index.js'
|
||||
|
||||
export type AcceptResult = {
|
||||
accepted: boolean
|
||||
errorMessage?: string
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
// Stub function that can be filtered by plugins
|
||||
function isLocalVideoFileAccepted (object: {
|
||||
videoBody: VideoCreate
|
||||
videoFile: VideoUploadFile
|
||||
user: UserModel
|
||||
}): AcceptResult {
|
||||
return { accepted: true }
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
// Stub function that can be filtered by plugins
|
||||
function isLocalLiveVideoAccepted (object: {
|
||||
liveVideoBody: LiveVideoCreate
|
||||
user: UserModel
|
||||
}): AcceptResult {
|
||||
return { accepted: true }
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
// Stub function that can be filtered by plugins
|
||||
function isLocalVideoThreadAccepted (_object: {
|
||||
req: express.Request
|
||||
commentBody: VideoCommentCreate
|
||||
video: VideoModel
|
||||
user: UserModel
|
||||
}): AcceptResult {
|
||||
return { accepted: true }
|
||||
}
|
||||
|
||||
// Stub function that can be filtered by plugins
|
||||
function isLocalVideoCommentReplyAccepted (_object: {
|
||||
req: express.Request
|
||||
commentBody: VideoCommentCreate
|
||||
parentComment: VideoCommentModel
|
||||
video: VideoModel
|
||||
user: UserModel
|
||||
}): AcceptResult {
|
||||
return { accepted: true }
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
// Stub function that can be filtered by plugins
|
||||
function isRemoteVideoCommentAccepted (_object: {
|
||||
comment: MComment
|
||||
}): AcceptResult {
|
||||
return { accepted: true }
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
// Stub function that can be filtered by plugins
|
||||
function isPreImportVideoAccepted (object: {
|
||||
videoImportBody: VideoImportCreate
|
||||
user: MUser
|
||||
}): AcceptResult {
|
||||
return { accepted: true }
|
||||
}
|
||||
|
||||
// Stub function that can be filtered by plugins
|
||||
function isPostImportVideoAccepted (object: {
|
||||
videoFilePath: PathLike
|
||||
videoFile: VideoFileModel
|
||||
user: MUser
|
||||
}): AcceptResult {
|
||||
return { accepted: true }
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
async function createVideoAbuse (options: {
|
||||
baseAbuse: FilteredModelAttributes<AbuseModel>
|
||||
videoInstance: MVideoAccountLightBlacklistAllFiles
|
||||
startAt: number
|
||||
endAt: number
|
||||
transaction: Transaction
|
||||
reporterAccount: MAccountDefault
|
||||
skipNotification: boolean
|
||||
}) {
|
||||
const { baseAbuse, videoInstance, startAt, endAt, transaction, reporterAccount, skipNotification } = options
|
||||
|
||||
const associateFun = async (abuseInstance: MAbuseFull) => {
|
||||
const videoAbuseInstance: MVideoAbuseVideoFull = await VideoAbuseModel.create({
|
||||
abuseId: abuseInstance.id,
|
||||
videoId: videoInstance.id,
|
||||
startAt,
|
||||
endAt
|
||||
}, { transaction })
|
||||
|
||||
videoAbuseInstance.Video = videoInstance
|
||||
abuseInstance.VideoAbuse = videoAbuseInstance
|
||||
|
||||
return { isOwned: videoInstance.isOwned() }
|
||||
}
|
||||
|
||||
return createAbuse({
|
||||
base: baseAbuse,
|
||||
reporterAccount,
|
||||
flaggedAccount: videoInstance.VideoChannel.Account,
|
||||
transaction,
|
||||
skipNotification,
|
||||
associateFun
|
||||
})
|
||||
}
|
||||
|
||||
function createVideoCommentAbuse (options: {
|
||||
baseAbuse: FilteredModelAttributes<AbuseModel>
|
||||
commentInstance: MCommentOwnerVideo
|
||||
transaction: Transaction
|
||||
reporterAccount: MAccountDefault
|
||||
skipNotification: boolean
|
||||
}) {
|
||||
const { baseAbuse, commentInstance, transaction, reporterAccount, skipNotification } = options
|
||||
|
||||
const associateFun = async (abuseInstance: MAbuseFull) => {
|
||||
const commentAbuseInstance: MCommentAbuseAccountVideo = await VideoCommentAbuseModel.create({
|
||||
abuseId: abuseInstance.id,
|
||||
videoCommentId: commentInstance.id
|
||||
}, { transaction })
|
||||
|
||||
commentAbuseInstance.VideoComment = commentInstance
|
||||
abuseInstance.VideoCommentAbuse = commentAbuseInstance
|
||||
|
||||
return { isOwned: commentInstance.isOwned() }
|
||||
}
|
||||
|
||||
return createAbuse({
|
||||
base: baseAbuse,
|
||||
reporterAccount,
|
||||
flaggedAccount: commentInstance.Account,
|
||||
transaction,
|
||||
skipNotification,
|
||||
associateFun
|
||||
})
|
||||
}
|
||||
|
||||
function createAccountAbuse (options: {
|
||||
baseAbuse: FilteredModelAttributes<AbuseModel>
|
||||
accountInstance: MAccountDefault
|
||||
transaction: Transaction
|
||||
reporterAccount: MAccountDefault
|
||||
skipNotification: boolean
|
||||
}) {
|
||||
const { baseAbuse, accountInstance, transaction, reporterAccount, skipNotification } = options
|
||||
|
||||
const associateFun = () => {
|
||||
return Promise.resolve({ isOwned: accountInstance.isOwned() })
|
||||
}
|
||||
|
||||
return createAbuse({
|
||||
base: baseAbuse,
|
||||
reporterAccount,
|
||||
flaggedAccount: accountInstance,
|
||||
transaction,
|
||||
skipNotification,
|
||||
associateFun
|
||||
})
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
export {
|
||||
isLocalLiveVideoAccepted,
|
||||
|
||||
isLocalVideoFileAccepted,
|
||||
isLocalVideoThreadAccepted,
|
||||
isRemoteVideoCommentAccepted,
|
||||
isLocalVideoCommentReplyAccepted,
|
||||
isPreImportVideoAccepted,
|
||||
isPostImportVideoAccepted,
|
||||
|
||||
createAbuse,
|
||||
createVideoAbuse,
|
||||
createVideoCommentAbuse,
|
||||
createAccountAbuse
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
async function createAbuse (options: {
|
||||
base: FilteredModelAttributes<AbuseModel>
|
||||
reporterAccount: MAccountDefault
|
||||
flaggedAccount: MAccountLight
|
||||
associateFun: (abuseInstance: MAbuseFull) => Promise<{ isOwned: boolean }>
|
||||
skipNotification: boolean
|
||||
transaction: Transaction
|
||||
}) {
|
||||
const { base, reporterAccount, flaggedAccount, associateFun, transaction, skipNotification } = options
|
||||
const auditLogger = auditLoggerFactory('abuse')
|
||||
|
||||
const abuseAttributes = Object.assign({}, base, { flaggedAccountId: flaggedAccount.id })
|
||||
const abuseInstance: MAbuseFull = await AbuseModel.create(abuseAttributes, { transaction })
|
||||
|
||||
abuseInstance.ReporterAccount = reporterAccount
|
||||
abuseInstance.FlaggedAccount = flaggedAccount
|
||||
|
||||
const { isOwned } = await associateFun(abuseInstance)
|
||||
|
||||
if (isOwned === false) {
|
||||
sendAbuse(reporterAccount.Actor, abuseInstance, abuseInstance.FlaggedAccount, transaction)
|
||||
}
|
||||
|
||||
const abuseJSON = abuseInstance.toFormattedAdminJSON()
|
||||
auditLogger.create(reporterAccount.Actor.getIdentifier(), new AbuseAuditView(abuseJSON))
|
||||
|
||||
if (!skipNotification) {
|
||||
afterCommitIfTransaction(transaction, () => {
|
||||
Notifier.Instance.notifyOnNewAbuse({
|
||||
abuse: abuseJSON,
|
||||
abuseInstance,
|
||||
reporter: reporterAccount.Actor.getIdentifier()
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
logger.info('Abuse report %d created.', abuseInstance.id)
|
||||
|
||||
return abuseJSON
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue