diff options
Diffstat (limited to 'server/initializers')
-rw-r--r-- | server/initializers/checker-after-init.ts | 50 | ||||
-rw-r--r-- | server/initializers/checker-before-init.ts | 13 | ||||
-rw-r--r-- | server/initializers/config.ts | 41 | ||||
-rw-r--r-- | server/initializers/constants.ts | 52 | ||||
-rw-r--r-- | server/initializers/database.ts | 6 | ||||
-rw-r--r-- | server/initializers/migrations/0785-video-password-protection.ts | 31 | ||||
-rw-r--r-- | server/initializers/migrations/0790-thumbnail-disk.ts | 47 |
7 files changed, 193 insertions, 47 deletions
diff --git a/server/initializers/checker-after-init.ts b/server/initializers/checker-after-init.ts index 68dea909d..5ef72058b 100644 --- a/server/initializers/checker-after-init.ts +++ b/server/initializers/checker-after-init.ts | |||
@@ -1,4 +1,5 @@ | |||
1 | import config from 'config' | 1 | import config from 'config' |
2 | import { readFileSync, writeFileSync } from 'fs-extra' | ||
2 | import { URL } from 'url' | 3 | import { URL } from 'url' |
3 | import { uniqify } from '@shared/core-utils' | 4 | import { uniqify } from '@shared/core-utils' |
4 | import { getFFmpegVersion } from '@shared/ffmpeg' | 5 | import { getFFmpegVersion } from '@shared/ffmpeg' |
@@ -10,7 +11,7 @@ import { logger } from '../helpers/logger' | |||
10 | import { ApplicationModel, getServerActor } from '../models/application/application' | 11 | import { ApplicationModel, getServerActor } from '../models/application/application' |
11 | import { OAuthClientModel } from '../models/oauth/oauth-client' | 12 | import { OAuthClientModel } from '../models/oauth/oauth-client' |
12 | import { UserModel } from '../models/user/user' | 13 | import { UserModel } from '../models/user/user' |
13 | import { CONFIG, isEmailEnabled } from './config' | 14 | import { CONFIG, getLocalConfigFilePath, isEmailEnabled, reloadConfig } from './config' |
14 | import { WEBSERVER } from './constants' | 15 | import { WEBSERVER } from './constants' |
15 | 16 | ||
16 | async function checkActivityPubUrls () { | 17 | async function checkActivityPubUrls () { |
@@ -37,10 +38,7 @@ function checkConfig () { | |||
37 | const configFiles = config.util.getConfigSources().map(s => s.name).join(' -> ') | 38 | const configFiles = config.util.getConfigSources().map(s => s.name).join(' -> ') |
38 | logger.info('Using following configuration file hierarchy: %s.', configFiles) | 39 | logger.info('Using following configuration file hierarchy: %s.', configFiles) |
39 | 40 | ||
40 | // Moved configuration keys | 41 | checkRemovedConfigKeys() |
41 | if (config.has('services.csp-logger')) { | ||
42 | logger.warn('services.csp-logger configuration has been renamed to csp.report_uri. Please update your configuration file.') | ||
43 | } | ||
44 | 42 | ||
45 | checkSecretsConfig() | 43 | checkSecretsConfig() |
46 | checkEmailConfig() | 44 | checkEmailConfig() |
@@ -104,6 +102,34 @@ export { | |||
104 | 102 | ||
105 | // --------------------------------------------------------------------------- | 103 | // --------------------------------------------------------------------------- |
106 | 104 | ||
105 | function checkRemovedConfigKeys () { | ||
106 | // Moved configuration keys | ||
107 | if (config.has('services.csp-logger')) { | ||
108 | logger.warn('services.csp-logger configuration has been renamed to csp.report_uri. Please update your configuration file.') | ||
109 | } | ||
110 | |||
111 | if (config.has('transcoding.webtorrent.enabled')) { | ||
112 | const localConfigPath = getLocalConfigFilePath() | ||
113 | |||
114 | const content = readFileSync(localConfigPath, { encoding: 'utf-8' }) | ||
115 | if (!content.includes('"webtorrent"')) { | ||
116 | throw new Error('Please rename transcoding.webtorrent.enabled key to transcoding.web_videos.enabled in your configuration file') | ||
117 | } | ||
118 | |||
119 | try { | ||
120 | logger.info( | ||
121 | 'Replacing "transcoding.webtorrent.enabled" key to "transcoding.web_videos.enabled" in your local configuration ' + localConfigPath | ||
122 | ) | ||
123 | |||
124 | writeFileSync(localConfigPath, content.replace('"webtorrent"', '"web_videos"'), { encoding: 'utf-8' }) | ||
125 | |||
126 | reloadConfig() | ||
127 | } catch (err) { | ||
128 | logger.error('Cannot write new configuration to file ' + localConfigPath, { err }) | ||
129 | } | ||
130 | } | ||
131 | } | ||
132 | |||
107 | function checkSecretsConfig () { | 133 | function checkSecretsConfig () { |
108 | if (!CONFIG.SECRETS.PEERTUBE) { | 134 | if (!CONFIG.SECRETS.PEERTUBE) { |
109 | throw new Error('secrets.peertube is missing in config. Generate one using `openssl rand -hex 32`') | 135 | throw new Error('secrets.peertube is missing in config. Generate one using `openssl rand -hex 32`') |
@@ -191,15 +217,15 @@ function checkStorageConfig () { | |||
191 | } | 217 | } |
192 | } | 218 | } |
193 | 219 | ||
194 | if (CONFIG.STORAGE.VIDEOS_DIR === CONFIG.STORAGE.REDUNDANCY_DIR) { | 220 | if (CONFIG.STORAGE.WEB_VIDEOS_DIR === CONFIG.STORAGE.REDUNDANCY_DIR) { |
195 | logger.warn('Redundancy directory should be different than the videos folder.') | 221 | logger.warn('Redundancy directory should be different than the videos folder.') |
196 | } | 222 | } |
197 | } | 223 | } |
198 | 224 | ||
199 | function checkTranscodingConfig () { | 225 | function checkTranscodingConfig () { |
200 | if (CONFIG.TRANSCODING.ENABLED) { | 226 | if (CONFIG.TRANSCODING.ENABLED) { |
201 | if (CONFIG.TRANSCODING.WEBTORRENT.ENABLED === false && CONFIG.TRANSCODING.HLS.ENABLED === false) { | 227 | if (CONFIG.TRANSCODING.WEB_VIDEOS.ENABLED === false && CONFIG.TRANSCODING.HLS.ENABLED === false) { |
202 | throw new Error('You need to enable at least WebTorrent transcoding or HLS transcoding.') | 228 | throw new Error('You need to enable at least Web Video transcoding or HLS transcoding.') |
203 | } | 229 | } |
204 | 230 | ||
205 | if (CONFIG.TRANSCODING.CONCURRENCY <= 0) { | 231 | if (CONFIG.TRANSCODING.CONCURRENCY <= 0) { |
@@ -264,7 +290,7 @@ function checkLiveConfig () { | |||
264 | function checkObjectStorageConfig () { | 290 | function checkObjectStorageConfig () { |
265 | if (CONFIG.OBJECT_STORAGE.ENABLED === true) { | 291 | if (CONFIG.OBJECT_STORAGE.ENABLED === true) { |
266 | 292 | ||
267 | if (!CONFIG.OBJECT_STORAGE.VIDEOS.BUCKET_NAME) { | 293 | if (!CONFIG.OBJECT_STORAGE.WEB_VIDEOS.BUCKET_NAME) { |
268 | throw new Error('videos_bucket should be set when object storage support is enabled.') | 294 | throw new Error('videos_bucket should be set when object storage support is enabled.') |
269 | } | 295 | } |
270 | 296 | ||
@@ -273,10 +299,10 @@ function checkObjectStorageConfig () { | |||
273 | } | 299 | } |
274 | 300 | ||
275 | if ( | 301 | if ( |
276 | CONFIG.OBJECT_STORAGE.VIDEOS.BUCKET_NAME === CONFIG.OBJECT_STORAGE.STREAMING_PLAYLISTS.BUCKET_NAME && | 302 | CONFIG.OBJECT_STORAGE.WEB_VIDEOS.BUCKET_NAME === CONFIG.OBJECT_STORAGE.STREAMING_PLAYLISTS.BUCKET_NAME && |
277 | CONFIG.OBJECT_STORAGE.VIDEOS.PREFIX === CONFIG.OBJECT_STORAGE.STREAMING_PLAYLISTS.PREFIX | 303 | CONFIG.OBJECT_STORAGE.WEB_VIDEOS.PREFIX === CONFIG.OBJECT_STORAGE.STREAMING_PLAYLISTS.PREFIX |
278 | ) { | 304 | ) { |
279 | if (CONFIG.OBJECT_STORAGE.VIDEOS.PREFIX === '') { | 305 | if (CONFIG.OBJECT_STORAGE.WEB_VIDEOS.PREFIX === '') { |
280 | throw new Error('Object storage bucket prefixes should be set when the same bucket is used for both types of video.') | 306 | throw new Error('Object storage bucket prefixes should be set when the same bucket is used for both types of video.') |
281 | } | 307 | } |
282 | 308 | ||
diff --git a/server/initializers/checker-before-init.ts b/server/initializers/checker-before-init.ts index 0a315ea70..a872fcba3 100644 --- a/server/initializers/checker-before-init.ts +++ b/server/initializers/checker-before-init.ts | |||
@@ -18,7 +18,7 @@ function checkMissedConfig () { | |||
18 | 'database.hostname', 'database.port', 'database.username', 'database.password', 'database.pool.max', | 18 | 'database.hostname', 'database.port', 'database.username', 'database.password', 'database.pool.max', |
19 | 'smtp.hostname', 'smtp.port', 'smtp.username', 'smtp.password', 'smtp.tls', 'smtp.from_address', | 19 | 'smtp.hostname', 'smtp.port', 'smtp.username', 'smtp.password', 'smtp.tls', 'smtp.from_address', |
20 | 'email.body.signature', 'email.subject.prefix', | 20 | 'email.body.signature', 'email.subject.prefix', |
21 | 'storage.avatars', 'storage.videos', 'storage.logs', 'storage.previews', 'storage.thumbnails', 'storage.torrents', 'storage.cache', | 21 | 'storage.avatars', 'storage.web_videos', 'storage.logs', 'storage.previews', 'storage.thumbnails', 'storage.torrents', 'storage.cache', |
22 | 'storage.redundancy', 'storage.tmp', 'storage.streaming_playlists', 'storage.plugins', 'storage.well_known', | 22 | 'storage.redundancy', 'storage.tmp', 'storage.streaming_playlists', 'storage.plugins', 'storage.well_known', |
23 | 'log.level', 'log.rotation.enabled', 'log.rotation.max_file_size', 'log.rotation.max_files', 'log.anonymize_ip', | 23 | 'log.level', 'log.rotation.enabled', 'log.rotation.max_file_size', 'log.rotation.max_files', 'log.anonymize_ip', |
24 | 'log.log_ping_requests', 'log.log_tracker_unknown_infohash', 'log.prettify_sql', 'log.accept_client_log', | 24 | 'log.log_ping_requests', 'log.log_tracker_unknown_infohash', 'log.prettify_sql', 'log.accept_client_log', |
@@ -29,12 +29,13 @@ function checkMissedConfig () { | |||
29 | 'video_channels.max_per_user', | 29 | 'video_channels.max_per_user', |
30 | 'csp.enabled', 'csp.report_only', 'csp.report_uri', | 30 | 'csp.enabled', 'csp.report_only', 'csp.report_uri', |
31 | 'security.frameguard.enabled', 'security.powered_by_header.enabled', | 31 | 'security.frameguard.enabled', 'security.powered_by_header.enabled', |
32 | 'cache.previews.size', 'cache.captions.size', 'cache.torrents.size', 'admin.email', 'contact_form.enabled', | 32 | 'cache.previews.size', 'cache.captions.size', 'cache.torrents.size', 'cache.storyboards.size', |
33 | 'admin.email', 'contact_form.enabled', | ||
33 | 'signup.enabled', 'signup.limit', 'signup.requires_approval', 'signup.requires_email_verification', 'signup.minimum_age', | 34 | 'signup.enabled', 'signup.limit', 'signup.requires_approval', 'signup.requires_email_verification', 'signup.minimum_age', |
34 | 'signup.filters.cidr.whitelist', 'signup.filters.cidr.blacklist', | 35 | 'signup.filters.cidr.whitelist', 'signup.filters.cidr.blacklist', |
35 | 'redundancy.videos.strategies', 'redundancy.videos.check_interval', | 36 | 'redundancy.videos.strategies', 'redundancy.videos.check_interval', |
36 | 'transcoding.enabled', 'transcoding.threads', 'transcoding.allow_additional_extensions', 'transcoding.hls.enabled', | 37 | 'transcoding.enabled', 'transcoding.threads', 'transcoding.allow_additional_extensions', 'transcoding.web_videos.enabled', |
37 | 'transcoding.profile', 'transcoding.concurrency', | 38 | 'transcoding.hls.enabled', 'transcoding.profile', 'transcoding.concurrency', |
38 | 'transcoding.resolutions.0p', 'transcoding.resolutions.144p', 'transcoding.resolutions.240p', 'transcoding.resolutions.360p', | 39 | 'transcoding.resolutions.0p', 'transcoding.resolutions.144p', 'transcoding.resolutions.240p', 'transcoding.resolutions.360p', |
39 | 'transcoding.resolutions.480p', 'transcoding.resolutions.720p', 'transcoding.resolutions.1080p', 'transcoding.resolutions.1440p', | 40 | 'transcoding.resolutions.480p', 'transcoding.resolutions.720p', 'transcoding.resolutions.1080p', 'transcoding.resolutions.1440p', |
40 | 'transcoding.resolutions.2160p', 'transcoding.always_transcode_original_resolution', 'transcoding.remote_runners.enabled', | 41 | 'transcoding.resolutions.2160p', 'transcoding.always_transcode_original_resolution', 'transcoding.remote_runners.enabled', |
@@ -59,8 +60,8 @@ function checkMissedConfig () { | |||
59 | 'object_storage.enabled', 'object_storage.endpoint', 'object_storage.region', 'object_storage.upload_acl.public', | 60 | 'object_storage.enabled', 'object_storage.endpoint', 'object_storage.region', 'object_storage.upload_acl.public', |
60 | 'object_storage.upload_acl.private', 'object_storage.proxy.proxify_private_files', 'object_storage.credentials.access_key_id', | 61 | 'object_storage.upload_acl.private', 'object_storage.proxy.proxify_private_files', 'object_storage.credentials.access_key_id', |
61 | 'object_storage.credentials.secret_access_key', 'object_storage.max_upload_part', 'object_storage.streaming_playlists.bucket_name', | 62 | 'object_storage.credentials.secret_access_key', 'object_storage.max_upload_part', 'object_storage.streaming_playlists.bucket_name', |
62 | 'object_storage.streaming_playlists.prefix', 'object_storage.streaming_playlists.base_url', 'object_storage.videos.bucket_name', | 63 | 'object_storage.streaming_playlists.prefix', 'object_storage.streaming_playlists.base_url', 'object_storage.web_videos.bucket_name', |
63 | 'object_storage.videos.prefix', 'object_storage.videos.base_url', | 64 | 'object_storage.web_videos.prefix', 'object_storage.web_videos.base_url', |
64 | 'theme.default', | 65 | 'theme.default', |
65 | 'feeds.videos.count', 'feeds.comments.count', | 66 | 'feeds.videos.count', 'feeds.comments.count', |
66 | 'geo_ip.enabled', 'geo_ip.country.database_url', | 67 | 'geo_ip.enabled', 'geo_ip.country.database_url', |
diff --git a/server/initializers/config.ts b/server/initializers/config.ts index 51ac5d0ce..37cd852f1 100644 --- a/server/initializers/config.ts +++ b/server/initializers/config.ts | |||
@@ -106,12 +106,13 @@ const CONFIG = { | |||
106 | TMP_DIR: buildPath(config.get<string>('storage.tmp')), | 106 | TMP_DIR: buildPath(config.get<string>('storage.tmp')), |
107 | TMP_PERSISTENT_DIR: buildPath(config.get<string>('storage.tmp_persistent')), | 107 | TMP_PERSISTENT_DIR: buildPath(config.get<string>('storage.tmp_persistent')), |
108 | BIN_DIR: buildPath(config.get<string>('storage.bin')), | 108 | BIN_DIR: buildPath(config.get<string>('storage.bin')), |
109 | ACTOR_IMAGES: buildPath(config.get<string>('storage.avatars')), | 109 | ACTOR_IMAGES_DIR: buildPath(config.get<string>('storage.avatars')), |
110 | LOG_DIR: buildPath(config.get<string>('storage.logs')), | 110 | LOG_DIR: buildPath(config.get<string>('storage.logs')), |
111 | VIDEOS_DIR: buildPath(config.get<string>('storage.videos')), | 111 | WEB_VIDEOS_DIR: buildPath(config.get<string>('storage.web_videos')), |
112 | STREAMING_PLAYLISTS_DIR: buildPath(config.get<string>('storage.streaming_playlists')), | 112 | STREAMING_PLAYLISTS_DIR: buildPath(config.get<string>('storage.streaming_playlists')), |
113 | REDUNDANCY_DIR: buildPath(config.get<string>('storage.redundancy')), | 113 | REDUNDANCY_DIR: buildPath(config.get<string>('storage.redundancy')), |
114 | THUMBNAILS_DIR: buildPath(config.get<string>('storage.thumbnails')), | 114 | THUMBNAILS_DIR: buildPath(config.get<string>('storage.thumbnails')), |
115 | STORYBOARDS_DIR: buildPath(config.get<string>('storage.storyboards')), | ||
115 | PREVIEWS_DIR: buildPath(config.get<string>('storage.previews')), | 116 | PREVIEWS_DIR: buildPath(config.get<string>('storage.previews')), |
116 | CAPTIONS_DIR: buildPath(config.get<string>('storage.captions')), | 117 | CAPTIONS_DIR: buildPath(config.get<string>('storage.captions')), |
117 | TORRENTS_DIR: buildPath(config.get<string>('storage.torrents')), | 118 | TORRENTS_DIR: buildPath(config.get<string>('storage.torrents')), |
@@ -139,10 +140,10 @@ const CONFIG = { | |||
139 | PROXY: { | 140 | PROXY: { |
140 | PROXIFY_PRIVATE_FILES: config.get<boolean>('object_storage.proxy.proxify_private_files') | 141 | PROXIFY_PRIVATE_FILES: config.get<boolean>('object_storage.proxy.proxify_private_files') |
141 | }, | 142 | }, |
142 | VIDEOS: { | 143 | WEB_VIDEOS: { |
143 | BUCKET_NAME: config.get<string>('object_storage.videos.bucket_name'), | 144 | BUCKET_NAME: config.get<string>('object_storage.web_videos.bucket_name'), |
144 | PREFIX: config.get<string>('object_storage.videos.prefix'), | 145 | PREFIX: config.get<string>('object_storage.web_videos.prefix'), |
145 | BASE_URL: config.get<string>('object_storage.videos.base_url') | 146 | BASE_URL: config.get<string>('object_storage.web_videos.base_url') |
146 | }, | 147 | }, |
147 | STREAMING_PLAYLISTS: { | 148 | STREAMING_PLAYLISTS: { |
148 | BUCKET_NAME: config.get<string>('object_storage.streaming_playlists.bucket_name'), | 149 | BUCKET_NAME: config.get<string>('object_storage.streaming_playlists.bucket_name'), |
@@ -370,8 +371,8 @@ const CONFIG = { | |||
370 | HLS: { | 371 | HLS: { |
371 | get ENABLED () { return config.get<boolean>('transcoding.hls.enabled') } | 372 | get ENABLED () { return config.get<boolean>('transcoding.hls.enabled') } |
372 | }, | 373 | }, |
373 | WEBTORRENT: { | 374 | WEB_VIDEOS: { |
374 | get ENABLED () { return config.get<boolean>('transcoding.webtorrent.enabled') } | 375 | get ENABLED () { return config.get<boolean>('transcoding.web_videos.enabled') } |
375 | }, | 376 | }, |
376 | REMOTE_RUNNERS: { | 377 | REMOTE_RUNNERS: { |
377 | get ENABLED () { return config.get<boolean>('transcoding.remote_runners.enabled') } | 378 | get ENABLED () { return config.get<boolean>('transcoding.remote_runners.enabled') } |
@@ -482,6 +483,9 @@ const CONFIG = { | |||
482 | }, | 483 | }, |
483 | TORRENTS: { | 484 | TORRENTS: { |
484 | get SIZE () { return config.get<number>('cache.torrents.size') } | 485 | get SIZE () { return config.get<number>('cache.torrents.size') } |
486 | }, | ||
487 | STORYBOARDS: { | ||
488 | get SIZE () { return config.get<number>('cache.storyboards.size') } | ||
485 | } | 489 | } |
486 | }, | 490 | }, |
487 | INSTANCE: { | 491 | INSTANCE: { |
@@ -580,16 +584,6 @@ function isEmailEnabled () { | |||
580 | return false | 584 | return false |
581 | } | 585 | } |
582 | 586 | ||
583 | // --------------------------------------------------------------------------- | ||
584 | |||
585 | export { | ||
586 | CONFIG, | ||
587 | registerConfigChangedHandler, | ||
588 | isEmailEnabled | ||
589 | } | ||
590 | |||
591 | // --------------------------------------------------------------------------- | ||
592 | |||
593 | function getLocalConfigFilePath () { | 587 | function getLocalConfigFilePath () { |
594 | const localConfigDir = getLocalConfigDir() | 588 | const localConfigDir = getLocalConfigDir() |
595 | 589 | ||
@@ -600,6 +594,17 @@ function getLocalConfigFilePath () { | |||
600 | return join(localConfigDir, filename + '.json') | 594 | return join(localConfigDir, filename + '.json') |
601 | } | 595 | } |
602 | 596 | ||
597 | // --------------------------------------------------------------------------- | ||
598 | |||
599 | export { | ||
600 | CONFIG, | ||
601 | getLocalConfigFilePath, | ||
602 | registerConfigChangedHandler, | ||
603 | isEmailEnabled | ||
604 | } | ||
605 | |||
606 | // --------------------------------------------------------------------------- | ||
607 | |||
603 | function getLocalConfigDir () { | 608 | function getLocalConfigDir () { |
604 | if (process.env.PEERTUBE_LOCAL_CONFIG) return process.env.PEERTUBE_LOCAL_CONFIG | 609 | if (process.env.PEERTUBE_LOCAL_CONFIG) return process.env.PEERTUBE_LOCAL_CONFIG |
605 | 610 | ||
diff --git a/server/initializers/constants.ts b/server/initializers/constants.ts index a92fd22d6..03ae94d35 100644 --- a/server/initializers/constants.ts +++ b/server/initializers/constants.ts | |||
@@ -27,7 +27,7 @@ import { CONFIG, registerConfigChangedHandler } from './config' | |||
27 | 27 | ||
28 | // --------------------------------------------------------------------------- | 28 | // --------------------------------------------------------------------------- |
29 | 29 | ||
30 | const LAST_MIGRATION_VERSION = 780 | 30 | const LAST_MIGRATION_VERSION = 790 |
31 | 31 | ||
32 | // --------------------------------------------------------------------------- | 32 | // --------------------------------------------------------------------------- |
33 | 33 | ||
@@ -76,6 +76,8 @@ const SORTABLE_COLUMNS = { | |||
76 | VIDEO_COMMENT_THREADS: [ 'createdAt', 'totalReplies' ], | 76 | VIDEO_COMMENT_THREADS: [ 'createdAt', 'totalReplies' ], |
77 | VIDEO_COMMENTS: [ 'createdAt' ], | 77 | VIDEO_COMMENTS: [ 'createdAt' ], |
78 | 78 | ||
79 | VIDEO_PASSWORDS: [ 'createdAt' ], | ||
80 | |||
79 | VIDEO_RATES: [ 'createdAt' ], | 81 | VIDEO_RATES: [ 'createdAt' ], |
80 | BLACKLISTS: [ 'id', 'name', 'duration', 'views', 'likes', 'dislikes', 'uuid', 'createdAt' ], | 82 | BLACKLISTS: [ 'id', 'name', 'duration', 'views', 'likes', 'dislikes', 'uuid', 'createdAt' ], |
81 | 83 | ||
@@ -172,6 +174,7 @@ const JOB_ATTEMPTS: { [id in JobType]: number } = { | |||
172 | 'after-video-channel-import': 1, | 174 | 'after-video-channel-import': 1, |
173 | 'move-to-object-storage': 3, | 175 | 'move-to-object-storage': 3, |
174 | 'transcoding-job-builder': 1, | 176 | 'transcoding-job-builder': 1, |
177 | 'generate-video-storyboard': 1, | ||
175 | 'notify': 1, | 178 | 'notify': 1, |
176 | 'federate-video': 1 | 179 | 'federate-video': 1 |
177 | } | 180 | } |
@@ -196,6 +199,7 @@ const JOB_CONCURRENCY: { [id in Exclude<JobType, 'video-transcoding' | 'video-im | |||
196 | 'video-channel-import': 1, | 199 | 'video-channel-import': 1, |
197 | 'after-video-channel-import': 1, | 200 | 'after-video-channel-import': 1, |
198 | 'transcoding-job-builder': 1, | 201 | 'transcoding-job-builder': 1, |
202 | 'generate-video-storyboard': 1, | ||
199 | 'notify': 5, | 203 | 'notify': 5, |
200 | 'federate-video': 3 | 204 | 'federate-video': 3 |
201 | } | 205 | } |
@@ -216,6 +220,7 @@ const JOB_TTL: { [id in JobType]: number } = { | |||
216 | 'activitypub-refresher': 60000 * 10, // 10 minutes | 220 | 'activitypub-refresher': 60000 * 10, // 10 minutes |
217 | 'video-redundancy': 1000 * 3600 * 3, // 3 hours | 221 | 'video-redundancy': 1000 * 3600 * 3, // 3 hours |
218 | 'video-live-ending': 1000 * 60 * 10, // 10 minutes | 222 | 'video-live-ending': 1000 * 60 * 10, // 10 minutes |
223 | 'generate-video-storyboard': 1000 * 60 * 10, // 10 minutes | ||
219 | 'manage-video-torrent': 1000 * 3600 * 3, // 3 hours | 224 | 'manage-video-torrent': 1000 * 3600 * 3, // 3 hours |
220 | 'move-to-object-storage': 1000 * 60 * 60 * 3, // 3 hours | 225 | 'move-to-object-storage': 1000 * 60 * 60 * 3, // 3 hours |
221 | 'video-channel-import': 1000 * 60 * 60 * 4, // 4 hours | 226 | 'video-channel-import': 1000 * 60 * 60 * 4, // 4 hours |
@@ -444,6 +449,9 @@ const CONSTRAINTS_FIELDS = { | |||
444 | REASON: { min: 1, max: 5000 }, // Length | 449 | REASON: { min: 1, max: 5000 }, // Length |
445 | ERROR_MESSAGE: { min: 1, max: 5000 }, // Length | 450 | ERROR_MESSAGE: { min: 1, max: 5000 }, // Length |
446 | PROGRESS: { min: 0, max: 100 } // Value | 451 | PROGRESS: { min: 0, max: 100 } // Value |
452 | }, | ||
453 | VIDEO_PASSWORD: { | ||
454 | LENGTH: { min: 2, max: 100 } | ||
447 | } | 455 | } |
448 | } | 456 | } |
449 | 457 | ||
@@ -520,7 +528,8 @@ const VIDEO_PRIVACIES: { [ id in VideoPrivacy ]: string } = { | |||
520 | [VideoPrivacy.PUBLIC]: 'Public', | 528 | [VideoPrivacy.PUBLIC]: 'Public', |
521 | [VideoPrivacy.UNLISTED]: 'Unlisted', | 529 | [VideoPrivacy.UNLISTED]: 'Unlisted', |
522 | [VideoPrivacy.PRIVATE]: 'Private', | 530 | [VideoPrivacy.PRIVATE]: 'Private', |
523 | [VideoPrivacy.INTERNAL]: 'Internal' | 531 | [VideoPrivacy.INTERNAL]: 'Internal', |
532 | [VideoPrivacy.PASSWORD_PROTECTED]: 'Password protected' | ||
524 | } | 533 | } |
525 | 534 | ||
526 | const VIDEO_STATES: { [ id in VideoState ]: string } = { | 535 | const VIDEO_STATES: { [ id in VideoState ]: string } = { |
@@ -738,10 +747,16 @@ const NSFW_POLICY_TYPES: { [ id: string ]: NSFWPolicyType } = { | |||
738 | 747 | ||
739 | // Express static paths (router) | 748 | // Express static paths (router) |
740 | const STATIC_PATHS = { | 749 | const STATIC_PATHS = { |
750 | // TODO: deprecated in v6, to remove | ||
741 | THUMBNAILS: '/static/thumbnails/', | 751 | THUMBNAILS: '/static/thumbnails/', |
742 | 752 | ||
743 | WEBSEED: '/static/webseed/', | 753 | // Need to keep this legacy path for previously generated torrents |
744 | PRIVATE_WEBSEED: '/static/webseed/private/', | 754 | LEGACY_WEB_VIDEOS: '/static/webseed/', |
755 | WEB_VIDEOS: '/static/web-videos/', | ||
756 | |||
757 | // Need to keep this legacy path for previously generated torrents | ||
758 | LEGACY_PRIVATE_WEB_VIDEOS: '/static/webseed/private/', | ||
759 | PRIVATE_WEB_VIDEOS: '/static/web-videos/private/', | ||
745 | 760 | ||
746 | REDUNDANCY: '/static/redundancy/', | 761 | REDUNDANCY: '/static/redundancy/', |
747 | 762 | ||
@@ -756,14 +771,18 @@ const STATIC_DOWNLOAD_PATHS = { | |||
756 | HLS_VIDEOS: '/download/streaming-playlists/hls/videos/' | 771 | HLS_VIDEOS: '/download/streaming-playlists/hls/videos/' |
757 | } | 772 | } |
758 | const LAZY_STATIC_PATHS = { | 773 | const LAZY_STATIC_PATHS = { |
774 | THUMBNAILS: '/lazy-static/thumbnails/', | ||
759 | BANNERS: '/lazy-static/banners/', | 775 | BANNERS: '/lazy-static/banners/', |
760 | AVATARS: '/lazy-static/avatars/', | 776 | AVATARS: '/lazy-static/avatars/', |
761 | PREVIEWS: '/lazy-static/previews/', | 777 | PREVIEWS: '/lazy-static/previews/', |
762 | VIDEO_CAPTIONS: '/lazy-static/video-captions/', | 778 | VIDEO_CAPTIONS: '/lazy-static/video-captions/', |
763 | TORRENTS: '/lazy-static/torrents/' | 779 | TORRENTS: '/lazy-static/torrents/', |
780 | STORYBOARDS: '/lazy-static/storyboards/' | ||
764 | } | 781 | } |
765 | const OBJECT_STORAGE_PROXY_PATHS = { | 782 | const OBJECT_STORAGE_PROXY_PATHS = { |
766 | PRIVATE_WEBSEED: '/object-storage-proxy/webseed/private/', | 783 | // Need to keep this legacy path for previously generated torrents |
784 | LEGACY_PRIVATE_WEB_VIDEOS: '/object-storage-proxy/webseed/private/', | ||
785 | PRIVATE_WEB_VIDEOS: '/object-storage-proxy/web-videos/private/', | ||
767 | 786 | ||
768 | STREAMING_PLAYLISTS: { | 787 | STREAMING_PLAYLISTS: { |
769 | PRIVATE_HLS: '/object-storage-proxy/streaming-playlists/hls/private/' | 788 | PRIVATE_HLS: '/object-storage-proxy/streaming-playlists/hls/private/' |
@@ -807,6 +826,14 @@ const ACTOR_IMAGES_SIZE: { [key in ActorImageType]: { width: number, height: num | |||
807 | ] | 826 | ] |
808 | } | 827 | } |
809 | 828 | ||
829 | const STORYBOARD = { | ||
830 | SPRITE_SIZE: { | ||
831 | width: 192, | ||
832 | height: 108 | ||
833 | }, | ||
834 | SPRITES_MAX_EDGE_COUNT: 10 | ||
835 | } | ||
836 | |||
810 | const EMBED_SIZE = { | 837 | const EMBED_SIZE = { |
811 | width: 560, | 838 | width: 560, |
812 | height: 315 | 839 | height: 315 |
@@ -818,6 +845,10 @@ const FILES_CACHE = { | |||
818 | DIRECTORY: join(CONFIG.STORAGE.CACHE_DIR, 'previews'), | 845 | DIRECTORY: join(CONFIG.STORAGE.CACHE_DIR, 'previews'), |
819 | MAX_AGE: 1000 * 3600 * 3 // 3 hours | 846 | MAX_AGE: 1000 * 3600 * 3 // 3 hours |
820 | }, | 847 | }, |
848 | STORYBOARDS: { | ||
849 | DIRECTORY: join(CONFIG.STORAGE.CACHE_DIR, 'storyboards'), | ||
850 | MAX_AGE: 1000 * 3600 * 24 // 24 hours | ||
851 | }, | ||
821 | VIDEO_CAPTIONS: { | 852 | VIDEO_CAPTIONS: { |
822 | DIRECTORY: join(CONFIG.STORAGE.CACHE_DIR, 'video-captions'), | 853 | DIRECTORY: join(CONFIG.STORAGE.CACHE_DIR, 'video-captions'), |
823 | MAX_AGE: 1000 * 3600 * 3 // 3 hours | 854 | MAX_AGE: 1000 * 3600 * 3 // 3 hours |
@@ -832,8 +863,8 @@ const LRU_CACHE = { | |||
832 | USER_TOKENS: { | 863 | USER_TOKENS: { |
833 | MAX_SIZE: 1000 | 864 | MAX_SIZE: 1000 |
834 | }, | 865 | }, |
835 | ACTOR_IMAGE_STATIC: { | 866 | FILENAME_TO_PATH_PERMANENT_FILE_CACHE: { |
836 | MAX_SIZE: 500 | 867 | MAX_SIZE: 1000 |
837 | }, | 868 | }, |
838 | STATIC_VIDEO_FILES_RIGHTS_CHECK: { | 869 | STATIC_VIDEO_FILES_RIGHTS_CHECK: { |
839 | MAX_SIZE: 5000, | 870 | MAX_SIZE: 5000, |
@@ -857,8 +888,8 @@ const DIRECTORIES = { | |||
857 | }, | 888 | }, |
858 | 889 | ||
859 | VIDEOS: { | 890 | VIDEOS: { |
860 | PUBLIC: CONFIG.STORAGE.VIDEOS_DIR, | 891 | PUBLIC: CONFIG.STORAGE.WEB_VIDEOS_DIR, |
861 | PRIVATE: join(CONFIG.STORAGE.VIDEOS_DIR, 'private') | 892 | PRIVATE: join(CONFIG.STORAGE.WEB_VIDEOS_DIR, 'private') |
862 | }, | 893 | }, |
863 | 894 | ||
864 | HLS_REDUNDANCY: join(CONFIG.STORAGE.REDUNDANCY_DIR, 'hls') | 895 | HLS_REDUNDANCY: join(CONFIG.STORAGE.REDUNDANCY_DIR, 'hls') |
@@ -1084,6 +1115,7 @@ export { | |||
1084 | RESUMABLE_UPLOAD_SESSION_LIFETIME, | 1115 | RESUMABLE_UPLOAD_SESSION_LIFETIME, |
1085 | RUNNER_JOB_STATES, | 1116 | RUNNER_JOB_STATES, |
1086 | P2P_MEDIA_LOADER_PEER_VERSION, | 1117 | P2P_MEDIA_LOADER_PEER_VERSION, |
1118 | STORYBOARD, | ||
1087 | ACTOR_IMAGES_SIZE, | 1119 | ACTOR_IMAGES_SIZE, |
1088 | ACCEPT_HEADERS, | 1120 | ACCEPT_HEADERS, |
1089 | BCRYPT_SALT_SIZE, | 1121 | BCRYPT_SALT_SIZE, |
diff --git a/server/initializers/database.ts b/server/initializers/database.ts index 14dd8c379..bc120e398 100644 --- a/server/initializers/database.ts +++ b/server/initializers/database.ts | |||
@@ -10,6 +10,7 @@ import { UserModel } from '@server/models/user/user' | |||
10 | import { UserNotificationModel } from '@server/models/user/user-notification' | 10 | import { UserNotificationModel } from '@server/models/user/user-notification' |
11 | import { UserRegistrationModel } from '@server/models/user/user-registration' | 11 | import { UserRegistrationModel } from '@server/models/user/user-registration' |
12 | import { UserVideoHistoryModel } from '@server/models/user/user-video-history' | 12 | import { UserVideoHistoryModel } from '@server/models/user/user-video-history' |
13 | import { StoryboardModel } from '@server/models/video/storyboard' | ||
13 | import { VideoChannelSyncModel } from '@server/models/video/video-channel-sync' | 14 | import { VideoChannelSyncModel } from '@server/models/video/video-channel-sync' |
14 | import { VideoJobInfoModel } from '@server/models/video/video-job-info' | 15 | import { VideoJobInfoModel } from '@server/models/video/video-job-info' |
15 | import { VideoLiveReplaySettingModel } from '@server/models/video/video-live-replay-setting' | 16 | import { VideoLiveReplaySettingModel } from '@server/models/video/video-live-replay-setting' |
@@ -56,6 +57,7 @@ import { VideoStreamingPlaylistModel } from '../models/video/video-streaming-pla | |||
56 | import { VideoTagModel } from '../models/video/video-tag' | 57 | import { VideoTagModel } from '../models/video/video-tag' |
57 | import { VideoViewModel } from '../models/view/video-view' | 58 | import { VideoViewModel } from '../models/view/video-view' |
58 | import { CONFIG } from './config' | 59 | import { CONFIG } from './config' |
60 | import { VideoPasswordModel } from '@server/models/video/video-password' | ||
59 | 61 | ||
60 | require('pg').defaults.parseInt8 = true // Avoid BIGINT to be converted to string | 62 | require('pg').defaults.parseInt8 = true // Avoid BIGINT to be converted to string |
61 | 63 | ||
@@ -163,9 +165,11 @@ async function initDatabaseModels (silent: boolean) { | |||
163 | VideoJobInfoModel, | 165 | VideoJobInfoModel, |
164 | VideoChannelSyncModel, | 166 | VideoChannelSyncModel, |
165 | UserRegistrationModel, | 167 | UserRegistrationModel, |
168 | VideoPasswordModel, | ||
166 | RunnerRegistrationTokenModel, | 169 | RunnerRegistrationTokenModel, |
167 | RunnerModel, | 170 | RunnerModel, |
168 | RunnerJobModel | 171 | RunnerJobModel, |
172 | StoryboardModel | ||
169 | ]) | 173 | ]) |
170 | 174 | ||
171 | // Check extensions exist in the database | 175 | // Check extensions exist in the database |
diff --git a/server/initializers/migrations/0785-video-password-protection.ts b/server/initializers/migrations/0785-video-password-protection.ts new file mode 100644 index 000000000..1d85f4489 --- /dev/null +++ b/server/initializers/migrations/0785-video-password-protection.ts | |||
@@ -0,0 +1,31 @@ | |||
1 | import * as Sequelize from 'sequelize' | ||
2 | |||
3 | async function up (utils: { | ||
4 | transaction: Sequelize.Transaction | ||
5 | queryInterface: Sequelize.QueryInterface | ||
6 | sequelize: Sequelize.Sequelize | ||
7 | }): Promise<void> { | ||
8 | { | ||
9 | const query = ` | ||
10 | CREATE TABLE IF NOT EXISTS "videoPassword" ( | ||
11 | "id" SERIAL, | ||
12 | "password" VARCHAR(255) NOT NULL, | ||
13 | "videoId" INTEGER NOT NULL REFERENCES "video" ("id") ON DELETE CASCADE ON UPDATE CASCADE, | ||
14 | "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL, | ||
15 | "updatedAt" TIMESTAMP WITH TIME ZONE NOT NULL, | ||
16 | PRIMARY KEY ("id") | ||
17 | ); | ||
18 | ` | ||
19 | |||
20 | await utils.sequelize.query(query, { transaction : utils.transaction }) | ||
21 | } | ||
22 | } | ||
23 | |||
24 | function down (options) { | ||
25 | throw new Error('Not implemented.') | ||
26 | } | ||
27 | |||
28 | export { | ||
29 | up, | ||
30 | down | ||
31 | } | ||
diff --git a/server/initializers/migrations/0790-thumbnail-disk.ts b/server/initializers/migrations/0790-thumbnail-disk.ts new file mode 100644 index 000000000..0824c042e --- /dev/null +++ b/server/initializers/migrations/0790-thumbnail-disk.ts | |||
@@ -0,0 +1,47 @@ | |||
1 | import * as Sequelize from 'sequelize' | ||
2 | |||
3 | async function up (utils: { | ||
4 | transaction: Sequelize.Transaction | ||
5 | queryInterface: Sequelize.QueryInterface | ||
6 | sequelize: Sequelize.Sequelize | ||
7 | }): Promise<void> { | ||
8 | const { transaction } = utils | ||
9 | |||
10 | { | ||
11 | const data = { | ||
12 | type: Sequelize.BOOLEAN, | ||
13 | allowNull: true, | ||
14 | defaultValue: true | ||
15 | } | ||
16 | |||
17 | await utils.queryInterface.addColumn('thumbnail', 'onDisk', data, { transaction }) | ||
18 | } | ||
19 | |||
20 | { | ||
21 | // Remote previews are not on the disk | ||
22 | await utils.sequelize.query( | ||
23 | 'UPDATE "thumbnail" SET "onDisk" = FALSE ' + | ||
24 | 'WHERE "type" = 2 AND "videoId" NOT IN (SELECT "id" FROM "video" WHERE "remote" IS FALSE)', | ||
25 | { transaction } | ||
26 | ) | ||
27 | } | ||
28 | |||
29 | { | ||
30 | const data = { | ||
31 | type: Sequelize.BOOLEAN, | ||
32 | allowNull: false, | ||
33 | defaultValue: null | ||
34 | } | ||
35 | |||
36 | await utils.queryInterface.changeColumn('thumbnail', 'onDisk', data, { transaction }) | ||
37 | } | ||
38 | } | ||
39 | |||
40 | function down (options) { | ||
41 | throw new Error('Not implemented.') | ||
42 | } | ||
43 | |||
44 | export { | ||
45 | up, | ||
46 | down | ||
47 | } | ||