diff options
-rw-r--r-- | server/controllers/api/config.ts | 2 | ||||
-rw-r--r-- | server/controllers/api/video-channel.ts | 8 | ||||
-rw-r--r-- | server/controllers/api/videos/index.ts | 5 | ||||
-rw-r--r-- | server/helpers/core-utils.ts | 29 | ||||
-rw-r--r-- | server/helpers/database-utils.ts | 10 | ||||
-rw-r--r-- | server/helpers/express-utils.ts | 24 | ||||
-rw-r--r-- | server/helpers/ffmpeg-utils.ts | 23 | ||||
-rw-r--r-- | server/helpers/signup.ts | 59 | ||||
-rw-r--r-- | server/helpers/utils.ts | 151 | ||||
-rw-r--r-- | server/lib/activitypub/process/process-update.ts | 3 | ||||
-rw-r--r-- | server/lib/job-queue/handlers/video-file.ts | 2 | ||||
-rw-r--r-- | server/middlewares/cache.ts | 2 | ||||
-rw-r--r-- | server/middlewares/sort.ts | 2 | ||||
-rw-r--r-- | server/middlewares/validators/avatar.ts | 2 | ||||
-rw-r--r-- | server/middlewares/validators/users.ts | 2 | ||||
-rw-r--r-- | server/middlewares/validators/video-captions.ts | 2 | ||||
-rw-r--r-- | server/middlewares/validators/video-imports.ts | 2 | ||||
-rw-r--r-- | server/middlewares/validators/videos.ts | 2 | ||||
-rw-r--r-- | server/models/utils.ts | 3 | ||||
-rw-r--r-- | server/models/video/video-blacklist.ts | 6 |
20 files changed, 173 insertions, 166 deletions
diff --git a/server/controllers/api/config.ts b/server/controllers/api/config.ts index 6f05c33db..e0539c414 100644 --- a/server/controllers/api/config.ts +++ b/server/controllers/api/config.ts | |||
@@ -4,7 +4,7 @@ import { ServerConfig, UserRight } from '../../../shared' | |||
4 | import { About } from '../../../shared/models/server/about.model' | 4 | import { About } from '../../../shared/models/server/about.model' |
5 | import { CustomConfig } from '../../../shared/models/server/custom-config.model' | 5 | import { CustomConfig } from '../../../shared/models/server/custom-config.model' |
6 | import { unlinkPromise, writeFilePromise } from '../../helpers/core-utils' | 6 | import { unlinkPromise, writeFilePromise } from '../../helpers/core-utils' |
7 | import { isSignupAllowed, isSignupAllowedForCurrentIP } from '../../helpers/utils' | 7 | import { isSignupAllowed, isSignupAllowedForCurrentIP } from '../../helpers/signup' |
8 | import { CONFIG, CONSTRAINTS_FIELDS, reloadConfig } from '../../initializers' | 8 | import { CONFIG, CONSTRAINTS_FIELDS, reloadConfig } from '../../initializers' |
9 | import { asyncMiddleware, authenticate, ensureUserHasRight } from '../../middlewares' | 9 | import { asyncMiddleware, authenticate, ensureUserHasRight } from '../../middlewares' |
10 | import { customConfigUpdateValidator } from '../../middlewares/validators/config' | 10 | import { customConfigUpdateValidator } from '../../middlewares/validators/config' |
diff --git a/server/controllers/api/video-channel.ts b/server/controllers/api/video-channel.ts index 3a444547b..023ebbedf 100644 --- a/server/controllers/api/video-channel.ts +++ b/server/controllers/api/video-channel.ts | |||
@@ -1,9 +1,10 @@ | |||
1 | import * as express from 'express' | 1 | import * as express from 'express' |
2 | import { getFormattedObjects, resetSequelizeInstance } from '../../helpers/utils' | 2 | import { getFormattedObjects } from '../../helpers/utils' |
3 | import { | 3 | import { |
4 | asyncMiddleware, | 4 | asyncMiddleware, |
5 | asyncRetryTransactionMiddleware, | 5 | asyncRetryTransactionMiddleware, |
6 | authenticate, commonVideosFiltersValidator, | 6 | authenticate, |
7 | commonVideosFiltersValidator, | ||
7 | optionalAuthenticate, | 8 | optionalAuthenticate, |
8 | paginationValidator, | 9 | paginationValidator, |
9 | setDefaultPagination, | 10 | setDefaultPagination, |
@@ -19,7 +20,7 @@ import { videosSortValidator } from '../../middlewares/validators' | |||
19 | import { sendUpdateActor } from '../../lib/activitypub/send' | 20 | import { sendUpdateActor } from '../../lib/activitypub/send' |
20 | import { VideoChannelCreate, VideoChannelUpdate } from '../../../shared' | 21 | import { VideoChannelCreate, VideoChannelUpdate } from '../../../shared' |
21 | import { createVideoChannel } from '../../lib/video-channel' | 22 | import { createVideoChannel } from '../../lib/video-channel' |
22 | import { createReqFiles, buildNSFWFilter } from '../../helpers/express-utils' | 23 | import { buildNSFWFilter, createReqFiles } from '../../helpers/express-utils' |
23 | import { setAsyncActorKeys } from '../../lib/activitypub' | 24 | import { setAsyncActorKeys } from '../../lib/activitypub' |
24 | import { AccountModel } from '../../models/account/account' | 25 | import { AccountModel } from '../../models/account/account' |
25 | import { CONFIG, IMAGE_MIMETYPE_EXT, sequelizeTypescript } from '../../initializers' | 26 | import { CONFIG, IMAGE_MIMETYPE_EXT, sequelizeTypescript } from '../../initializers' |
@@ -28,6 +29,7 @@ import { VideoModel } from '../../models/video/video' | |||
28 | import { updateAvatarValidator } from '../../middlewares/validators/avatar' | 29 | import { updateAvatarValidator } from '../../middlewares/validators/avatar' |
29 | import { updateActorAvatarFile } from '../../lib/avatar' | 30 | import { updateActorAvatarFile } from '../../lib/avatar' |
30 | import { auditLoggerFactory, VideoChannelAuditView } from '../../helpers/audit-logger' | 31 | import { auditLoggerFactory, VideoChannelAuditView } from '../../helpers/audit-logger' |
32 | import { resetSequelizeInstance } from '../../helpers/database-utils' | ||
31 | 33 | ||
32 | const auditLogger = auditLoggerFactory('channels') | 34 | const auditLogger = auditLoggerFactory('channels') |
33 | const reqAvatarFile = createReqFiles([ 'avatarfile' ], IMAGE_MIMETYPE_EXT, { avatarfile: CONFIG.STORAGE.AVATARS_DIR }) | 35 | const reqAvatarFile = createReqFiles([ 'avatarfile' ], IMAGE_MIMETYPE_EXT, { avatarfile: CONFIG.STORAGE.AVATARS_DIR }) |
diff --git a/server/controllers/api/videos/index.ts b/server/controllers/api/videos/index.ts index c9365da08..92c6ee697 100644 --- a/server/controllers/api/videos/index.ts +++ b/server/controllers/api/videos/index.ts | |||
@@ -6,7 +6,7 @@ import { getVideoFileFPS, getVideoFileResolution } from '../../../helpers/ffmpeg | |||
6 | import { processImage } from '../../../helpers/image-utils' | 6 | import { processImage } from '../../../helpers/image-utils' |
7 | import { logger } from '../../../helpers/logger' | 7 | import { logger } from '../../../helpers/logger' |
8 | import { auditLoggerFactory, VideoAuditView } from '../../../helpers/audit-logger' | 8 | import { auditLoggerFactory, VideoAuditView } from '../../../helpers/audit-logger' |
9 | import { getFormattedObjects, getServerActor, resetSequelizeInstance } from '../../../helpers/utils' | 9 | import { getFormattedObjects, getServerActor } from '../../../helpers/utils' |
10 | import { | 10 | import { |
11 | CONFIG, | 11 | CONFIG, |
12 | IMAGE_MIMETYPE_EXT, | 12 | IMAGE_MIMETYPE_EXT, |
@@ -51,10 +51,11 @@ import { blacklistRouter } from './blacklist' | |||
51 | import { videoCommentRouter } from './comment' | 51 | import { videoCommentRouter } from './comment' |
52 | import { rateVideoRouter } from './rate' | 52 | import { rateVideoRouter } from './rate' |
53 | import { VideoFilter } from '../../../../shared/models/videos/video-query.type' | 53 | import { VideoFilter } from '../../../../shared/models/videos/video-query.type' |
54 | import { createReqFiles, buildNSFWFilter } from '../../../helpers/express-utils' | 54 | import { buildNSFWFilter, createReqFiles } from '../../../helpers/express-utils' |
55 | import { ScheduleVideoUpdateModel } from '../../../models/video/schedule-video-update' | 55 | import { ScheduleVideoUpdateModel } from '../../../models/video/schedule-video-update' |
56 | import { videoCaptionsRouter } from './captions' | 56 | import { videoCaptionsRouter } from './captions' |
57 | import { videoImportsRouter } from './import' | 57 | import { videoImportsRouter } from './import' |
58 | import { resetSequelizeInstance } from '../../../helpers/database-utils' | ||
58 | 59 | ||
59 | const auditLogger = auditLoggerFactory('videos') | 60 | const auditLogger = auditLoggerFactory('videos') |
60 | const videosRouter = express.Router() | 61 | const videosRouter = express.Router() |
diff --git a/server/helpers/core-utils.ts b/server/helpers/core-utils.ts index 3b38da66c..90d2cd9b3 100644 --- a/server/helpers/core-utils.ts +++ b/server/helpers/core-utils.ts | |||
@@ -14,6 +14,35 @@ import * as rimraf from 'rimraf' | |||
14 | import { URL } from 'url' | 14 | import { URL } from 'url' |
15 | import { truncate } from 'lodash' | 15 | import { truncate } from 'lodash' |
16 | 16 | ||
17 | const timeTable = { | ||
18 | ms: 1, | ||
19 | second: 1000, | ||
20 | minute: 60000, | ||
21 | hour: 3600000, | ||
22 | day: 3600000 * 24, | ||
23 | week: 3600000 * 24 * 7, | ||
24 | month: 3600000 * 24 * 30 | ||
25 | } | ||
26 | export function parseDuration (duration: number | string): number { | ||
27 | if (typeof duration === 'number') return duration | ||
28 | |||
29 | if (typeof duration === 'string') { | ||
30 | const split = duration.match(/^([\d\.,]+)\s?(\w+)$/) | ||
31 | |||
32 | if (split.length === 3) { | ||
33 | const len = parseFloat(split[1]) | ||
34 | let unit = split[2].replace(/s$/i,'').toLowerCase() | ||
35 | if (unit === 'm') { | ||
36 | unit = 'ms' | ||
37 | } | ||
38 | |||
39 | return (len || 1) * (timeTable[unit] || 0) | ||
40 | } | ||
41 | } | ||
42 | |||
43 | throw new Error('Duration could not be properly parsed') | ||
44 | } | ||
45 | |||
17 | function sanitizeUrl (url: string) { | 46 | function sanitizeUrl (url: string) { |
18 | const urlObject = new URL(url) | 47 | const urlObject = new URL(url) |
19 | 48 | ||
diff --git a/server/helpers/database-utils.ts b/server/helpers/database-utils.ts index 53f881fb3..1005d2cf1 100644 --- a/server/helpers/database-utils.ts +++ b/server/helpers/database-utils.ts | |||
@@ -1,6 +1,6 @@ | |||
1 | import * as retry from 'async/retry' | 1 | import * as retry from 'async/retry' |
2 | import * as Bluebird from 'bluebird' | 2 | import * as Bluebird from 'bluebird' |
3 | import { Model, Sequelize } from 'sequelize-typescript' | 3 | import { Model } from 'sequelize-typescript' |
4 | import { logger } from './logger' | 4 | import { logger } from './logger' |
5 | 5 | ||
6 | function retryTransactionWrapper <T, A, B, C> ( | 6 | function retryTransactionWrapper <T, A, B, C> ( |
@@ -66,9 +66,17 @@ function updateInstanceWithAnother <T extends Model<T>> (instanceToUpdate: Model | |||
66 | } | 66 | } |
67 | } | 67 | } |
68 | 68 | ||
69 | function resetSequelizeInstance (instance: Model<any>, savedFields: object) { | ||
70 | Object.keys(savedFields).forEach(key => { | ||
71 | const value = savedFields[key] | ||
72 | instance.set(key, value) | ||
73 | }) | ||
74 | } | ||
75 | |||
69 | // --------------------------------------------------------------------------- | 76 | // --------------------------------------------------------------------------- |
70 | 77 | ||
71 | export { | 78 | export { |
79 | resetSequelizeInstance, | ||
72 | retryTransactionWrapper, | 80 | retryTransactionWrapper, |
73 | transactionRetryer, | 81 | transactionRetryer, |
74 | updateInstanceWithAnother | 82 | updateInstanceWithAnother |
diff --git a/server/helpers/express-utils.ts b/server/helpers/express-utils.ts index b3cc40848..1d7bee87e 100644 --- a/server/helpers/express-utils.ts +++ b/server/helpers/express-utils.ts | |||
@@ -3,8 +3,9 @@ import * as multer from 'multer' | |||
3 | import { CONFIG, REMOTE_SCHEME } from '../initializers' | 3 | import { CONFIG, REMOTE_SCHEME } from '../initializers' |
4 | import { logger } from './logger' | 4 | import { logger } from './logger' |
5 | import { User } from '../../shared/models/users' | 5 | import { User } from '../../shared/models/users' |
6 | import { generateRandomString } from './utils' | 6 | import { deleteFileAsync, generateRandomString } from './utils' |
7 | import { extname } from 'path' | 7 | import { extname } from 'path' |
8 | import { isArray } from './custom-validators/misc' | ||
8 | 9 | ||
9 | function buildNSFWFilter (res: express.Response, paramNSFW?: string) { | 10 | function buildNSFWFilter (res: express.Response, paramNSFW?: string) { |
10 | if (paramNSFW === 'true') return true | 11 | if (paramNSFW === 'true') return true |
@@ -23,6 +24,24 @@ function buildNSFWFilter (res: express.Response, paramNSFW?: string) { | |||
23 | return null | 24 | return null |
24 | } | 25 | } |
25 | 26 | ||
27 | function cleanUpReqFiles (req: { files: { [ fieldname: string ]: Express.Multer.File[] } | Express.Multer.File[] }) { | ||
28 | const files = req.files | ||
29 | |||
30 | if (!files) return | ||
31 | |||
32 | if (isArray(files)) { | ||
33 | (files as Express.Multer.File[]).forEach(f => deleteFileAsync(f.path)) | ||
34 | return | ||
35 | } | ||
36 | |||
37 | for (const key of Object.keys(files)) { | ||
38 | const file = files[ key ] | ||
39 | |||
40 | if (isArray(file)) file.forEach(f => deleteFileAsync(f.path)) | ||
41 | else deleteFileAsync(file.path) | ||
42 | } | ||
43 | } | ||
44 | |||
26 | function getHostWithPort (host: string) { | 45 | function getHostWithPort (host: string) { |
27 | const splitted = host.split(':') | 46 | const splitted = host.split(':') |
28 | 47 | ||
@@ -82,5 +101,6 @@ export { | |||
82 | buildNSFWFilter, | 101 | buildNSFWFilter, |
83 | getHostWithPort, | 102 | getHostWithPort, |
84 | badRequest, | 103 | badRequest, |
85 | createReqFiles | 104 | createReqFiles, |
105 | cleanUpReqFiles | ||
86 | } | 106 | } |
diff --git a/server/helpers/ffmpeg-utils.ts b/server/helpers/ffmpeg-utils.ts index ced56b82d..f8299c36f 100644 --- a/server/helpers/ffmpeg-utils.ts +++ b/server/helpers/ffmpeg-utils.ts | |||
@@ -7,6 +7,28 @@ import { processImage } from './image-utils' | |||
7 | import { logger } from './logger' | 7 | import { logger } from './logger' |
8 | import { checkFFmpegEncoders } from '../initializers/checker' | 8 | import { checkFFmpegEncoders } from '../initializers/checker' |
9 | 9 | ||
10 | function computeResolutionsToTranscode (videoFileHeight: number) { | ||
11 | const resolutionsEnabled: number[] = [] | ||
12 | const configResolutions = CONFIG.TRANSCODING.RESOLUTIONS | ||
13 | |||
14 | // Put in the order we want to proceed jobs | ||
15 | const resolutions = [ | ||
16 | VideoResolution.H_480P, | ||
17 | VideoResolution.H_360P, | ||
18 | VideoResolution.H_720P, | ||
19 | VideoResolution.H_240P, | ||
20 | VideoResolution.H_1080P | ||
21 | ] | ||
22 | |||
23 | for (const resolution of resolutions) { | ||
24 | if (configResolutions[ resolution + 'p' ] === true && videoFileHeight > resolution) { | ||
25 | resolutionsEnabled.push(resolution) | ||
26 | } | ||
27 | } | ||
28 | |||
29 | return resolutionsEnabled | ||
30 | } | ||
31 | |||
10 | async function getVideoFileResolution (path: string) { | 32 | async function getVideoFileResolution (path: string) { |
11 | const videoStream = await getVideoFileStream(path) | 33 | const videoStream = await getVideoFileStream(path) |
12 | 34 | ||
@@ -134,6 +156,7 @@ export { | |||
134 | generateImageFromVideoFile, | 156 | generateImageFromVideoFile, |
135 | transcode, | 157 | transcode, |
136 | getVideoFileFPS, | 158 | getVideoFileFPS, |
159 | computeResolutionsToTranscode, | ||
137 | audio | 160 | audio |
138 | } | 161 | } |
139 | 162 | ||
diff --git a/server/helpers/signup.ts b/server/helpers/signup.ts new file mode 100644 index 000000000..cdce7989d --- /dev/null +++ b/server/helpers/signup.ts | |||
@@ -0,0 +1,59 @@ | |||
1 | import { CONFIG } from '../initializers' | ||
2 | import { UserModel } from '../models/account/user' | ||
3 | import * as ipaddr from 'ipaddr.js' | ||
4 | const isCidr = require('is-cidr') | ||
5 | |||
6 | async function isSignupAllowed () { | ||
7 | if (CONFIG.SIGNUP.ENABLED === false) { | ||
8 | return false | ||
9 | } | ||
10 | |||
11 | // No limit and signup is enabled | ||
12 | if (CONFIG.SIGNUP.LIMIT === -1) { | ||
13 | return true | ||
14 | } | ||
15 | |||
16 | const totalUsers = await UserModel.countTotal() | ||
17 | |||
18 | return totalUsers < CONFIG.SIGNUP.LIMIT | ||
19 | } | ||
20 | |||
21 | function isSignupAllowedForCurrentIP (ip: string) { | ||
22 | const addr = ipaddr.parse(ip) | ||
23 | let excludeList = [ 'blacklist' ] | ||
24 | let matched = '' | ||
25 | |||
26 | // if there is a valid, non-empty whitelist, we exclude all unknown adresses too | ||
27 | if (CONFIG.SIGNUP.FILTERS.CIDR.WHITELIST.filter(cidr => isCidr(cidr)).length > 0) { | ||
28 | excludeList.push('unknown') | ||
29 | } | ||
30 | |||
31 | if (addr.kind() === 'ipv4') { | ||
32 | const addrV4 = ipaddr.IPv4.parse(ip) | ||
33 | const rangeList = { | ||
34 | whitelist: CONFIG.SIGNUP.FILTERS.CIDR.WHITELIST.filter(cidr => isCidr.v4(cidr)) | ||
35 | .map(cidr => ipaddr.IPv4.parseCIDR(cidr)), | ||
36 | blacklist: CONFIG.SIGNUP.FILTERS.CIDR.BLACKLIST.filter(cidr => isCidr.v4(cidr)) | ||
37 | .map(cidr => ipaddr.IPv4.parseCIDR(cidr)) | ||
38 | } | ||
39 | matched = ipaddr.subnetMatch(addrV4, rangeList, 'unknown') | ||
40 | } else if (addr.kind() === 'ipv6') { | ||
41 | const addrV6 = ipaddr.IPv6.parse(ip) | ||
42 | const rangeList = { | ||
43 | whitelist: CONFIG.SIGNUP.FILTERS.CIDR.WHITELIST.filter(cidr => isCidr.v6(cidr)) | ||
44 | .map(cidr => ipaddr.IPv6.parseCIDR(cidr)), | ||
45 | blacklist: CONFIG.SIGNUP.FILTERS.CIDR.BLACKLIST.filter(cidr => isCidr.v6(cidr)) | ||
46 | .map(cidr => ipaddr.IPv6.parseCIDR(cidr)) | ||
47 | } | ||
48 | matched = ipaddr.subnetMatch(addrV6, rangeList, 'unknown') | ||
49 | } | ||
50 | |||
51 | return !excludeList.includes(matched) | ||
52 | } | ||
53 | |||
54 | // --------------------------------------------------------------------------- | ||
55 | |||
56 | export { | ||
57 | isSignupAllowed, | ||
58 | isSignupAllowedForCurrentIP | ||
59 | } | ||
diff --git a/server/helpers/utils.ts b/server/helpers/utils.ts index eaad55555..703e57887 100644 --- a/server/helpers/utils.ts +++ b/server/helpers/utils.ts | |||
@@ -1,37 +1,12 @@ | |||
1 | import { Model } from 'sequelize-typescript' | ||
2 | import * as ipaddr from 'ipaddr.js' | ||
3 | import { ResultList } from '../../shared' | 1 | import { ResultList } from '../../shared' |
4 | import { VideoResolution } from '../../shared/models/videos' | ||
5 | import { CONFIG } from '../initializers' | 2 | import { CONFIG } from '../initializers' |
6 | import { UserModel } from '../models/account/user' | ||
7 | import { ActorModel } from '../models/activitypub/actor' | 3 | import { ActorModel } from '../models/activitypub/actor' |
8 | import { ApplicationModel } from '../models/application/application' | 4 | import { ApplicationModel } from '../models/application/application' |
9 | import { pseudoRandomBytesPromise, sha256, unlinkPromise } from './core-utils' | 5 | import { pseudoRandomBytesPromise, sha256, unlinkPromise } from './core-utils' |
10 | import { logger } from './logger' | 6 | import { logger } from './logger' |
11 | import { isArray } from './custom-validators/misc' | ||
12 | import { join } from 'path' | 7 | import { join } from 'path' |
13 | import { Instance as ParseTorrent } from 'parse-torrent' | 8 | import { Instance as ParseTorrent } from 'parse-torrent' |
14 | 9 | ||
15 | const isCidr = require('is-cidr') | ||
16 | |||
17 | function cleanUpReqFiles (req: { files: { [ fieldname: string ]: Express.Multer.File[] } | Express.Multer.File[] }) { | ||
18 | const files = req.files | ||
19 | |||
20 | if (!files) return | ||
21 | |||
22 | if (isArray(files)) { | ||
23 | (files as Express.Multer.File[]).forEach(f => deleteFileAsync(f.path)) | ||
24 | return | ||
25 | } | ||
26 | |||
27 | for (const key of Object.keys(files)) { | ||
28 | const file = files[key] | ||
29 | |||
30 | if (isArray(file)) file.forEach(f => deleteFileAsync(f.path)) | ||
31 | else deleteFileAsync(file.path) | ||
32 | } | ||
33 | } | ||
34 | |||
35 | function deleteFileAsync (path: string) { | 10 | function deleteFileAsync (path: string) { |
36 | unlinkPromise(path) | 11 | unlinkPromise(path) |
37 | .catch(err => logger.error('Cannot delete the file %s asynchronously.', path, { err })) | 12 | .catch(err => logger.error('Cannot delete the file %s asynchronously.', path, { err })) |
@@ -60,127 +35,23 @@ function getFormattedObjects<U, T extends FormattableToJSON> (objects: T[], obje | |||
60 | } as ResultList<U> | 35 | } as ResultList<U> |
61 | } | 36 | } |
62 | 37 | ||
63 | async function isSignupAllowed () { | ||
64 | if (CONFIG.SIGNUP.ENABLED === false) { | ||
65 | return false | ||
66 | } | ||
67 | |||
68 | // No limit and signup is enabled | ||
69 | if (CONFIG.SIGNUP.LIMIT === -1) { | ||
70 | return true | ||
71 | } | ||
72 | |||
73 | const totalUsers = await UserModel.countTotal() | ||
74 | |||
75 | return totalUsers < CONFIG.SIGNUP.LIMIT | ||
76 | } | ||
77 | |||
78 | function isSignupAllowedForCurrentIP (ip: string) { | ||
79 | const addr = ipaddr.parse(ip) | ||
80 | let excludeList = [ 'blacklist' ] | ||
81 | let matched = '' | ||
82 | |||
83 | // if there is a valid, non-empty whitelist, we exclude all unknown adresses too | ||
84 | if (CONFIG.SIGNUP.FILTERS.CIDR.WHITELIST.filter(cidr => isCidr(cidr)).length > 0) { | ||
85 | excludeList.push('unknown') | ||
86 | } | ||
87 | |||
88 | if (addr.kind() === 'ipv4') { | ||
89 | const addrV4 = ipaddr.IPv4.parse(ip) | ||
90 | const rangeList = { | ||
91 | whitelist: CONFIG.SIGNUP.FILTERS.CIDR.WHITELIST.filter(cidr => isCidr.v4(cidr)) | ||
92 | .map(cidr => ipaddr.IPv4.parseCIDR(cidr)), | ||
93 | blacklist: CONFIG.SIGNUP.FILTERS.CIDR.BLACKLIST.filter(cidr => isCidr.v4(cidr)) | ||
94 | .map(cidr => ipaddr.IPv4.parseCIDR(cidr)) | ||
95 | } | ||
96 | matched = ipaddr.subnetMatch(addrV4, rangeList, 'unknown') | ||
97 | } else if (addr.kind() === 'ipv6') { | ||
98 | const addrV6 = ipaddr.IPv6.parse(ip) | ||
99 | const rangeList = { | ||
100 | whitelist: CONFIG.SIGNUP.FILTERS.CIDR.WHITELIST.filter(cidr => isCidr.v6(cidr)) | ||
101 | .map(cidr => ipaddr.IPv6.parseCIDR(cidr)), | ||
102 | blacklist: CONFIG.SIGNUP.FILTERS.CIDR.BLACKLIST.filter(cidr => isCidr.v6(cidr)) | ||
103 | .map(cidr => ipaddr.IPv6.parseCIDR(cidr)) | ||
104 | } | ||
105 | matched = ipaddr.subnetMatch(addrV6, rangeList, 'unknown') | ||
106 | } | ||
107 | |||
108 | return !excludeList.includes(matched) | ||
109 | } | ||
110 | |||
111 | function computeResolutionsToTranscode (videoFileHeight: number) { | ||
112 | const resolutionsEnabled: number[] = [] | ||
113 | const configResolutions = CONFIG.TRANSCODING.RESOLUTIONS | ||
114 | |||
115 | // Put in the order we want to proceed jobs | ||
116 | const resolutions = [ | ||
117 | VideoResolution.H_480P, | ||
118 | VideoResolution.H_360P, | ||
119 | VideoResolution.H_720P, | ||
120 | VideoResolution.H_240P, | ||
121 | VideoResolution.H_1080P | ||
122 | ] | ||
123 | |||
124 | for (const resolution of resolutions) { | ||
125 | if (configResolutions[ resolution + 'p' ] === true && videoFileHeight > resolution) { | ||
126 | resolutionsEnabled.push(resolution) | ||
127 | } | ||
128 | } | ||
129 | |||
130 | return resolutionsEnabled | ||
131 | } | ||
132 | |||
133 | const timeTable = { | ||
134 | ms: 1, | ||
135 | second: 1000, | ||
136 | minute: 60000, | ||
137 | hour: 3600000, | ||
138 | day: 3600000 * 24, | ||
139 | week: 3600000 * 24 * 7, | ||
140 | month: 3600000 * 24 * 30 | ||
141 | } | ||
142 | export function parseDuration (duration: number | string): number { | ||
143 | if (typeof duration === 'number') return duration | ||
144 | |||
145 | if (typeof duration === 'string') { | ||
146 | const split = duration.match(/^([\d\.,]+)\s?(\w+)$/) | ||
147 | |||
148 | if (split.length === 3) { | ||
149 | const len = parseFloat(split[1]) | ||
150 | let unit = split[2].replace(/s$/i,'').toLowerCase() | ||
151 | if (unit === 'm') { | ||
152 | unit = 'ms' | ||
153 | } | ||
154 | |||
155 | return (len || 1) * (timeTable[unit] || 0) | ||
156 | } | ||
157 | } | ||
158 | |||
159 | throw new Error('Duration could not be properly parsed') | ||
160 | } | ||
161 | |||
162 | function resetSequelizeInstance (instance: Model<any>, savedFields: object) { | ||
163 | Object.keys(savedFields).forEach(key => { | ||
164 | const value = savedFields[key] | ||
165 | instance.set(key, value) | ||
166 | }) | ||
167 | } | ||
168 | |||
169 | let serverActor: ActorModel | ||
170 | async function getServerActor () { | 38 | async function getServerActor () { |
171 | if (serverActor === undefined) { | 39 | if (getServerActor.serverActor === undefined) { |
172 | const application = await ApplicationModel.load() | 40 | const application = await ApplicationModel.load() |
173 | if (!application) throw Error('Could not load Application from database.') | 41 | if (!application) throw Error('Could not load Application from database.') |
174 | 42 | ||
175 | serverActor = application.Account.Actor | 43 | getServerActor.serverActor = application.Account.Actor |
176 | } | 44 | } |
177 | 45 | ||
178 | if (!serverActor) { | 46 | if (!getServerActor.serverActor) { |
179 | logger.error('Cannot load server actor.') | 47 | logger.error('Cannot load server actor.') |
180 | process.exit(0) | 48 | process.exit(0) |
181 | } | 49 | } |
182 | 50 | ||
183 | return Promise.resolve(serverActor) | 51 | return Promise.resolve(getServerActor.serverActor) |
52 | } | ||
53 | namespace getServerActor { | ||
54 | export let serverActor: ActorModel | ||
184 | } | 55 | } |
185 | 56 | ||
186 | function generateVideoTmpPath (target: string | ParseTorrent) { | 57 | function generateVideoTmpPath (target: string | ParseTorrent) { |
@@ -194,21 +65,13 @@ function getSecureTorrentName (originalName: string) { | |||
194 | return sha256(originalName) + '.torrent' | 65 | return sha256(originalName) + '.torrent' |
195 | } | 66 | } |
196 | 67 | ||
197 | type SortType = { sortModel: any, sortValue: string } | ||
198 | |||
199 | // --------------------------------------------------------------------------- | 68 | // --------------------------------------------------------------------------- |
200 | 69 | ||
201 | export { | 70 | export { |
202 | cleanUpReqFiles, | ||
203 | deleteFileAsync, | 71 | deleteFileAsync, |
204 | generateRandomString, | 72 | generateRandomString, |
205 | getFormattedObjects, | 73 | getFormattedObjects, |
206 | isSignupAllowed, | ||
207 | getSecureTorrentName, | 74 | getSecureTorrentName, |
208 | isSignupAllowedForCurrentIP, | ||
209 | computeResolutionsToTranscode, | ||
210 | resetSequelizeInstance, | ||
211 | getServerActor, | 75 | getServerActor, |
212 | SortType, | ||
213 | generateVideoTmpPath | 76 | generateVideoTmpPath |
214 | } | 77 | } |
diff --git a/server/lib/activitypub/process/process-update.ts b/server/lib/activitypub/process/process-update.ts index 82b661a03..11226e275 100644 --- a/server/lib/activitypub/process/process-update.ts +++ b/server/lib/activitypub/process/process-update.ts | |||
@@ -1,9 +1,8 @@ | |||
1 | import * as Bluebird from 'bluebird' | 1 | import * as Bluebird from 'bluebird' |
2 | import { ActivityUpdate, VideoTorrentObject } from '../../../../shared/models/activitypub' | 2 | import { ActivityUpdate, VideoTorrentObject } from '../../../../shared/models/activitypub' |
3 | import { ActivityPubActor } from '../../../../shared/models/activitypub/activitypub-actor' | 3 | import { ActivityPubActor } from '../../../../shared/models/activitypub/activitypub-actor' |
4 | import { retryTransactionWrapper } from '../../../helpers/database-utils' | 4 | import { resetSequelizeInstance, retryTransactionWrapper } from '../../../helpers/database-utils' |
5 | import { logger } from '../../../helpers/logger' | 5 | import { logger } from '../../../helpers/logger' |
6 | import { resetSequelizeInstance } from '../../../helpers/utils' | ||
7 | import { sequelizeTypescript } from '../../../initializers' | 6 | import { sequelizeTypescript } from '../../../initializers' |
8 | import { AccountModel } from '../../../models/account/account' | 7 | import { AccountModel } from '../../../models/account/account' |
9 | import { ActorModel } from '../../../models/activitypub/actor' | 8 | import { ActorModel } from '../../../models/activitypub/actor' |
diff --git a/server/lib/job-queue/handlers/video-file.ts b/server/lib/job-queue/handlers/video-file.ts index 6b1a8f132..c6308f7a6 100644 --- a/server/lib/job-queue/handlers/video-file.ts +++ b/server/lib/job-queue/handlers/video-file.ts | |||
@@ -1,13 +1,13 @@ | |||
1 | import * as Bull from 'bull' | 1 | import * as Bull from 'bull' |
2 | import { VideoResolution, VideoState } from '../../../../shared' | 2 | import { VideoResolution, VideoState } from '../../../../shared' |
3 | import { logger } from '../../../helpers/logger' | 3 | import { logger } from '../../../helpers/logger' |
4 | import { computeResolutionsToTranscode } from '../../../helpers/utils' | ||
5 | import { VideoModel } from '../../../models/video/video' | 4 | import { VideoModel } from '../../../models/video/video' |
6 | import { JobQueue } from '../job-queue' | 5 | import { JobQueue } from '../job-queue' |
7 | import { federateVideoIfNeeded } from '../../activitypub' | 6 | import { federateVideoIfNeeded } from '../../activitypub' |
8 | import { retryTransactionWrapper } from '../../../helpers/database-utils' | 7 | import { retryTransactionWrapper } from '../../../helpers/database-utils' |
9 | import { sequelizeTypescript } from '../../../initializers' | 8 | import { sequelizeTypescript } from '../../../initializers' |
10 | import * as Bluebird from 'bluebird' | 9 | import * as Bluebird from 'bluebird' |
10 | import { computeResolutionsToTranscode } from '../../../helpers/ffmpeg-utils' | ||
11 | 11 | ||
12 | export type VideoFilePayload = { | 12 | export type VideoFilePayload = { |
13 | videoUUID: string | 13 | videoUUID: string |
diff --git a/server/middlewares/cache.ts b/server/middlewares/cache.ts index c671b88c9..b40486e4b 100644 --- a/server/middlewares/cache.ts +++ b/server/middlewares/cache.ts | |||
@@ -1,6 +1,6 @@ | |||
1 | import * as express from 'express' | 1 | import * as express from 'express' |
2 | import * as AsyncLock from 'async-lock' | 2 | import * as AsyncLock from 'async-lock' |
3 | import { parseDuration } from '../helpers/utils' | 3 | import { parseDuration } from '../helpers/core-utils' |
4 | import { Redis } from '../lib/redis' | 4 | import { Redis } from '../lib/redis' |
5 | import { logger } from '../helpers/logger' | 5 | import { logger } from '../helpers/logger' |
6 | 6 | ||
diff --git a/server/middlewares/sort.ts b/server/middlewares/sort.ts index 5120804b3..6507aa5b8 100644 --- a/server/middlewares/sort.ts +++ b/server/middlewares/sort.ts | |||
@@ -1,6 +1,6 @@ | |||
1 | import * as express from 'express' | 1 | import * as express from 'express' |
2 | import 'express-validator' | 2 | import 'express-validator' |
3 | import { SortType } from '../helpers/utils' | 3 | import { SortType } from '../models/utils' |
4 | 4 | ||
5 | function setDefaultSort (req: express.Request, res: express.Response, next: express.NextFunction) { | 5 | function setDefaultSort (req: express.Request, res: express.Response, next: express.NextFunction) { |
6 | if (!req.query.sort) req.query.sort = '-createdAt' | 6 | if (!req.query.sort) req.query.sort = '-createdAt' |
diff --git a/server/middlewares/validators/avatar.ts b/server/middlewares/validators/avatar.ts index 5860735c6..ddc14f531 100644 --- a/server/middlewares/validators/avatar.ts +++ b/server/middlewares/validators/avatar.ts | |||
@@ -4,7 +4,7 @@ import { isAvatarFile } from '../../helpers/custom-validators/users' | |||
4 | import { areValidationErrors } from './utils' | 4 | import { areValidationErrors } from './utils' |
5 | import { CONSTRAINTS_FIELDS } from '../../initializers' | 5 | import { CONSTRAINTS_FIELDS } from '../../initializers' |
6 | import { logger } from '../../helpers/logger' | 6 | import { logger } from '../../helpers/logger' |
7 | import { cleanUpReqFiles } from '../../helpers/utils' | 7 | import { cleanUpReqFiles } from '../../helpers/express-utils' |
8 | 8 | ||
9 | const updateAvatarValidator = [ | 9 | const updateAvatarValidator = [ |
10 | body('avatarfile').custom((value, { req }) => isAvatarFile(req.files)).withMessage( | 10 | body('avatarfile').custom((value, { req }) => isAvatarFile(req.files)).withMessage( |
diff --git a/server/middlewares/validators/users.ts b/server/middlewares/validators/users.ts index 771c414a0..f47fa8b48 100644 --- a/server/middlewares/validators/users.ts +++ b/server/middlewares/validators/users.ts | |||
@@ -16,7 +16,7 @@ import { | |||
16 | } from '../../helpers/custom-validators/users' | 16 | } from '../../helpers/custom-validators/users' |
17 | import { isVideoExist } from '../../helpers/custom-validators/videos' | 17 | import { isVideoExist } from '../../helpers/custom-validators/videos' |
18 | import { logger } from '../../helpers/logger' | 18 | import { logger } from '../../helpers/logger' |
19 | import { isSignupAllowed, isSignupAllowedForCurrentIP } from '../../helpers/utils' | 19 | import { isSignupAllowed, isSignupAllowedForCurrentIP } from '../../helpers/signup' |
20 | import { Redis } from '../../lib/redis' | 20 | import { Redis } from '../../lib/redis' |
21 | import { UserModel } from '../../models/account/user' | 21 | import { UserModel } from '../../models/account/user' |
22 | import { areValidationErrors } from './utils' | 22 | import { areValidationErrors } from './utils' |
diff --git a/server/middlewares/validators/video-captions.ts b/server/middlewares/validators/video-captions.ts index 18d537bc4..4f393ea84 100644 --- a/server/middlewares/validators/video-captions.ts +++ b/server/middlewares/validators/video-captions.ts | |||
@@ -7,7 +7,7 @@ import { CONSTRAINTS_FIELDS } from '../../initializers' | |||
7 | import { UserRight } from '../../../shared' | 7 | import { UserRight } from '../../../shared' |
8 | import { logger } from '../../helpers/logger' | 8 | import { logger } from '../../helpers/logger' |
9 | import { isVideoCaptionExist, isVideoCaptionFile, isVideoCaptionLanguageValid } from '../../helpers/custom-validators/video-captions' | 9 | import { isVideoCaptionExist, isVideoCaptionFile, isVideoCaptionLanguageValid } from '../../helpers/custom-validators/video-captions' |
10 | import { cleanUpReqFiles } from '../../helpers/utils' | 10 | import { cleanUpReqFiles } from '../../helpers/express-utils' |
11 | 11 | ||
12 | const addVideoCaptionValidator = [ | 12 | const addVideoCaptionValidator = [ |
13 | param('videoId').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid video id'), | 13 | param('videoId').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid video id'), |
diff --git a/server/middlewares/validators/video-imports.ts b/server/middlewares/validators/video-imports.ts index 9ac739101..b2063b8da 100644 --- a/server/middlewares/validators/video-imports.ts +++ b/server/middlewares/validators/video-imports.ts | |||
@@ -5,7 +5,7 @@ import { logger } from '../../helpers/logger' | |||
5 | import { areValidationErrors } from './utils' | 5 | import { areValidationErrors } from './utils' |
6 | import { getCommonVideoAttributes } from './videos' | 6 | import { getCommonVideoAttributes } from './videos' |
7 | import { isVideoImportTargetUrlValid, isVideoImportTorrentFile } from '../../helpers/custom-validators/video-imports' | 7 | import { isVideoImportTargetUrlValid, isVideoImportTorrentFile } from '../../helpers/custom-validators/video-imports' |
8 | import { cleanUpReqFiles } from '../../helpers/utils' | 8 | import { cleanUpReqFiles } from '../../helpers/express-utils' |
9 | import { isVideoChannelOfAccountExist, isVideoMagnetUriValid, isVideoNameValid } from '../../helpers/custom-validators/videos' | 9 | import { isVideoChannelOfAccountExist, isVideoMagnetUriValid, isVideoNameValid } from '../../helpers/custom-validators/videos' |
10 | import { CONFIG } from '../../initializers/constants' | 10 | import { CONFIG } from '../../initializers/constants' |
11 | import { CONSTRAINTS_FIELDS } from '../../initializers' | 11 | import { CONSTRAINTS_FIELDS } from '../../initializers' |
diff --git a/server/middlewares/validators/videos.ts b/server/middlewares/validators/videos.ts index 77d601a4d..53c32abb8 100644 --- a/server/middlewares/validators/videos.ts +++ b/server/middlewares/validators/videos.ts | |||
@@ -34,7 +34,7 @@ import { CONSTRAINTS_FIELDS } from '../../initializers' | |||
34 | import { VideoShareModel } from '../../models/video/video-share' | 34 | import { VideoShareModel } from '../../models/video/video-share' |
35 | import { authenticate } from '../oauth' | 35 | import { authenticate } from '../oauth' |
36 | import { areValidationErrors } from './utils' | 36 | import { areValidationErrors } from './utils' |
37 | import { cleanUpReqFiles } from '../../helpers/utils' | 37 | import { cleanUpReqFiles } from '../../helpers/express-utils' |
38 | import { VideoModel } from '../../models/video/video' | 38 | import { VideoModel } from '../../models/video/video' |
39 | import { UserModel } from '../../models/account/user' | 39 | import { UserModel } from '../../models/account/user' |
40 | 40 | ||
diff --git a/server/models/utils.ts b/server/models/utils.ts index 58a18c97a..eb6653f3d 100644 --- a/server/models/utils.ts +++ b/server/models/utils.ts | |||
@@ -1,6 +1,8 @@ | |||
1 | // Translate for example "-name" to [ [ 'name', 'DESC' ], [ 'id', 'ASC' ] ] | 1 | // Translate for example "-name" to [ [ 'name', 'DESC' ], [ 'id', 'ASC' ] ] |
2 | import { Sequelize } from 'sequelize-typescript' | 2 | import { Sequelize } from 'sequelize-typescript' |
3 | 3 | ||
4 | type SortType = { sortModel: any, sortValue: string } | ||
5 | |||
4 | function getSort (value: string, lastSort: string[] = [ 'id', 'ASC' ]) { | 6 | function getSort (value: string, lastSort: string[] = [ 'id', 'ASC' ]) { |
5 | let field: any | 7 | let field: any |
6 | let direction: 'ASC' | 'DESC' | 8 | let direction: 'ASC' | 'DESC' |
@@ -54,6 +56,7 @@ function createSimilarityAttribute (col: string, value: string) { | |||
54 | // --------------------------------------------------------------------------- | 56 | // --------------------------------------------------------------------------- |
55 | 57 | ||
56 | export { | 58 | export { |
59 | SortType, | ||
57 | getSort, | 60 | getSort, |
58 | getSortOnModel, | 61 | getSortOnModel, |
59 | createSimilarityAttribute, | 62 | createSimilarityAttribute, |
diff --git a/server/models/video/video-blacklist.ts b/server/models/video/video-blacklist.ts index eabc37ef0..67f7cd487 100644 --- a/server/models/video/video-blacklist.ts +++ b/server/models/video/video-blacklist.ts | |||
@@ -4,15 +4,15 @@ import { | |||
4 | AllowNull, | 4 | AllowNull, |
5 | BelongsTo, | 5 | BelongsTo, |
6 | Column, | 6 | Column, |
7 | CreatedAt, DataType, | 7 | CreatedAt, |
8 | DataType, | ||
8 | ForeignKey, | 9 | ForeignKey, |
9 | Is, | 10 | Is, |
10 | Model, | 11 | Model, |
11 | Table, | 12 | Table, |
12 | UpdatedAt | 13 | UpdatedAt |
13 | } from 'sequelize-typescript' | 14 | } from 'sequelize-typescript' |
14 | import { SortType } from '../../helpers/utils' | 15 | import { getSortOnModel, SortType, throwIfNotValid } from '../utils' |
15 | import { getSortOnModel, throwIfNotValid } from '../utils' | ||
16 | import { VideoModel } from './video' | 16 | import { VideoModel } from './video' |
17 | import { isVideoBlacklistReasonValid } from '../../helpers/custom-validators/video-blacklist' | 17 | import { isVideoBlacklistReasonValid } from '../../helpers/custom-validators/video-blacklist' |
18 | import { Emailer } from '../../lib/emailer' | 18 | import { Emailer } from '../../lib/emailer' |