diff options
author | Chocobozzz <me@florianbigard.com> | 2021-12-15 15:58:10 +0100 |
---|---|---|
committer | Chocobozzz <me@florianbigard.com> | 2021-12-16 10:08:55 +0100 |
commit | a9bfa85d2cdf13670aaced740da5b493fbeddfce (patch) | |
tree | 3781c9218d4cc7786b6589365c0efbed2151703d /client/src/app/core | |
parent | c77fdc605b3ccc1ab6890f889d8200fbe9372949 (diff) | |
download | PeerTube-a9bfa85d2cdf13670aaced740da5b493fbeddfce.tar.gz PeerTube-a9bfa85d2cdf13670aaced740da5b493fbeddfce.tar.zst PeerTube-a9bfa85d2cdf13670aaced740da5b493fbeddfce.zip |
Add ability for admins to set default p2p policy
Diffstat (limited to 'client/src/app/core')
-rw-r--r-- | client/src/app/core/auth/auth-user.model.ts | 44 | ||||
-rw-r--r-- | client/src/app/core/auth/auth.service.ts | 16 | ||||
-rw-r--r-- | client/src/app/core/core.module.ts | 3 | ||||
-rw-r--r-- | client/src/app/core/users/index.ts | 1 | ||||
-rw-r--r-- | client/src/app/core/users/user-local-storage.service.ts | 186 | ||||
-rw-r--r-- | client/src/app/core/users/user.model.ts | 8 | ||||
-rw-r--r-- | client/src/app/core/users/user.service.ts | 104 |
7 files changed, 226 insertions, 136 deletions
diff --git a/client/src/app/core/auth/auth-user.model.ts b/client/src/app/core/auth/auth-user.model.ts index f10b37e5a..cd9665e37 100644 --- a/client/src/app/core/auth/auth-user.model.ts +++ b/client/src/app/core/auth/auth-user.model.ts | |||
@@ -1,13 +1,7 @@ | |||
1 | import { Observable, of } from 'rxjs' | 1 | import { Observable, of } from 'rxjs' |
2 | import { map } from 'rxjs/operators' | 2 | import { map } from 'rxjs/operators' |
3 | import { User } from '@app/core/users/user.model' | 3 | import { User } from '@app/core/users/user.model' |
4 | import { | 4 | import { UserTokens } from '@root-helpers/users' |
5 | flushUserInfoFromLocalStorage, | ||
6 | getUserInfoFromLocalStorage, | ||
7 | saveUserInfoIntoLocalStorage, | ||
8 | TokenOptions, | ||
9 | Tokens | ||
10 | } from '@root-helpers/users' | ||
11 | import { hasUserRight } from '@shared/core-utils/users' | 5 | import { hasUserRight } from '@shared/core-utils/users' |
12 | import { | 6 | import { |
13 | MyUser as ServerMyUserModel, | 7 | MyUser as ServerMyUserModel, |
@@ -19,31 +13,15 @@ import { | |||
19 | } from '@shared/models' | 13 | } from '@shared/models' |
20 | 14 | ||
21 | export class AuthUser extends User implements ServerMyUserModel { | 15 | export class AuthUser extends User implements ServerMyUserModel { |
22 | tokens: Tokens | 16 | tokens: UserTokens |
23 | specialPlaylists: MyUserSpecialPlaylist[] | 17 | specialPlaylists: MyUserSpecialPlaylist[] |
24 | 18 | ||
25 | canSeeVideosLink = true | 19 | canSeeVideosLink = true |
26 | 20 | ||
27 | static load () { | 21 | constructor (userHash: Partial<ServerMyUserModel>, hashTokens: Partial<UserTokens>) { |
28 | const tokens = Tokens.load() | ||
29 | if (!tokens) return null | ||
30 | |||
31 | const userInfo = getUserInfoFromLocalStorage() | ||
32 | if (!userInfo) return null | ||
33 | |||
34 | return new AuthUser(userInfo, tokens) | ||
35 | } | ||
36 | |||
37 | static flush () { | ||
38 | flushUserInfoFromLocalStorage() | ||
39 | |||
40 | Tokens.flush() | ||
41 | } | ||
42 | |||
43 | constructor (userHash: Partial<ServerMyUserModel>, hashTokens: TokenOptions) { | ||
44 | super(userHash) | 22 | super(userHash) |
45 | 23 | ||
46 | this.tokens = new Tokens(hashTokens) | 24 | this.tokens = new UserTokens(hashTokens) |
47 | this.specialPlaylists = userHash.specialPlaylists | 25 | this.specialPlaylists = userHash.specialPlaylists |
48 | } | 26 | } |
49 | 27 | ||
@@ -77,20 +55,6 @@ export class AuthUser extends User implements ServerMyUserModel { | |||
77 | return user.role === UserRole.USER | 55 | return user.role === UserRole.USER |
78 | } | 56 | } |
79 | 57 | ||
80 | save () { | ||
81 | saveUserInfoIntoLocalStorage({ | ||
82 | id: this.id, | ||
83 | username: this.username, | ||
84 | email: this.email, | ||
85 | role: this.role, | ||
86 | nsfwPolicy: this.nsfwPolicy, | ||
87 | webTorrentEnabled: this.webTorrentEnabled, | ||
88 | autoPlayVideo: this.autoPlayVideo | ||
89 | }) | ||
90 | |||
91 | this.tokens.save() | ||
92 | } | ||
93 | |||
94 | computeCanSeeVideosLink (quotaObservable: Observable<UserVideoQuota>): Observable<boolean> { | 58 | computeCanSeeVideosLink (quotaObservable: Observable<UserVideoQuota>): Observable<boolean> { |
95 | if (!this.isUploadDisabled()) { | 59 | if (!this.isUploadDisabled()) { |
96 | this.canSeeVideosLink = true | 60 | this.canSeeVideosLink = true |
diff --git a/client/src/app/core/auth/auth.service.ts b/client/src/app/core/auth/auth.service.ts index 79239a17a..2ac88c185 100644 --- a/client/src/app/core/auth/auth.service.ts +++ b/client/src/app/core/auth/auth.service.ts | |||
@@ -5,7 +5,7 @@ import { HttpClient, HttpHeaders, HttpParams } from '@angular/common/http' | |||
5 | import { Injectable } from '@angular/core' | 5 | import { Injectable } from '@angular/core' |
6 | import { Router } from '@angular/router' | 6 | import { Router } from '@angular/router' |
7 | import { Notifier } from '@app/core/notification/notifier.service' | 7 | import { Notifier } from '@app/core/notification/notifier.service' |
8 | import { objectToUrlEncoded, peertubeLocalStorage } from '@root-helpers/index' | 8 | import { objectToUrlEncoded, peertubeLocalStorage, UserTokens } from '@root-helpers/index' |
9 | import { HttpStatusCode, MyUser as UserServerModel, OAuthClientLocal, User, UserLogin, UserRefreshToken } from '@shared/models' | 9 | import { HttpStatusCode, MyUser as UserServerModel, OAuthClientLocal, User, UserLogin, UserRefreshToken } from '@shared/models' |
10 | import { environment } from '../../../environments/environment' | 10 | import { environment } from '../../../environments/environment' |
11 | import { RestExtractor } from '../rest/rest-extractor.service' | 11 | import { RestExtractor } from '../rest/rest-extractor.service' |
@@ -34,6 +34,7 @@ export class AuthService { | |||
34 | 34 | ||
35 | loginChangedSource: Observable<AuthStatus> | 35 | loginChangedSource: Observable<AuthStatus> |
36 | userInformationLoaded = new ReplaySubject<boolean>(1) | 36 | userInformationLoaded = new ReplaySubject<boolean>(1) |
37 | tokensRefreshed = new ReplaySubject<void>(1) | ||
37 | hotkeys: Hotkey[] | 38 | hotkeys: Hotkey[] |
38 | 39 | ||
39 | private clientId: string = peertubeLocalStorage.getItem(AuthService.LOCAL_STORAGE_OAUTH_CLIENT_KEYS.CLIENT_ID) | 40 | private clientId: string = peertubeLocalStorage.getItem(AuthService.LOCAL_STORAGE_OAUTH_CLIENT_KEYS.CLIENT_ID) |
@@ -52,9 +53,6 @@ export class AuthService { | |||
52 | this.loginChanged = new Subject<AuthStatus>() | 53 | this.loginChanged = new Subject<AuthStatus>() |
53 | this.loginChangedSource = this.loginChanged.asObservable() | 54 | this.loginChangedSource = this.loginChanged.asObservable() |
54 | 55 | ||
55 | // Return null if there is nothing to load | ||
56 | this.user = AuthUser.load() | ||
57 | |||
58 | // Set HotKeys | 56 | // Set HotKeys |
59 | this.hotkeys = [ | 57 | this.hotkeys = [ |
60 | new Hotkey('m s', (event: KeyboardEvent): boolean => { | 58 | new Hotkey('m s', (event: KeyboardEvent): boolean => { |
@@ -76,6 +74,10 @@ export class AuthService { | |||
76 | ] | 74 | ] |
77 | } | 75 | } |
78 | 76 | ||
77 | buildAuthUser (userInfo: Partial<User>, tokens: UserTokens) { | ||
78 | this.user = new AuthUser(userInfo, tokens) | ||
79 | } | ||
80 | |||
79 | loadClientCredentials () { | 81 | loadClientCredentials () { |
80 | // Fetch the client_id/client_secret | 82 | // Fetch the client_id/client_secret |
81 | this.http.get<OAuthClientLocal>(AuthService.BASE_CLIENT_URL) | 83 | this.http.get<OAuthClientLocal>(AuthService.BASE_CLIENT_URL) |
@@ -180,8 +182,6 @@ Ensure you have correctly configured PeerTube (config/ directory), in particular | |||
180 | 182 | ||
181 | this.user = null | 183 | this.user = null |
182 | 184 | ||
183 | AuthUser.flush() | ||
184 | |||
185 | this.setStatus(AuthStatus.LoggedOut) | 185 | this.setStatus(AuthStatus.LoggedOut) |
186 | 186 | ||
187 | this.hotkeysService.remove(this.hotkeys) | 187 | this.hotkeysService.remove(this.hotkeys) |
@@ -239,7 +239,6 @@ Ensure you have correctly configured PeerTube (config/ directory), in particular | |||
239 | .subscribe({ | 239 | .subscribe({ |
240 | next: res => { | 240 | next: res => { |
241 | this.user.patch(res) | 241 | this.user.patch(res) |
242 | this.user.save() | ||
243 | 242 | ||
244 | this.userInformationLoaded.next(true) | 243 | this.userInformationLoaded.next(true) |
245 | } | 244 | } |
@@ -262,7 +261,6 @@ Ensure you have correctly configured PeerTube (config/ directory), in particular | |||
262 | } | 261 | } |
263 | 262 | ||
264 | this.user = new AuthUser(obj, hashTokens) | 263 | this.user = new AuthUser(obj, hashTokens) |
265 | this.user.save() | ||
266 | 264 | ||
267 | this.setStatus(AuthStatus.LoggedIn) | 265 | this.setStatus(AuthStatus.LoggedIn) |
268 | this.userInformationLoaded.next(true) | 266 | this.userInformationLoaded.next(true) |
@@ -272,7 +270,7 @@ Ensure you have correctly configured PeerTube (config/ directory), in particular | |||
272 | 270 | ||
273 | private handleRefreshToken (obj: UserRefreshToken) { | 271 | private handleRefreshToken (obj: UserRefreshToken) { |
274 | this.user.refreshTokens(obj.access_token, obj.refresh_token) | 272 | this.user.refreshTokens(obj.access_token, obj.refresh_token) |
275 | this.user.save() | 273 | this.tokensRefreshed.next() |
276 | } | 274 | } |
277 | 275 | ||
278 | private setStatus (status: AuthStatus) { | 276 | private setStatus (status: AuthStatus) { |
diff --git a/client/src/app/core/core.module.ts b/client/src/app/core/core.module.ts index 04be0671c..d80f95ed6 100644 --- a/client/src/app/core/core.module.ts +++ b/client/src/app/core/core.module.ts | |||
@@ -30,7 +30,7 @@ import { ServerConfigResolver } from './routing/server-config-resolver.service' | |||
30 | import { ScopedTokensService } from './scoped-tokens' | 30 | import { ScopedTokensService } from './scoped-tokens' |
31 | import { ServerService } from './server' | 31 | import { ServerService } from './server' |
32 | import { ThemeService } from './theme' | 32 | import { ThemeService } from './theme' |
33 | import { UserService } from './users' | 33 | import { UserLocalStorageService, UserService } from './users' |
34 | import { LocalStorageService, ScreenService, SessionStorageService } from './wrappers' | 34 | import { LocalStorageService, ScreenService, SessionStorageService } from './wrappers' |
35 | 35 | ||
36 | @NgModule({ | 36 | @NgModule({ |
@@ -79,6 +79,7 @@ import { LocalStorageService, ScreenService, SessionStorageService } from './wra | |||
79 | RestService, | 79 | RestService, |
80 | 80 | ||
81 | UserService, | 81 | UserService, |
82 | UserLocalStorageService, | ||
82 | 83 | ||
83 | ScreenService, | 84 | ScreenService, |
84 | LocalStorageService, | 85 | LocalStorageService, |
diff --git a/client/src/app/core/users/index.ts b/client/src/app/core/users/index.ts index 7b5a67bc7..e235a875b 100644 --- a/client/src/app/core/users/index.ts +++ b/client/src/app/core/users/index.ts | |||
@@ -1,2 +1,3 @@ | |||
1 | export * from './user-local-storage.service' | ||
1 | export * from './user.model' | 2 | export * from './user.model' |
2 | export * from './user.service' | 3 | export * from './user.service' |
diff --git a/client/src/app/core/users/user-local-storage.service.ts b/client/src/app/core/users/user-local-storage.service.ts new file mode 100644 index 000000000..85da46e0d --- /dev/null +++ b/client/src/app/core/users/user-local-storage.service.ts | |||
@@ -0,0 +1,186 @@ | |||
1 | |||
2 | import { filter, throttleTime } from 'rxjs' | ||
3 | import { Injectable } from '@angular/core' | ||
4 | import { AuthService, AuthStatus } from '@app/core/auth' | ||
5 | import { UserLocalStorageKeys, UserTokens } from '@root-helpers/users' | ||
6 | import { getBoolOrDefault } from '@root-helpers/local-storage-utils' | ||
7 | import { UserRole, UserUpdateMe } from '@shared/models' | ||
8 | import { NSFWPolicyType } from '@shared/models/videos' | ||
9 | import { ServerService } from '../server' | ||
10 | import { LocalStorageService } from '../wrappers/storage.service' | ||
11 | |||
12 | @Injectable() | ||
13 | export class UserLocalStorageService { | ||
14 | |||
15 | constructor ( | ||
16 | private authService: AuthService, | ||
17 | private server: ServerService, | ||
18 | private localStorageService: LocalStorageService | ||
19 | ) { | ||
20 | this.authService.userInformationLoaded.subscribe({ | ||
21 | next: () => { | ||
22 | const user = this.authService.getUser() | ||
23 | |||
24 | this.setLoggedInUser(user) | ||
25 | this.setUserInfo(user) | ||
26 | this.setTokens(user.tokens) | ||
27 | } | ||
28 | }) | ||
29 | |||
30 | this.authService.loginChangedSource | ||
31 | .pipe(filter(status => status === AuthStatus.LoggedOut)) | ||
32 | .subscribe({ | ||
33 | next: () => { | ||
34 | this.flushLoggedInUser() | ||
35 | this.flushUserInfo() | ||
36 | this.flushTokens() | ||
37 | } | ||
38 | }) | ||
39 | |||
40 | this.authService.tokensRefreshed | ||
41 | .subscribe({ | ||
42 | next: () => { | ||
43 | const user = this.authService.getUser() | ||
44 | |||
45 | this.setTokens(user.tokens) | ||
46 | } | ||
47 | }) | ||
48 | } | ||
49 | |||
50 | // --------------------------------------------------------------------------- | ||
51 | |||
52 | getLoggedInUser () { | ||
53 | const usernameLocalStorage = this.localStorageService.getItem(UserLocalStorageKeys.USERNAME) | ||
54 | |||
55 | if (!usernameLocalStorage) return undefined | ||
56 | |||
57 | return { | ||
58 | id: parseInt(this.localStorageService.getItem(UserLocalStorageKeys.ID), 10), | ||
59 | username: this.localStorageService.getItem(UserLocalStorageKeys.USERNAME), | ||
60 | email: this.localStorageService.getItem(UserLocalStorageKeys.EMAIL), | ||
61 | role: parseInt(this.localStorageService.getItem(UserLocalStorageKeys.ROLE), 10) as UserRole, | ||
62 | |||
63 | ...this.getUserInfo() | ||
64 | } | ||
65 | } | ||
66 | |||
67 | setLoggedInUser (user: { | ||
68 | id: number | ||
69 | username: string | ||
70 | email: string | ||
71 | role: UserRole | ||
72 | }) { | ||
73 | this.localStorageService.setItem(UserLocalStorageKeys.ID, user.id.toString()) | ||
74 | this.localStorageService.setItem(UserLocalStorageKeys.USERNAME, user.username) | ||
75 | this.localStorageService.setItem(UserLocalStorageKeys.EMAIL, user.email) | ||
76 | this.localStorageService.setItem(UserLocalStorageKeys.ROLE, user.role.toString()) | ||
77 | } | ||
78 | |||
79 | flushLoggedInUser () { | ||
80 | this.localStorageService.removeItem(UserLocalStorageKeys.ID) | ||
81 | this.localStorageService.removeItem(UserLocalStorageKeys.USERNAME) | ||
82 | this.localStorageService.removeItem(UserLocalStorageKeys.EMAIL) | ||
83 | this.localStorageService.removeItem(UserLocalStorageKeys.ROLE) | ||
84 | } | ||
85 | |||
86 | // --------------------------------------------------------------------------- | ||
87 | |||
88 | getUserInfo () { | ||
89 | let videoLanguages: string[] | ||
90 | |||
91 | try { | ||
92 | const languagesString = this.localStorageService.getItem(UserLocalStorageKeys.VIDEO_LANGUAGES) | ||
93 | videoLanguages = languagesString && languagesString !== 'undefined' | ||
94 | ? JSON.parse(languagesString) | ||
95 | : null | ||
96 | } catch (err) { | ||
97 | videoLanguages = null | ||
98 | console.error('Cannot parse desired video languages from localStorage.', err) | ||
99 | } | ||
100 | |||
101 | const htmlConfig = this.server.getHTMLConfig() | ||
102 | |||
103 | const defaultNSFWPolicy = htmlConfig.instance.defaultNSFWPolicy | ||
104 | const defaultP2PEnabled = htmlConfig.defaults.p2p.enabled | ||
105 | |||
106 | return { | ||
107 | nsfwPolicy: this.localStorageService.getItem<NSFWPolicyType>(UserLocalStorageKeys.NSFW_POLICY) || defaultNSFWPolicy, | ||
108 | p2pEnabled: getBoolOrDefault(this.localStorageService.getItem(UserLocalStorageKeys.P2P_ENABLED), defaultP2PEnabled), | ||
109 | theme: this.localStorageService.getItem(UserLocalStorageKeys.THEME) || 'instance-default', | ||
110 | videoLanguages, | ||
111 | |||
112 | autoPlayVideo: getBoolOrDefault(this.localStorageService.getItem(UserLocalStorageKeys.AUTO_PLAY_VIDEO), true), | ||
113 | autoPlayNextVideo: getBoolOrDefault(this.localStorageService.getItem(UserLocalStorageKeys.AUTO_PLAY_NEXT_VIDEO), false), | ||
114 | autoPlayNextVideoPlaylist: getBoolOrDefault(this.localStorageService.getItem(UserLocalStorageKeys.AUTO_PLAY_VIDEO_PLAYLIST), true) | ||
115 | } | ||
116 | } | ||
117 | |||
118 | setUserInfo (profile: UserUpdateMe) { | ||
119 | const localStorageKeys: { [ id in keyof UserUpdateMe ]: string } = { | ||
120 | nsfwPolicy: UserLocalStorageKeys.NSFW_POLICY, | ||
121 | p2pEnabled: UserLocalStorageKeys.P2P_ENABLED, | ||
122 | autoPlayNextVideo: UserLocalStorageKeys.AUTO_PLAY_VIDEO, | ||
123 | autoPlayNextVideoPlaylist: UserLocalStorageKeys.AUTO_PLAY_VIDEO_PLAYLIST, | ||
124 | theme: UserLocalStorageKeys.THEME, | ||
125 | videoLanguages: UserLocalStorageKeys.VIDEO_LANGUAGES | ||
126 | } | ||
127 | |||
128 | const obj = Object.keys(localStorageKeys) | ||
129 | .filter(key => key in profile) | ||
130 | .map(key => ([ localStorageKeys[key], profile[key] ])) | ||
131 | |||
132 | for (const [ key, value ] of obj) { | ||
133 | try { | ||
134 | if (value === undefined) { | ||
135 | this.localStorageService.removeItem(key) | ||
136 | continue | ||
137 | } | ||
138 | |||
139 | const localStorageValue = typeof value === 'string' | ||
140 | ? value | ||
141 | : JSON.stringify(value) | ||
142 | |||
143 | this.localStorageService.setItem(key, localStorageValue) | ||
144 | } catch (err) { | ||
145 | console.error(`Cannot set ${key}->${value} in localStorage. Likely due to a value impossible to stringify.`, err) | ||
146 | } | ||
147 | } | ||
148 | } | ||
149 | |||
150 | flushUserInfo () { | ||
151 | this.localStorageService.removeItem(UserLocalStorageKeys.NSFW_POLICY) | ||
152 | this.localStorageService.removeItem(UserLocalStorageKeys.P2P_ENABLED) | ||
153 | this.localStorageService.removeItem(UserLocalStorageKeys.AUTO_PLAY_VIDEO) | ||
154 | this.localStorageService.removeItem(UserLocalStorageKeys.AUTO_PLAY_VIDEO_PLAYLIST) | ||
155 | this.localStorageService.removeItem(UserLocalStorageKeys.THEME) | ||
156 | this.localStorageService.removeItem(UserLocalStorageKeys.VIDEO_LANGUAGES) | ||
157 | } | ||
158 | |||
159 | listenUserInfoChange () { | ||
160 | return this.localStorageService.watch([ | ||
161 | UserLocalStorageKeys.NSFW_POLICY, | ||
162 | UserLocalStorageKeys.P2P_ENABLED, | ||
163 | UserLocalStorageKeys.AUTO_PLAY_VIDEO, | ||
164 | UserLocalStorageKeys.AUTO_PLAY_VIDEO_PLAYLIST, | ||
165 | UserLocalStorageKeys.THEME, | ||
166 | UserLocalStorageKeys.VIDEO_LANGUAGES | ||
167 | ]).pipe( | ||
168 | throttleTime(200), | ||
169 | filter(() => this.authService.isLoggedIn() !== true) | ||
170 | ) | ||
171 | } | ||
172 | |||
173 | // --------------------------------------------------------------------------- | ||
174 | |||
175 | getTokens () { | ||
176 | return UserTokens.getUserTokens(this.localStorageService) | ||
177 | } | ||
178 | |||
179 | setTokens (tokens: UserTokens) { | ||
180 | UserTokens.saveToLocalStorage(this.localStorageService, tokens) | ||
181 | } | ||
182 | |||
183 | flushTokens () { | ||
184 | UserTokens.flushLocalStorage(this.localStorageService) | ||
185 | } | ||
186 | } | ||
diff --git a/client/src/app/core/users/user.model.ts b/client/src/app/core/users/user.model.ts index c0e5d3169..f211051ce 100644 --- a/client/src/app/core/users/user.model.ts +++ b/client/src/app/core/users/user.model.ts | |||
@@ -26,7 +26,11 @@ export class User implements UserServerModel { | |||
26 | autoPlayVideo: boolean | 26 | autoPlayVideo: boolean |
27 | autoPlayNextVideo: boolean | 27 | autoPlayNextVideo: boolean |
28 | autoPlayNextVideoPlaylist: boolean | 28 | autoPlayNextVideoPlaylist: boolean |
29 | webTorrentEnabled: boolean | 29 | |
30 | p2pEnabled: boolean | ||
31 | // FIXME: deprecated in 4.1 | ||
32 | webTorrentEnabled: never | ||
33 | |||
30 | videosHistoryEnabled: boolean | 34 | videosHistoryEnabled: boolean |
31 | videoLanguages: string[] | 35 | videoLanguages: string[] |
32 | 36 | ||
@@ -84,7 +88,7 @@ export class User implements UserServerModel { | |||
84 | this.videoCommentsCount = hash.videoCommentsCount | 88 | this.videoCommentsCount = hash.videoCommentsCount |
85 | 89 | ||
86 | this.nsfwPolicy = hash.nsfwPolicy | 90 | this.nsfwPolicy = hash.nsfwPolicy |
87 | this.webTorrentEnabled = hash.webTorrentEnabled | 91 | this.p2pEnabled = hash.p2pEnabled |
88 | this.autoPlayVideo = hash.autoPlayVideo | 92 | this.autoPlayVideo = hash.autoPlayVideo |
89 | this.autoPlayNextVideo = hash.autoPlayNextVideo | 93 | this.autoPlayNextVideo = hash.autoPlayNextVideo |
90 | this.autoPlayNextVideoPlaylist = hash.autoPlayNextVideoPlaylist | 94 | this.autoPlayNextVideoPlaylist = hash.autoPlayNextVideoPlaylist |
diff --git a/client/src/app/core/users/user.service.ts b/client/src/app/core/users/user.service.ts index 632361e9b..a6a0474ab 100644 --- a/client/src/app/core/users/user.service.ts +++ b/client/src/app/core/users/user.service.ts | |||
@@ -1,11 +1,10 @@ | |||
1 | import { SortMeta } from 'primeng/api' | 1 | import { SortMeta } from 'primeng/api' |
2 | import { from, Observable, of } from 'rxjs' | 2 | import { from, Observable, of } from 'rxjs' |
3 | import { catchError, concatMap, filter, first, map, shareReplay, tap, throttleTime, toArray } from 'rxjs/operators' | 3 | import { catchError, concatMap, first, map, shareReplay, tap, toArray } from 'rxjs/operators' |
4 | import { HttpClient, HttpParams } from '@angular/common/http' | 4 | import { HttpClient, HttpParams } from '@angular/common/http' |
5 | import { Injectable } from '@angular/core' | 5 | import { Injectable } from '@angular/core' |
6 | import { AuthService } from '@app/core/auth' | 6 | import { AuthService } from '@app/core/auth' |
7 | import { getBytes } from '@root-helpers/bytes' | 7 | import { getBytes } from '@root-helpers/bytes' |
8 | import { UserLocalStorageKeys } from '@root-helpers/users' | ||
9 | import { | 8 | import { |
10 | ActorImage, | 9 | ActorImage, |
11 | ResultList, | 10 | ResultList, |
@@ -17,10 +16,9 @@ import { | |||
17 | UserUpdateMe, | 16 | UserUpdateMe, |
18 | UserVideoQuota | 17 | UserVideoQuota |
19 | } from '@shared/models' | 18 | } from '@shared/models' |
20 | import { ServerService } from '../' | ||
21 | import { environment } from '../../../environments/environment' | 19 | import { environment } from '../../../environments/environment' |
22 | import { RestExtractor, RestPagination, RestService } from '../rest' | 20 | import { RestExtractor, RestPagination, RestService } from '../rest' |
23 | import { LocalStorageService, SessionStorageService } from '../wrappers/storage.service' | 21 | import { UserLocalStorageService } from './' |
24 | import { User } from './user.model' | 22 | import { User } from './user.model' |
25 | 23 | ||
26 | @Injectable() | 24 | @Injectable() |
@@ -33,12 +31,10 @@ export class UserService { | |||
33 | 31 | ||
34 | constructor ( | 32 | constructor ( |
35 | private authHttp: HttpClient, | 33 | private authHttp: HttpClient, |
36 | private server: ServerService, | ||
37 | private authService: AuthService, | 34 | private authService: AuthService, |
38 | private restExtractor: RestExtractor, | 35 | private restExtractor: RestExtractor, |
39 | private restService: RestService, | 36 | private restService: RestService, |
40 | private localStorageService: LocalStorageService, | 37 | private userLocalStorageService: UserLocalStorageService |
41 | private sessionStorageService: SessionStorageService | ||
42 | ) { } | 38 | ) { } |
43 | 39 | ||
44 | hasSignupInThisSession () { | 40 | hasSignupInThisSession () { |
@@ -73,6 +69,23 @@ export class UserService { | |||
73 | ) | 69 | ) |
74 | } | 70 | } |
75 | 71 | ||
72 | // --------------------------------------------------------------------------- | ||
73 | |||
74 | updateMyAnonymousProfile (profile: UserUpdateMe) { | ||
75 | this.userLocalStorageService.setUserInfo(profile) | ||
76 | } | ||
77 | |||
78 | listenAnonymousUpdate () { | ||
79 | return this.userLocalStorageService.listenUserInfoChange() | ||
80 | .pipe(map(() => this.getAnonymousUser())) | ||
81 | } | ||
82 | |||
83 | getAnonymousUser () { | ||
84 | return new User(this.userLocalStorageService.getUserInfo()) | ||
85 | } | ||
86 | |||
87 | // --------------------------------------------------------------------------- | ||
88 | |||
76 | updateMyProfile (profile: UserUpdateMe) { | 89 | updateMyProfile (profile: UserUpdateMe) { |
77 | const url = UserService.BASE_USERS_URL + 'me' | 90 | const url = UserService.BASE_USERS_URL + 'me' |
78 | 91 | ||
@@ -83,53 +96,6 @@ export class UserService { | |||
83 | ) | 96 | ) |
84 | } | 97 | } |
85 | 98 | ||
86 | updateMyAnonymousProfile (profile: UserUpdateMe) { | ||
87 | const localStorageKeys: { [ id in keyof UserUpdateMe ]: string } = { | ||
88 | nsfwPolicy: UserLocalStorageKeys.NSFW_POLICY, | ||
89 | webTorrentEnabled: UserLocalStorageKeys.WEBTORRENT_ENABLED, | ||
90 | autoPlayNextVideo: UserLocalStorageKeys.AUTO_PLAY_VIDEO, | ||
91 | autoPlayNextVideoPlaylist: UserLocalStorageKeys.AUTO_PLAY_VIDEO_PLAYLIST, | ||
92 | theme: UserLocalStorageKeys.THEME, | ||
93 | videoLanguages: UserLocalStorageKeys.VIDEO_LANGUAGES | ||
94 | } | ||
95 | |||
96 | const obj = Object.keys(localStorageKeys) | ||
97 | .filter(key => key in profile) | ||
98 | .map(key => ([ localStorageKeys[key], profile[key] ])) | ||
99 | |||
100 | for (const [ key, value ] of obj) { | ||
101 | try { | ||
102 | if (value === undefined) { | ||
103 | this.localStorageService.removeItem(key) | ||
104 | continue | ||
105 | } | ||
106 | |||
107 | const localStorageValue = typeof value === 'string' | ||
108 | ? value | ||
109 | : JSON.stringify(value) | ||
110 | |||
111 | this.localStorageService.setItem(key, localStorageValue) | ||
112 | } catch (err) { | ||
113 | console.error(`Cannot set ${key}->${value} in localStorage. Likely due to a value impossible to stringify.`, err) | ||
114 | } | ||
115 | } | ||
116 | } | ||
117 | |||
118 | listenAnonymousUpdate () { | ||
119 | return this.localStorageService.watch([ | ||
120 | UserLocalStorageKeys.NSFW_POLICY, | ||
121 | UserLocalStorageKeys.WEBTORRENT_ENABLED, | ||
122 | UserLocalStorageKeys.AUTO_PLAY_VIDEO, | ||
123 | UserLocalStorageKeys.AUTO_PLAY_VIDEO_PLAYLIST, | ||
124 | UserLocalStorageKeys.THEME, | ||
125 | UserLocalStorageKeys.VIDEO_LANGUAGES | ||
126 | ]).pipe( | ||
127 | throttleTime(200), | ||
128 | filter(() => this.authService.isLoggedIn() !== true), | ||
129 | map(() => this.getAnonymousUser()) | ||
130 | ) | ||
131 | } | ||
132 | |||
133 | deleteMe () { | 99 | deleteMe () { |
134 | const url = UserService.BASE_USERS_URL + 'me' | 100 | const url = UserService.BASE_USERS_URL + 'me' |
135 | 101 | ||
@@ -287,36 +253,6 @@ export class UserService { | |||
287 | .pipe(catchError(err => this.restExtractor.handleError(err))) | 253 | .pipe(catchError(err => this.restExtractor.handleError(err))) |
288 | } | 254 | } |
289 | 255 | ||
290 | getAnonymousUser () { | ||
291 | let videoLanguages: string[] | ||
292 | |||
293 | try { | ||
294 | const languagesString = this.localStorageService.getItem(UserLocalStorageKeys.VIDEO_LANGUAGES) | ||
295 | videoLanguages = languagesString && languagesString !== 'undefined' | ||
296 | ? JSON.parse(languagesString) | ||
297 | : null | ||
298 | } catch (err) { | ||
299 | videoLanguages = null | ||
300 | console.error('Cannot parse desired video languages from localStorage.', err) | ||
301 | } | ||
302 | |||
303 | const defaultNSFWPolicy = this.server.getHTMLConfig().instance.defaultNSFWPolicy | ||
304 | |||
305 | return new User({ | ||
306 | // local storage keys | ||
307 | nsfwPolicy: this.localStorageService.getItem(UserLocalStorageKeys.NSFW_POLICY) || defaultNSFWPolicy, | ||
308 | webTorrentEnabled: this.localStorageService.getItem(UserLocalStorageKeys.WEBTORRENT_ENABLED) !== 'false', | ||
309 | theme: this.localStorageService.getItem(UserLocalStorageKeys.THEME) || 'instance-default', | ||
310 | videoLanguages, | ||
311 | |||
312 | autoPlayNextVideoPlaylist: this.localStorageService.getItem(UserLocalStorageKeys.AUTO_PLAY_VIDEO_PLAYLIST) !== 'false', | ||
313 | autoPlayVideo: this.localStorageService.getItem(UserLocalStorageKeys.AUTO_PLAY_VIDEO) === 'true', | ||
314 | |||
315 | // session storage keys | ||
316 | autoPlayNextVideo: this.sessionStorageService.getItem(UserLocalStorageKeys.SESSION_STORAGE_AUTO_PLAY_NEXT_VIDEO) === 'true' | ||
317 | }) | ||
318 | } | ||
319 | |||
320 | getUsers (parameters: { | 256 | getUsers (parameters: { |
321 | pagination: RestPagination | 257 | pagination: RestPagination |
322 | sort: SortMeta | 258 | sort: SortMeta |