diff options
Diffstat (limited to 'server/helpers/utils.ts')
-rw-r--r-- | server/helpers/utils.ts | 151 |
1 files changed, 7 insertions, 144 deletions
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 | } |