diff options
Diffstat (limited to 'client/src/standalone')
-rw-r--r-- | client/src/standalone/videos/embed.ts | 22 | ||||
-rw-r--r-- | client/src/standalone/videos/shared/auth-http.ts | 28 | ||||
-rw-r--r-- | client/src/standalone/videos/shared/player-manager-options.ts | 12 | ||||
-rw-r--r-- | client/src/standalone/videos/shared/video-fetcher.ts | 17 |
4 files changed, 52 insertions, 27 deletions
diff --git a/client/src/standalone/videos/embed.ts b/client/src/standalone/videos/embed.ts index 451e54840..c6160151a 100644 --- a/client/src/standalone/videos/embed.ts +++ b/client/src/standalone/videos/embed.ts | |||
@@ -6,7 +6,7 @@ import { peertubeTranslate } from '../../../../shared/core-utils/i18n' | |||
6 | import { HTMLServerConfig, LiveVideo, ResultList, VideoDetails, VideoPlaylist, VideoPlaylistElement } from '../../../../shared/models' | 6 | import { HTMLServerConfig, LiveVideo, ResultList, VideoDetails, VideoPlaylist, VideoPlaylistElement } from '../../../../shared/models' |
7 | import { PeertubePlayerManager } from '../../assets/player' | 7 | import { PeertubePlayerManager } from '../../assets/player' |
8 | import { TranslationsManager } from '../../assets/player/translations-manager' | 8 | import { TranslationsManager } from '../../assets/player/translations-manager' |
9 | import { getParamString, logger } from '../../root-helpers' | 9 | import { getParamString, logger, videoRequiresAuth } from '../../root-helpers' |
10 | import { PeerTubeEmbedApi } from './embed-api' | 10 | import { PeerTubeEmbedApi } from './embed-api' |
11 | import { AuthHTTP, LiveManager, PeerTubePlugin, PlayerManagerOptions, PlaylistFetcher, PlaylistTracker, VideoFetcher } from './shared' | 11 | import { AuthHTTP, LiveManager, PeerTubePlugin, PlayerManagerOptions, PlaylistFetcher, PlaylistTracker, VideoFetcher } from './shared' |
12 | import { PlayerHTML } from './shared/player-html' | 12 | import { PlayerHTML } from './shared/player-html' |
@@ -167,22 +167,25 @@ export class PeerTubeEmbed { | |||
167 | private async buildVideoPlayer (videoResponse: Response, captionsPromise: Promise<Response>) { | 167 | private async buildVideoPlayer (videoResponse: Response, captionsPromise: Promise<Response>) { |
168 | const alreadyHadPlayer = this.resetPlayerElement() | 168 | const alreadyHadPlayer = this.resetPlayerElement() |
169 | 169 | ||
170 | const videoInfoPromise: Promise<{ video: VideoDetails, live?: LiveVideo }> = videoResponse.json() | 170 | const videoInfoPromise = videoResponse.json() |
171 | .then((videoInfo: VideoDetails) => { | 171 | .then(async (videoInfo: VideoDetails) => { |
172 | this.playerManagerOptions.loadParams(this.config, videoInfo) | 172 | this.playerManagerOptions.loadParams(this.config, videoInfo) |
173 | 173 | ||
174 | if (!alreadyHadPlayer && !this.playerManagerOptions.hasAutoplay()) { | 174 | if (!alreadyHadPlayer && !this.playerManagerOptions.hasAutoplay()) { |
175 | this.playerHTML.buildPlaceholder(videoInfo) | 175 | this.playerHTML.buildPlaceholder(videoInfo) |
176 | } | 176 | } |
177 | const live = videoInfo.isLive | ||
178 | ? await this.videoFetcher.loadLive(videoInfo) | ||
179 | : undefined | ||
177 | 180 | ||
178 | if (!videoInfo.isLive) { | 181 | const videoFileToken = videoRequiresAuth(videoInfo) |
179 | return { video: videoInfo } | 182 | ? await this.videoFetcher.loadVideoToken(videoInfo) |
180 | } | 183 | : undefined |
181 | 184 | ||
182 | return this.videoFetcher.loadVideoWithLive(videoInfo) | 185 | return { live, video: videoInfo, videoFileToken } |
183 | }) | 186 | }) |
184 | 187 | ||
185 | const [ { video, live }, translations, captionsResponse, PeertubePlayerManagerModule ] = await Promise.all([ | 188 | const [ { video, live, videoFileToken }, translations, captionsResponse, PeertubePlayerManagerModule ] = await Promise.all([ |
186 | videoInfoPromise, | 189 | videoInfoPromise, |
187 | this.translationsPromise, | 190 | this.translationsPromise, |
188 | captionsPromise, | 191 | captionsPromise, |
@@ -200,6 +203,9 @@ export class PeerTubeEmbed { | |||
200 | translations, | 203 | translations, |
201 | serverConfig: this.config, | 204 | serverConfig: this.config, |
202 | 205 | ||
206 | authorizationHeader: () => this.http.getHeaderTokenValue(), | ||
207 | videoFileToken: () => videoFileToken, | ||
208 | |||
203 | onVideoUpdate: (uuid: string) => this.loadVideoAndBuildPlayer(uuid), | 209 | onVideoUpdate: (uuid: string) => this.loadVideoAndBuildPlayer(uuid), |
204 | 210 | ||
205 | playlistTracker: this.playlistTracker, | 211 | playlistTracker: this.playlistTracker, |
diff --git a/client/src/standalone/videos/shared/auth-http.ts b/client/src/standalone/videos/shared/auth-http.ts index 0356ab8a6..43af5dff4 100644 --- a/client/src/standalone/videos/shared/auth-http.ts +++ b/client/src/standalone/videos/shared/auth-http.ts | |||
@@ -1,5 +1,5 @@ | |||
1 | import { HttpStatusCode, OAuth2ErrorCode, UserRefreshToken } from '../../../../../shared/models' | 1 | import { HttpStatusCode, OAuth2ErrorCode, UserRefreshToken } from '../../../../../shared/models' |
2 | import { objectToUrlEncoded, UserTokens } from '../../../root-helpers' | 2 | import { OAuthUserTokens, objectToUrlEncoded } from '../../../root-helpers' |
3 | import { peertubeLocalStorage } from '../../../root-helpers/peertube-web-storage' | 3 | import { peertubeLocalStorage } from '../../../root-helpers/peertube-web-storage' |
4 | 4 | ||
5 | export class AuthHTTP { | 5 | export class AuthHTTP { |
@@ -8,30 +8,30 @@ export class AuthHTTP { | |||
8 | CLIENT_SECRET: 'client_secret' | 8 | CLIENT_SECRET: 'client_secret' |
9 | } | 9 | } |
10 | 10 | ||
11 | private userTokens: UserTokens | 11 | private userOAuthTokens: OAuthUserTokens |
12 | 12 | ||
13 | private headers = new Headers() | 13 | private headers = new Headers() |
14 | 14 | ||
15 | constructor () { | 15 | constructor () { |
16 | this.userTokens = UserTokens.getUserTokens(peertubeLocalStorage) | 16 | this.userOAuthTokens = OAuthUserTokens.getUserTokens(peertubeLocalStorage) |
17 | 17 | ||
18 | if (this.userTokens) this.setHeadersFromTokens() | 18 | if (this.userOAuthTokens) this.setHeadersFromTokens() |
19 | } | 19 | } |
20 | 20 | ||
21 | fetch (url: string, { optionalAuth }: { optionalAuth: boolean }) { | 21 | fetch (url: string, { optionalAuth, method }: { optionalAuth: boolean, method?: string }) { |
22 | const refreshFetchOptions = optionalAuth | 22 | const refreshFetchOptions = optionalAuth |
23 | ? { headers: this.headers } | 23 | ? { headers: this.headers } |
24 | : {} | 24 | : {} |
25 | 25 | ||
26 | return this.refreshFetch(url.toString(), refreshFetchOptions) | 26 | return this.refreshFetch(url.toString(), { ...refreshFetchOptions, method }) |
27 | } | 27 | } |
28 | 28 | ||
29 | getHeaderTokenValue () { | 29 | getHeaderTokenValue () { |
30 | return `${this.userTokens.tokenType} ${this.userTokens.accessToken}` | 30 | return `${this.userOAuthTokens.tokenType} ${this.userOAuthTokens.accessToken}` |
31 | } | 31 | } |
32 | 32 | ||
33 | isLoggedIn () { | 33 | isLoggedIn () { |
34 | return !!this.userTokens | 34 | return !!this.userOAuthTokens |
35 | } | 35 | } |
36 | 36 | ||
37 | private refreshFetch (url: string, options?: RequestInit) { | 37 | private refreshFetch (url: string, options?: RequestInit) { |
@@ -47,7 +47,7 @@ export class AuthHTTP { | |||
47 | headers.set('Content-Type', 'application/x-www-form-urlencoded') | 47 | headers.set('Content-Type', 'application/x-www-form-urlencoded') |
48 | 48 | ||
49 | const data = { | 49 | const data = { |
50 | refresh_token: this.userTokens.refreshToken, | 50 | refresh_token: this.userOAuthTokens.refreshToken, |
51 | client_id: clientId, | 51 | client_id: clientId, |
52 | client_secret: clientSecret, | 52 | client_secret: clientSecret, |
53 | response_type: 'code', | 53 | response_type: 'code', |
@@ -64,15 +64,15 @@ export class AuthHTTP { | |||
64 | return res.json() | 64 | return res.json() |
65 | }).then((obj: UserRefreshToken & { code?: OAuth2ErrorCode }) => { | 65 | }).then((obj: UserRefreshToken & { code?: OAuth2ErrorCode }) => { |
66 | if (!obj || obj.code === OAuth2ErrorCode.INVALID_GRANT) { | 66 | if (!obj || obj.code === OAuth2ErrorCode.INVALID_GRANT) { |
67 | UserTokens.flushLocalStorage(peertubeLocalStorage) | 67 | OAuthUserTokens.flushLocalStorage(peertubeLocalStorage) |
68 | this.removeTokensFromHeaders() | 68 | this.removeTokensFromHeaders() |
69 | 69 | ||
70 | return resolve() | 70 | return resolve() |
71 | } | 71 | } |
72 | 72 | ||
73 | this.userTokens.accessToken = obj.access_token | 73 | this.userOAuthTokens.accessToken = obj.access_token |
74 | this.userTokens.refreshToken = obj.refresh_token | 74 | this.userOAuthTokens.refreshToken = obj.refresh_token |
75 | UserTokens.saveToLocalStorage(peertubeLocalStorage, this.userTokens) | 75 | OAuthUserTokens.saveToLocalStorage(peertubeLocalStorage, this.userOAuthTokens) |
76 | 76 | ||
77 | this.setHeadersFromTokens() | 77 | this.setHeadersFromTokens() |
78 | 78 | ||
@@ -84,7 +84,7 @@ export class AuthHTTP { | |||
84 | 84 | ||
85 | return refreshingTokenPromise | 85 | return refreshingTokenPromise |
86 | .catch(() => { | 86 | .catch(() => { |
87 | UserTokens.flushLocalStorage(peertubeLocalStorage) | 87 | OAuthUserTokens.flushLocalStorage(peertubeLocalStorage) |
88 | 88 | ||
89 | this.removeTokensFromHeaders() | 89 | this.removeTokensFromHeaders() |
90 | }).then(() => fetch(url, { | 90 | }).then(() => fetch(url, { |
diff --git a/client/src/standalone/videos/shared/player-manager-options.ts b/client/src/standalone/videos/shared/player-manager-options.ts index eed821994..87a84975b 100644 --- a/client/src/standalone/videos/shared/player-manager-options.ts +++ b/client/src/standalone/videos/shared/player-manager-options.ts | |||
@@ -17,7 +17,8 @@ import { | |||
17 | isP2PEnabled, | 17 | isP2PEnabled, |
18 | logger, | 18 | logger, |
19 | peertubeLocalStorage, | 19 | peertubeLocalStorage, |
20 | UserLocalStorageKeys | 20 | UserLocalStorageKeys, |
21 | videoRequiresAuth | ||
21 | } from '../../../root-helpers' | 22 | } from '../../../root-helpers' |
22 | import { PeerTubePlugin } from './peertube-plugin' | 23 | import { PeerTubePlugin } from './peertube-plugin' |
23 | import { PlayerHTML } from './player-html' | 24 | import { PlayerHTML } from './player-html' |
@@ -154,6 +155,9 @@ export class PlayerManagerOptions { | |||
154 | captionsResponse: Response | 155 | captionsResponse: Response |
155 | live?: LiveVideo | 156 | live?: LiveVideo |
156 | 157 | ||
158 | authorizationHeader: () => string | ||
159 | videoFileToken: () => string | ||
160 | |||
157 | serverConfig: HTMLServerConfig | 161 | serverConfig: HTMLServerConfig |
158 | 162 | ||
159 | alreadyHadPlayer: boolean | 163 | alreadyHadPlayer: boolean |
@@ -169,9 +173,11 @@ export class PlayerManagerOptions { | |||
169 | video, | 173 | video, |
170 | captionsResponse, | 174 | captionsResponse, |
171 | alreadyHadPlayer, | 175 | alreadyHadPlayer, |
176 | videoFileToken, | ||
172 | translations, | 177 | translations, |
173 | playlistTracker, | 178 | playlistTracker, |
174 | live, | 179 | live, |
180 | authorizationHeader, | ||
175 | serverConfig | 181 | serverConfig |
176 | } = options | 182 | } = options |
177 | 183 | ||
@@ -227,6 +233,10 @@ export class PlayerManagerOptions { | |||
227 | embedUrl: window.location.origin + video.embedPath, | 233 | embedUrl: window.location.origin + video.embedPath, |
228 | embedTitle: video.name, | 234 | embedTitle: video.name, |
229 | 235 | ||
236 | requiresAuth: videoRequiresAuth(video), | ||
237 | authorizationHeader, | ||
238 | videoFileToken, | ||
239 | |||
230 | errorNotifier: () => { | 240 | errorNotifier: () => { |
231 | // Empty, we don't have a notifier in the embed | 241 | // Empty, we don't have a notifier in the embed |
232 | }, | 242 | }, |
diff --git a/client/src/standalone/videos/shared/video-fetcher.ts b/client/src/standalone/videos/shared/video-fetcher.ts index b42d622f9..cf6d12831 100644 --- a/client/src/standalone/videos/shared/video-fetcher.ts +++ b/client/src/standalone/videos/shared/video-fetcher.ts | |||
@@ -1,4 +1,4 @@ | |||
1 | import { HttpStatusCode, LiveVideo, VideoDetails } from '../../../../../shared/models' | 1 | import { HttpStatusCode, LiveVideo, VideoDetails, VideoToken } from '../../../../../shared/models' |
2 | import { logger } from '../../../root-helpers' | 2 | import { logger } from '../../../root-helpers' |
3 | import { AuthHTTP } from './auth-http' | 3 | import { AuthHTTP } from './auth-http' |
4 | 4 | ||
@@ -36,10 +36,15 @@ export class VideoFetcher { | |||
36 | return { captionsPromise, videoResponse } | 36 | return { captionsPromise, videoResponse } |
37 | } | 37 | } |
38 | 38 | ||
39 | loadVideoWithLive (video: VideoDetails) { | 39 | loadLive (video: VideoDetails) { |
40 | return this.http.fetch(this.getLiveUrl(video.uuid), { optionalAuth: true }) | 40 | return this.http.fetch(this.getLiveUrl(video.uuid), { optionalAuth: true }) |
41 | .then(res => res.json()) | 41 | .then(res => res.json() as Promise<LiveVideo>) |
42 | .then((live: LiveVideo) => ({ video, live })) | 42 | } |
43 | |||
44 | loadVideoToken (video: VideoDetails) { | ||
45 | return this.http.fetch(this.getVideoTokenUrl(video.uuid), { optionalAuth: true, method: 'POST' }) | ||
46 | .then(res => res.json() as Promise<VideoToken>) | ||
47 | .then(token => token.files.token) | ||
43 | } | 48 | } |
44 | 49 | ||
45 | getVideoViewsUrl (videoUUID: string) { | 50 | getVideoViewsUrl (videoUUID: string) { |
@@ -61,4 +66,8 @@ export class VideoFetcher { | |||
61 | private getLiveUrl (videoId: string) { | 66 | private getLiveUrl (videoId: string) { |
62 | return window.location.origin + '/api/v1/videos/live/' + videoId | 67 | return window.location.origin + '/api/v1/videos/live/' + videoId |
63 | } | 68 | } |
69 | |||
70 | private getVideoTokenUrl (id: string) { | ||
71 | return this.getVideoUrl(id) + '/token' | ||
72 | } | ||
64 | } | 73 | } |