diff options
Diffstat (limited to 'server/lib')
-rw-r--r-- | server/lib/client-html.ts | 3 | ||||
-rw-r--r-- | server/lib/video-pre-import.ts | 11 | ||||
-rw-r--r-- | server/lib/video-privacy.ts | 10 | ||||
-rw-r--r-- | server/lib/video-tokens-manager.ts | 25 |
4 files changed, 39 insertions, 10 deletions
diff --git a/server/lib/client-html.ts b/server/lib/client-html.ts index 18b16bee1..be6df1792 100644 --- a/server/lib/client-html.ts +++ b/server/lib/client-html.ts | |||
@@ -32,6 +32,7 @@ import { getActivityStreamDuration } from './activitypub/activity' | |||
32 | import { getBiggestActorImage } from './actor-image' | 32 | import { getBiggestActorImage } from './actor-image' |
33 | import { Hooks } from './plugins/hooks' | 33 | import { Hooks } from './plugins/hooks' |
34 | import { ServerConfigManager } from './server-config-manager' | 34 | import { ServerConfigManager } from './server-config-manager' |
35 | import { isVideoInPrivateDirectory } from './video-privacy' | ||
35 | 36 | ||
36 | type Tags = { | 37 | type Tags = { |
37 | ogType: string | 38 | ogType: string |
@@ -106,7 +107,7 @@ class ClientHtml { | |||
106 | ]) | 107 | ]) |
107 | 108 | ||
108 | // Let Angular application handle errors | 109 | // Let Angular application handle errors |
109 | if (!video || video.privacy === VideoPrivacy.PRIVATE || video.privacy === VideoPrivacy.INTERNAL || video.VideoBlacklist) { | 110 | if (!video || isVideoInPrivateDirectory(video.privacy) || video.VideoBlacklist) { |
110 | res.status(HttpStatusCode.NOT_FOUND_404) | 111 | res.status(HttpStatusCode.NOT_FOUND_404) |
111 | return html | 112 | return html |
112 | } | 113 | } |
diff --git a/server/lib/video-pre-import.ts b/server/lib/video-pre-import.ts index df67dc953..0ac667ba3 100644 --- a/server/lib/video-pre-import.ts +++ b/server/lib/video-pre-import.ts | |||
@@ -30,6 +30,7 @@ import { | |||
30 | import { ThumbnailType, VideoImportCreate, VideoImportPayload, VideoImportState, VideoPrivacy, VideoState } from '@shared/models' | 30 | import { ThumbnailType, VideoImportCreate, VideoImportPayload, VideoImportState, VideoPrivacy, VideoState } from '@shared/models' |
31 | import { getLocalVideoActivityPubUrl } from './activitypub/url' | 31 | import { getLocalVideoActivityPubUrl } from './activitypub/url' |
32 | import { updateVideoMiniatureFromExisting, updateVideoMiniatureFromUrl } from './thumbnail' | 32 | import { updateVideoMiniatureFromExisting, updateVideoMiniatureFromUrl } from './thumbnail' |
33 | import { VideoPasswordModel } from '@server/models/video/video-password' | ||
33 | 34 | ||
34 | class YoutubeDlImportError extends Error { | 35 | class YoutubeDlImportError extends Error { |
35 | code: YoutubeDlImportError.CODE | 36 | code: YoutubeDlImportError.CODE |
@@ -64,8 +65,9 @@ async function insertFromImportIntoDB (parameters: { | |||
64 | tags: string[] | 65 | tags: string[] |
65 | videoImportAttributes: FilteredModelAttributes<VideoImportModel> | 66 | videoImportAttributes: FilteredModelAttributes<VideoImportModel> |
66 | user: MUser | 67 | user: MUser |
68 | videoPasswords?: string[] | ||
67 | }): Promise<MVideoImportFormattable> { | 69 | }): Promise<MVideoImportFormattable> { |
68 | const { video, thumbnailModel, previewModel, videoChannel, tags, videoImportAttributes, user } = parameters | 70 | const { video, thumbnailModel, previewModel, videoChannel, tags, videoImportAttributes, user, videoPasswords } = parameters |
69 | 71 | ||
70 | const videoImport = await sequelizeTypescript.transaction(async t => { | 72 | const videoImport = await sequelizeTypescript.transaction(async t => { |
71 | const sequelizeOptions = { transaction: t } | 73 | const sequelizeOptions = { transaction: t } |
@@ -77,6 +79,10 @@ async function insertFromImportIntoDB (parameters: { | |||
77 | if (thumbnailModel) await videoCreated.addAndSaveThumbnail(thumbnailModel, t) | 79 | if (thumbnailModel) await videoCreated.addAndSaveThumbnail(thumbnailModel, t) |
78 | if (previewModel) await videoCreated.addAndSaveThumbnail(previewModel, t) | 80 | if (previewModel) await videoCreated.addAndSaveThumbnail(previewModel, t) |
79 | 81 | ||
82 | if (videoCreated.privacy === VideoPrivacy.PASSWORD_PROTECTED) { | ||
83 | await VideoPasswordModel.addPasswords(videoPasswords, video.id, t) | ||
84 | } | ||
85 | |||
80 | await autoBlacklistVideoIfNeeded({ | 86 | await autoBlacklistVideoIfNeeded({ |
81 | video: videoCreated, | 87 | video: videoCreated, |
82 | user, | 88 | user, |
@@ -208,7 +214,8 @@ async function buildYoutubeDLImport (options: { | |||
208 | state: VideoImportState.PENDING, | 214 | state: VideoImportState.PENDING, |
209 | userId: user.id, | 215 | userId: user.id, |
210 | videoChannelSyncId: channelSync?.id | 216 | videoChannelSyncId: channelSync?.id |
211 | } | 217 | }, |
218 | videoPasswords: importDataOverride.videoPasswords | ||
212 | }) | 219 | }) |
213 | 220 | ||
214 | // Get video subtitles | 221 | // Get video subtitles |
diff --git a/server/lib/video-privacy.ts b/server/lib/video-privacy.ts index 41f9d62b3..39430ef1e 100644 --- a/server/lib/video-privacy.ts +++ b/server/lib/video-privacy.ts | |||
@@ -6,6 +6,12 @@ import { MVideo, MVideoFile, MVideoFullLight } from '@server/types/models' | |||
6 | import { VideoPrivacy, VideoStorage } from '@shared/models' | 6 | import { VideoPrivacy, VideoStorage } from '@shared/models' |
7 | import { updateHLSFilesACL, updateWebTorrentFileACL } from './object-storage' | 7 | import { updateHLSFilesACL, updateWebTorrentFileACL } from './object-storage' |
8 | 8 | ||
9 | const validPrivacySet = new Set([ | ||
10 | VideoPrivacy.PRIVATE, | ||
11 | VideoPrivacy.INTERNAL, | ||
12 | VideoPrivacy.PASSWORD_PROTECTED | ||
13 | ]) | ||
14 | |||
9 | function setVideoPrivacy (video: MVideo, newPrivacy: VideoPrivacy) { | 15 | function setVideoPrivacy (video: MVideo, newPrivacy: VideoPrivacy) { |
10 | if (video.privacy === VideoPrivacy.PRIVATE && newPrivacy !== VideoPrivacy.PRIVATE) { | 16 | if (video.privacy === VideoPrivacy.PRIVATE && newPrivacy !== VideoPrivacy.PRIVATE) { |
11 | video.publishedAt = new Date() | 17 | video.publishedAt = new Date() |
@@ -14,8 +20,8 @@ function setVideoPrivacy (video: MVideo, newPrivacy: VideoPrivacy) { | |||
14 | video.privacy = newPrivacy | 20 | video.privacy = newPrivacy |
15 | } | 21 | } |
16 | 22 | ||
17 | function isVideoInPrivateDirectory (privacy: VideoPrivacy) { | 23 | function isVideoInPrivateDirectory (privacy) { |
18 | return privacy === VideoPrivacy.PRIVATE || privacy === VideoPrivacy.INTERNAL | 24 | return validPrivacySet.has(privacy) |
19 | } | 25 | } |
20 | 26 | ||
21 | function isVideoInPublicDirectory (privacy: VideoPrivacy) { | 27 | function isVideoInPublicDirectory (privacy: VideoPrivacy) { |
diff --git a/server/lib/video-tokens-manager.ts b/server/lib/video-tokens-manager.ts index 660533528..e28e55cf7 100644 --- a/server/lib/video-tokens-manager.ts +++ b/server/lib/video-tokens-manager.ts | |||
@@ -12,26 +12,34 @@ class VideoTokensManager { | |||
12 | 12 | ||
13 | private static instance: VideoTokensManager | 13 | private static instance: VideoTokensManager |
14 | 14 | ||
15 | private readonly lruCache = new LRUCache<string, { videoUUID: string, user: MUserAccountUrl }>({ | 15 | private readonly lruCache = new LRUCache<string, { videoUUID: string, user?: MUserAccountUrl }>({ |
16 | max: LRU_CACHE.VIDEO_TOKENS.MAX_SIZE, | 16 | max: LRU_CACHE.VIDEO_TOKENS.MAX_SIZE, |
17 | ttl: LRU_CACHE.VIDEO_TOKENS.TTL | 17 | ttl: LRU_CACHE.VIDEO_TOKENS.TTL |
18 | }) | 18 | }) |
19 | 19 | ||
20 | private constructor () {} | 20 | private constructor () {} |
21 | 21 | ||
22 | create (options: { | 22 | createForAuthUser (options: { |
23 | user: MUserAccountUrl | 23 | user: MUserAccountUrl |
24 | videoUUID: string | 24 | videoUUID: string |
25 | }) { | 25 | }) { |
26 | const token = buildUUID() | 26 | const { token, expires } = this.generateVideoToken() |
27 | |||
28 | const expires = new Date(new Date().getTime() + LRU_CACHE.VIDEO_TOKENS.TTL) | ||
29 | 27 | ||
30 | this.lruCache.set(token, pick(options, [ 'user', 'videoUUID' ])) | 28 | this.lruCache.set(token, pick(options, [ 'user', 'videoUUID' ])) |
31 | 29 | ||
32 | return { token, expires } | 30 | return { token, expires } |
33 | } | 31 | } |
34 | 32 | ||
33 | createForPasswordProtectedVideo (options: { | ||
34 | videoUUID: string | ||
35 | }) { | ||
36 | const { token, expires } = this.generateVideoToken() | ||
37 | |||
38 | this.lruCache.set(token, pick(options, [ 'videoUUID' ])) | ||
39 | |||
40 | return { token, expires } | ||
41 | } | ||
42 | |||
35 | hasToken (options: { | 43 | hasToken (options: { |
36 | token: string | 44 | token: string |
37 | videoUUID: string | 45 | videoUUID: string |
@@ -54,6 +62,13 @@ class VideoTokensManager { | |||
54 | static get Instance () { | 62 | static get Instance () { |
55 | return this.instance || (this.instance = new this()) | 63 | return this.instance || (this.instance = new this()) |
56 | } | 64 | } |
65 | |||
66 | private generateVideoToken () { | ||
67 | const token = buildUUID() | ||
68 | const expires = new Date(new Date().getTime() + LRU_CACHE.VIDEO_TOKENS.TTL) | ||
69 | |||
70 | return { token, expires } | ||
71 | } | ||
57 | } | 72 | } |
58 | 73 | ||
59 | // --------------------------------------------------------------------------- | 74 | // --------------------------------------------------------------------------- |