aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/initializers
diff options
context:
space:
mode:
Diffstat (limited to 'server/initializers')
-rw-r--r--server/initializers/checker-after-init.ts50
-rw-r--r--server/initializers/checker-before-init.ts13
-rw-r--r--server/initializers/config.ts41
-rw-r--r--server/initializers/constants.ts52
-rw-r--r--server/initializers/database.ts6
-rw-r--r--server/initializers/migrations/0785-video-password-protection.ts31
-rw-r--r--server/initializers/migrations/0790-thumbnail-disk.ts47
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 @@
1import config from 'config' 1import config from 'config'
2import { readFileSync, writeFileSync } from 'fs-extra'
2import { URL } from 'url' 3import { URL } from 'url'
3import { uniqify } from '@shared/core-utils' 4import { uniqify } from '@shared/core-utils'
4import { getFFmpegVersion } from '@shared/ffmpeg' 5import { getFFmpegVersion } from '@shared/ffmpeg'
@@ -10,7 +11,7 @@ import { logger } from '../helpers/logger'
10import { ApplicationModel, getServerActor } from '../models/application/application' 11import { ApplicationModel, getServerActor } from '../models/application/application'
11import { OAuthClientModel } from '../models/oauth/oauth-client' 12import { OAuthClientModel } from '../models/oauth/oauth-client'
12import { UserModel } from '../models/user/user' 13import { UserModel } from '../models/user/user'
13import { CONFIG, isEmailEnabled } from './config' 14import { CONFIG, getLocalConfigFilePath, isEmailEnabled, reloadConfig } from './config'
14import { WEBSERVER } from './constants' 15import { WEBSERVER } from './constants'
15 16
16async function checkActivityPubUrls () { 17async 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
105function 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
107function checkSecretsConfig () { 133function 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
199function checkTranscodingConfig () { 225function 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 () {
264function checkObjectStorageConfig () { 290function 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
585export {
586 CONFIG,
587 registerConfigChangedHandler,
588 isEmailEnabled
589}
590
591// ---------------------------------------------------------------------------
592
593function getLocalConfigFilePath () { 587function 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
599export {
600 CONFIG,
601 getLocalConfigFilePath,
602 registerConfigChangedHandler,
603 isEmailEnabled
604}
605
606// ---------------------------------------------------------------------------
607
603function getLocalConfigDir () { 608function 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
30const LAST_MIGRATION_VERSION = 780 30const 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
526const VIDEO_STATES: { [ id in VideoState ]: string } = { 535const 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)
740const STATIC_PATHS = { 749const 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}
758const LAZY_STATIC_PATHS = { 773const 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}
765const OBJECT_STORAGE_PROXY_PATHS = { 782const 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
829const STORYBOARD = {
830 SPRITE_SIZE: {
831 width: 192,
832 height: 108
833 },
834 SPRITES_MAX_EDGE_COUNT: 10
835}
836
810const EMBED_SIZE = { 837const 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'
10import { UserNotificationModel } from '@server/models/user/user-notification' 10import { UserNotificationModel } from '@server/models/user/user-notification'
11import { UserRegistrationModel } from '@server/models/user/user-registration' 11import { UserRegistrationModel } from '@server/models/user/user-registration'
12import { UserVideoHistoryModel } from '@server/models/user/user-video-history' 12import { UserVideoHistoryModel } from '@server/models/user/user-video-history'
13import { StoryboardModel } from '@server/models/video/storyboard'
13import { VideoChannelSyncModel } from '@server/models/video/video-channel-sync' 14import { VideoChannelSyncModel } from '@server/models/video/video-channel-sync'
14import { VideoJobInfoModel } from '@server/models/video/video-job-info' 15import { VideoJobInfoModel } from '@server/models/video/video-job-info'
15import { VideoLiveReplaySettingModel } from '@server/models/video/video-live-replay-setting' 16import { VideoLiveReplaySettingModel } from '@server/models/video/video-live-replay-setting'
@@ -56,6 +57,7 @@ import { VideoStreamingPlaylistModel } from '../models/video/video-streaming-pla
56import { VideoTagModel } from '../models/video/video-tag' 57import { VideoTagModel } from '../models/video/video-tag'
57import { VideoViewModel } from '../models/view/video-view' 58import { VideoViewModel } from '../models/view/video-view'
58import { CONFIG } from './config' 59import { CONFIG } from './config'
60import { VideoPasswordModel } from '@server/models/video/video-password'
59 61
60require('pg').defaults.parseInt8 = true // Avoid BIGINT to be converted to string 62require('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 @@
1import * as Sequelize from 'sequelize'
2
3async 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
24function down (options) {
25 throw new Error('Not implemented.')
26}
27
28export {
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 @@
1import * as Sequelize from 'sequelize'
2
3async 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
40function down (options) {
41 throw new Error('Not implemented.')
42}
43
44export {
45 up,
46 down
47}