diff --git a/client/src/standalone/videos/embed.ts b/client/src/standalone/videos/embed.ts index dca23ca7ea21..3bc0cd58e4f3 100644 --- a/client/src/standalone/videos/embed.ts +++ b/client/src/standalone/videos/embed.ts @@ -4,7 +4,8 @@ import { peertubeTranslate, ResultList, ServerConfig, - VideoDetails + VideoDetails, + UserRefreshToken } from '../../../../shared' import { VideoCaption } from '../../../../shared/models/videos/caption/video-caption.model' import { @@ -17,7 +18,8 @@ import { PeerTubeEmbedApi } from './embed-api' import { TranslationsManager } from '../../assets/player/translations-manager' import videojs from 'video.js' import { VideoJSCaption } from '../../assets/player/peertube-videojs-typings' -import { AuthUser } from '@app/core/auth/auth-user.model' +import { AuthUser } from '../../app/core/auth/auth-user.model' +import { peertubeLocalStorage, objectToUrlEncoded } from '../../app/helpers' type Translations = { [ id: string ]: string } @@ -45,6 +47,10 @@ export class PeerTubeEmbed { user: AuthUser headers = new Headers() + LOCAL_STORAGE_OAUTH_CLIENT_KEYS = { + CLIENT_ID: 'client_id', + CLIENT_SECRET: 'client_secret' + } static async main () { const videoContainerId = 'video-container' @@ -60,12 +66,66 @@ export class PeerTubeEmbed { return window.location.origin + '/api/v1/videos/' + id } + refreshFetch (url: string, options?: Object) { + return fetch(url, options) + .then((res: Response) => { + // 401 unauthorized is not catch-ed, but then-ed + const error = res + + if (res.status === 401) { + let refreshingTokenPromise = new Promise((resolve, reject) => { + const clientId: string = peertubeLocalStorage.getItem(this.LOCAL_STORAGE_OAUTH_CLIENT_KEYS.CLIENT_ID) + const clientSecret: string = peertubeLocalStorage.getItem(this.LOCAL_STORAGE_OAUTH_CLIENT_KEYS.CLIENT_SECRET) + const headers = new Headers() + headers.set('Content-Type', 'application/x-www-form-urlencoded') + const data = { + refresh_token: this.user.getRefreshToken(), + client_id: clientId, + client_secret: clientSecret, + response_type: 'code', + grant_type: 'refresh_token' + } + + fetch('/api/v1/users/token', { + headers, + method: 'POST', + body: objectToUrlEncoded(data) + }) + .then(async (res: Response) => { + const obj: UserRefreshToken = await res.json() + this.user.refreshTokens(obj.access_token, obj.refresh_token) + this.user.save() + this.headers.set('Authorization', `${this.user.getTokenType()} ${this.user.getAccessToken()}`) + refreshingTokenPromise = null + resolve() + }) + .catch((refreshTokenError: any) => { + refreshingTokenPromise = null + reject(refreshTokenError) + }) + }) + + return refreshingTokenPromise + .catch(() => { + // If refreshing fails, continue with original error + throw error + }) + .then(() => fetch(url, { + ...options, + headers: this.headers + })) + } + + return res + }) + } + loadVideoInfo (videoId: string): Promise { - return fetch(this.getVideoUrl(videoId), { headers: this.headers }) + return this.refreshFetch(this.getVideoUrl(videoId), { headers: this.headers }) } loadVideoCaptions (videoId: string): Promise { - return fetch(this.getVideoUrl(videoId) + '/captions', { headers: this.headers }) + return fetch(this.getVideoUrl(videoId) + '/captions') } loadConfig (): Promise {