diff options
Diffstat (limited to 'server/helpers')
-rw-r--r-- | server/helpers/actor.ts | 16 | ||||
-rw-r--r-- | server/helpers/custom-validators/video-comments.ts | 72 | ||||
-rw-r--r-- | server/helpers/custom-validators/video-imports.ts | 19 | ||||
-rw-r--r-- | server/helpers/custom-validators/video-ownership.ts | 25 | ||||
-rw-r--r-- | server/helpers/middlewares/abuses.ts | 25 | ||||
-rw-r--r-- | server/helpers/middlewares/accounts.ts | 65 | ||||
-rw-r--r-- | server/helpers/middlewares/index.ts | 7 | ||||
-rw-r--r-- | server/helpers/middlewares/video-blacklists.ts | 24 | ||||
-rw-r--r-- | server/helpers/middlewares/video-captions.ts | 25 | ||||
-rw-r--r-- | server/helpers/middlewares/video-channels.ts | 43 | ||||
-rw-r--r-- | server/helpers/middlewares/video-playlists.ts | 39 | ||||
-rw-r--r-- | server/helpers/middlewares/videos.ts | 125 | ||||
-rw-r--r-- | server/helpers/signup.ts | 62 | ||||
-rw-r--r-- | server/helpers/video.ts | 65 | ||||
-rw-r--r-- | server/helpers/webfinger.ts | 67 |
15 files changed, 8 insertions, 671 deletions
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 @@ | |||
1 | |||
2 | import { ActorModel } from '../models/actor/actor' | ||
3 | import { MActorAccountChannelId, MActorFull } from '../types/models' | ||
4 | |||
5 | type ActorFetchByUrlType = 'all' | 'association-ids' | ||
6 | |||
7 | function fetchActorByUrl (url: string, fetchType: ActorFetchByUrlType): Promise<MActorFull | MActorAccountChannelId> { | ||
8 | if (fetchType === 'all') return ActorModel.loadByUrlAndPopulateAccountAndChannel(url) | ||
9 | |||
10 | if (fetchType === 'association-ids') return ActorModel.loadByUrl(url) | ||
11 | } | ||
12 | |||
13 | export { | ||
14 | ActorFetchByUrlType, | ||
15 | fetchActorByUrl | ||
16 | } | ||
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 @@ | |||
1 | import * as express from 'express' | ||
2 | import validator from 'validator' | 1 | import validator from 'validator' |
3 | import { VideoCommentModel } from '@server/models/video/video-comment' | ||
4 | import { CONSTRAINTS_FIELDS } from '../../initializers/constants' | 2 | import { CONSTRAINTS_FIELDS } from '../../initializers/constants' |
5 | import { MVideoId } from '@server/types/models' | ||
6 | import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes' | ||
7 | 3 | ||
8 | const VIDEO_COMMENTS_CONSTRAINTS_FIELDS = CONSTRAINTS_FIELDS.VIDEO_COMMENTS | 4 | const VIDEO_COMMENTS_CONSTRAINTS_FIELDS = CONSTRAINTS_FIELDS.VIDEO_COMMENTS |
9 | 5 | ||
@@ -11,74 +7,8 @@ function isValidVideoCommentText (value: string) { | |||
11 | return value === null || validator.isLength(value, VIDEO_COMMENTS_CONSTRAINTS_FIELDS.TEXT) | 7 | return value === null || validator.isLength(value, VIDEO_COMMENTS_CONSTRAINTS_FIELDS.TEXT) |
12 | } | 8 | } |
13 | 9 | ||
14 | async function doesVideoCommentThreadExist (idArg: number | string, video: MVideoId, res: express.Response) { | ||
15 | const id = parseInt(idArg + '', 10) | ||
16 | const videoComment = await VideoCommentModel.loadById(id) | ||
17 | |||
18 | if (!videoComment) { | ||
19 | res.fail({ | ||
20 | status: HttpStatusCode.NOT_FOUND_404, | ||
21 | message: 'Video comment thread not found' | ||
22 | }) | ||
23 | return false | ||
24 | } | ||
25 | |||
26 | if (videoComment.videoId !== video.id) { | ||
27 | res.fail({ message: 'Video comment is not associated to this video.' }) | ||
28 | return false | ||
29 | } | ||
30 | |||
31 | if (videoComment.inReplyToCommentId !== null) { | ||
32 | res.fail({ message: 'Video comment is not a thread.' }) | ||
33 | return false | ||
34 | } | ||
35 | |||
36 | res.locals.videoCommentThread = videoComment | ||
37 | return true | ||
38 | } | ||
39 | |||
40 | async function doesVideoCommentExist (idArg: number | string, video: MVideoId, res: express.Response) { | ||
41 | const id = parseInt(idArg + '', 10) | ||
42 | const videoComment = await VideoCommentModel.loadByIdAndPopulateVideoAndAccountAndReply(id) | ||
43 | |||
44 | if (!videoComment) { | ||
45 | res.fail({ | ||
46 | status: HttpStatusCode.NOT_FOUND_404, | ||
47 | message: 'Video comment thread not found' | ||
48 | }) | ||
49 | return false | ||
50 | } | ||
51 | |||
52 | if (videoComment.videoId !== video.id) { | ||
53 | res.fail({ message: 'Video comment is not associated to this video.' }) | ||
54 | return false | ||
55 | } | ||
56 | |||
57 | res.locals.videoCommentFull = videoComment | ||
58 | return true | ||
59 | } | ||
60 | |||
61 | async function doesCommentIdExist (idArg: number | string, res: express.Response) { | ||
62 | const id = parseInt(idArg + '', 10) | ||
63 | const videoComment = await VideoCommentModel.loadByIdAndPopulateVideoAndAccountAndReply(id) | ||
64 | |||
65 | if (!videoComment) { | ||
66 | res.fail({ | ||
67 | status: HttpStatusCode.NOT_FOUND_404, | ||
68 | message: 'Video comment thread not found' | ||
69 | }) | ||
70 | return false | ||
71 | } | ||
72 | |||
73 | res.locals.videoCommentFull = videoComment | ||
74 | return true | ||
75 | } | ||
76 | |||
77 | // --------------------------------------------------------------------------- | 10 | // --------------------------------------------------------------------------- |
78 | 11 | ||
79 | export { | 12 | export { |
80 | isValidVideoCommentText, | 13 | isValidVideoCommentText |
81 | doesVideoCommentThreadExist, | ||
82 | doesVideoCommentExist, | ||
83 | doesCommentIdExist | ||
84 | } | 14 | } |
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' | |||
2 | import validator from 'validator' | 2 | import validator from 'validator' |
3 | import { CONSTRAINTS_FIELDS, MIMETYPES, VIDEO_IMPORT_STATES } from '../../initializers/constants' | 3 | import { CONSTRAINTS_FIELDS, MIMETYPES, VIDEO_IMPORT_STATES } from '../../initializers/constants' |
4 | import { exists, isFileValid } from './misc' | 4 | import { exists, isFileValid } from './misc' |
5 | import * as express from 'express' | ||
6 | import { VideoImportModel } from '../../models/video/video-import' | ||
7 | import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes' | ||
8 | 5 | ||
9 | function isVideoImportTargetUrlValid (url: string) { | 6 | function isVideoImportTargetUrlValid (url: string) { |
10 | const isURLOptions = { | 7 | const isURLOptions = { |
@@ -32,26 +29,10 @@ function isVideoImportTorrentFile (files: { [ fieldname: string ]: Express.Multe | |||
32 | return isFileValid(files, videoTorrentImportRegex, 'torrentfile', CONSTRAINTS_FIELDS.VIDEO_IMPORTS.TORRENT_FILE.FILE_SIZE.max, true) | 29 | return isFileValid(files, videoTorrentImportRegex, 'torrentfile', CONSTRAINTS_FIELDS.VIDEO_IMPORTS.TORRENT_FILE.FILE_SIZE.max, true) |
33 | } | 30 | } |
34 | 31 | ||
35 | async function doesVideoImportExist (id: number, res: express.Response) { | ||
36 | const videoImport = await VideoImportModel.loadAndPopulateVideo(id) | ||
37 | |||
38 | if (!videoImport) { | ||
39 | res.fail({ | ||
40 | status: HttpStatusCode.NOT_FOUND_404, | ||
41 | message: 'Video import not found' | ||
42 | }) | ||
43 | return false | ||
44 | } | ||
45 | |||
46 | res.locals.videoImport = videoImport | ||
47 | return true | ||
48 | } | ||
49 | |||
50 | // --------------------------------------------------------------------------- | 32 | // --------------------------------------------------------------------------- |
51 | 33 | ||
52 | export { | 34 | export { |
53 | isVideoImportStateValid, | 35 | isVideoImportStateValid, |
54 | isVideoImportTargetUrlValid, | 36 | isVideoImportTargetUrlValid, |
55 | doesVideoImportExist, | ||
56 | isVideoImportTorrentFile | 37 | isVideoImportTorrentFile |
57 | } | 38 | } |
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 @@ | |||
1 | import { Response } from 'express' | 1 | import { Response } from 'express' |
2 | import { VideoChangeOwnershipModel } from '../../models/video/video-change-ownership' | ||
3 | import { MVideoChangeOwnershipFull } from '@server/types/models/video/video-change-ownership' | ||
4 | import { MUserId } from '@server/types/models' | 2 | import { MUserId } from '@server/types/models' |
3 | import { MVideoChangeOwnershipFull } from '@server/types/models/video/video-change-ownership' | ||
5 | import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes' | 4 | import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes' |
6 | 5 | ||
7 | export async function doesChangeVideoOwnershipExist (idArg: number | string, res: Response) { | 6 | function checkUserCanTerminateOwnershipChange (user: MUserId, videoChangeOwnership: MVideoChangeOwnershipFull, res: Response) { |
8 | const id = parseInt(idArg + '', 10) | ||
9 | const videoChangeOwnership = await VideoChangeOwnershipModel.load(id) | ||
10 | |||
11 | if (!videoChangeOwnership) { | ||
12 | res.fail({ | ||
13 | status: HttpStatusCode.NOT_FOUND_404, | ||
14 | message: 'Video change ownership not found' | ||
15 | }) | ||
16 | return false | ||
17 | } | ||
18 | |||
19 | res.locals.videoChangeOwnership = videoChangeOwnership | ||
20 | return true | ||
21 | } | ||
22 | |||
23 | export function checkUserCanTerminateOwnershipChange (user: MUserId, videoChangeOwnership: MVideoChangeOwnershipFull, res: Response) { | ||
24 | if (videoChangeOwnership.NextOwner.userId === user.id) { | 7 | if (videoChangeOwnership.NextOwner.userId === user.id) { |
25 | return true | 8 | return true |
26 | } | 9 | } |
@@ -31,3 +14,7 @@ export function checkUserCanTerminateOwnershipChange (user: MUserId, videoChange | |||
31 | }) | 14 | }) |
32 | return false | 15 | return false |
33 | } | 16 | } |
17 | |||
18 | export { | ||
19 | checkUserCanTerminateOwnershipChange | ||
20 | } | ||
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 @@ | |||
1 | import { Response } from 'express' | ||
2 | import { AbuseModel } from '../../models/abuse/abuse' | ||
3 | import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes' | ||
4 | |||
5 | async function doesAbuseExist (abuseId: number | string, res: Response) { | ||
6 | const abuse = await AbuseModel.loadByIdWithReporter(parseInt(abuseId + '', 10)) | ||
7 | |||
8 | if (!abuse) { | ||
9 | res.fail({ | ||
10 | status: HttpStatusCode.NOT_FOUND_404, | ||
11 | message: 'Abuse not found' | ||
12 | }) | ||
13 | |||
14 | return false | ||
15 | } | ||
16 | |||
17 | res.locals.abuse = abuse | ||
18 | return true | ||
19 | } | ||
20 | |||
21 | // --------------------------------------------------------------------------- | ||
22 | |||
23 | export { | ||
24 | doesAbuseExist | ||
25 | } | ||
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 @@ | |||
1 | import { Response } from 'express' | ||
2 | import { UserModel } from '@server/models/user/user' | ||
3 | import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes' | ||
4 | import { AccountModel } from '../../models/account/account' | ||
5 | import { MAccountDefault } from '../../types/models' | ||
6 | |||
7 | function doesAccountIdExist (id: number | string, res: Response, sendNotFound = true) { | ||
8 | const promise = AccountModel.load(parseInt(id + '', 10)) | ||
9 | |||
10 | return doesAccountExist(promise, res, sendNotFound) | ||
11 | } | ||
12 | |||
13 | function doesLocalAccountNameExist (name: string, res: Response, sendNotFound = true) { | ||
14 | const promise = AccountModel.loadLocalByName(name) | ||
15 | |||
16 | return doesAccountExist(promise, res, sendNotFound) | ||
17 | } | ||
18 | |||
19 | function doesAccountNameWithHostExist (nameWithDomain: string, res: Response, sendNotFound = true) { | ||
20 | const promise = AccountModel.loadByNameWithHost(nameWithDomain) | ||
21 | |||
22 | return doesAccountExist(promise, res, sendNotFound) | ||
23 | } | ||
24 | |||
25 | async function doesAccountExist (p: Promise<MAccountDefault>, res: Response, sendNotFound: boolean) { | ||
26 | const account = await p | ||
27 | |||
28 | if (!account) { | ||
29 | if (sendNotFound === true) { | ||
30 | res.fail({ | ||
31 | status: HttpStatusCode.NOT_FOUND_404, | ||
32 | message: 'Account not found' | ||
33 | }) | ||
34 | } | ||
35 | return false | ||
36 | } | ||
37 | |||
38 | res.locals.account = account | ||
39 | return true | ||
40 | } | ||
41 | |||
42 | async function doesUserFeedTokenCorrespond (id: number, token: string, res: Response) { | ||
43 | const user = await UserModel.loadByIdWithChannels(parseInt(id + '', 10)) | ||
44 | |||
45 | if (token !== user.feedToken) { | ||
46 | res.fail({ | ||
47 | status: HttpStatusCode.FORBIDDEN_403, | ||
48 | message: 'User and token mismatch' | ||
49 | }) | ||
50 | return false | ||
51 | } | ||
52 | |||
53 | res.locals.user = user | ||
54 | return true | ||
55 | } | ||
56 | |||
57 | // --------------------------------------------------------------------------- | ||
58 | |||
59 | export { | ||
60 | doesAccountIdExist, | ||
61 | doesLocalAccountNameExist, | ||
62 | doesAccountNameWithHostExist, | ||
63 | doesAccountExist, | ||
64 | doesUserFeedTokenCorrespond | ||
65 | } | ||
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 @@ | |||
1 | export * from './abuses' | ||
2 | export * from './accounts' | ||
3 | export * from './video-blacklists' | ||
4 | export * from './video-captions' | ||
5 | export * from './video-channels' | ||
6 | export * from './video-playlists' | ||
7 | 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 @@ | |||
1 | import { Response } from 'express' | ||
2 | import { VideoBlacklistModel } from '../../models/video/video-blacklist' | ||
3 | import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes' | ||
4 | |||
5 | async function doesVideoBlacklistExist (videoId: number, res: Response) { | ||
6 | const videoBlacklist = await VideoBlacklistModel.loadByVideoId(videoId) | ||
7 | |||
8 | if (videoBlacklist === null) { | ||
9 | res.fail({ | ||
10 | status: HttpStatusCode.NOT_FOUND_404, | ||
11 | message: 'Blacklisted video not found' | ||
12 | }) | ||
13 | return false | ||
14 | } | ||
15 | |||
16 | res.locals.videoBlacklist = videoBlacklist | ||
17 | return true | ||
18 | } | ||
19 | |||
20 | // --------------------------------------------------------------------------- | ||
21 | |||
22 | export { | ||
23 | doesVideoBlacklistExist | ||
24 | } | ||
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 @@ | |||
1 | import { Response } from 'express' | ||
2 | import { VideoCaptionModel } from '../../models/video/video-caption' | ||
3 | import { MVideoId } from '@server/types/models' | ||
4 | import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes' | ||
5 | |||
6 | async function doesVideoCaptionExist (video: MVideoId, language: string, res: Response) { | ||
7 | const videoCaption = await VideoCaptionModel.loadByVideoIdAndLanguage(video.id, language) | ||
8 | |||
9 | if (!videoCaption) { | ||
10 | res.fail({ | ||
11 | status: HttpStatusCode.NOT_FOUND_404, | ||
12 | message: 'Video caption not found' | ||
13 | }) | ||
14 | return false | ||
15 | } | ||
16 | |||
17 | res.locals.videoCaption = videoCaption | ||
18 | return true | ||
19 | } | ||
20 | |||
21 | // --------------------------------------------------------------------------- | ||
22 | |||
23 | export { | ||
24 | doesVideoCaptionExist | ||
25 | } | ||
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 @@ | |||
1 | import * as express from 'express' | ||
2 | import { MChannelBannerAccountDefault } from '@server/types/models' | ||
3 | import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes' | ||
4 | import { VideoChannelModel } from '../../models/video/video-channel' | ||
5 | |||
6 | async function doesLocalVideoChannelNameExist (name: string, res: express.Response) { | ||
7 | const videoChannel = await VideoChannelModel.loadLocalByNameAndPopulateAccount(name) | ||
8 | |||
9 | return processVideoChannelExist(videoChannel, res) | ||
10 | } | ||
11 | |||
12 | async function doesVideoChannelIdExist (id: number, res: express.Response) { | ||
13 | const videoChannel = await VideoChannelModel.loadAndPopulateAccount(+id) | ||
14 | |||
15 | return processVideoChannelExist(videoChannel, res) | ||
16 | } | ||
17 | |||
18 | async function doesVideoChannelNameWithHostExist (nameWithDomain: string, res: express.Response) { | ||
19 | const videoChannel = await VideoChannelModel.loadByNameWithHostAndPopulateAccount(nameWithDomain) | ||
20 | |||
21 | return processVideoChannelExist(videoChannel, res) | ||
22 | } | ||
23 | |||
24 | // --------------------------------------------------------------------------- | ||
25 | |||
26 | export { | ||
27 | doesLocalVideoChannelNameExist, | ||
28 | doesVideoChannelIdExist, | ||
29 | doesVideoChannelNameWithHostExist | ||
30 | } | ||
31 | |||
32 | function processVideoChannelExist (videoChannel: MChannelBannerAccountDefault, res: express.Response) { | ||
33 | if (!videoChannel) { | ||
34 | res.fail({ | ||
35 | status: HttpStatusCode.NOT_FOUND_404, | ||
36 | message: 'Video channel not found' | ||
37 | }) | ||
38 | return false | ||
39 | } | ||
40 | |||
41 | res.locals.videoChannel = videoChannel | ||
42 | return true | ||
43 | } | ||
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 @@ | |||
1 | import * as express from 'express' | ||
2 | import { VideoPlaylistModel } from '../../models/video/video-playlist' | ||
3 | import { MVideoPlaylist } from '../../types/models/video/video-playlist' | ||
4 | import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes' | ||
5 | |||
6 | export type VideoPlaylistFetchType = 'summary' | 'all' | ||
7 | async function doesVideoPlaylistExist (id: number | string, res: express.Response, fetchType: VideoPlaylistFetchType = 'summary') { | ||
8 | if (fetchType === 'summary') { | ||
9 | const videoPlaylist = await VideoPlaylistModel.loadWithAccountAndChannelSummary(id, undefined) | ||
10 | res.locals.videoPlaylistSummary = videoPlaylist | ||
11 | |||
12 | return handleVideoPlaylist(videoPlaylist, res) | ||
13 | } | ||
14 | |||
15 | const videoPlaylist = await VideoPlaylistModel.loadWithAccountAndChannel(id, undefined) | ||
16 | res.locals.videoPlaylistFull = videoPlaylist | ||
17 | |||
18 | return handleVideoPlaylist(videoPlaylist, res) | ||
19 | } | ||
20 | |||
21 | // --------------------------------------------------------------------------- | ||
22 | |||
23 | export { | ||
24 | doesVideoPlaylistExist | ||
25 | } | ||
26 | |||
27 | // --------------------------------------------------------------------------- | ||
28 | |||
29 | function handleVideoPlaylist (videoPlaylist: MVideoPlaylist, res: express.Response) { | ||
30 | if (!videoPlaylist) { | ||
31 | res.fail({ | ||
32 | status: HttpStatusCode.NOT_FOUND_404, | ||
33 | message: 'Video playlist not found' | ||
34 | }) | ||
35 | return false | ||
36 | } | ||
37 | |||
38 | return true | ||
39 | } | ||
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 @@ | |||
1 | import { Response } from 'express' | ||
2 | import { fetchVideo, VideoFetchType } from '../video' | ||
3 | import { UserRight } from '../../../shared/models/users' | ||
4 | import { VideoChannelModel } from '../../models/video/video-channel' | ||
5 | import { | ||
6 | MUser, | ||
7 | MUserAccountId, | ||
8 | MVideoAccountLight, | ||
9 | MVideoFullLight, | ||
10 | MVideoIdThumbnail, | ||
11 | MVideoImmutable, | ||
12 | MVideoThumbnail, | ||
13 | MVideoWithRights | ||
14 | } from '@server/types/models' | ||
15 | import { VideoFileModel } from '@server/models/video/video-file' | ||
16 | import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes' | ||
17 | |||
18 | async function doesVideoExist (id: number | string, res: Response, fetchType: VideoFetchType = 'all') { | ||
19 | const userId = res.locals.oauth ? res.locals.oauth.token.User.id : undefined | ||
20 | |||
21 | const video = await fetchVideo(id, fetchType, userId) | ||
22 | |||
23 | if (video === null) { | ||
24 | res.fail({ | ||
25 | status: HttpStatusCode.NOT_FOUND_404, | ||
26 | message: 'Video not found' | ||
27 | }) | ||
28 | return false | ||
29 | } | ||
30 | |||
31 | switch (fetchType) { | ||
32 | case 'all': | ||
33 | res.locals.videoAll = video as MVideoFullLight | ||
34 | break | ||
35 | |||
36 | case 'only-immutable-attributes': | ||
37 | res.locals.onlyImmutableVideo = video as MVideoImmutable | ||
38 | break | ||
39 | |||
40 | case 'id': | ||
41 | res.locals.videoId = video as MVideoIdThumbnail | ||
42 | break | ||
43 | |||
44 | case 'only-video': | ||
45 | res.locals.onlyVideo = video as MVideoThumbnail | ||
46 | break | ||
47 | |||
48 | case 'only-video-with-rights': | ||
49 | res.locals.onlyVideoWithRights = video as MVideoWithRights | ||
50 | break | ||
51 | } | ||
52 | |||
53 | return true | ||
54 | } | ||
55 | |||
56 | async function doesVideoFileOfVideoExist (id: number, videoIdOrUUID: number | string, res: Response) { | ||
57 | if (!await VideoFileModel.doesVideoExistForVideoFile(id, videoIdOrUUID)) { | ||
58 | res.fail({ | ||
59 | status: HttpStatusCode.NOT_FOUND_404, | ||
60 | message: 'VideoFile matching Video not found' | ||
61 | }) | ||
62 | return false | ||
63 | } | ||
64 | |||
65 | return true | ||
66 | } | ||
67 | |||
68 | async function doesVideoChannelOfAccountExist (channelId: number, user: MUserAccountId, res: Response) { | ||
69 | const videoChannel = await VideoChannelModel.loadAndPopulateAccount(channelId) | ||
70 | |||
71 | if (videoChannel === null) { | ||
72 | res.fail({ message: 'Unknown video "video channel" for this instance.' }) | ||
73 | return false | ||
74 | } | ||
75 | |||
76 | // Don't check account id if the user can update any video | ||
77 | if (user.hasRight(UserRight.UPDATE_ANY_VIDEO) === true) { | ||
78 | res.locals.videoChannel = videoChannel | ||
79 | return true | ||
80 | } | ||
81 | |||
82 | if (videoChannel.Account.id !== user.Account.id) { | ||
83 | res.fail({ | ||
84 | message: 'Unknown video "video channel" for this account.' | ||
85 | }) | ||
86 | return false | ||
87 | } | ||
88 | |||
89 | res.locals.videoChannel = videoChannel | ||
90 | return true | ||
91 | } | ||
92 | |||
93 | function checkUserCanManageVideo (user: MUser, video: MVideoAccountLight, right: UserRight, res: Response, onlyOwned = true) { | ||
94 | // Retrieve the user who did the request | ||
95 | if (onlyOwned && video.isOwned() === false) { | ||
96 | res.fail({ | ||
97 | status: HttpStatusCode.FORBIDDEN_403, | ||
98 | message: 'Cannot manage a video of another server.' | ||
99 | }) | ||
100 | return false | ||
101 | } | ||
102 | |||
103 | // Check if the user can delete the video | ||
104 | // The user can delete it if he has the right | ||
105 | // Or if s/he is the video's account | ||
106 | const account = video.VideoChannel.Account | ||
107 | if (user.hasRight(right) === false && account.userId !== user.id) { | ||
108 | res.fail({ | ||
109 | status: HttpStatusCode.FORBIDDEN_403, | ||
110 | message: 'Cannot manage a video of another user.' | ||
111 | }) | ||
112 | return false | ||
113 | } | ||
114 | |||
115 | return true | ||
116 | } | ||
117 | |||
118 | // --------------------------------------------------------------------------- | ||
119 | |||
120 | export { | ||
121 | doesVideoChannelOfAccountExist, | ||
122 | doesVideoExist, | ||
123 | doesVideoFileOfVideoExist, | ||
124 | checkUserCanManageVideo | ||
125 | } | ||
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 @@ | |||
1 | import { UserModel } from '../models/user/user' | ||
2 | import * as ipaddr from 'ipaddr.js' | ||
3 | import { CONFIG } from '../initializers/config' | ||
4 | |||
5 | const isCidr = require('is-cidr') | ||
6 | |||
7 | async function isSignupAllowed (): Promise<{ allowed: boolean, errorMessage?: string }> { | ||
8 | if (CONFIG.SIGNUP.ENABLED === false) { | ||
9 | return { allowed: false } | ||
10 | } | ||
11 | |||
12 | // No limit and signup is enabled | ||
13 | if (CONFIG.SIGNUP.LIMIT === -1) { | ||
14 | return { allowed: true } | ||
15 | } | ||
16 | |||
17 | const totalUsers = await UserModel.countTotal() | ||
18 | |||
19 | return { allowed: totalUsers < CONFIG.SIGNUP.LIMIT } | ||
20 | } | ||
21 | |||
22 | function isSignupAllowedForCurrentIP (ip: string) { | ||
23 | if (!ip) return false | ||
24 | |||
25 | const addr = ipaddr.parse(ip) | ||
26 | const excludeList = [ 'blacklist' ] | ||
27 | let matched = '' | ||
28 | |||
29 | // if there is a valid, non-empty whitelist, we exclude all unknown adresses too | ||
30 | if (CONFIG.SIGNUP.FILTERS.CIDR.WHITELIST.filter(cidr => isCidr(cidr)).length > 0) { | ||
31 | excludeList.push('unknown') | ||
32 | } | ||
33 | |||
34 | if (addr.kind() === 'ipv4') { | ||
35 | const addrV4 = ipaddr.IPv4.parse(ip) | ||
36 | const rangeList = { | ||
37 | whitelist: CONFIG.SIGNUP.FILTERS.CIDR.WHITELIST.filter(cidr => isCidr.v4(cidr)) | ||
38 | .map(cidr => ipaddr.IPv4.parseCIDR(cidr)), | ||
39 | blacklist: CONFIG.SIGNUP.FILTERS.CIDR.BLACKLIST.filter(cidr => isCidr.v4(cidr)) | ||
40 | .map(cidr => ipaddr.IPv4.parseCIDR(cidr)) | ||
41 | } | ||
42 | matched = ipaddr.subnetMatch(addrV4, rangeList, 'unknown') | ||
43 | } else if (addr.kind() === 'ipv6') { | ||
44 | const addrV6 = ipaddr.IPv6.parse(ip) | ||
45 | const rangeList = { | ||
46 | whitelist: CONFIG.SIGNUP.FILTERS.CIDR.WHITELIST.filter(cidr => isCidr.v6(cidr)) | ||
47 | .map(cidr => ipaddr.IPv6.parseCIDR(cidr)), | ||
48 | blacklist: CONFIG.SIGNUP.FILTERS.CIDR.BLACKLIST.filter(cidr => isCidr.v6(cidr)) | ||
49 | .map(cidr => ipaddr.IPv6.parseCIDR(cidr)) | ||
50 | } | ||
51 | matched = ipaddr.subnetMatch(addrV6, rangeList, 'unknown') | ||
52 | } | ||
53 | |||
54 | return !excludeList.includes(matched) | ||
55 | } | ||
56 | |||
57 | // --------------------------------------------------------------------------- | ||
58 | |||
59 | export { | ||
60 | isSignupAllowed, | ||
61 | isSignupAllowedForCurrentIP | ||
62 | } | ||
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 @@ | |||
1 | import { Response } from 'express' | 1 | import { Response } from 'express' |
2 | import { CONFIG } from '@server/initializers/config' | 2 | import { CONFIG } from '@server/initializers/config' |
3 | import { | 3 | import { isStreamingPlaylist, MStreamingPlaylistVideo, MVideo } from '@server/types/models' |
4 | isStreamingPlaylist, | ||
5 | MStreamingPlaylistVideo, | ||
6 | MVideo, | ||
7 | MVideoAccountLightBlacklistAllFiles, | ||
8 | MVideoFullLight, | ||
9 | MVideoIdThumbnail, | ||
10 | MVideoImmutable, | ||
11 | MVideoThumbnail, | ||
12 | MVideoWithRights | ||
13 | } from '@server/types/models' | ||
14 | import { VideoPrivacy, VideoState } from '@shared/models' | 4 | import { VideoPrivacy, VideoState } from '@shared/models' |
15 | import { VideoModel } from '../models/video/video' | ||
16 | |||
17 | type VideoFetchType = 'all' | 'only-video' | 'only-video-with-rights' | 'id' | 'none' | 'only-immutable-attributes' | ||
18 | |||
19 | function fetchVideo (id: number | string, fetchType: 'all', userId?: number): Promise<MVideoFullLight> | ||
20 | function fetchVideo (id: number | string, fetchType: 'only-immutable-attributes'): Promise<MVideoImmutable> | ||
21 | function fetchVideo (id: number | string, fetchType: 'only-video', userId?: number): Promise<MVideoThumbnail> | ||
22 | function fetchVideo (id: number | string, fetchType: 'only-video-with-rights', userId?: number): Promise<MVideoWithRights> | ||
23 | function fetchVideo (id: number | string, fetchType: 'id' | 'none', userId?: number): Promise<MVideoIdThumbnail> | ||
24 | function fetchVideo ( | ||
25 | id: number | string, | ||
26 | fetchType: VideoFetchType, | ||
27 | userId?: number | ||
28 | ): Promise<MVideoFullLight | MVideoThumbnail | MVideoWithRights | MVideoIdThumbnail | MVideoImmutable> | ||
29 | function fetchVideo ( | ||
30 | id: number | string, | ||
31 | fetchType: VideoFetchType, | ||
32 | userId?: number | ||
33 | ): Promise<MVideoFullLight | MVideoThumbnail | MVideoWithRights | MVideoIdThumbnail | MVideoImmutable> { | ||
34 | if (fetchType === 'all') return VideoModel.loadAndPopulateAccountAndServerAndTags(id, undefined, userId) | ||
35 | |||
36 | if (fetchType === 'only-immutable-attributes') return VideoModel.loadImmutableAttributes(id) | ||
37 | |||
38 | if (fetchType === 'only-video-with-rights') return VideoModel.loadWithRights(id) | ||
39 | |||
40 | if (fetchType === 'only-video') return VideoModel.load(id) | ||
41 | |||
42 | if (fetchType === 'id' || fetchType === 'none') return VideoModel.loadOnlyId(id) | ||
43 | } | ||
44 | |||
45 | type VideoFetchByUrlType = 'all' | 'only-video' | 'only-immutable-attributes' | ||
46 | |||
47 | function fetchVideoByUrl (url: string, fetchType: 'all'): Promise<MVideoAccountLightBlacklistAllFiles> | ||
48 | function fetchVideoByUrl (url: string, fetchType: 'only-immutable-attributes'): Promise<MVideoImmutable> | ||
49 | function fetchVideoByUrl (url: string, fetchType: 'only-video'): Promise<MVideoThumbnail> | ||
50 | function fetchVideoByUrl ( | ||
51 | url: string, | ||
52 | fetchType: VideoFetchByUrlType | ||
53 | ): Promise<MVideoAccountLightBlacklistAllFiles | MVideoThumbnail | MVideoImmutable> | ||
54 | function fetchVideoByUrl ( | ||
55 | url: string, | ||
56 | fetchType: VideoFetchByUrlType | ||
57 | ): Promise<MVideoAccountLightBlacklistAllFiles | MVideoThumbnail | MVideoImmutable> { | ||
58 | if (fetchType === 'all') return VideoModel.loadByUrlAndPopulateAccount(url) | ||
59 | |||
60 | if (fetchType === 'only-immutable-attributes') return VideoModel.loadByUrlImmutableAttributes(url) | ||
61 | |||
62 | if (fetchType === 'only-video') return VideoModel.loadByUrl(url) | ||
63 | } | ||
64 | 5 | ||
65 | function getVideoWithAttributes (res: Response) { | 6 | function getVideoWithAttributes (res: Response) { |
66 | return res.locals.videoAll || res.locals.onlyVideo || res.locals.onlyVideoWithRights | 7 | return res.locals.videoAll || res.locals.onlyVideo || res.locals.onlyVideoWithRights |
@@ -100,11 +41,7 @@ function getExtFromMimetype (mimeTypes: { [id: string]: string | string[] }, mim | |||
100 | } | 41 | } |
101 | 42 | ||
102 | export { | 43 | export { |
103 | VideoFetchType, | ||
104 | VideoFetchByUrlType, | ||
105 | fetchVideo, | ||
106 | getVideoWithAttributes, | 44 | getVideoWithAttributes, |
107 | fetchVideoByUrl, | ||
108 | extractVideo, | 45 | extractVideo, |
109 | getExtFromMimetype, | 46 | getExtFromMimetype, |
110 | isStateForFederation, | 47 | 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 @@ | |||
1 | import * as WebFinger from 'webfinger.js' | ||
2 | import { WebFingerData } from '../../shared' | ||
3 | import { WEBSERVER } from '../initializers/constants' | ||
4 | import { ActorModel } from '../models/actor/actor' | ||
5 | import { MActorFull } from '../types/models' | ||
6 | import { isTestInstance } from './core-utils' | ||
7 | import { isActivityPubUrlValid } from './custom-validators/activitypub/misc' | ||
8 | |||
9 | const webfinger = new WebFinger({ | ||
10 | webfist_fallback: false, | ||
11 | tls_only: isTestInstance(), | ||
12 | uri_fallback: false, | ||
13 | request_timeout: 3000 | ||
14 | }) | ||
15 | |||
16 | async function loadActorUrlOrGetFromWebfinger (uriArg: string) { | ||
17 | // Handle strings like @toto@example.com | ||
18 | const uri = uriArg.startsWith('@') ? uriArg.slice(1) : uriArg | ||
19 | |||
20 | const [ name, host ] = uri.split('@') | ||
21 | let actor: MActorFull | ||
22 | |||
23 | if (!host || host === WEBSERVER.HOST) { | ||
24 | actor = await ActorModel.loadLocalByName(name) | ||
25 | } else { | ||
26 | actor = await ActorModel.loadByNameAndHost(name, host) | ||
27 | } | ||
28 | |||
29 | if (actor) return actor.url | ||
30 | |||
31 | return getUrlFromWebfinger(uri) | ||
32 | } | ||
33 | |||
34 | async function getUrlFromWebfinger (uri: string) { | ||
35 | const webfingerData: WebFingerData = await webfingerLookup(uri) | ||
36 | return getLinkOrThrow(webfingerData) | ||
37 | } | ||
38 | |||
39 | // --------------------------------------------------------------------------- | ||
40 | |||
41 | export { | ||
42 | getUrlFromWebfinger, | ||
43 | loadActorUrlOrGetFromWebfinger | ||
44 | } | ||
45 | |||
46 | // --------------------------------------------------------------------------- | ||
47 | |||
48 | function getLinkOrThrow (webfingerData: WebFingerData) { | ||
49 | if (Array.isArray(webfingerData.links) === false) throw new Error('WebFinger links is not an array.') | ||
50 | |||
51 | const selfLink = webfingerData.links.find(l => l.rel === 'self') | ||
52 | if (selfLink === undefined || isActivityPubUrlValid(selfLink.href) === false) { | ||
53 | throw new Error('Cannot find self link or href is not a valid URL.') | ||
54 | } | ||
55 | |||
56 | return selfLink.href | ||
57 | } | ||
58 | |||
59 | function webfingerLookup (nameWithHost: string) { | ||
60 | return new Promise<WebFingerData>((res, rej) => { | ||
61 | webfinger.lookup(nameWithHost, (err, p) => { | ||
62 | if (err) return rej(err) | ||
63 | |||
64 | return res(p.object) | ||
65 | }) | ||
66 | }) | ||
67 | } | ||