From 10363c74c1d869f0e0c7bc4d0367b1f34d1bb6a4 Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Thu, 3 Jun 2021 17:33:44 +0200 Subject: Move middleware utils in middlewares helpers modules should not import models --- server/controllers/api/search.ts | 3 +- server/helpers/actor.ts | 16 --- server/helpers/custom-validators/video-comments.ts | 72 +----------- server/helpers/custom-validators/video-imports.ts | 19 ---- .../helpers/custom-validators/video-ownership.ts | 25 +---- server/helpers/middlewares/abuses.ts | 25 ----- server/helpers/middlewares/accounts.ts | 65 ----------- server/helpers/middlewares/index.ts | 7 -- server/helpers/middlewares/video-blacklists.ts | 24 ---- server/helpers/middlewares/video-captions.ts | 25 ----- server/helpers/middlewares/video-channels.ts | 43 ------- server/helpers/middlewares/video-playlists.ts | 39 ------- server/helpers/middlewares/videos.ts | 125 --------------------- server/helpers/signup.ts | 62 ---------- server/helpers/video.ts | 65 +---------- server/helpers/webfinger.ts | 67 ----------- server/lib/activitypub/actors/get.ts | 2 +- server/lib/activitypub/actors/index.ts | 1 + server/lib/activitypub/actors/refresh.ts | 4 +- server/lib/activitypub/actors/shared/index.ts | 2 +- server/lib/activitypub/actors/webfinger.ts | 67 +++++++++++ server/lib/activitypub/videos/get.ts | 2 +- server/lib/activitypub/videos/refresh.ts | 2 +- .../lib/job-queue/handlers/activitypub-follow.ts | 3 +- .../job-queue/handlers/activitypub-refresher.ts | 2 +- server/lib/model-loaders/actor.ts | 16 +++ server/lib/model-loaders/index.ts | 2 + server/lib/model-loaders/video.ts | 64 +++++++++++ server/lib/server-config-manager.ts | 2 +- server/lib/signup.ts | 62 ++++++++++ server/middlewares/activitypub.ts | 9 +- server/middlewares/validators/abuse.ts | 4 +- server/middlewares/validators/account.ts | 3 +- .../validators/activitypub/pagination.ts | 4 +- .../validators/activitypub/signature.ts | 5 +- server/middlewares/validators/actor-image.ts | 2 +- server/middlewares/validators/blocklist.ts | 15 ++- server/middlewares/validators/bulk.ts | 5 +- server/middlewares/validators/config.ts | 2 +- server/middlewares/validators/feeds.ts | 10 +- server/middlewares/validators/follows.ts | 4 +- server/middlewares/validators/jobs.ts | 2 +- server/middlewares/validators/logs.ts | 6 +- server/middlewares/validators/oembed.ts | 4 +- server/middlewares/validators/pagination.ts | 4 +- server/middlewares/validators/plugins.ts | 2 +- server/middlewares/validators/redundancy.ts | 9 +- server/middlewares/validators/search.ts | 6 +- server/middlewares/validators/server.ts | 12 +- server/middlewares/validators/shared/abuses.ts | 25 +++++ server/middlewares/validators/shared/accounts.ts | 65 +++++++++++ server/middlewares/validators/shared/index.ts | 11 ++ server/middlewares/validators/shared/utils.ts | 50 +++++++++ .../validators/shared/video-blacklists.ts | 24 ++++ .../validators/shared/video-captions.ts | 25 +++++ .../validators/shared/video-channels.ts | 43 +++++++ .../validators/shared/video-comments.ts | 73 ++++++++++++ .../middlewares/validators/shared/video-imports.ts | 22 ++++ .../validators/shared/video-ownerships.ts | 24 ++++ .../validators/shared/video-playlists.ts | 39 +++++++ server/middlewares/validators/shared/videos.ts | 125 +++++++++++++++++++++ server/middlewares/validators/sort.ts | 2 +- server/middlewares/validators/themes.ts | 8 +- server/middlewares/validators/user-history.ts | 4 +- .../middlewares/validators/user-notifications.ts | 6 +- .../middlewares/validators/user-subscriptions.ts | 2 +- server/middlewares/validators/users.ts | 7 +- server/middlewares/validators/utils.ts | 50 --------- .../validators/videos/video-blacklist.ts | 5 +- .../validators/videos/video-captions.ts | 9 +- .../validators/videos/video-channels.ts | 3 +- .../validators/videos/video-comments.ts | 11 +- .../middlewares/validators/videos/video-imports.ts | 5 +- server/middlewares/validators/videos/video-live.ts | 13 +-- .../validators/videos/video-playlists.ts | 3 +- .../middlewares/validators/videos/video-rates.ts | 9 +- .../middlewares/validators/videos/video-shares.ts | 5 +- .../middlewares/validators/videos/video-watch.ts | 7 +- server/middlewares/validators/videos/videos.ts | 17 +-- server/middlewares/validators/webfinger.ts | 2 +- 80 files changed, 859 insertions(+), 856 deletions(-) delete mode 100644 server/helpers/actor.ts delete mode 100644 server/helpers/middlewares/abuses.ts delete mode 100644 server/helpers/middlewares/accounts.ts delete mode 100644 server/helpers/middlewares/index.ts delete mode 100644 server/helpers/middlewares/video-blacklists.ts delete mode 100644 server/helpers/middlewares/video-captions.ts delete mode 100644 server/helpers/middlewares/video-channels.ts delete mode 100644 server/helpers/middlewares/video-playlists.ts delete mode 100644 server/helpers/middlewares/videos.ts delete mode 100644 server/helpers/signup.ts delete mode 100644 server/helpers/webfinger.ts create mode 100644 server/lib/activitypub/actors/webfinger.ts create mode 100644 server/lib/model-loaders/actor.ts create mode 100644 server/lib/model-loaders/index.ts create mode 100644 server/lib/model-loaders/video.ts create mode 100644 server/lib/signup.ts create mode 100644 server/middlewares/validators/shared/abuses.ts create mode 100644 server/middlewares/validators/shared/accounts.ts create mode 100644 server/middlewares/validators/shared/index.ts create mode 100644 server/middlewares/validators/shared/utils.ts create mode 100644 server/middlewares/validators/shared/video-blacklists.ts create mode 100644 server/middlewares/validators/shared/video-captions.ts create mode 100644 server/middlewares/validators/shared/video-channels.ts create mode 100644 server/middlewares/validators/shared/video-comments.ts create mode 100644 server/middlewares/validators/shared/video-imports.ts create mode 100644 server/middlewares/validators/shared/video-ownerships.ts create mode 100644 server/middlewares/validators/shared/video-playlists.ts create mode 100644 server/middlewares/validators/shared/videos.ts delete mode 100644 server/middlewares/validators/utils.ts diff --git a/server/controllers/api/search.ts b/server/controllers/api/search.ts index ef0f4285d..a3b66b2a6 100644 --- a/server/controllers/api/search.ts +++ b/server/controllers/api/search.ts @@ -14,8 +14,7 @@ import { VideoChannelsSearchQuery, VideosSearchQuery } from '../../../shared/mod import { buildNSFWFilter, isUserAbleToSearchRemoteURI } from '../../helpers/express-utils' import { logger } from '../../helpers/logger' import { getFormattedObjects } from '../../helpers/utils' -import { loadActorUrlOrGetFromWebfinger } from '../../helpers/webfinger' -import { getOrCreateAPActor } from '../../lib/activitypub/actors' +import { getOrCreateAPActor, loadActorUrlOrGetFromWebfinger } from '../../lib/activitypub/actors' import { asyncMiddleware, commonVideosFiltersValidator, diff --git a/server/helpers/actor.ts b/server/helpers/actor.ts deleted file mode 100644 index 5f742505b..000000000 --- a/server/helpers/actor.ts +++ /dev/null @@ -1,16 +0,0 @@ - -import { ActorModel } from '../models/actor/actor' -import { MActorAccountChannelId, MActorFull } from '../types/models' - -type ActorFetchByUrlType = 'all' | 'association-ids' - -function fetchActorByUrl (url: string, fetchType: ActorFetchByUrlType): Promise { - if (fetchType === 'all') return ActorModel.loadByUrlAndPopulateAccountAndChannel(url) - - if (fetchType === 'association-ids') return ActorModel.loadByUrl(url) -} - -export { - ActorFetchByUrlType, - fetchActorByUrl -} diff --git a/server/helpers/custom-validators/video-comments.ts b/server/helpers/custom-validators/video-comments.ts index 5c88447ad..94bdf237a 100644 --- a/server/helpers/custom-validators/video-comments.ts +++ b/server/helpers/custom-validators/video-comments.ts @@ -1,9 +1,5 @@ -import * as express from 'express' import validator from 'validator' -import { VideoCommentModel } from '@server/models/video/video-comment' import { CONSTRAINTS_FIELDS } from '../../initializers/constants' -import { MVideoId } from '@server/types/models' -import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes' const VIDEO_COMMENTS_CONSTRAINTS_FIELDS = CONSTRAINTS_FIELDS.VIDEO_COMMENTS @@ -11,74 +7,8 @@ function isValidVideoCommentText (value: string) { return value === null || validator.isLength(value, VIDEO_COMMENTS_CONSTRAINTS_FIELDS.TEXT) } -async function doesVideoCommentThreadExist (idArg: number | string, video: MVideoId, res: express.Response) { - const id = parseInt(idArg + '', 10) - const videoComment = await VideoCommentModel.loadById(id) - - if (!videoComment) { - res.fail({ - status: HttpStatusCode.NOT_FOUND_404, - message: 'Video comment thread not found' - }) - return false - } - - if (videoComment.videoId !== video.id) { - res.fail({ message: 'Video comment is not associated to this video.' }) - return false - } - - if (videoComment.inReplyToCommentId !== null) { - res.fail({ message: 'Video comment is not a thread.' }) - return false - } - - res.locals.videoCommentThread = videoComment - return true -} - -async function doesVideoCommentExist (idArg: number | string, video: MVideoId, res: express.Response) { - const id = parseInt(idArg + '', 10) - const videoComment = await VideoCommentModel.loadByIdAndPopulateVideoAndAccountAndReply(id) - - if (!videoComment) { - res.fail({ - status: HttpStatusCode.NOT_FOUND_404, - message: 'Video comment thread not found' - }) - return false - } - - if (videoComment.videoId !== video.id) { - res.fail({ message: 'Video comment is not associated to this video.' }) - return false - } - - res.locals.videoCommentFull = videoComment - return true -} - -async function doesCommentIdExist (idArg: number | string, res: express.Response) { - const id = parseInt(idArg + '', 10) - const videoComment = await VideoCommentModel.loadByIdAndPopulateVideoAndAccountAndReply(id) - - if (!videoComment) { - res.fail({ - status: HttpStatusCode.NOT_FOUND_404, - message: 'Video comment thread not found' - }) - return false - } - - res.locals.videoCommentFull = videoComment - return true -} - // --------------------------------------------------------------------------- export { - isValidVideoCommentText, - doesVideoCommentThreadExist, - doesVideoCommentExist, - doesCommentIdExist + isValidVideoCommentText } diff --git a/server/helpers/custom-validators/video-imports.ts b/server/helpers/custom-validators/video-imports.ts index 3ad7a4648..dbf6a3504 100644 --- a/server/helpers/custom-validators/video-imports.ts +++ b/server/helpers/custom-validators/video-imports.ts @@ -2,9 +2,6 @@ import 'multer' import validator from 'validator' import { CONSTRAINTS_FIELDS, MIMETYPES, VIDEO_IMPORT_STATES } from '../../initializers/constants' import { exists, isFileValid } from './misc' -import * as express from 'express' -import { VideoImportModel } from '../../models/video/video-import' -import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes' function isVideoImportTargetUrlValid (url: string) { const isURLOptions = { @@ -32,26 +29,10 @@ function isVideoImportTorrentFile (files: { [ fieldname: string ]: Express.Multe return isFileValid(files, videoTorrentImportRegex, 'torrentfile', CONSTRAINTS_FIELDS.VIDEO_IMPORTS.TORRENT_FILE.FILE_SIZE.max, true) } -async function doesVideoImportExist (id: number, res: express.Response) { - const videoImport = await VideoImportModel.loadAndPopulateVideo(id) - - if (!videoImport) { - res.fail({ - status: HttpStatusCode.NOT_FOUND_404, - message: 'Video import not found' - }) - return false - } - - res.locals.videoImport = videoImport - return true -} - // --------------------------------------------------------------------------- export { isVideoImportStateValid, isVideoImportTargetUrlValid, - doesVideoImportExist, isVideoImportTorrentFile } diff --git a/server/helpers/custom-validators/video-ownership.ts b/server/helpers/custom-validators/video-ownership.ts index 21a6b7203..0e1c63bad 100644 --- a/server/helpers/custom-validators/video-ownership.ts +++ b/server/helpers/custom-validators/video-ownership.ts @@ -1,26 +1,9 @@ import { Response } from 'express' -import { VideoChangeOwnershipModel } from '../../models/video/video-change-ownership' -import { MVideoChangeOwnershipFull } from '@server/types/models/video/video-change-ownership' import { MUserId } from '@server/types/models' +import { MVideoChangeOwnershipFull } from '@server/types/models/video/video-change-ownership' import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes' -export async function doesChangeVideoOwnershipExist (idArg: number | string, res: Response) { - const id = parseInt(idArg + '', 10) - const videoChangeOwnership = await VideoChangeOwnershipModel.load(id) - - if (!videoChangeOwnership) { - res.fail({ - status: HttpStatusCode.NOT_FOUND_404, - message: 'Video change ownership not found' - }) - return false - } - - res.locals.videoChangeOwnership = videoChangeOwnership - return true -} - -export function checkUserCanTerminateOwnershipChange (user: MUserId, videoChangeOwnership: MVideoChangeOwnershipFull, res: Response) { +function checkUserCanTerminateOwnershipChange (user: MUserId, videoChangeOwnership: MVideoChangeOwnershipFull, res: Response) { if (videoChangeOwnership.NextOwner.userId === user.id) { return true } @@ -31,3 +14,7 @@ export function checkUserCanTerminateOwnershipChange (user: MUserId, videoChange }) return false } + +export { + checkUserCanTerminateOwnershipChange +} diff --git a/server/helpers/middlewares/abuses.ts b/server/helpers/middlewares/abuses.ts deleted file mode 100644 index f0b1caba8..000000000 --- a/server/helpers/middlewares/abuses.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { Response } from 'express' -import { AbuseModel } from '../../models/abuse/abuse' -import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes' - -async function doesAbuseExist (abuseId: number | string, res: Response) { - const abuse = await AbuseModel.loadByIdWithReporter(parseInt(abuseId + '', 10)) - - if (!abuse) { - res.fail({ - status: HttpStatusCode.NOT_FOUND_404, - message: 'Abuse not found' - }) - - return false - } - - res.locals.abuse = abuse - return true -} - -// --------------------------------------------------------------------------- - -export { - doesAbuseExist -} diff --git a/server/helpers/middlewares/accounts.ts b/server/helpers/middlewares/accounts.ts deleted file mode 100644 index 7db79bc48..000000000 --- a/server/helpers/middlewares/accounts.ts +++ /dev/null @@ -1,65 +0,0 @@ -import { Response } from 'express' -import { UserModel } from '@server/models/user/user' -import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes' -import { AccountModel } from '../../models/account/account' -import { MAccountDefault } from '../../types/models' - -function doesAccountIdExist (id: number | string, res: Response, sendNotFound = true) { - const promise = AccountModel.load(parseInt(id + '', 10)) - - return doesAccountExist(promise, res, sendNotFound) -} - -function doesLocalAccountNameExist (name: string, res: Response, sendNotFound = true) { - const promise = AccountModel.loadLocalByName(name) - - return doesAccountExist(promise, res, sendNotFound) -} - -function doesAccountNameWithHostExist (nameWithDomain: string, res: Response, sendNotFound = true) { - const promise = AccountModel.loadByNameWithHost(nameWithDomain) - - return doesAccountExist(promise, res, sendNotFound) -} - -async function doesAccountExist (p: Promise, res: Response, sendNotFound: boolean) { - const account = await p - - if (!account) { - if (sendNotFound === true) { - res.fail({ - status: HttpStatusCode.NOT_FOUND_404, - message: 'Account not found' - }) - } - return false - } - - res.locals.account = account - return true -} - -async function doesUserFeedTokenCorrespond (id: number, token: string, res: Response) { - const user = await UserModel.loadByIdWithChannels(parseInt(id + '', 10)) - - if (token !== user.feedToken) { - res.fail({ - status: HttpStatusCode.FORBIDDEN_403, - message: 'User and token mismatch' - }) - return false - } - - res.locals.user = user - return true -} - -// --------------------------------------------------------------------------- - -export { - doesAccountIdExist, - doesLocalAccountNameExist, - doesAccountNameWithHostExist, - doesAccountExist, - doesUserFeedTokenCorrespond -} diff --git a/server/helpers/middlewares/index.ts b/server/helpers/middlewares/index.ts deleted file mode 100644 index f57f3ad31..000000000 --- a/server/helpers/middlewares/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -export * from './abuses' -export * from './accounts' -export * from './video-blacklists' -export * from './video-captions' -export * from './video-channels' -export * from './video-playlists' -export * from './videos' diff --git a/server/helpers/middlewares/video-blacklists.ts b/server/helpers/middlewares/video-blacklists.ts deleted file mode 100644 index 3494fd6b0..000000000 --- a/server/helpers/middlewares/video-blacklists.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { Response } from 'express' -import { VideoBlacklistModel } from '../../models/video/video-blacklist' -import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes' - -async function doesVideoBlacklistExist (videoId: number, res: Response) { - const videoBlacklist = await VideoBlacklistModel.loadByVideoId(videoId) - - if (videoBlacklist === null) { - res.fail({ - status: HttpStatusCode.NOT_FOUND_404, - message: 'Blacklisted video not found' - }) - return false - } - - res.locals.videoBlacklist = videoBlacklist - return true -} - -// --------------------------------------------------------------------------- - -export { - doesVideoBlacklistExist -} diff --git a/server/helpers/middlewares/video-captions.ts b/server/helpers/middlewares/video-captions.ts deleted file mode 100644 index 2a12c4813..000000000 --- a/server/helpers/middlewares/video-captions.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { Response } from 'express' -import { VideoCaptionModel } from '../../models/video/video-caption' -import { MVideoId } from '@server/types/models' -import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes' - -async function doesVideoCaptionExist (video: MVideoId, language: string, res: Response) { - const videoCaption = await VideoCaptionModel.loadByVideoIdAndLanguage(video.id, language) - - if (!videoCaption) { - res.fail({ - status: HttpStatusCode.NOT_FOUND_404, - message: 'Video caption not found' - }) - return false - } - - res.locals.videoCaption = videoCaption - return true -} - -// --------------------------------------------------------------------------- - -export { - doesVideoCaptionExist -} diff --git a/server/helpers/middlewares/video-channels.ts b/server/helpers/middlewares/video-channels.ts deleted file mode 100644 index f5ed5ef0f..000000000 --- a/server/helpers/middlewares/video-channels.ts +++ /dev/null @@ -1,43 +0,0 @@ -import * as express from 'express' -import { MChannelBannerAccountDefault } from '@server/types/models' -import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes' -import { VideoChannelModel } from '../../models/video/video-channel' - -async function doesLocalVideoChannelNameExist (name: string, res: express.Response) { - const videoChannel = await VideoChannelModel.loadLocalByNameAndPopulateAccount(name) - - return processVideoChannelExist(videoChannel, res) -} - -async function doesVideoChannelIdExist (id: number, res: express.Response) { - const videoChannel = await VideoChannelModel.loadAndPopulateAccount(+id) - - return processVideoChannelExist(videoChannel, res) -} - -async function doesVideoChannelNameWithHostExist (nameWithDomain: string, res: express.Response) { - const videoChannel = await VideoChannelModel.loadByNameWithHostAndPopulateAccount(nameWithDomain) - - return processVideoChannelExist(videoChannel, res) -} - -// --------------------------------------------------------------------------- - -export { - doesLocalVideoChannelNameExist, - doesVideoChannelIdExist, - doesVideoChannelNameWithHostExist -} - -function processVideoChannelExist (videoChannel: MChannelBannerAccountDefault, res: express.Response) { - if (!videoChannel) { - res.fail({ - status: HttpStatusCode.NOT_FOUND_404, - message: 'Video channel not found' - }) - return false - } - - res.locals.videoChannel = videoChannel - return true -} diff --git a/server/helpers/middlewares/video-playlists.ts b/server/helpers/middlewares/video-playlists.ts deleted file mode 100644 index 3faeab677..000000000 --- a/server/helpers/middlewares/video-playlists.ts +++ /dev/null @@ -1,39 +0,0 @@ -import * as express from 'express' -import { VideoPlaylistModel } from '../../models/video/video-playlist' -import { MVideoPlaylist } from '../../types/models/video/video-playlist' -import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes' - -export type VideoPlaylistFetchType = 'summary' | 'all' -async function doesVideoPlaylistExist (id: number | string, res: express.Response, fetchType: VideoPlaylistFetchType = 'summary') { - if (fetchType === 'summary') { - const videoPlaylist = await VideoPlaylistModel.loadWithAccountAndChannelSummary(id, undefined) - res.locals.videoPlaylistSummary = videoPlaylist - - return handleVideoPlaylist(videoPlaylist, res) - } - - const videoPlaylist = await VideoPlaylistModel.loadWithAccountAndChannel(id, undefined) - res.locals.videoPlaylistFull = videoPlaylist - - return handleVideoPlaylist(videoPlaylist, res) -} - -// --------------------------------------------------------------------------- - -export { - doesVideoPlaylistExist -} - -// --------------------------------------------------------------------------- - -function handleVideoPlaylist (videoPlaylist: MVideoPlaylist, res: express.Response) { - if (!videoPlaylist) { - res.fail({ - status: HttpStatusCode.NOT_FOUND_404, - message: 'Video playlist not found' - }) - return false - } - - return true -} diff --git a/server/helpers/middlewares/videos.ts b/server/helpers/middlewares/videos.ts deleted file mode 100644 index 52b934eb7..000000000 --- a/server/helpers/middlewares/videos.ts +++ /dev/null @@ -1,125 +0,0 @@ -import { Response } from 'express' -import { fetchVideo, VideoFetchType } from '../video' -import { UserRight } from '../../../shared/models/users' -import { VideoChannelModel } from '../../models/video/video-channel' -import { - MUser, - MUserAccountId, - MVideoAccountLight, - MVideoFullLight, - MVideoIdThumbnail, - MVideoImmutable, - MVideoThumbnail, - MVideoWithRights -} from '@server/types/models' -import { VideoFileModel } from '@server/models/video/video-file' -import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes' - -async function doesVideoExist (id: number | string, res: Response, fetchType: VideoFetchType = 'all') { - const userId = res.locals.oauth ? res.locals.oauth.token.User.id : undefined - - const video = await fetchVideo(id, fetchType, userId) - - if (video === null) { - res.fail({ - status: HttpStatusCode.NOT_FOUND_404, - message: 'Video not found' - }) - return false - } - - switch (fetchType) { - case 'all': - res.locals.videoAll = video as MVideoFullLight - break - - case 'only-immutable-attributes': - res.locals.onlyImmutableVideo = video as MVideoImmutable - break - - case 'id': - res.locals.videoId = video as MVideoIdThumbnail - break - - case 'only-video': - res.locals.onlyVideo = video as MVideoThumbnail - break - - case 'only-video-with-rights': - res.locals.onlyVideoWithRights = video as MVideoWithRights - break - } - - return true -} - -async function doesVideoFileOfVideoExist (id: number, videoIdOrUUID: number | string, res: Response) { - if (!await VideoFileModel.doesVideoExistForVideoFile(id, videoIdOrUUID)) { - res.fail({ - status: HttpStatusCode.NOT_FOUND_404, - message: 'VideoFile matching Video not found' - }) - return false - } - - return true -} - -async function doesVideoChannelOfAccountExist (channelId: number, user: MUserAccountId, res: Response) { - const videoChannel = await VideoChannelModel.loadAndPopulateAccount(channelId) - - if (videoChannel === null) { - res.fail({ message: 'Unknown video "video channel" for this instance.' }) - return false - } - - // Don't check account id if the user can update any video - if (user.hasRight(UserRight.UPDATE_ANY_VIDEO) === true) { - res.locals.videoChannel = videoChannel - return true - } - - if (videoChannel.Account.id !== user.Account.id) { - res.fail({ - message: 'Unknown video "video channel" for this account.' - }) - return false - } - - res.locals.videoChannel = videoChannel - return true -} - -function checkUserCanManageVideo (user: MUser, video: MVideoAccountLight, right: UserRight, res: Response, onlyOwned = true) { - // Retrieve the user who did the request - if (onlyOwned && video.isOwned() === false) { - res.fail({ - status: HttpStatusCode.FORBIDDEN_403, - message: 'Cannot manage a video of another server.' - }) - return false - } - - // Check if the user can delete the video - // The user can delete it if he has the right - // Or if s/he is the video's account - const account = video.VideoChannel.Account - if (user.hasRight(right) === false && account.userId !== user.id) { - res.fail({ - status: HttpStatusCode.FORBIDDEN_403, - message: 'Cannot manage a video of another user.' - }) - return false - } - - return true -} - -// --------------------------------------------------------------------------- - -export { - doesVideoChannelOfAccountExist, - doesVideoExist, - doesVideoFileOfVideoExist, - checkUserCanManageVideo -} diff --git a/server/helpers/signup.ts b/server/helpers/signup.ts deleted file mode 100644 index 8fa81e601..000000000 --- a/server/helpers/signup.ts +++ /dev/null @@ -1,62 +0,0 @@ -import { UserModel } from '../models/user/user' -import * as ipaddr from 'ipaddr.js' -import { CONFIG } from '../initializers/config' - -const isCidr = require('is-cidr') - -async function isSignupAllowed (): Promise<{ allowed: boolean, errorMessage?: string }> { - if (CONFIG.SIGNUP.ENABLED === false) { - return { allowed: false } - } - - // No limit and signup is enabled - if (CONFIG.SIGNUP.LIMIT === -1) { - return { allowed: true } - } - - const totalUsers = await UserModel.countTotal() - - return { allowed: totalUsers < CONFIG.SIGNUP.LIMIT } -} - -function isSignupAllowedForCurrentIP (ip: string) { - if (!ip) return false - - const addr = ipaddr.parse(ip) - const excludeList = [ 'blacklist' ] - let matched = '' - - // if there is a valid, non-empty whitelist, we exclude all unknown adresses too - if (CONFIG.SIGNUP.FILTERS.CIDR.WHITELIST.filter(cidr => isCidr(cidr)).length > 0) { - excludeList.push('unknown') - } - - if (addr.kind() === 'ipv4') { - const addrV4 = ipaddr.IPv4.parse(ip) - const rangeList = { - whitelist: CONFIG.SIGNUP.FILTERS.CIDR.WHITELIST.filter(cidr => isCidr.v4(cidr)) - .map(cidr => ipaddr.IPv4.parseCIDR(cidr)), - blacklist: CONFIG.SIGNUP.FILTERS.CIDR.BLACKLIST.filter(cidr => isCidr.v4(cidr)) - .map(cidr => ipaddr.IPv4.parseCIDR(cidr)) - } - matched = ipaddr.subnetMatch(addrV4, rangeList, 'unknown') - } else if (addr.kind() === 'ipv6') { - const addrV6 = ipaddr.IPv6.parse(ip) - const rangeList = { - whitelist: CONFIG.SIGNUP.FILTERS.CIDR.WHITELIST.filter(cidr => isCidr.v6(cidr)) - .map(cidr => ipaddr.IPv6.parseCIDR(cidr)), - blacklist: CONFIG.SIGNUP.FILTERS.CIDR.BLACKLIST.filter(cidr => isCidr.v6(cidr)) - .map(cidr => ipaddr.IPv6.parseCIDR(cidr)) - } - matched = ipaddr.subnetMatch(addrV6, rangeList, 'unknown') - } - - return !excludeList.includes(matched) -} - -// --------------------------------------------------------------------------- - -export { - isSignupAllowed, - isSignupAllowedForCurrentIP -} diff --git a/server/helpers/video.ts b/server/helpers/video.ts index 7c510f474..d3445bed5 100644 --- a/server/helpers/video.ts +++ b/server/helpers/video.ts @@ -1,66 +1,7 @@ import { Response } from 'express' import { CONFIG } from '@server/initializers/config' -import { - isStreamingPlaylist, - MStreamingPlaylistVideo, - MVideo, - MVideoAccountLightBlacklistAllFiles, - MVideoFullLight, - MVideoIdThumbnail, - MVideoImmutable, - MVideoThumbnail, - MVideoWithRights -} from '@server/types/models' +import { isStreamingPlaylist, MStreamingPlaylistVideo, MVideo } from '@server/types/models' import { VideoPrivacy, VideoState } from '@shared/models' -import { VideoModel } from '../models/video/video' - -type VideoFetchType = 'all' | 'only-video' | 'only-video-with-rights' | 'id' | 'none' | 'only-immutable-attributes' - -function fetchVideo (id: number | string, fetchType: 'all', userId?: number): Promise -function fetchVideo (id: number | string, fetchType: 'only-immutable-attributes'): Promise -function fetchVideo (id: number | string, fetchType: 'only-video', userId?: number): Promise -function fetchVideo (id: number | string, fetchType: 'only-video-with-rights', userId?: number): Promise -function fetchVideo (id: number | string, fetchType: 'id' | 'none', userId?: number): Promise -function fetchVideo ( - id: number | string, - fetchType: VideoFetchType, - userId?: number -): Promise -function fetchVideo ( - id: number | string, - fetchType: VideoFetchType, - userId?: number -): Promise { - if (fetchType === 'all') return VideoModel.loadAndPopulateAccountAndServerAndTags(id, undefined, userId) - - if (fetchType === 'only-immutable-attributes') return VideoModel.loadImmutableAttributes(id) - - if (fetchType === 'only-video-with-rights') return VideoModel.loadWithRights(id) - - if (fetchType === 'only-video') return VideoModel.load(id) - - if (fetchType === 'id' || fetchType === 'none') return VideoModel.loadOnlyId(id) -} - -type VideoFetchByUrlType = 'all' | 'only-video' | 'only-immutable-attributes' - -function fetchVideoByUrl (url: string, fetchType: 'all'): Promise -function fetchVideoByUrl (url: string, fetchType: 'only-immutable-attributes'): Promise -function fetchVideoByUrl (url: string, fetchType: 'only-video'): Promise -function fetchVideoByUrl ( - url: string, - fetchType: VideoFetchByUrlType -): Promise -function fetchVideoByUrl ( - url: string, - fetchType: VideoFetchByUrlType -): Promise { - if (fetchType === 'all') return VideoModel.loadByUrlAndPopulateAccount(url) - - if (fetchType === 'only-immutable-attributes') return VideoModel.loadByUrlImmutableAttributes(url) - - if (fetchType === 'only-video') return VideoModel.loadByUrl(url) -} function getVideoWithAttributes (res: Response) { return res.locals.videoAll || res.locals.onlyVideo || res.locals.onlyVideoWithRights @@ -100,11 +41,7 @@ function getExtFromMimetype (mimeTypes: { [id: string]: string | string[] }, mim } export { - VideoFetchType, - VideoFetchByUrlType, - fetchVideo, getVideoWithAttributes, - fetchVideoByUrl, extractVideo, getExtFromMimetype, isStateForFederation, diff --git a/server/helpers/webfinger.ts b/server/helpers/webfinger.ts deleted file mode 100644 index 33367f651..000000000 --- a/server/helpers/webfinger.ts +++ /dev/null @@ -1,67 +0,0 @@ -import * as WebFinger from 'webfinger.js' -import { WebFingerData } from '../../shared' -import { WEBSERVER } from '../initializers/constants' -import { ActorModel } from '../models/actor/actor' -import { MActorFull } from '../types/models' -import { isTestInstance } from './core-utils' -import { isActivityPubUrlValid } from './custom-validators/activitypub/misc' - -const webfinger = new WebFinger({ - webfist_fallback: false, - tls_only: isTestInstance(), - uri_fallback: false, - request_timeout: 3000 -}) - -async function loadActorUrlOrGetFromWebfinger (uriArg: string) { - // Handle strings like @toto@example.com - const uri = uriArg.startsWith('@') ? uriArg.slice(1) : uriArg - - const [ name, host ] = uri.split('@') - let actor: MActorFull - - if (!host || host === WEBSERVER.HOST) { - actor = await ActorModel.loadLocalByName(name) - } else { - actor = await ActorModel.loadByNameAndHost(name, host) - } - - if (actor) return actor.url - - return getUrlFromWebfinger(uri) -} - -async function getUrlFromWebfinger (uri: string) { - const webfingerData: WebFingerData = await webfingerLookup(uri) - return getLinkOrThrow(webfingerData) -} - -// --------------------------------------------------------------------------- - -export { - getUrlFromWebfinger, - loadActorUrlOrGetFromWebfinger -} - -// --------------------------------------------------------------------------- - -function getLinkOrThrow (webfingerData: WebFingerData) { - if (Array.isArray(webfingerData.links) === false) throw new Error('WebFinger links is not an array.') - - const selfLink = webfingerData.links.find(l => l.rel === 'self') - if (selfLink === undefined || isActivityPubUrlValid(selfLink.href) === false) { - throw new Error('Cannot find self link or href is not a valid URL.') - } - - return selfLink.href -} - -function webfingerLookup (nameWithHost: string) { - return new Promise((res, rej) => { - webfinger.lookup(nameWithHost, (err, p) => { - if (err) return rej(err) - - return res(p.object) - }) - }) -} diff --git a/server/lib/activitypub/actors/get.ts b/server/lib/activitypub/actors/get.ts index 0d5bea789..e7e87a967 100644 --- a/server/lib/activitypub/actors/get.ts +++ b/server/lib/activitypub/actors/get.ts @@ -1,9 +1,9 @@ import { checkUrlsSameHost, getAPId } from '@server/helpers/activitypub' -import { ActorFetchByUrlType, fetchActorByUrl } from '@server/helpers/actor' import { retryTransactionWrapper } from '@server/helpers/database-utils' import { logger } from '@server/helpers/logger' import { JobQueue } from '@server/lib/job-queue' +import { ActorFetchByUrlType, fetchActorByUrl } from '@server/lib/model-loaders' import { MActor, MActorAccountChannelId, MActorAccountChannelIdActor, MActorAccountId, MActorFullActor } from '@server/types/models' import { ActivityPubActor } from '@shared/models' import { refreshActorIfNeeded } from './refresh' diff --git a/server/lib/activitypub/actors/index.ts b/server/lib/activitypub/actors/index.ts index a54da6798..5ee2a6f1a 100644 --- a/server/lib/activitypub/actors/index.ts +++ b/server/lib/activitypub/actors/index.ts @@ -3,3 +3,4 @@ export * from './image' export * from './keys' export * from './refresh' export * from './updater' +export * from './webfinger' diff --git a/server/lib/activitypub/actors/refresh.ts b/server/lib/activitypub/actors/refresh.ts index ff3b249d0..9f2289bfa 100644 --- a/server/lib/activitypub/actors/refresh.ts +++ b/server/lib/activitypub/actors/refresh.ts @@ -1,12 +1,12 @@ -import { ActorFetchByUrlType } from '@server/helpers/actor' import { logger } from '@server/helpers/logger' import { PeerTubeRequestError } from '@server/helpers/requests' -import { getUrlFromWebfinger } from '@server/helpers/webfinger' +import { ActorFetchByUrlType } from '@server/lib/model-loaders' import { ActorModel } from '@server/models/actor/actor' import { MActorAccountChannelId, MActorFull } from '@server/types/models' import { HttpStatusCode } from '@shared/core-utils' import { fetchRemoteActor } from './shared' import { APActorUpdater } from './updater' +import { getUrlFromWebfinger } from './webfinger' async function refreshActorIfNeeded ( actorArg: T, diff --git a/server/lib/activitypub/actors/shared/index.ts b/server/lib/activitypub/actors/shared/index.ts index a2ff468cf..52af1a8e1 100644 --- a/server/lib/activitypub/actors/shared/index.ts +++ b/server/lib/activitypub/actors/shared/index.ts @@ -1,3 +1,3 @@ export * from './creator' -export * from './url-to-object' export * from './object-to-model-attributes' +export * from './url-to-object' diff --git a/server/lib/activitypub/actors/webfinger.ts b/server/lib/activitypub/actors/webfinger.ts new file mode 100644 index 000000000..cf8eddfc7 --- /dev/null +++ b/server/lib/activitypub/actors/webfinger.ts @@ -0,0 +1,67 @@ +import * as WebFinger from 'webfinger.js' +import { isTestInstance } from '@server/helpers/core-utils' +import { isActivityPubUrlValid } from '@server/helpers/custom-validators/activitypub/misc' +import { WEBSERVER } from '@server/initializers/constants' +import { ActorModel } from '@server/models/actor/actor' +import { MActorFull } from '@server/types/models' +import { WebFingerData } from '@shared/models' + +const webfinger = new WebFinger({ + webfist_fallback: false, + tls_only: isTestInstance(), + uri_fallback: false, + request_timeout: 3000 +}) + +async function loadActorUrlOrGetFromWebfinger (uriArg: string) { + // Handle strings like @toto@example.com + const uri = uriArg.startsWith('@') ? uriArg.slice(1) : uriArg + + const [ name, host ] = uri.split('@') + let actor: MActorFull + + if (!host || host === WEBSERVER.HOST) { + actor = await ActorModel.loadLocalByName(name) + } else { + actor = await ActorModel.loadByNameAndHost(name, host) + } + + if (actor) return actor.url + + return getUrlFromWebfinger(uri) +} + +async function getUrlFromWebfinger (uri: string) { + const webfingerData: WebFingerData = await webfingerLookup(uri) + return getLinkOrThrow(webfingerData) +} + +// --------------------------------------------------------------------------- + +export { + getUrlFromWebfinger, + loadActorUrlOrGetFromWebfinger +} + +// --------------------------------------------------------------------------- + +function getLinkOrThrow (webfingerData: WebFingerData) { + if (Array.isArray(webfingerData.links) === false) throw new Error('WebFinger links is not an array.') + + const selfLink = webfingerData.links.find(l => l.rel === 'self') + if (selfLink === undefined || isActivityPubUrlValid(selfLink.href) === false) { + throw new Error('Cannot find self link or href is not a valid URL.') + } + + return selfLink.href +} + +function webfingerLookup (nameWithHost: string) { + return new Promise((res, rej) => { + webfinger.lookup(nameWithHost, (err, p) => { + if (err) return rej(err) + + return res(p.object) + }) + }) +} diff --git a/server/lib/activitypub/videos/get.ts b/server/lib/activitypub/videos/get.ts index a8c41e178..38ba4978c 100644 --- a/server/lib/activitypub/videos/get.ts +++ b/server/lib/activitypub/videos/get.ts @@ -1,7 +1,7 @@ import { getAPId } from '@server/helpers/activitypub' import { retryTransactionWrapper } from '@server/helpers/database-utils' -import { fetchVideoByUrl, VideoFetchByUrlType } from '@server/helpers/video' import { JobQueue } from '@server/lib/job-queue' +import { fetchVideoByUrl, VideoFetchByUrlType } from '@server/lib/model-loaders' import { MVideoAccountLightBlacklistAllFiles, MVideoImmutable, MVideoThumbnail } from '@server/types/models' import { refreshVideoIfNeeded } from './refresh' import { APVideoCreator, fetchRemoteVideo, SyncParam, syncVideoExternalAttributes } from './shared' diff --git a/server/lib/activitypub/videos/refresh.ts b/server/lib/activitypub/videos/refresh.ts index 71a4e75b0..f1a3a6fac 100644 --- a/server/lib/activitypub/videos/refresh.ts +++ b/server/lib/activitypub/videos/refresh.ts @@ -1,7 +1,7 @@ import { logger, loggerTagsFactory } from '@server/helpers/logger' import { PeerTubeRequestError } from '@server/helpers/requests' -import { VideoFetchByUrlType } from '@server/helpers/video' import { ActorFollowScoreCache } from '@server/lib/files-cache' +import { VideoFetchByUrlType } from '@server/lib/model-loaders' import { VideoModel } from '@server/models/video/video' import { MVideoAccountLightBlacklistAllFiles, MVideoThumbnail } from '@server/types/models' import { HttpStatusCode } from '@shared/core-utils' diff --git a/server/lib/job-queue/handlers/activitypub-follow.ts b/server/lib/job-queue/handlers/activitypub-follow.ts index 76b6fcaae..f896d7af4 100644 --- a/server/lib/job-queue/handlers/activitypub-follow.ts +++ b/server/lib/job-queue/handlers/activitypub-follow.ts @@ -4,13 +4,12 @@ import { ActivitypubFollowPayload } from '@shared/models' import { sanitizeHost } from '../../../helpers/core-utils' import { retryTransactionWrapper } from '../../../helpers/database-utils' import { logger } from '../../../helpers/logger' -import { loadActorUrlOrGetFromWebfinger } from '../../../helpers/webfinger' import { REMOTE_SCHEME, WEBSERVER } from '../../../initializers/constants' import { sequelizeTypescript } from '../../../initializers/database' import { ActorModel } from '../../../models/actor/actor' import { ActorFollowModel } from '../../../models/actor/actor-follow' import { MActor, MActorFollowActors, MActorFull } from '../../../types/models' -import { getOrCreateAPActor } from '../../activitypub/actors' +import { getOrCreateAPActor, loadActorUrlOrGetFromWebfinger } from '../../activitypub/actors' import { sendFollow } from '../../activitypub/send' import { Notifier } from '../../notifier' diff --git a/server/lib/job-queue/handlers/activitypub-refresher.ts b/server/lib/job-queue/handlers/activitypub-refresher.ts index 29483f310..2508a4793 100644 --- a/server/lib/job-queue/handlers/activitypub-refresher.ts +++ b/server/lib/job-queue/handlers/activitypub-refresher.ts @@ -1,9 +1,9 @@ import * as Bull from 'bull' import { refreshVideoPlaylistIfNeeded } from '@server/lib/activitypub/playlists' import { refreshVideoIfNeeded } from '@server/lib/activitypub/videos' +import { fetchVideoByUrl } from '@server/lib/model-loaders' import { RefreshPayload } from '@shared/models' import { logger } from '../../../helpers/logger' -import { fetchVideoByUrl } from '../../../helpers/video' import { ActorModel } from '../../../models/actor/actor' import { VideoPlaylistModel } from '../../../models/video/video-playlist' import { refreshActorIfNeeded } from '../../activitypub/actors' diff --git a/server/lib/model-loaders/actor.ts b/server/lib/model-loaders/actor.ts new file mode 100644 index 000000000..234cb344f --- /dev/null +++ b/server/lib/model-loaders/actor.ts @@ -0,0 +1,16 @@ + +import { ActorModel } from '../../models/actor/actor' +import { MActorAccountChannelId, MActorFull } from '../../types/models' + +type ActorFetchByUrlType = 'all' | 'association-ids' + +function fetchActorByUrl (url: string, fetchType: ActorFetchByUrlType): Promise { + if (fetchType === 'all') return ActorModel.loadByUrlAndPopulateAccountAndChannel(url) + + if (fetchType === 'association-ids') return ActorModel.loadByUrl(url) +} + +export { + ActorFetchByUrlType, + fetchActorByUrl +} diff --git a/server/lib/model-loaders/index.ts b/server/lib/model-loaders/index.ts new file mode 100644 index 000000000..9e5152cb2 --- /dev/null +++ b/server/lib/model-loaders/index.ts @@ -0,0 +1,2 @@ +export * from './actor' +export * from './video' diff --git a/server/lib/model-loaders/video.ts b/server/lib/model-loaders/video.ts new file mode 100644 index 000000000..7aaf00e89 --- /dev/null +++ b/server/lib/model-loaders/video.ts @@ -0,0 +1,64 @@ +import { VideoModel } from '@server/models/video/video' +import { + MVideoAccountLightBlacklistAllFiles, + MVideoFullLight, + MVideoIdThumbnail, + MVideoImmutable, + MVideoThumbnail, + MVideoWithRights +} from '@server/types/models' + +type VideoFetchType = 'all' | 'only-video' | 'only-video-with-rights' | 'id' | 'none' | 'only-immutable-attributes' + +function fetchVideo (id: number | string, fetchType: 'all', userId?: number): Promise +function fetchVideo (id: number | string, fetchType: 'only-immutable-attributes'): Promise +function fetchVideo (id: number | string, fetchType: 'only-video', userId?: number): Promise +function fetchVideo (id: number | string, fetchType: 'only-video-with-rights', userId?: number): Promise +function fetchVideo (id: number | string, fetchType: 'id' | 'none', userId?: number): Promise +function fetchVideo ( + id: number | string, + fetchType: VideoFetchType, + userId?: number +): Promise +function fetchVideo ( + id: number | string, + fetchType: VideoFetchType, + userId?: number +): Promise { + if (fetchType === 'all') return VideoModel.loadAndPopulateAccountAndServerAndTags(id, undefined, userId) + + if (fetchType === 'only-immutable-attributes') return VideoModel.loadImmutableAttributes(id) + + if (fetchType === 'only-video-with-rights') return VideoModel.loadWithRights(id) + + if (fetchType === 'only-video') return VideoModel.load(id) + + if (fetchType === 'id' || fetchType === 'none') return VideoModel.loadOnlyId(id) +} + +type VideoFetchByUrlType = 'all' | 'only-video' | 'only-immutable-attributes' + +function fetchVideoByUrl (url: string, fetchType: 'all'): Promise +function fetchVideoByUrl (url: string, fetchType: 'only-immutable-attributes'): Promise +function fetchVideoByUrl (url: string, fetchType: 'only-video'): Promise +function fetchVideoByUrl ( + url: string, + fetchType: VideoFetchByUrlType +): Promise +function fetchVideoByUrl ( + url: string, + fetchType: VideoFetchByUrlType +): Promise { + if (fetchType === 'all') return VideoModel.loadByUrlAndPopulateAccount(url) + + if (fetchType === 'only-immutable-attributes') return VideoModel.loadByUrlImmutableAttributes(url) + + if (fetchType === 'only-video') return VideoModel.loadByUrl(url) +} + +export { + VideoFetchType, + VideoFetchByUrlType, + fetchVideo, + fetchVideoByUrl +} diff --git a/server/lib/server-config-manager.ts b/server/lib/server-config-manager.ts index 25a770c6b..80d87a9d3 100644 --- a/server/lib/server-config-manager.ts +++ b/server/lib/server-config-manager.ts @@ -1,7 +1,7 @@ -import { isSignupAllowed, isSignupAllowedForCurrentIP } from '@server/helpers/signup' import { getServerCommit } from '@server/helpers/utils' import { CONFIG, isEmailEnabled } from '@server/initializers/config' import { CONSTRAINTS_FIELDS, DEFAULT_THEME_NAME, PEERTUBE_VERSION } from '@server/initializers/constants' +import { isSignupAllowed, isSignupAllowedForCurrentIP } from '@server/lib/signup' import { ActorCustomPageModel } from '@server/models/account/actor-custom-page' import { HTMLServerConfig, RegisteredExternalAuthConfig, RegisteredIdAndPassAuthConfig, ServerConfig } from '@shared/models' import { Hooks } from './plugins/hooks' diff --git a/server/lib/signup.ts b/server/lib/signup.ts new file mode 100644 index 000000000..8fa81e601 --- /dev/null +++ b/server/lib/signup.ts @@ -0,0 +1,62 @@ +import { UserModel } from '../models/user/user' +import * as ipaddr from 'ipaddr.js' +import { CONFIG } from '../initializers/config' + +const isCidr = require('is-cidr') + +async function isSignupAllowed (): Promise<{ allowed: boolean, errorMessage?: string }> { + if (CONFIG.SIGNUP.ENABLED === false) { + return { allowed: false } + } + + // No limit and signup is enabled + if (CONFIG.SIGNUP.LIMIT === -1) { + return { allowed: true } + } + + const totalUsers = await UserModel.countTotal() + + return { allowed: totalUsers < CONFIG.SIGNUP.LIMIT } +} + +function isSignupAllowedForCurrentIP (ip: string) { + if (!ip) return false + + const addr = ipaddr.parse(ip) + const excludeList = [ 'blacklist' ] + let matched = '' + + // if there is a valid, non-empty whitelist, we exclude all unknown adresses too + if (CONFIG.SIGNUP.FILTERS.CIDR.WHITELIST.filter(cidr => isCidr(cidr)).length > 0) { + excludeList.push('unknown') + } + + if (addr.kind() === 'ipv4') { + const addrV4 = ipaddr.IPv4.parse(ip) + const rangeList = { + whitelist: CONFIG.SIGNUP.FILTERS.CIDR.WHITELIST.filter(cidr => isCidr.v4(cidr)) + .map(cidr => ipaddr.IPv4.parseCIDR(cidr)), + blacklist: CONFIG.SIGNUP.FILTERS.CIDR.BLACKLIST.filter(cidr => isCidr.v4(cidr)) + .map(cidr => ipaddr.IPv4.parseCIDR(cidr)) + } + matched = ipaddr.subnetMatch(addrV4, rangeList, 'unknown') + } else if (addr.kind() === 'ipv6') { + const addrV6 = ipaddr.IPv6.parse(ip) + const rangeList = { + whitelist: CONFIG.SIGNUP.FILTERS.CIDR.WHITELIST.filter(cidr => isCidr.v6(cidr)) + .map(cidr => ipaddr.IPv6.parseCIDR(cidr)), + blacklist: CONFIG.SIGNUP.FILTERS.CIDR.BLACKLIST.filter(cidr => isCidr.v6(cidr)) + .map(cidr => ipaddr.IPv6.parseCIDR(cidr)) + } + matched = ipaddr.subnetMatch(addrV6, rangeList, 'unknown') + } + + return !excludeList.includes(matched) +} + +// --------------------------------------------------------------------------- + +export { + isSignupAllowed, + isSignupAllowedForCurrentIP +} diff --git a/server/middlewares/activitypub.ts b/server/middlewares/activitypub.ts index a1fdfafcf..6b43b7764 100644 --- a/server/middlewares/activitypub.ts +++ b/server/middlewares/activitypub.ts @@ -1,13 +1,12 @@ import { NextFunction, Request, Response } from 'express' +import { getAPId } from '@server/helpers/activitypub' +import { isActorDeleteActivityValid } from '@server/helpers/custom-validators/activitypub/actor' import { ActivityDelete, ActivityPubSignature } from '../../shared' +import { HttpStatusCode } from '../../shared/core-utils/miscs/http-error-codes' import { logger } from '../helpers/logger' import { isHTTPSignatureVerified, isJsonLDSignatureVerified, parseHTTPSignature } from '../helpers/peertube-crypto' import { ACCEPT_HEADERS, ACTIVITY_PUB, HTTP_SIGNATURE } from '../initializers/constants' -import { getOrCreateAPActor } from '../lib/activitypub/actors' -import { loadActorUrlOrGetFromWebfinger } from '../helpers/webfinger' -import { isActorDeleteActivityValid } from '@server/helpers/custom-validators/activitypub/actor' -import { getAPId } from '@server/helpers/activitypub' -import { HttpStatusCode } from '../../shared/core-utils/miscs/http-error-codes' +import { getOrCreateAPActor, loadActorUrlOrGetFromWebfinger } from '../lib/activitypub/actors' async function checkSignature (req: Request, res: Response, next: NextFunction) { try { diff --git a/server/middlewares/validators/abuse.ts b/server/middlewares/validators/abuse.ts index 7f002e0d5..56c97747c 100644 --- a/server/middlewares/validators/abuse.ts +++ b/server/middlewares/validators/abuse.ts @@ -13,13 +13,11 @@ import { isAbuseVideoIsValid } from '@server/helpers/custom-validators/abuses' import { exists, isIdOrUUIDValid, isIdValid, toIntOrNull } from '@server/helpers/custom-validators/misc' -import { doesCommentIdExist } from '@server/helpers/custom-validators/video-comments' import { logger } from '@server/helpers/logger' -import { doesAbuseExist, doesAccountIdExist, doesVideoExist } from '@server/helpers/middlewares' import { AbuseMessageModel } from '@server/models/abuse/abuse-message' import { AbuseCreate, UserRight } from '@shared/models' -import { areValidationErrors } from './utils' import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes' +import { areValidationErrors, doesAbuseExist, doesAccountIdExist, doesCommentIdExist, doesVideoExist } from './shared' const abuseReportValidator = [ body('account.id') diff --git a/server/middlewares/validators/account.ts b/server/middlewares/validators/account.ts index cbdcef2fd..599eb10bb 100644 --- a/server/middlewares/validators/account.ts +++ b/server/middlewares/validators/account.ts @@ -2,8 +2,7 @@ import * as express from 'express' import { param } from 'express-validator' import { isAccountNameValid } from '../../helpers/custom-validators/accounts' import { logger } from '../../helpers/logger' -import { areValidationErrors } from './utils' -import { doesAccountNameWithHostExist, doesLocalAccountNameExist } from '../../helpers/middlewares' +import { areValidationErrors, doesAccountNameWithHostExist, doesLocalAccountNameExist } from './shared' const localAccountValidator = [ param('name').custom(isAccountNameValid).withMessage('Should have a valid account name'), diff --git a/server/middlewares/validators/activitypub/pagination.ts b/server/middlewares/validators/activitypub/pagination.ts index fa21f063d..c8ec34eb6 100644 --- a/server/middlewares/validators/activitypub/pagination.ts +++ b/server/middlewares/validators/activitypub/pagination.ts @@ -1,8 +1,8 @@ import * as express from 'express' import { query } from 'express-validator' -import { logger } from '../../../helpers/logger' -import { areValidationErrors } from '../utils' import { PAGINATION } from '@server/initializers/constants' +import { logger } from '../../../helpers/logger' +import { areValidationErrors } from '../shared' const apPaginationValidator = [ query('page') diff --git a/server/middlewares/validators/activitypub/signature.ts b/server/middlewares/validators/activitypub/signature.ts index 7896a6128..f2f7d5848 100644 --- a/server/middlewares/validators/activitypub/signature.ts +++ b/server/middlewares/validators/activitypub/signature.ts @@ -1,12 +1,13 @@ import * as express from 'express' import { body } from 'express-validator' import { - isSignatureCreatorValid, isSignatureTypeValid, + isSignatureCreatorValid, + isSignatureTypeValid, isSignatureValueValid } from '../../../helpers/custom-validators/activitypub/signature' import { isDateValid } from '../../../helpers/custom-validators/misc' import { logger } from '../../../helpers/logger' -import { areValidationErrors } from '../utils' +import { areValidationErrors } from '../shared' const signatureValidator = [ body('signature.type') diff --git a/server/middlewares/validators/actor-image.ts b/server/middlewares/validators/actor-image.ts index 961d7a7e5..49daadd61 100644 --- a/server/middlewares/validators/actor-image.ts +++ b/server/middlewares/validators/actor-image.ts @@ -4,7 +4,7 @@ import { isActorImageFile } from '@server/helpers/custom-validators/actor-images import { cleanUpReqFiles } from '../../helpers/express-utils' import { logger } from '../../helpers/logger' import { CONSTRAINTS_FIELDS } from '../../initializers/constants' -import { areValidationErrors } from './utils' +import { areValidationErrors } from './shared' const updateActorImageValidatorFactory = (fieldname: string) => ([ body(fieldname).custom((value, { req }) => isActorImageFile(req.files, fieldname)).withMessage( diff --git a/server/middlewares/validators/blocklist.ts b/server/middlewares/validators/blocklist.ts index 125ff882c..826b16fc8 100644 --- a/server/middlewares/validators/blocklist.ts +++ b/server/middlewares/validators/blocklist.ts @@ -1,15 +1,14 @@ -import { body, param } from 'express-validator' import * as express from 'express' +import { body, param } from 'express-validator' +import { getServerActor } from '@server/models/application/application' +import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes' +import { isHostValid } from '../../helpers/custom-validators/servers' import { logger } from '../../helpers/logger' -import { areValidationErrors } from './utils' +import { WEBSERVER } from '../../initializers/constants' import { AccountBlocklistModel } from '../../models/account/account-blocklist' -import { isHostValid } from '../../helpers/custom-validators/servers' -import { ServerBlocklistModel } from '../../models/server/server-blocklist' import { ServerModel } from '../../models/server/server' -import { WEBSERVER } from '../../initializers/constants' -import { doesAccountNameWithHostExist } from '../../helpers/middlewares' -import { getServerActor } from '@server/models/application/application' -import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes' +import { ServerBlocklistModel } from '../../models/server/server-blocklist' +import { areValidationErrors, doesAccountNameWithHostExist } from './shared' const blockAccountValidator = [ body('accountName').exists().withMessage('Should have an account name with host'), diff --git a/server/middlewares/validators/bulk.ts b/server/middlewares/validators/bulk.ts index 847885101..9bb95f5b7 100644 --- a/server/middlewares/validators/bulk.ts +++ b/server/middlewares/validators/bulk.ts @@ -1,12 +1,11 @@ import * as express from 'express' import { body } from 'express-validator' import { isBulkRemoveCommentsOfScopeValid } from '@server/helpers/custom-validators/bulk' -import { doesAccountNameWithHostExist } from '@server/helpers/middlewares' +import { HttpStatusCode } from '@shared/core-utils/miscs/http-error-codes' import { UserRight } from '@shared/models' import { BulkRemoveCommentsOfBody } from '@shared/models/bulk/bulk-remove-comments-of-body.model' import { logger } from '../../helpers/logger' -import { areValidationErrors } from './utils' -import { HttpStatusCode } from '@shared/core-utils/miscs/http-error-codes' +import { areValidationErrors, doesAccountNameWithHostExist } from './shared' const bulkRemoveCommentsOfValidator = [ body('accountName').exists().withMessage('Should have an account name with host'), diff --git a/server/middlewares/validators/config.ts b/server/middlewares/validators/config.ts index b5d6b4622..1aeadbe65 100644 --- a/server/middlewares/validators/config.ts +++ b/server/middlewares/validators/config.ts @@ -7,7 +7,7 @@ import { isThemeNameValid } from '../../helpers/custom-validators/plugins' import { isUserNSFWPolicyValid, isUserVideoQuotaDailyValid, isUserVideoQuotaValid } from '../../helpers/custom-validators/users' import { logger } from '../../helpers/logger' import { isThemeRegistered } from '../../lib/plugins/theme-utils' -import { areValidationErrors } from './utils' +import { areValidationErrors } from './shared' const customConfigUpdateValidator = [ body('instance.name').exists().withMessage('Should have a valid instance name'), diff --git a/server/middlewares/validators/feeds.ts b/server/middlewares/validators/feeds.ts index aa16cc993..51e6d6fff 100644 --- a/server/middlewares/validators/feeds.ts +++ b/server/middlewares/validators/feeds.ts @@ -1,18 +1,18 @@ import * as express from 'express' import { param, query } from 'express-validator' +import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes' import { isValidRSSFeed } from '../../helpers/custom-validators/feeds' import { exists, isIdOrUUIDValid, isIdValid } from '../../helpers/custom-validators/misc' import { logger } from '../../helpers/logger' import { + areValidationErrors, doesAccountIdExist, doesAccountNameWithHostExist, doesUserFeedTokenCorrespond, doesVideoChannelIdExist, - doesVideoChannelNameWithHostExist -} from '../../helpers/middlewares' -import { doesVideoExist } from '../../helpers/middlewares/videos' -import { areValidationErrors } from './utils' -import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes' + doesVideoChannelNameWithHostExist, + doesVideoExist +} from './shared' const feedsFormatValidator = [ param('format').optional().custom(isValidRSSFeed).withMessage('Should have a valid format (rss, atom, json)'), diff --git a/server/middlewares/validators/follows.ts b/server/middlewares/validators/follows.ts index 733be379b..205baca48 100644 --- a/server/middlewares/validators/follows.ts +++ b/server/middlewares/validators/follows.ts @@ -1,6 +1,7 @@ import * as express from 'express' import { body, param, query } from 'express-validator' import { isFollowStateValid } from '@server/helpers/custom-validators/follows' +import { loadActorUrlOrGetFromWebfinger } from '@server/lib/activitypub/actors' import { getServerActor } from '@server/models/application/application' import { MActorFollowActorsDefault } from '@server/types/models' import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes' @@ -8,11 +9,10 @@ import { isTestInstance } from '../../helpers/core-utils' import { isActorTypeValid, isValidActorHandle } from '../../helpers/custom-validators/activitypub/actor' import { isEachUniqueHostValid, isHostValid } from '../../helpers/custom-validators/servers' import { logger } from '../../helpers/logger' -import { loadActorUrlOrGetFromWebfinger } from '../../helpers/webfinger' import { SERVER_ACTOR_NAME, WEBSERVER } from '../../initializers/constants' import { ActorModel } from '../../models/actor/actor' import { ActorFollowModel } from '../../models/actor/actor-follow' -import { areValidationErrors } from './utils' +import { areValidationErrors } from './shared' const listFollowsValidator = [ query('state') diff --git a/server/middlewares/validators/jobs.ts b/server/middlewares/validators/jobs.ts index d87b28c06..5d89d167f 100644 --- a/server/middlewares/validators/jobs.ts +++ b/server/middlewares/validators/jobs.ts @@ -2,7 +2,7 @@ import * as express from 'express' import { param, query } from 'express-validator' import { isValidJobState, isValidJobType } from '../../helpers/custom-validators/jobs' import { logger, loggerTagsFactory } from '../../helpers/logger' -import { areValidationErrors } from './utils' +import { areValidationErrors } from './shared' const lTags = loggerTagsFactory('validators', 'jobs') diff --git a/server/middlewares/validators/logs.ts b/server/middlewares/validators/logs.ts index ba817d9a9..c55baaee3 100644 --- a/server/middlewares/validators/logs.ts +++ b/server/middlewares/validators/logs.ts @@ -1,9 +1,9 @@ import * as express from 'express' -import { logger } from '../../helpers/logger' -import { areValidationErrors } from './utils' -import { isDateValid } from '../../helpers/custom-validators/misc' import { query } from 'express-validator' import { isValidLogLevel } from '../../helpers/custom-validators/logs' +import { isDateValid } from '../../helpers/custom-validators/misc' +import { logger } from '../../helpers/logger' +import { areValidationErrors } from './shared' const getLogsValidator = [ query('startDate') diff --git a/server/middlewares/validators/oembed.ts b/server/middlewares/validators/oembed.ts index b1d763fbe..ab117635e 100644 --- a/server/middlewares/validators/oembed.ts +++ b/server/middlewares/validators/oembed.ts @@ -1,7 +1,7 @@ import * as express from 'express' import { query } from 'express-validator' import { join } from 'path' -import { fetchVideo } from '@server/helpers/video' +import { fetchVideo } from '@server/lib/model-loaders' import { VideoPlaylistModel } from '@server/models/video/video-playlist' import { VideoPlaylistPrivacy, VideoPrivacy } from '@shared/models' import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes' @@ -9,7 +9,7 @@ import { isTestInstance } from '../../helpers/core-utils' import { isIdOrUUIDValid } from '../../helpers/custom-validators/misc' import { logger } from '../../helpers/logger' import { WEBSERVER } from '../../initializers/constants' -import { areValidationErrors } from './utils' +import { areValidationErrors } from './shared' const playlistPaths = [ join('videos', 'watch', 'playlist'), diff --git a/server/middlewares/validators/pagination.ts b/server/middlewares/validators/pagination.ts index 6b0a83d80..74eae251e 100644 --- a/server/middlewares/validators/pagination.ts +++ b/server/middlewares/validators/pagination.ts @@ -1,8 +1,8 @@ import * as express from 'express' import { query } from 'express-validator' -import { logger } from '../../helpers/logger' -import { areValidationErrors } from './utils' import { PAGINATION } from '@server/initializers/constants' +import { logger } from '../../helpers/logger' +import { areValidationErrors } from './shared' const paginationValidator = paginationValidatorBuilder() diff --git a/server/middlewares/validators/plugins.ts b/server/middlewares/validators/plugins.ts index 5934a28bc..8c76d2e36 100644 --- a/server/middlewares/validators/plugins.ts +++ b/server/middlewares/validators/plugins.ts @@ -9,7 +9,7 @@ import { logger } from '../../helpers/logger' import { CONFIG } from '../../initializers/config' import { PluginManager } from '../../lib/plugins/plugin-manager' import { PluginModel } from '../../models/server/plugin' -import { areValidationErrors } from './utils' +import { areValidationErrors } from './shared' const getPluginValidator = (pluginType: PluginType, withVersion = true) => { const validators: (ValidationChain | express.Handler)[] = [ diff --git a/server/middlewares/validators/redundancy.ts b/server/middlewares/validators/redundancy.ts index 3d557048a..da24f4c9b 100644 --- a/server/middlewares/validators/redundancy.ts +++ b/server/middlewares/validators/redundancy.ts @@ -1,14 +1,13 @@ import * as express from 'express' import { body, param, query } from 'express-validator' +import { isVideoRedundancyTarget } from '@server/helpers/custom-validators/video-redundancies' +import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes' import { exists, isBooleanValid, isIdOrUUIDValid, isIdValid, toBooleanOrNull, toIntOrNull } from '../../helpers/custom-validators/misc' +import { isHostValid } from '../../helpers/custom-validators/servers' import { logger } from '../../helpers/logger' -import { areValidationErrors } from './utils' import { VideoRedundancyModel } from '../../models/redundancy/video-redundancy' -import { isHostValid } from '../../helpers/custom-validators/servers' import { ServerModel } from '../../models/server/server' -import { doesVideoExist } from '../../helpers/middlewares' -import { isVideoRedundancyTarget } from '@server/helpers/custom-validators/video-redundancies' -import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes' +import { areValidationErrors, doesVideoExist } from './shared' const videoFileRedundancyGetValidator = [ param('videoId').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid video id'), diff --git a/server/middlewares/validators/search.ts b/server/middlewares/validators/search.ts index d2f527750..e2e1c6aae 100644 --- a/server/middlewares/validators/search.ts +++ b/server/middlewares/validators/search.ts @@ -1,9 +1,9 @@ import * as express from 'express' -import { areValidationErrors } from './utils' -import { logger } from '../../helpers/logger' import { query } from 'express-validator' -import { isDateValid } from '../../helpers/custom-validators/misc' import { isSearchTargetValid } from '@server/helpers/custom-validators/search' +import { isDateValid } from '../../helpers/custom-validators/misc' +import { logger } from '../../helpers/logger' +import { areValidationErrors } from './shared' const videosSearchValidator = [ query('search').optional().not().isEmpty().withMessage('Should have a valid search'), diff --git a/server/middlewares/validators/server.ts b/server/middlewares/validators/server.ts index 2b34c4a76..fc7239b25 100644 --- a/server/middlewares/validators/server.ts +++ b/server/middlewares/validators/server.ts @@ -1,13 +1,13 @@ import * as express from 'express' -import { logger } from '../../helpers/logger' -import { areValidationErrors } from './utils' -import { isHostValid, isValidContactBody } from '../../helpers/custom-validators/servers' -import { ServerModel } from '../../models/server/server' import { body } from 'express-validator' +import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes' +import { isHostValid, isValidContactBody } from '../../helpers/custom-validators/servers' import { isUserDisplayNameValid } from '../../helpers/custom-validators/users' -import { Redis } from '../../lib/redis' +import { logger } from '../../helpers/logger' import { CONFIG, isEmailEnabled } from '../../initializers/config' -import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes' +import { Redis } from '../../lib/redis' +import { ServerModel } from '../../models/server/server' +import { areValidationErrors } from './shared' const serverGetValidator = [ body('host').custom(isHostValid).withMessage('Should have a valid host'), diff --git a/server/middlewares/validators/shared/abuses.ts b/server/middlewares/validators/shared/abuses.ts new file mode 100644 index 000000000..4a20a55fa --- /dev/null +++ b/server/middlewares/validators/shared/abuses.ts @@ -0,0 +1,25 @@ +import { Response } from 'express' +import { AbuseModel } from '@server/models/abuse/abuse' +import { HttpStatusCode } from '@shared/core-utils' + +async function doesAbuseExist (abuseId: number | string, res: Response) { + const abuse = await AbuseModel.loadByIdWithReporter(parseInt(abuseId + '', 10)) + + if (!abuse) { + res.fail({ + status: HttpStatusCode.NOT_FOUND_404, + message: 'Abuse not found' + }) + + return false + } + + res.locals.abuse = abuse + return true +} + +// --------------------------------------------------------------------------- + +export { + doesAbuseExist +} diff --git a/server/middlewares/validators/shared/accounts.ts b/server/middlewares/validators/shared/accounts.ts new file mode 100644 index 000000000..04da15441 --- /dev/null +++ b/server/middlewares/validators/shared/accounts.ts @@ -0,0 +1,65 @@ +import { Response } from 'express' +import { AccountModel } from '@server/models/account/account' +import { UserModel } from '@server/models/user/user' +import { MAccountDefault } from '@server/types/models' +import { HttpStatusCode } from '@shared/core-utils' + +function doesAccountIdExist (id: number | string, res: Response, sendNotFound = true) { + const promise = AccountModel.load(parseInt(id + '', 10)) + + return doesAccountExist(promise, res, sendNotFound) +} + +function doesLocalAccountNameExist (name: string, res: Response, sendNotFound = true) { + const promise = AccountModel.loadLocalByName(name) + + return doesAccountExist(promise, res, sendNotFound) +} + +function doesAccountNameWithHostExist (nameWithDomain: string, res: Response, sendNotFound = true) { + const promise = AccountModel.loadByNameWithHost(nameWithDomain) + + return doesAccountExist(promise, res, sendNotFound) +} + +async function doesAccountExist (p: Promise, res: Response, sendNotFound: boolean) { + const account = await p + + if (!account) { + if (sendNotFound === true) { + res.fail({ + status: HttpStatusCode.NOT_FOUND_404, + message: 'Account not found' + }) + } + return false + } + + res.locals.account = account + return true +} + +async function doesUserFeedTokenCorrespond (id: number, token: string, res: Response) { + const user = await UserModel.loadByIdWithChannels(parseInt(id + '', 10)) + + if (token !== user.feedToken) { + res.fail({ + status: HttpStatusCode.FORBIDDEN_403, + message: 'User and token mismatch' + }) + return false + } + + res.locals.user = user + return true +} + +// --------------------------------------------------------------------------- + +export { + doesAccountIdExist, + doesLocalAccountNameExist, + doesAccountNameWithHostExist, + doesAccountExist, + doesUserFeedTokenCorrespond +} diff --git a/server/middlewares/validators/shared/index.ts b/server/middlewares/validators/shared/index.ts new file mode 100644 index 000000000..fa89d05f2 --- /dev/null +++ b/server/middlewares/validators/shared/index.ts @@ -0,0 +1,11 @@ +export * from './abuses' +export * from './accounts' +export * from './utils' +export * from './video-blacklists' +export * from './video-captions' +export * from './video-channels' +export * from './video-comments' +export * from './video-imports' +export * from './video-ownerships' +export * from './video-playlists' +export * from './videos' diff --git a/server/middlewares/validators/shared/utils.ts b/server/middlewares/validators/shared/utils.ts new file mode 100644 index 000000000..d3e4870a9 --- /dev/null +++ b/server/middlewares/validators/shared/utils.ts @@ -0,0 +1,50 @@ +import * as express from 'express' +import { query, validationResult } from 'express-validator' +import { logger } from '../../../helpers/logger' + +function areValidationErrors (req: express.Request, res: express.Response) { + const errors = validationResult(req) + + if (!errors.isEmpty()) { + logger.warn('Incorrect request parameters', { path: req.originalUrl, err: errors.mapped() }) + res.fail({ + message: 'Incorrect request parameters: ' + Object.keys(errors.mapped()).join(', '), + instance: req.originalUrl, + data: { + 'invalid-params': errors.mapped() + } + }) + + return true + } + + return false +} + +function checkSort (sortableColumns: string[], tags: string[] = []) { + return [ + query('sort').optional().isIn(sortableColumns).withMessage('Should have correct sortable column'), + + (req: express.Request, res: express.Response, next: express.NextFunction) => { + logger.debug('Checking sort parameters', { parameters: req.query, tags }) + + if (areValidationErrors(req, res)) return + + return next() + } + ] +} + +function createSortableColumns (sortableColumns: string[]) { + const sortableColumnDesc = sortableColumns.map(sortableColumn => '-' + sortableColumn) + + return sortableColumns.concat(sortableColumnDesc) +} + +// --------------------------------------------------------------------------- + +export { + areValidationErrors, + checkSort, + createSortableColumns +} diff --git a/server/middlewares/validators/shared/video-blacklists.ts b/server/middlewares/validators/shared/video-blacklists.ts new file mode 100644 index 000000000..01491c10f --- /dev/null +++ b/server/middlewares/validators/shared/video-blacklists.ts @@ -0,0 +1,24 @@ +import { Response } from 'express' +import { VideoBlacklistModel } from '@server/models/video/video-blacklist' +import { HttpStatusCode } from '@shared/core-utils' + +async function doesVideoBlacklistExist (videoId: number, res: Response) { + const videoBlacklist = await VideoBlacklistModel.loadByVideoId(videoId) + + if (videoBlacklist === null) { + res.fail({ + status: HttpStatusCode.NOT_FOUND_404, + message: 'Blacklisted video not found' + }) + return false + } + + res.locals.videoBlacklist = videoBlacklist + return true +} + +// --------------------------------------------------------------------------- + +export { + doesVideoBlacklistExist +} diff --git a/server/middlewares/validators/shared/video-captions.ts b/server/middlewares/validators/shared/video-captions.ts new file mode 100644 index 000000000..80f6c5a52 --- /dev/null +++ b/server/middlewares/validators/shared/video-captions.ts @@ -0,0 +1,25 @@ +import { Response } from 'express' +import { VideoCaptionModel } from '@server/models/video/video-caption' +import { MVideoId } from '@server/types/models' +import { HttpStatusCode } from '@shared/core-utils' + +async function doesVideoCaptionExist (video: MVideoId, language: string, res: Response) { + const videoCaption = await VideoCaptionModel.loadByVideoIdAndLanguage(video.id, language) + + if (!videoCaption) { + res.fail({ + status: HttpStatusCode.NOT_FOUND_404, + message: 'Video caption not found' + }) + return false + } + + res.locals.videoCaption = videoCaption + return true +} + +// --------------------------------------------------------------------------- + +export { + doesVideoCaptionExist +} diff --git a/server/middlewares/validators/shared/video-channels.ts b/server/middlewares/validators/shared/video-channels.ts new file mode 100644 index 000000000..fe2e663b7 --- /dev/null +++ b/server/middlewares/validators/shared/video-channels.ts @@ -0,0 +1,43 @@ +import * as express from 'express' +import { VideoChannelModel } from '@server/models/video/video-channel' +import { MChannelBannerAccountDefault } from '@server/types/models' +import { HttpStatusCode } from '@shared/core-utils' + +async function doesLocalVideoChannelNameExist (name: string, res: express.Response) { + const videoChannel = await VideoChannelModel.loadLocalByNameAndPopulateAccount(name) + + return processVideoChannelExist(videoChannel, res) +} + +async function doesVideoChannelIdExist (id: number, res: express.Response) { + const videoChannel = await VideoChannelModel.loadAndPopulateAccount(+id) + + return processVideoChannelExist(videoChannel, res) +} + +async function doesVideoChannelNameWithHostExist (nameWithDomain: string, res: express.Response) { + const videoChannel = await VideoChannelModel.loadByNameWithHostAndPopulateAccount(nameWithDomain) + + return processVideoChannelExist(videoChannel, res) +} + +// --------------------------------------------------------------------------- + +export { + doesLocalVideoChannelNameExist, + doesVideoChannelIdExist, + doesVideoChannelNameWithHostExist +} + +function processVideoChannelExist (videoChannel: MChannelBannerAccountDefault, res: express.Response) { + if (!videoChannel) { + res.fail({ + status: HttpStatusCode.NOT_FOUND_404, + message: 'Video channel not found' + }) + return false + } + + res.locals.videoChannel = videoChannel + return true +} diff --git a/server/middlewares/validators/shared/video-comments.ts b/server/middlewares/validators/shared/video-comments.ts new file mode 100644 index 000000000..83ea15c98 --- /dev/null +++ b/server/middlewares/validators/shared/video-comments.ts @@ -0,0 +1,73 @@ +import * as express from 'express' +import { VideoCommentModel } from '@server/models/video/video-comment' +import { MVideoId } from '@server/types/models' +import { HttpStatusCode } from '@shared/core-utils' + +async function doesVideoCommentThreadExist (idArg: number | string, video: MVideoId, res: express.Response) { + const id = parseInt(idArg + '', 10) + const videoComment = await VideoCommentModel.loadById(id) + + if (!videoComment) { + res.fail({ + status: HttpStatusCode.NOT_FOUND_404, + message: 'Video comment thread not found' + }) + return false + } + + if (videoComment.videoId !== video.id) { + res.fail({ message: 'Video comment is not associated to this video.' }) + return false + } + + if (videoComment.inReplyToCommentId !== null) { + res.fail({ message: 'Video comment is not a thread.' }) + return false + } + + res.locals.videoCommentThread = videoComment + return true +} + +async function doesVideoCommentExist (idArg: number | string, video: MVideoId, res: express.Response) { + const id = parseInt(idArg + '', 10) + const videoComment = await VideoCommentModel.loadByIdAndPopulateVideoAndAccountAndReply(id) + + if (!videoComment) { + res.fail({ + status: HttpStatusCode.NOT_FOUND_404, + message: 'Video comment thread not found' + }) + return false + } + + if (videoComment.videoId !== video.id) { + res.fail({ message: 'Video comment is not associated to this video.' }) + return false + } + + res.locals.videoCommentFull = videoComment + return true +} + +async function doesCommentIdExist (idArg: number | string, res: express.Response) { + const id = parseInt(idArg + '', 10) + const videoComment = await VideoCommentModel.loadByIdAndPopulateVideoAndAccountAndReply(id) + + if (!videoComment) { + res.fail({ + status: HttpStatusCode.NOT_FOUND_404, + message: 'Video comment thread not found' + }) + return false + } + + res.locals.videoCommentFull = videoComment + return true +} + +export { + doesVideoCommentThreadExist, + doesVideoCommentExist, + doesCommentIdExist +} diff --git a/server/middlewares/validators/shared/video-imports.ts b/server/middlewares/validators/shared/video-imports.ts new file mode 100644 index 000000000..0f984bc17 --- /dev/null +++ b/server/middlewares/validators/shared/video-imports.ts @@ -0,0 +1,22 @@ +import * as express from 'express' +import { VideoImportModel } from '@server/models/video/video-import' +import { HttpStatusCode } from '@shared/core-utils' + +async function doesVideoImportExist (id: number, res: express.Response) { + const videoImport = await VideoImportModel.loadAndPopulateVideo(id) + + if (!videoImport) { + res.fail({ + status: HttpStatusCode.NOT_FOUND_404, + message: 'Video import not found' + }) + return false + } + + res.locals.videoImport = videoImport + return true +} + +export { + doesVideoImportExist +} diff --git a/server/middlewares/validators/shared/video-ownerships.ts b/server/middlewares/validators/shared/video-ownerships.ts new file mode 100644 index 000000000..fc27006ce --- /dev/null +++ b/server/middlewares/validators/shared/video-ownerships.ts @@ -0,0 +1,24 @@ +import * as express from 'express' +import { VideoChangeOwnershipModel } from '@server/models/video/video-change-ownership' +import { HttpStatusCode } from '@shared/core-utils' + +async function doesChangeVideoOwnershipExist (idArg: number | string, res: express.Response) { + const id = parseInt(idArg + '', 10) + const videoChangeOwnership = await VideoChangeOwnershipModel.load(id) + + if (!videoChangeOwnership) { + res.fail({ + status: HttpStatusCode.NOT_FOUND_404, + message: 'Video change ownership not found' + }) + return false + } + + res.locals.videoChangeOwnership = videoChangeOwnership + + return true +} + +export { + doesChangeVideoOwnershipExist +} diff --git a/server/middlewares/validators/shared/video-playlists.ts b/server/middlewares/validators/shared/video-playlists.ts new file mode 100644 index 000000000..d762859a8 --- /dev/null +++ b/server/middlewares/validators/shared/video-playlists.ts @@ -0,0 +1,39 @@ +import * as express from 'express' +import { VideoPlaylistModel } from '@server/models/video/video-playlist' +import { MVideoPlaylist } from '@server/types/models' +import { HttpStatusCode } from '@shared/core-utils' + +export type VideoPlaylistFetchType = 'summary' | 'all' +async function doesVideoPlaylistExist (id: number | string, res: express.Response, fetchType: VideoPlaylistFetchType = 'summary') { + if (fetchType === 'summary') { + const videoPlaylist = await VideoPlaylistModel.loadWithAccountAndChannelSummary(id, undefined) + res.locals.videoPlaylistSummary = videoPlaylist + + return handleVideoPlaylist(videoPlaylist, res) + } + + const videoPlaylist = await VideoPlaylistModel.loadWithAccountAndChannel(id, undefined) + res.locals.videoPlaylistFull = videoPlaylist + + return handleVideoPlaylist(videoPlaylist, res) +} + +// --------------------------------------------------------------------------- + +export { + doesVideoPlaylistExist +} + +// --------------------------------------------------------------------------- + +function handleVideoPlaylist (videoPlaylist: MVideoPlaylist, res: express.Response) { + if (!videoPlaylist) { + res.fail({ + status: HttpStatusCode.NOT_FOUND_404, + message: 'Video playlist not found' + }) + return false + } + + return true +} diff --git a/server/middlewares/validators/shared/videos.ts b/server/middlewares/validators/shared/videos.ts new file mode 100644 index 000000000..a6dad4374 --- /dev/null +++ b/server/middlewares/validators/shared/videos.ts @@ -0,0 +1,125 @@ +import { Response } from 'express' +import { fetchVideo, VideoFetchType } from '@server/lib/model-loaders' +import { VideoChannelModel } from '@server/models/video/video-channel' +import { VideoFileModel } from '@server/models/video/video-file' +import { + MUser, + MUserAccountId, + MVideoAccountLight, + MVideoFullLight, + MVideoIdThumbnail, + MVideoImmutable, + MVideoThumbnail, + MVideoWithRights +} from '@server/types/models' +import { HttpStatusCode } from '@shared/core-utils' +import { UserRight } from '@shared/models' + +async function doesVideoExist (id: number | string, res: Response, fetchType: VideoFetchType = 'all') { + const userId = res.locals.oauth ? res.locals.oauth.token.User.id : undefined + + const video = await fetchVideo(id, fetchType, userId) + + if (video === null) { + res.fail({ + status: HttpStatusCode.NOT_FOUND_404, + message: 'Video not found' + }) + return false + } + + switch (fetchType) { + case 'all': + res.locals.videoAll = video as MVideoFullLight + break + + case 'only-immutable-attributes': + res.locals.onlyImmutableVideo = video as MVideoImmutable + break + + case 'id': + res.locals.videoId = video as MVideoIdThumbnail + break + + case 'only-video': + res.locals.onlyVideo = video as MVideoThumbnail + break + + case 'only-video-with-rights': + res.locals.onlyVideoWithRights = video as MVideoWithRights + break + } + + return true +} + +async function doesVideoFileOfVideoExist (id: number, videoIdOrUUID: number | string, res: Response) { + if (!await VideoFileModel.doesVideoExistForVideoFile(id, videoIdOrUUID)) { + res.fail({ + status: HttpStatusCode.NOT_FOUND_404, + message: 'VideoFile matching Video not found' + }) + return false + } + + return true +} + +async function doesVideoChannelOfAccountExist (channelId: number, user: MUserAccountId, res: Response) { + const videoChannel = await VideoChannelModel.loadAndPopulateAccount(channelId) + + if (videoChannel === null) { + res.fail({ message: 'Unknown video "video channel" for this instance.' }) + return false + } + + // Don't check account id if the user can update any video + if (user.hasRight(UserRight.UPDATE_ANY_VIDEO) === true) { + res.locals.videoChannel = videoChannel + return true + } + + if (videoChannel.Account.id !== user.Account.id) { + res.fail({ + message: 'Unknown video "video channel" for this account.' + }) + return false + } + + res.locals.videoChannel = videoChannel + return true +} + +function checkUserCanManageVideo (user: MUser, video: MVideoAccountLight, right: UserRight, res: Response, onlyOwned = true) { + // Retrieve the user who did the request + if (onlyOwned && video.isOwned() === false) { + res.fail({ + status: HttpStatusCode.FORBIDDEN_403, + message: 'Cannot manage a video of another server.' + }) + return false + } + + // Check if the user can delete the video + // The user can delete it if he has the right + // Or if s/he is the video's account + const account = video.VideoChannel.Account + if (user.hasRight(right) === false && account.userId !== user.id) { + res.fail({ + status: HttpStatusCode.FORBIDDEN_403, + message: 'Cannot manage a video of another user.' + }) + return false + } + + return true +} + +// --------------------------------------------------------------------------- + +export { + doesVideoChannelOfAccountExist, + doesVideoExist, + doesVideoFileOfVideoExist, + checkUserCanManageVideo +} diff --git a/server/middlewares/validators/sort.ts b/server/middlewares/validators/sort.ts index beecc155b..d67b6f3ba 100644 --- a/server/middlewares/validators/sort.ts +++ b/server/middlewares/validators/sort.ts @@ -1,5 +1,5 @@ import { SORTABLE_COLUMNS } from '../../initializers/constants' -import { checkSort, createSortableColumns } from './utils' +import { checkSort, createSortableColumns } from './shared' // Initialize constants here for better performances const SORTABLE_USERS_COLUMNS = createSortableColumns(SORTABLE_COLUMNS.USERS) diff --git a/server/middlewares/validators/themes.ts b/server/middlewares/validators/themes.ts index 91ec0d7ac..d4716257f 100644 --- a/server/middlewares/validators/themes.ts +++ b/server/middlewares/validators/themes.ts @@ -1,11 +1,11 @@ import * as express from 'express' import { param } from 'express-validator' -import { logger } from '../../helpers/logger' -import { areValidationErrors } from './utils' +import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes' +import { isSafePath } from '../../helpers/custom-validators/misc' import { isPluginNameValid, isPluginVersionValid } from '../../helpers/custom-validators/plugins' +import { logger } from '../../helpers/logger' import { PluginManager } from '../../lib/plugins/plugin-manager' -import { isSafePath } from '../../helpers/custom-validators/misc' -import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes' +import { areValidationErrors } from './shared' const serveThemeCSSValidator = [ param('themeName').custom(isPluginNameValid).withMessage('Should have a valid theme name'), diff --git a/server/middlewares/validators/user-history.ts b/server/middlewares/validators/user-history.ts index 647294cc3..1db0d9b26 100644 --- a/server/middlewares/validators/user-history.ts +++ b/server/middlewares/validators/user-history.ts @@ -1,8 +1,8 @@ import * as express from 'express' import { body, query } from 'express-validator' -import { logger } from '../../helpers/logger' -import { areValidationErrors } from './utils' import { exists, isDateValid } from '../../helpers/custom-validators/misc' +import { logger } from '../../helpers/logger' +import { areValidationErrors } from './shared' const userHistoryListValidator = [ query('search') diff --git a/server/middlewares/validators/user-notifications.ts b/server/middlewares/validators/user-notifications.ts index 21a7be08d..2f8e7686e 100644 --- a/server/middlewares/validators/user-notifications.ts +++ b/server/middlewares/validators/user-notifications.ts @@ -1,9 +1,9 @@ import * as express from 'express' import { body, query } from 'express-validator' -import { logger } from '../../helpers/logger' -import { areValidationErrors } from './utils' -import { isUserNotificationSettingValid } from '../../helpers/custom-validators/user-notifications' import { isNotEmptyIntArray, toBooleanOrNull } from '../../helpers/custom-validators/misc' +import { isUserNotificationSettingValid } from '../../helpers/custom-validators/user-notifications' +import { logger } from '../../helpers/logger' +import { areValidationErrors } from './shared' const listUserNotificationsValidator = [ query('unread') diff --git a/server/middlewares/validators/user-subscriptions.ts b/server/middlewares/validators/user-subscriptions.ts index 5f928b05b..ab7962923 100644 --- a/server/middlewares/validators/user-subscriptions.ts +++ b/server/middlewares/validators/user-subscriptions.ts @@ -6,7 +6,7 @@ import { toArray } from '../../helpers/custom-validators/misc' import { logger } from '../../helpers/logger' import { WEBSERVER } from '../../initializers/constants' import { ActorFollowModel } from '../../models/actor/actor-follow' -import { areValidationErrors } from './utils' +import { areValidationErrors } from './shared' const userSubscriptionListValidator = [ query('search').optional().not().isEmpty().withMessage('Should have a valid search'), diff --git a/server/middlewares/validators/users.ts b/server/middlewares/validators/users.ts index 0eb9172c4..218633b8d 100644 --- a/server/middlewares/validators/users.ts +++ b/server/middlewares/validators/users.ts @@ -30,13 +30,12 @@ import { } from '../../helpers/custom-validators/users' import { isVideoChannelNameValid } from '../../helpers/custom-validators/video-channels' import { logger } from '../../helpers/logger' -import { doesVideoExist } from '../../helpers/middlewares' -import { isSignupAllowed, isSignupAllowedForCurrentIP } from '../../helpers/signup' import { isThemeRegistered } from '../../lib/plugins/theme-utils' import { Redis } from '../../lib/redis' -import { UserModel } from '../../models/user/user' +import { isSignupAllowed, isSignupAllowedForCurrentIP } from '../../lib/signup' import { ActorModel } from '../../models/actor/actor' -import { areValidationErrors } from './utils' +import { UserModel } from '../../models/user/user' +import { areValidationErrors, doesVideoExist } from './shared' const usersListValidator = [ query('blocked') diff --git a/server/middlewares/validators/utils.ts b/server/middlewares/validators/utils.ts deleted file mode 100644 index e291f1b17..000000000 --- a/server/middlewares/validators/utils.ts +++ /dev/null @@ -1,50 +0,0 @@ -import * as express from 'express' -import { query, validationResult } from 'express-validator' -import { logger } from '../../helpers/logger' - -function areValidationErrors (req: express.Request, res: express.Response) { - const errors = validationResult(req) - - if (!errors.isEmpty()) { - logger.warn('Incorrect request parameters', { path: req.originalUrl, err: errors.mapped() }) - res.fail({ - message: 'Incorrect request parameters: ' + Object.keys(errors.mapped()).join(', '), - instance: req.originalUrl, - data: { - 'invalid-params': errors.mapped() - } - }) - - return true - } - - return false -} - -function checkSort (sortableColumns: string[], tags: string[] = []) { - return [ - query('sort').optional().isIn(sortableColumns).withMessage('Should have correct sortable column'), - - (req: express.Request, res: express.Response, next: express.NextFunction) => { - logger.debug('Checking sort parameters', { parameters: req.query, tags }) - - if (areValidationErrors(req, res)) return - - return next() - } - ] -} - -function createSortableColumns (sortableColumns: string[]) { - const sortableColumnDesc = sortableColumns.map(sortableColumn => '-' + sortableColumn) - - return sortableColumns.concat(sortableColumnDesc) -} - -// --------------------------------------------------------------------------- - -export { - areValidationErrors, - checkSort, - createSortableColumns -} diff --git a/server/middlewares/validators/videos/video-blacklist.ts b/server/middlewares/validators/videos/video-blacklist.ts index 65132a09f..7374ba774 100644 --- a/server/middlewares/validators/videos/video-blacklist.ts +++ b/server/middlewares/validators/videos/video-blacklist.ts @@ -1,11 +1,10 @@ import * as express from 'express' import { body, param, query } from 'express-validator' +import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes' import { isBooleanValid, isIdOrUUIDValid, toBooleanOrNull, toIntOrNull } from '../../../helpers/custom-validators/misc' import { isVideoBlacklistReasonValid, isVideoBlacklistTypeValid } from '../../../helpers/custom-validators/video-blacklist' import { logger } from '../../../helpers/logger' -import { doesVideoBlacklistExist, doesVideoExist } from '../../../helpers/middlewares' -import { areValidationErrors } from '../utils' -import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes' +import { areValidationErrors, doesVideoBlacklistExist, doesVideoExist } from '../shared' const videosBlacklistRemoveValidator = [ param('videoId').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid videoId'), diff --git a/server/middlewares/validators/videos/video-captions.ts b/server/middlewares/validators/videos/video-captions.ts index 872d9c2ab..2295e049a 100644 --- a/server/middlewares/validators/videos/video-captions.ts +++ b/server/middlewares/validators/videos/video-captions.ts @@ -1,13 +1,12 @@ import * as express from 'express' -import { areValidationErrors } from '../utils' -import { isIdOrUUIDValid } from '../../../helpers/custom-validators/misc' import { body, param } from 'express-validator' -import { CONSTRAINTS_FIELDS, MIMETYPES } from '../../../initializers/constants' import { UserRight } from '../../../../shared' -import { logger } from '../../../helpers/logger' +import { isIdOrUUIDValid } from '../../../helpers/custom-validators/misc' import { isVideoCaptionFile, isVideoCaptionLanguageValid } from '../../../helpers/custom-validators/video-captions' import { cleanUpReqFiles } from '../../../helpers/express-utils' -import { checkUserCanManageVideo, doesVideoCaptionExist, doesVideoExist } from '../../../helpers/middlewares' +import { logger } from '../../../helpers/logger' +import { CONSTRAINTS_FIELDS, MIMETYPES } from '../../../initializers/constants' +import { areValidationErrors, checkUserCanManageVideo, doesVideoCaptionExist, doesVideoExist } from '../shared' const addVideoCaptionValidator = [ param('videoId').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid video id'), diff --git a/server/middlewares/validators/videos/video-channels.ts b/server/middlewares/validators/videos/video-channels.ts index 331a51007..911a25bfb 100644 --- a/server/middlewares/validators/videos/video-channels.ts +++ b/server/middlewares/validators/videos/video-channels.ts @@ -12,10 +12,9 @@ import { isVideoChannelSupportValid } from '../../../helpers/custom-validators/video-channels' import { logger } from '../../../helpers/logger' -import { doesLocalVideoChannelNameExist, doesVideoChannelNameWithHostExist } from '../../../helpers/middlewares' import { ActorModel } from '../../../models/actor/actor' import { VideoChannelModel } from '../../../models/video/video-channel' -import { areValidationErrors } from '../utils' +import { areValidationErrors, doesLocalVideoChannelNameExist, doesVideoChannelNameWithHostExist } from '../shared' const videoChannelsAddValidator = [ body('name').custom(isActorPreferredUsernameValid).withMessage('Should have a valid channel name'), diff --git a/server/middlewares/validators/videos/video-comments.ts b/server/middlewares/validators/videos/video-comments.ts index aac25a787..1451ab988 100644 --- a/server/middlewares/validators/videos/video-comments.ts +++ b/server/middlewares/validators/videos/video-comments.ts @@ -2,19 +2,14 @@ import * as express from 'express' import { body, param, query } from 'express-validator' import { MUserAccountUrl } from '@server/types/models' import { UserRight } from '../../../../shared' +import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes' import { exists, isBooleanValid, isIdOrUUIDValid, isIdValid, toBooleanOrNull } from '../../../helpers/custom-validators/misc' -import { - doesVideoCommentExist, - doesVideoCommentThreadExist, - isValidVideoCommentText -} from '../../../helpers/custom-validators/video-comments' +import { isValidVideoCommentText } from '../../../helpers/custom-validators/video-comments' import { logger } from '../../../helpers/logger' -import { doesVideoExist } from '../../../helpers/middlewares' import { AcceptResult, isLocalVideoCommentReplyAccepted, isLocalVideoThreadAccepted } from '../../../lib/moderation' import { Hooks } from '../../../lib/plugins/hooks' import { MCommentOwnerVideoReply, MVideo, MVideoFullLight } from '../../../types/models/video' -import { areValidationErrors } from '../utils' -import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes' +import { areValidationErrors, doesVideoCommentExist, doesVideoCommentThreadExist, doesVideoExist } from '../shared' const listVideoCommentsValidator = [ query('isLocal') diff --git a/server/middlewares/validators/videos/video-imports.ts b/server/middlewares/validators/videos/video-imports.ts index 55ff09124..85dc647ce 100644 --- a/server/middlewares/validators/videos/video-imports.ts +++ b/server/middlewares/validators/videos/video-imports.ts @@ -2,18 +2,17 @@ import * as express from 'express' import { body } from 'express-validator' import { isPreImportVideoAccepted } from '@server/lib/moderation' import { Hooks } from '@server/lib/plugins/hooks' +import { HttpStatusCode } from '@shared/core-utils/miscs/http-error-codes' import { VideoImportCreate } from '@shared/models/videos/import/video-import-create.model' import { isIdValid, toIntOrNull } from '../../../helpers/custom-validators/misc' import { isVideoImportTargetUrlValid, isVideoImportTorrentFile } from '../../../helpers/custom-validators/video-imports' import { isVideoMagnetUriValid, isVideoNameValid } from '../../../helpers/custom-validators/videos' import { cleanUpReqFiles } from '../../../helpers/express-utils' import { logger } from '../../../helpers/logger' -import { doesVideoChannelOfAccountExist } from '../../../helpers/middlewares' import { CONFIG } from '../../../initializers/config' import { CONSTRAINTS_FIELDS } from '../../../initializers/constants' -import { areValidationErrors } from '../utils' +import { areValidationErrors, doesVideoChannelOfAccountExist } from '../shared' import { getCommonVideoEditAttributes } from './videos' -import { HttpStatusCode } from '@shared/core-utils/miscs/http-error-codes' const videoImportAddValidator = getCommonVideoEditAttributes().concat([ body('channelId') diff --git a/server/middlewares/validators/videos/video-live.ts b/server/middlewares/validators/videos/video-live.ts index 0fb864098..ffc8c47b3 100644 --- a/server/middlewares/validators/videos/video-live.ts +++ b/server/middlewares/validators/videos/video-live.ts @@ -1,20 +1,19 @@ import * as express from 'express' import { body, param } from 'express-validator' -import { checkUserCanManageVideo, doesVideoChannelOfAccountExist, doesVideoExist } from '@server/helpers/middlewares/videos' +import { CONSTRAINTS_FIELDS } from '@server/initializers/constants' +import { isLocalLiveVideoAccepted } from '@server/lib/moderation' +import { Hooks } from '@server/lib/plugins/hooks' +import { VideoModel } from '@server/models/video/video' import { VideoLiveModel } from '@server/models/video/video-live' +import { HttpStatusCode } from '@shared/core-utils/miscs/http-error-codes' import { ServerErrorCode, UserRight, VideoState } from '@shared/models' import { isBooleanValid, isIdOrUUIDValid, isIdValid, toBooleanOrNull, toIntOrNull } from '../../../helpers/custom-validators/misc' import { isVideoNameValid } from '../../../helpers/custom-validators/videos' import { cleanUpReqFiles } from '../../../helpers/express-utils' import { logger } from '../../../helpers/logger' import { CONFIG } from '../../../initializers/config' -import { areValidationErrors } from '../utils' +import { areValidationErrors, checkUserCanManageVideo, doesVideoChannelOfAccountExist, doesVideoExist } from '../shared' import { getCommonVideoEditAttributes } from './videos' -import { VideoModel } from '@server/models/video/video' -import { Hooks } from '@server/lib/plugins/hooks' -import { isLocalLiveVideoAccepted } from '@server/lib/moderation' -import { HttpStatusCode } from '@shared/core-utils/miscs/http-error-codes' -import { CONSTRAINTS_FIELDS } from '@server/initializers/constants' const videoLiveGetValidator = [ param('videoId').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid videoId'), diff --git a/server/middlewares/validators/videos/video-playlists.ts b/server/middlewares/validators/videos/video-playlists.ts index 90815dd3a..0d2e6e90c 100644 --- a/server/middlewares/validators/videos/video-playlists.ts +++ b/server/middlewares/validators/videos/video-playlists.ts @@ -25,12 +25,11 @@ import { import { isVideoImage } from '../../../helpers/custom-validators/videos' import { cleanUpReqFiles } from '../../../helpers/express-utils' import { logger } from '../../../helpers/logger' -import { doesVideoChannelIdExist, doesVideoExist, doesVideoPlaylistExist, VideoPlaylistFetchType } from '../../../helpers/middlewares' import { CONSTRAINTS_FIELDS } from '../../../initializers/constants' import { VideoPlaylistElementModel } from '../../../models/video/video-playlist-element' import { MVideoPlaylist } from '../../../types/models/video/video-playlist' import { authenticatePromiseIfNeeded } from '../../auth' -import { areValidationErrors } from '../utils' +import { areValidationErrors, doesVideoChannelIdExist, doesVideoExist, doesVideoPlaylistExist, VideoPlaylistFetchType } from '../shared' const videoPlaylistsAddValidator = getCommonPlaylistEditAttributes().concat([ body('displayName') diff --git a/server/middlewares/validators/videos/video-rates.ts b/server/middlewares/validators/videos/video-rates.ts index 5c4176f54..4a802e75e 100644 --- a/server/middlewares/validators/videos/video-rates.ts +++ b/server/middlewares/validators/videos/video-rates.ts @@ -1,15 +1,14 @@ import * as express from 'express' import { body, param, query } from 'express-validator' +import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes' +import { VideoRateType } from '../../../../shared/models/videos' +import { isAccountNameValid } from '../../../helpers/custom-validators/accounts' import { isIdOrUUIDValid, isIdValid } from '../../../helpers/custom-validators/misc' import { isRatingValid } from '../../../helpers/custom-validators/video-rates' import { isVideoRatingTypeValid } from '../../../helpers/custom-validators/videos' import { logger } from '../../../helpers/logger' -import { areValidationErrors } from '../utils' import { AccountVideoRateModel } from '../../../models/account/account-video-rate' -import { VideoRateType } from '../../../../shared/models/videos' -import { isAccountNameValid } from '../../../helpers/custom-validators/accounts' -import { doesVideoExist } from '../../../helpers/middlewares' -import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes' +import { areValidationErrors, doesVideoExist } from '../shared' const videoUpdateRateValidator = [ param('id').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid id'), diff --git a/server/middlewares/validators/videos/video-shares.ts b/server/middlewares/validators/videos/video-shares.ts index f0d8e0c36..cc2f66e94 100644 --- a/server/middlewares/validators/videos/video-shares.ts +++ b/server/middlewares/validators/videos/video-shares.ts @@ -1,11 +1,10 @@ import * as express from 'express' import { param } from 'express-validator' +import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes' import { isIdOrUUIDValid, isIdValid } from '../../../helpers/custom-validators/misc' import { logger } from '../../../helpers/logger' import { VideoShareModel } from '../../../models/video/video-share' -import { areValidationErrors } from '../utils' -import { doesVideoExist } from '../../../helpers/middlewares' -import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes' +import { areValidationErrors, doesVideoExist } from '../shared' const videosShareValidator = [ param('id').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid id'), diff --git a/server/middlewares/validators/videos/video-watch.ts b/server/middlewares/validators/videos/video-watch.ts index 00c739d31..ef8b89ece 100644 --- a/server/middlewares/validators/videos/video-watch.ts +++ b/server/middlewares/validators/videos/video-watch.ts @@ -1,10 +1,9 @@ -import { body, param } from 'express-validator' import * as express from 'express' +import { body, param } from 'express-validator' +import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes' import { isIdOrUUIDValid, toIntOrNull } from '../../../helpers/custom-validators/misc' -import { areValidationErrors } from '../utils' import { logger } from '../../../helpers/logger' -import { doesVideoExist } from '../../../helpers/middlewares' -import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes' +import { areValidationErrors, doesVideoExist } from '../shared' const videoWatchingValidator = [ param('videoId').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid id'), diff --git a/server/middlewares/validators/videos/videos.ts b/server/middlewares/validators/videos/videos.ts index b7a9bcbe3..52e6c5762 100644 --- a/server/middlewares/validators/videos/videos.ts +++ b/server/middlewares/validators/videos/videos.ts @@ -22,7 +22,7 @@ import { toValueOrNull } from '../../../helpers/custom-validators/misc' import { isBooleanBothQueryValid, isNumberArray, isStringArray } from '../../../helpers/custom-validators/search' -import { checkUserCanTerminateOwnershipChange, doesChangeVideoOwnershipExist } from '../../../helpers/custom-validators/video-ownership' +import { checkUserCanTerminateOwnershipChange } from '../../../helpers/custom-validators/video-ownership' import { isScheduleVideoUpdatePrivacyValid, isVideoCategoryValid, @@ -42,12 +42,6 @@ import { import { cleanUpReqFiles } from '../../../helpers/express-utils' import { getDurationFromVideoFile } from '../../../helpers/ffprobe-utils' import { logger } from '../../../helpers/logger' -import { - checkUserCanManageVideo, - doesVideoChannelOfAccountExist, - doesVideoExist, - doesVideoFileOfVideoExist -} from '../../../helpers/middlewares' import { deleteFileAndCatch } from '../../../helpers/utils' import { getVideoWithAttributes } from '../../../helpers/video' import { CONFIG } from '../../../initializers/config' @@ -57,7 +51,14 @@ import { Hooks } from '../../../lib/plugins/hooks' import { AccountModel } from '../../../models/account/account' import { VideoModel } from '../../../models/video/video' import { authenticatePromiseIfNeeded } from '../../auth' -import { areValidationErrors } from '../utils' +import { + areValidationErrors, + checkUserCanManageVideo, + doesChangeVideoOwnershipExist, + doesVideoChannelOfAccountExist, + doesVideoExist, + doesVideoFileOfVideoExist +} from '../shared' const videosAddLegacyValidator = getCommonVideoEditAttributes().concat([ body('videofile') diff --git a/server/middlewares/validators/webfinger.ts b/server/middlewares/validators/webfinger.ts index 097a5ece1..bcdd136c6 100644 --- a/server/middlewares/validators/webfinger.ts +++ b/server/middlewares/validators/webfinger.ts @@ -5,7 +5,7 @@ import { isWebfingerLocalResourceValid } from '../../helpers/custom-validators/w import { getHostWithPort } from '../../helpers/express-utils' import { logger } from '../../helpers/logger' import { ActorModel } from '../../models/actor/actor' -import { areValidationErrors } from './utils' +import { areValidationErrors } from './shared' const webfingerValidator = [ query('resource').custom(isWebfingerLocalResourceValid).withMessage('Should have a valid webfinger resource'), -- cgit v1.2.3