diff options
author | Chocobozzz <me@florianbigard.com> | 2018-03-23 14:26:20 +0100 |
---|---|---|
committer | Chocobozzz <me@florianbigard.com> | 2018-03-23 14:26:20 +0100 |
commit | 0bd78bf30b2ae159791bdc90d17ed18e0327f621 (patch) | |
tree | e8f69cef499a99c51deeea39f7197b7ff93a80a2 | |
parent | 9c673970f66fe91c665e1e3905fa768f57e11a18 (diff) | |
download | PeerTube-0bd78bf30b2ae159791bdc90d17ed18e0327f621.tar.gz PeerTube-0bd78bf30b2ae159791bdc90d17ed18e0327f621.tar.zst PeerTube-0bd78bf30b2ae159791bdc90d17ed18e0327f621.zip |
Proxify local storage and handle if it is unavailable
6 files changed, 116 insertions, 39 deletions
diff --git a/client/src/app/+admin/jobs/jobs-list/jobs-list.component.ts b/client/src/app/+admin/jobs/jobs-list/jobs-list.component.ts index e3f317e6d..ad2f05c6b 100644 --- a/client/src/app/+admin/jobs/jobs-list/jobs-list.component.ts +++ b/client/src/app/+admin/jobs/jobs-list/jobs-list.component.ts | |||
@@ -1,12 +1,12 @@ | |||
1 | import { Component, OnInit } from '@angular/core' | 1 | import { Component, OnInit } from '@angular/core' |
2 | import { peertubeLocalStorage } from '@app/shared/misc/peertube-local-storage' | ||
2 | import { NotificationsService } from 'angular2-notifications' | 3 | import { NotificationsService } from 'angular2-notifications' |
3 | import { SortMeta } from 'primeng/primeng' | 4 | import { SortMeta } from 'primeng/primeng' |
4 | import { Job } from '../../../../../../shared/index' | 5 | import { Job } from '../../../../../../shared/index' |
5 | import { JobState } from '../../../../../../shared/models' | 6 | import { JobState } from '../../../../../../shared/models' |
6 | import { RestPagination, RestTable } from '../../../shared' | 7 | import { RestPagination, RestTable } from '../../../shared' |
7 | import { viewportHeight } from '../../../shared/misc/utils' | ||
8 | import { JobService } from '../shared' | ||
9 | import { RestExtractor } from '../../../shared/rest/rest-extractor.service' | 8 | import { RestExtractor } from '../../../shared/rest/rest-extractor.service' |
9 | import { JobService } from '../shared' | ||
10 | 10 | ||
11 | @Component({ | 11 | @Component({ |
12 | selector: 'my-jobs-list', | 12 | selector: 'my-jobs-list', |
@@ -56,12 +56,12 @@ export class JobsListComponent extends RestTable implements OnInit { | |||
56 | } | 56 | } |
57 | 57 | ||
58 | private loadJobState () { | 58 | private loadJobState () { |
59 | const result = localStorage.getItem(JobsListComponent.JOB_STATE_LOCAL_STORAGE_STATE) | 59 | const result = peertubeLocalStorage.getItem(JobsListComponent.JOB_STATE_LOCAL_STORAGE_STATE) |
60 | 60 | ||
61 | if (result) this.jobState = result as JobState | 61 | if (result) this.jobState = result as JobState |
62 | } | 62 | } |
63 | 63 | ||
64 | private saveJobState () { | 64 | private saveJobState () { |
65 | localStorage.setItem(JobsListComponent.JOB_STATE_LOCAL_STORAGE_STATE, this.jobState) | 65 | peertubeLocalStorage.setItem(JobsListComponent.JOB_STATE_LOCAL_STORAGE_STATE, this.jobState) |
66 | } | 66 | } |
67 | } | 67 | } |
diff --git a/client/src/app/core/auth/auth-user.model.ts b/client/src/app/core/auth/auth-user.model.ts index 9ad275392..366eea110 100644 --- a/client/src/app/core/auth/auth-user.model.ts +++ b/client/src/app/core/auth/auth-user.model.ts | |||
@@ -1,7 +1,8 @@ | |||
1 | import { peertubeLocalStorage } from '@app/shared/misc/peertube-local-storage' | ||
2 | import { UserRight } from '../../../../../shared/models/users/user-right.enum' | ||
1 | // Do not use the barrel (dependency loop) | 3 | // Do not use the barrel (dependency loop) |
2 | import { hasUserRight, UserRole } from '../../../../../shared/models/users/user-role' | 4 | import { hasUserRight, UserRole } from '../../../../../shared/models/users/user-role' |
3 | import { User, UserConstructorHash } from '../../shared/users/user.model' | 5 | import { User, UserConstructorHash } from '../../shared/users/user.model' |
4 | import { UserRight } from '../../../../../shared/models/users/user-right.enum' | ||
5 | 6 | ||
6 | export type TokenOptions = { | 7 | export type TokenOptions = { |
7 | accessToken: string | 8 | accessToken: string |
@@ -22,9 +23,9 @@ class Tokens { | |||
22 | tokenType: string | 23 | tokenType: string |
23 | 24 | ||
24 | static load () { | 25 | static load () { |
25 | const accessTokenLocalStorage = localStorage.getItem(this.KEYS.ACCESS_TOKEN) | 26 | const accessTokenLocalStorage = peertubeLocalStorage.getItem(this.KEYS.ACCESS_TOKEN) |
26 | const refreshTokenLocalStorage = localStorage.getItem(this.KEYS.REFRESH_TOKEN) | 27 | const refreshTokenLocalStorage = peertubeLocalStorage.getItem(this.KEYS.REFRESH_TOKEN) |
27 | const tokenTypeLocalStorage = localStorage.getItem(this.KEYS.TOKEN_TYPE) | 28 | const tokenTypeLocalStorage = peertubeLocalStorage.getItem(this.KEYS.TOKEN_TYPE) |
28 | 29 | ||
29 | if (accessTokenLocalStorage && refreshTokenLocalStorage && tokenTypeLocalStorage) { | 30 | if (accessTokenLocalStorage && refreshTokenLocalStorage && tokenTypeLocalStorage) { |
30 | return new Tokens({ | 31 | return new Tokens({ |
@@ -38,9 +39,9 @@ class Tokens { | |||
38 | } | 39 | } |
39 | 40 | ||
40 | static flush () { | 41 | static flush () { |
41 | localStorage.removeItem(this.KEYS.ACCESS_TOKEN) | 42 | peertubeLocalStorage.removeItem(this.KEYS.ACCESS_TOKEN) |
42 | localStorage.removeItem(this.KEYS.REFRESH_TOKEN) | 43 | peertubeLocalStorage.removeItem(this.KEYS.REFRESH_TOKEN) |
43 | localStorage.removeItem(this.KEYS.TOKEN_TYPE) | 44 | peertubeLocalStorage.removeItem(this.KEYS.TOKEN_TYPE) |
44 | } | 45 | } |
45 | 46 | ||
46 | constructor (hash?: TokenOptions) { | 47 | constructor (hash?: TokenOptions) { |
@@ -57,9 +58,9 @@ class Tokens { | |||
57 | } | 58 | } |
58 | 59 | ||
59 | save () { | 60 | save () { |
60 | localStorage.setItem(Tokens.KEYS.ACCESS_TOKEN, this.accessToken) | 61 | peertubeLocalStorage.setItem(Tokens.KEYS.ACCESS_TOKEN, this.accessToken) |
61 | localStorage.setItem(Tokens.KEYS.REFRESH_TOKEN, this.refreshToken) | 62 | peertubeLocalStorage.setItem(Tokens.KEYS.REFRESH_TOKEN, this.refreshToken) |
62 | localStorage.setItem(Tokens.KEYS.TOKEN_TYPE, this.tokenType) | 63 | peertubeLocalStorage.setItem(Tokens.KEYS.TOKEN_TYPE, this.tokenType) |
63 | } | 64 | } |
64 | } | 65 | } |
65 | 66 | ||
@@ -76,16 +77,16 @@ export class AuthUser extends User { | |||
76 | tokens: Tokens | 77 | tokens: Tokens |
77 | 78 | ||
78 | static load () { | 79 | static load () { |
79 | const usernameLocalStorage = localStorage.getItem(this.KEYS.USERNAME) | 80 | const usernameLocalStorage = peertubeLocalStorage.getItem(this.KEYS.USERNAME) |
80 | if (usernameLocalStorage) { | 81 | if (usernameLocalStorage) { |
81 | return new AuthUser( | 82 | return new AuthUser( |
82 | { | 83 | { |
83 | id: parseInt(localStorage.getItem(this.KEYS.ID), 10), | 84 | id: parseInt(peertubeLocalStorage.getItem(this.KEYS.ID), 10), |
84 | username: localStorage.getItem(this.KEYS.USERNAME), | 85 | username: peertubeLocalStorage.getItem(this.KEYS.USERNAME), |
85 | email: localStorage.getItem(this.KEYS.EMAIL), | 86 | email: peertubeLocalStorage.getItem(this.KEYS.EMAIL), |
86 | role: parseInt(localStorage.getItem(this.KEYS.ROLE), 10) as UserRole, | 87 | role: parseInt(peertubeLocalStorage.getItem(this.KEYS.ROLE), 10) as UserRole, |
87 | displayNSFW: localStorage.getItem(this.KEYS.DISPLAY_NSFW) === 'true', | 88 | displayNSFW: peertubeLocalStorage.getItem(this.KEYS.DISPLAY_NSFW) === 'true', |
88 | autoPlayVideo: localStorage.getItem(this.KEYS.AUTO_PLAY_VIDEO) === 'true' | 89 | autoPlayVideo: peertubeLocalStorage.getItem(this.KEYS.AUTO_PLAY_VIDEO) === 'true' |
89 | }, | 90 | }, |
90 | Tokens.load() | 91 | Tokens.load() |
91 | ) | 92 | ) |
@@ -95,12 +96,12 @@ export class AuthUser extends User { | |||
95 | } | 96 | } |
96 | 97 | ||
97 | static flush () { | 98 | static flush () { |
98 | localStorage.removeItem(this.KEYS.USERNAME) | 99 | peertubeLocalStorage.removeItem(this.KEYS.USERNAME) |
99 | localStorage.removeItem(this.KEYS.ID) | 100 | peertubeLocalStorage.removeItem(this.KEYS.ID) |
100 | localStorage.removeItem(this.KEYS.ROLE) | 101 | peertubeLocalStorage.removeItem(this.KEYS.ROLE) |
101 | localStorage.removeItem(this.KEYS.DISPLAY_NSFW) | 102 | peertubeLocalStorage.removeItem(this.KEYS.DISPLAY_NSFW) |
102 | localStorage.removeItem(this.KEYS.AUTO_PLAY_VIDEO) | 103 | peertubeLocalStorage.removeItem(this.KEYS.AUTO_PLAY_VIDEO) |
103 | localStorage.removeItem(this.KEYS.EMAIL) | 104 | peertubeLocalStorage.removeItem(this.KEYS.EMAIL) |
104 | Tokens.flush() | 105 | Tokens.flush() |
105 | } | 106 | } |
106 | 107 | ||
@@ -131,12 +132,12 @@ export class AuthUser extends User { | |||
131 | } | 132 | } |
132 | 133 | ||
133 | save () { | 134 | save () { |
134 | localStorage.setItem(AuthUser.KEYS.ID, this.id.toString()) | 135 | peertubeLocalStorage.setItem(AuthUser.KEYS.ID, this.id.toString()) |
135 | localStorage.setItem(AuthUser.KEYS.USERNAME, this.username) | 136 | peertubeLocalStorage.setItem(AuthUser.KEYS.USERNAME, this.username) |
136 | localStorage.setItem(AuthUser.KEYS.EMAIL, this.email) | 137 | peertubeLocalStorage.setItem(AuthUser.KEYS.EMAIL, this.email) |
137 | localStorage.setItem(AuthUser.KEYS.ROLE, this.role.toString()) | 138 | peertubeLocalStorage.setItem(AuthUser.KEYS.ROLE, this.role.toString()) |
138 | localStorage.setItem(AuthUser.KEYS.DISPLAY_NSFW, JSON.stringify(this.displayNSFW)) | 139 | peertubeLocalStorage.setItem(AuthUser.KEYS.DISPLAY_NSFW, JSON.stringify(this.displayNSFW)) |
139 | localStorage.setItem(AuthUser.KEYS.AUTO_PLAY_VIDEO, JSON.stringify(this.autoPlayVideo)) | 140 | peertubeLocalStorage.setItem(AuthUser.KEYS.AUTO_PLAY_VIDEO, JSON.stringify(this.autoPlayVideo)) |
140 | this.tokens.save() | 141 | this.tokens.save() |
141 | } | 142 | } |
142 | } | 143 | } |
diff --git a/client/src/app/core/server/server.service.ts b/client/src/app/core/server/server.service.ts index 0b63ef5be..206ec7bcd 100644 --- a/client/src/app/core/server/server.service.ts +++ b/client/src/app/core/server/server.service.ts | |||
@@ -1,5 +1,6 @@ | |||
1 | import { HttpClient } from '@angular/common/http' | 1 | import { HttpClient } from '@angular/common/http' |
2 | import { Injectable } from '@angular/core' | 2 | import { Injectable } from '@angular/core' |
3 | import { peertubeLocalStorage } from '@app/shared/misc/peertube-local-storage' | ||
3 | import 'rxjs/add/operator/do' | 4 | import 'rxjs/add/operator/do' |
4 | import { ReplaySubject } from 'rxjs/ReplaySubject' | 5 | import { ReplaySubject } from 'rxjs/ReplaySubject' |
5 | import { ServerConfig } from '../../../../../shared' | 6 | import { ServerConfig } from '../../../../../shared' |
@@ -140,11 +141,11 @@ export class ServerService { | |||
140 | } | 141 | } |
141 | 142 | ||
142 | private saveConfigLocally (config: ServerConfig) { | 143 | private saveConfigLocally (config: ServerConfig) { |
143 | localStorage.setItem(ServerService.CONFIG_LOCAL_STORAGE_KEY, JSON.stringify(config)) | 144 | peertubeLocalStorage.setItem(ServerService.CONFIG_LOCAL_STORAGE_KEY, JSON.stringify(config)) |
144 | } | 145 | } |
145 | 146 | ||
146 | private loadConfigLocally () { | 147 | private loadConfigLocally () { |
147 | const configString = localStorage.getItem(ServerService.CONFIG_LOCAL_STORAGE_KEY) | 148 | const configString = peertubeLocalStorage.getItem(ServerService.CONFIG_LOCAL_STORAGE_KEY) |
148 | 149 | ||
149 | if (configString) { | 150 | if (configString) { |
150 | try { | 151 | try { |
diff --git a/client/src/app/shared/misc/peertube-local-storage.ts b/client/src/app/shared/misc/peertube-local-storage.ts new file mode 100644 index 000000000..ad761c82f --- /dev/null +++ b/client/src/app/shared/misc/peertube-local-storage.ts | |||
@@ -0,0 +1,70 @@ | |||
1 | // Thanks: https://github.com/capaj/localstorage-polyfill | ||
2 | |||
3 | const valuesMap = new Map() | ||
4 | |||
5 | class MemoryStorage { | ||
6 | [key: string]: any | ||
7 | [index: number]: string | ||
8 | |||
9 | getItem (key) { | ||
10 | const stringKey = String(key) | ||
11 | if (valuesMap.has(key)) { | ||
12 | return String(valuesMap.get(stringKey)) | ||
13 | } | ||
14 | |||
15 | return null | ||
16 | } | ||
17 | |||
18 | setItem (key, val) { | ||
19 | valuesMap.set(String(key), String(val)) | ||
20 | } | ||
21 | |||
22 | removeItem (key) { | ||
23 | valuesMap.delete(key) | ||
24 | } | ||
25 | |||
26 | clear () { | ||
27 | valuesMap.clear() | ||
28 | } | ||
29 | |||
30 | key (i: any) { | ||
31 | if (arguments.length === 0) { | ||
32 | throw new TypeError('Failed to execute "key" on "Storage": 1 argument required, but only 0 present.') | ||
33 | } | ||
34 | |||
35 | const arr = Array.from(valuesMap.keys()) | ||
36 | return arr[i] | ||
37 | } | ||
38 | |||
39 | get length () { | ||
40 | return valuesMap.size | ||
41 | } | ||
42 | } | ||
43 | |||
44 | let peertubeLocalStorage: Storage | ||
45 | try { | ||
46 | peertubeLocalStorage = localStorage | ||
47 | } catch (err) { | ||
48 | const instance = new MemoryStorage() | ||
49 | |||
50 | peertubeLocalStorage = new Proxy(instance, { | ||
51 | set: function (obj, prop, value) { | ||
52 | if (MemoryStorage.prototype.hasOwnProperty(prop)) { | ||
53 | instance[prop] = value | ||
54 | } else { | ||
55 | instance.setItem(prop, value) | ||
56 | } | ||
57 | return true | ||
58 | }, | ||
59 | get: function (target, name) { | ||
60 | if (MemoryStorage.prototype.hasOwnProperty(name)) { | ||
61 | return instance[name] | ||
62 | } | ||
63 | if (valuesMap.has(name)) { | ||
64 | return instance.getItem(name) | ||
65 | } | ||
66 | } | ||
67 | }) | ||
68 | } | ||
69 | |||
70 | export { peertubeLocalStorage } | ||
diff --git a/client/src/app/shared/rest/rest-table.ts b/client/src/app/shared/rest/rest-table.ts index 165fc4e45..fe1a91d2d 100644 --- a/client/src/app/shared/rest/rest-table.ts +++ b/client/src/app/shared/rest/rest-table.ts | |||
@@ -1,3 +1,4 @@ | |||
1 | import { peertubeLocalStorage } from '@app/shared/misc/peertube-local-storage' | ||
1 | import { LazyLoadEvent } from 'primeng/components/common/lazyloadevent' | 2 | import { LazyLoadEvent } from 'primeng/components/common/lazyloadevent' |
2 | import { SortMeta } from 'primeng/components/common/sortmeta' | 3 | import { SortMeta } from 'primeng/components/common/sortmeta' |
3 | 4 | ||
@@ -15,7 +16,7 @@ export abstract class RestTable { | |||
15 | protected abstract loadData (): void | 16 | protected abstract loadData (): void |
16 | 17 | ||
17 | loadSort () { | 18 | loadSort () { |
18 | const result = localStorage.getItem(this.sortLocalStorageKey) | 19 | const result = peertubeLocalStorage.getItem(this.sortLocalStorageKey) |
19 | 20 | ||
20 | if (result) { | 21 | if (result) { |
21 | try { | 22 | try { |
@@ -42,7 +43,7 @@ export abstract class RestTable { | |||
42 | } | 43 | } |
43 | 44 | ||
44 | saveSort () { | 45 | saveSort () { |
45 | localStorage.setItem(this.sortLocalStorageKey, JSON.stringify(this.sort)) | 46 | peertubeLocalStorage.setItem(this.sortLocalStorageKey, JSON.stringify(this.sort)) |
46 | } | 47 | } |
47 | 48 | ||
48 | } | 49 | } |
diff --git a/client/src/app/videos/+video-watch/video-watch.component.ts b/client/src/app/videos/+video-watch/video-watch.component.ts index b60e58fb0..fda69efab 100644 --- a/client/src/app/videos/+video-watch/video-watch.component.ts +++ b/client/src/app/videos/+video-watch/video-watch.component.ts | |||
@@ -1,6 +1,7 @@ | |||
1 | import { Component, ElementRef, NgZone, OnDestroy, OnInit, ViewChild } from '@angular/core' | 1 | import { Component, ElementRef, NgZone, OnDestroy, OnInit, ViewChild } from '@angular/core' |
2 | import { ActivatedRoute, Router } from '@angular/router' | 2 | import { ActivatedRoute, Router } from '@angular/router' |
3 | import { RedirectService } from '@app/core/routing/redirect.service' | 3 | import { RedirectService } from '@app/core/routing/redirect.service' |
4 | import { peertubeLocalStorage } from '@app/shared/misc/peertube-local-storage' | ||
4 | import { VideoSupportComponent } from '@app/videos/+video-watch/modal/video-support.component' | 5 | import { VideoSupportComponent } from '@app/videos/+video-watch/modal/video-support.component' |
5 | import { MetaService } from '@ngx-meta/core' | 6 | import { MetaService } from '@ngx-meta/core' |
6 | import { NotificationsService } from 'angular2-notifications' | 7 | import { NotificationsService } from 'angular2-notifications' |
@@ -75,7 +76,10 @@ export class VideoWatchComponent implements OnInit, OnDestroy { | |||
75 | } | 76 | } |
76 | 77 | ||
77 | ngOnInit () { | 78 | ngOnInit () { |
78 | if (WebTorrent.WEBRTC_SUPPORT === false || localStorage.getItem(VideoWatchComponent.LOCAL_STORAGE_PRIVACY_CONCERN_KEY) === 'true') { | 79 | if ( |
80 | WebTorrent.WEBRTC_SUPPORT === false || | ||
81 | peertubeLocalStorage.getItem(VideoWatchComponent.LOCAL_STORAGE_PRIVACY_CONCERN_KEY) === 'true' | ||
82 | ) { | ||
79 | this.hasAlreadyAcceptedPrivacyConcern = true | 83 | this.hasAlreadyAcceptedPrivacyConcern = true |
80 | } | 84 | } |
81 | 85 | ||
@@ -262,7 +266,7 @@ export class VideoWatchComponent implements OnInit, OnDestroy { | |||
262 | } | 266 | } |
263 | 267 | ||
264 | acceptedPrivacyConcern () { | 268 | acceptedPrivacyConcern () { |
265 | localStorage.setItem(VideoWatchComponent.LOCAL_STORAGE_PRIVACY_CONCERN_KEY, 'true') | 269 | peertubeLocalStorage.setItem(VideoWatchComponent.LOCAL_STORAGE_PRIVACY_CONCERN_KEY, 'true') |
266 | this.hasAlreadyAcceptedPrivacyConcern = true | 270 | this.hasAlreadyAcceptedPrivacyConcern = true |
267 | } | 271 | } |
268 | 272 | ||