From 4504f09f6e85f09b0489debb547a17209d7176ea Mon Sep 17 00:00:00 2001 From: Rigel Kent Date: Mon, 3 Aug 2020 18:06:49 +0200 Subject: deal with refresh token in embed --- client/src/root-helpers/index.ts | 4 + client/src/root-helpers/peertube-web-storage.ts | 81 ++++++++++++++++ client/src/root-helpers/pure-auth-user.model.ts | 123 ++++++++++++++++++++++++ client/src/root-helpers/user-keys.ts | 15 +++ client/src/root-helpers/utils.ts | 12 +++ 5 files changed, 235 insertions(+) create mode 100644 client/src/root-helpers/index.ts create mode 100644 client/src/root-helpers/peertube-web-storage.ts create mode 100644 client/src/root-helpers/pure-auth-user.model.ts create mode 100644 client/src/root-helpers/user-keys.ts create mode 100644 client/src/root-helpers/utils.ts (limited to 'client/src/root-helpers') diff --git a/client/src/root-helpers/index.ts b/client/src/root-helpers/index.ts new file mode 100644 index 000000000..5ed4933f1 --- /dev/null +++ b/client/src/root-helpers/index.ts @@ -0,0 +1,4 @@ +export * from './peertube-web-storage' +export * from './utils' +export * from './user-keys' +export * from './pure-auth-user.model' diff --git a/client/src/root-helpers/peertube-web-storage.ts b/client/src/root-helpers/peertube-web-storage.ts new file mode 100644 index 000000000..0db1301bd --- /dev/null +++ b/client/src/root-helpers/peertube-web-storage.ts @@ -0,0 +1,81 @@ +// Thanks: https://github.com/capaj/localstorage-polyfill + +const valuesMap = new Map() + +function proxify (instance: MemoryStorage) { + return new Proxy(instance, { + set: function (obj, prop: string | number, value) { + if (MemoryStorage.prototype.hasOwnProperty(prop)) { + instance[prop] = value + } else { + instance.setItem(prop, value) + } + return true + }, + get: function (target, name: string | number) { + if (MemoryStorage.prototype.hasOwnProperty(name)) { + return instance[name] + } + if (valuesMap.has(name)) { + return instance.getItem(name) + } + } + }) +} + +class MemoryStorage { + [key: string]: any + [index: number]: string + + getItem (key: any) { + const stringKey = String(key) + if (valuesMap.has(key)) { + return String(valuesMap.get(stringKey)) + } + + return null + } + + setItem (key: any, val: any) { + valuesMap.set(String(key), String(val)) + } + + removeItem (key: any) { + valuesMap.delete(key) + } + + clear () { + valuesMap.clear() + } + + key (i: any) { + if (arguments.length === 0) { + throw new TypeError('Failed to execute "key" on "Storage": 1 argument required, but only 0 present.') + } + + const arr = Array.from(valuesMap.keys()) + return arr[i] + } + + get length () { + return valuesMap.size + } +} + +let peertubeLocalStorage: Storage +let peertubeSessionStorage: Storage +try { + peertubeLocalStorage = localStorage + peertubeSessionStorage = sessionStorage +} catch (err) { + const instanceLocalStorage = new MemoryStorage() + const instanceSessionStorage = new MemoryStorage() + + peertubeLocalStorage = proxify(instanceLocalStorage) + peertubeSessionStorage = proxify(instanceSessionStorage) +} + +export { + peertubeLocalStorage, + peertubeSessionStorage +} diff --git a/client/src/root-helpers/pure-auth-user.model.ts b/client/src/root-helpers/pure-auth-user.model.ts new file mode 100644 index 000000000..81226da01 --- /dev/null +++ b/client/src/root-helpers/pure-auth-user.model.ts @@ -0,0 +1,123 @@ +// pure version of auth-user, that doesn't import app packages +import { peertubeLocalStorage } from '@root-helpers/peertube-web-storage' +import { + MyUser as ServerMyUserModel, + MyUserSpecialPlaylist, + NSFWPolicyType, + UserRole +} from '@shared/models' +import { UserKeys } from '@root-helpers/user-keys' + +export type TokenOptions = { + accessToken: string + refreshToken: string + tokenType: string +} + +// Private class only used by User +export class Tokens { + private static KEYS = { + ACCESS_TOKEN: 'access_token', + REFRESH_TOKEN: 'refresh_token', + TOKEN_TYPE: 'token_type' + } + + accessToken: string + refreshToken: string + tokenType: string + + static load () { + const accessTokenLocalStorage = peertubeLocalStorage.getItem(this.KEYS.ACCESS_TOKEN) + const refreshTokenLocalStorage = peertubeLocalStorage.getItem(this.KEYS.REFRESH_TOKEN) + const tokenTypeLocalStorage = peertubeLocalStorage.getItem(this.KEYS.TOKEN_TYPE) + + if (accessTokenLocalStorage && refreshTokenLocalStorage && tokenTypeLocalStorage) { + return new Tokens({ + accessToken: accessTokenLocalStorage, + refreshToken: refreshTokenLocalStorage, + tokenType: tokenTypeLocalStorage + }) + } + + return null + } + + static flush () { + peertubeLocalStorage.removeItem(this.KEYS.ACCESS_TOKEN) + peertubeLocalStorage.removeItem(this.KEYS.REFRESH_TOKEN) + peertubeLocalStorage.removeItem(this.KEYS.TOKEN_TYPE) + } + + constructor (hash?: TokenOptions) { + if (hash) { + this.accessToken = hash.accessToken + this.refreshToken = hash.refreshToken + + if (hash.tokenType === 'bearer') { + this.tokenType = 'Bearer' + } else { + this.tokenType = hash.tokenType + } + } + } + + save () { + peertubeLocalStorage.setItem(Tokens.KEYS.ACCESS_TOKEN, this.accessToken) + peertubeLocalStorage.setItem(Tokens.KEYS.REFRESH_TOKEN, this.refreshToken) + peertubeLocalStorage.setItem(Tokens.KEYS.TOKEN_TYPE, this.tokenType) + } +} + +export class PureAuthUser { + tokens: Tokens + specialPlaylists: MyUserSpecialPlaylist[] + + canSeeVideosLink = true + + static load () { + const usernameLocalStorage = peertubeLocalStorage.getItem(UserKeys.USERNAME) + if (usernameLocalStorage) { + return new PureAuthUser( + { + id: parseInt(peertubeLocalStorage.getItem(UserKeys.ID), 10), + username: peertubeLocalStorage.getItem(UserKeys.USERNAME), + email: peertubeLocalStorage.getItem(UserKeys.EMAIL), + role: parseInt(peertubeLocalStorage.getItem(UserKeys.ROLE), 10) as UserRole, + nsfwPolicy: peertubeLocalStorage.getItem(UserKeys.NSFW_POLICY) as NSFWPolicyType, + webTorrentEnabled: peertubeLocalStorage.getItem(UserKeys.WEBTORRENT_ENABLED) === 'true', + autoPlayVideo: peertubeLocalStorage.getItem(UserKeys.AUTO_PLAY_VIDEO) === 'true', + videosHistoryEnabled: peertubeLocalStorage.getItem(UserKeys.VIDEOS_HISTORY_ENABLED) === 'true' + }, + Tokens.load() + ) + } + + return null + } + + constructor (userHash: Partial, hashTokens: TokenOptions) { + this.tokens = new Tokens(hashTokens) + this.specialPlaylists = userHash.specialPlaylists + } + + getAccessToken () { + return this.tokens.accessToken + } + + getRefreshToken () { + return this.tokens.refreshToken + } + + getTokenType () { + return this.tokens.tokenType + } + + refreshTokens (accessToken: string, refreshToken: string) { + this.tokens.accessToken = accessToken + this.tokens.refreshToken = refreshToken + } + + save () { + this.tokens.save() + } +} diff --git a/client/src/root-helpers/user-keys.ts b/client/src/root-helpers/user-keys.ts new file mode 100644 index 000000000..897be8c43 --- /dev/null +++ b/client/src/root-helpers/user-keys.ts @@ -0,0 +1,15 @@ +export const UserKeys = { + ID: 'id', + ROLE: 'role', + EMAIL: 'email', + VIDEOS_HISTORY_ENABLED: 'videos-history-enabled', + USERNAME: 'username', + NSFW_POLICY: 'nsfw_policy', + WEBTORRENT_ENABLED: 'peertube-videojs-' + 'webtorrent_enabled', + AUTO_PLAY_VIDEO: 'auto_play_video', + SESSION_STORAGE_AUTO_PLAY_NEXT_VIDEO: 'auto_play_next_video', + AUTO_PLAY_VIDEO_PLAYLIST: 'auto_play_video_playlist', + THEME: 'theme', + LAST_ACTIVE_THEME: 'last_active_theme', + VIDEO_LANGUAGES: 'video_languages' +} diff --git a/client/src/root-helpers/utils.ts b/client/src/root-helpers/utils.ts new file mode 100644 index 000000000..acfb565a3 --- /dev/null +++ b/client/src/root-helpers/utils.ts @@ -0,0 +1,12 @@ +function objectToUrlEncoded (obj: any) { + const str: string[] = [] + for (const key of Object.keys(obj)) { + str.push(encodeURIComponent(key) + '=' + encodeURIComponent(obj[key])) + } + + return str.join('&') +} + +export { + objectToUrlEncoded +} -- cgit v1.2.3