aboutsummaryrefslogtreecommitdiffhomepage
path: root/client/src/app/core/users/user.service.ts
diff options
context:
space:
mode:
Diffstat (limited to 'client/src/app/core/users/user.service.ts')
-rw-r--r--client/src/app/core/users/user.service.ts284
1 files changed, 57 insertions, 227 deletions
diff --git a/client/src/app/core/users/user.service.ts b/client/src/app/core/users/user.service.ts
index f173c356a..b14bff193 100644
--- a/client/src/app/core/users/user.service.ts
+++ b/client/src/app/core/users/user.service.ts
@@ -1,24 +1,12 @@
1import { SortMeta } from 'primeng/api' 1import { Observable, of } from 'rxjs'
2import { from, Observable, of } from 'rxjs' 2import { catchError, first, map, shareReplay } from 'rxjs/operators'
3import { catchError, concatMap, first, map, shareReplay, tap, toArray } from 'rxjs/operators'
4import { HttpClient, HttpParams } from '@angular/common/http' 3import { HttpClient, HttpParams } from '@angular/common/http'
5import { Injectable } from '@angular/core' 4import { Injectable } from '@angular/core'
6import { AuthService } from '@app/core/auth' 5import { AuthService } from '@app/core/auth'
7import { getBytes } from '@root-helpers/bytes' 6import { ActorImage, User as UserServerModel, UserUpdateMe, UserVideoQuota } from '@shared/models'
8import {
9 ActorImage,
10 ResultList,
11 User as UserServerModel,
12 UserCreate,
13 UserRegister,
14 UserRole,
15 UserUpdate,
16 UserUpdateMe,
17 UserVideoQuota
18} from '@shared/models'
19import { environment } from '../../../environments/environment' 7import { environment } from '../../../environments/environment'
20import { RestExtractor, RestPagination, RestService } from '../rest' 8import { RestExtractor } from '../rest'
21import { UserLocalStorageService } from './' 9import { UserLocalStorageService } from './user-local-storage.service'
22import { User } from './user.model' 10import { User } from './user.model'
23 11
24@Injectable() 12@Injectable()
@@ -26,45 +14,44 @@ export class UserService {
26 static BASE_USERS_URL = environment.apiUrl + '/api/v1/users/' 14 static BASE_USERS_URL = environment.apiUrl + '/api/v1/users/'
27 15
28 private userCache: { [ id: number ]: Observable<UserServerModel> } = {} 16 private userCache: { [ id: number ]: Observable<UserServerModel> } = {}
29
30 private signupInThisSession = false 17 private signupInThisSession = false
31 18
32 constructor ( 19 constructor (
33 private authHttp: HttpClient, 20 private authHttp: HttpClient,
34 private authService: AuthService, 21 private authService: AuthService,
35 private restExtractor: RestExtractor, 22 private restExtractor: RestExtractor,
36 private restService: RestService,
37 private userLocalStorageService: UserLocalStorageService 23 private userLocalStorageService: UserLocalStorageService
38 ) { } 24 ) { }
39 25
40 hasSignupInThisSession () { 26 // ---------------------------------------------------------------------------
41 return this.signupInThisSession
42 }
43 27
44 changePassword (currentPassword: string, newPassword: string) { 28 getUserWithCache (userId: number) {
45 const url = UserService.BASE_USERS_URL + 'me' 29 if (!this.userCache[userId]) {
46 const body: UserUpdateMe = { 30 this.userCache[userId] = this.getUser(userId).pipe(shareReplay())
47 currentPassword,
48 password: newPassword
49 } 31 }
50 32
51 return this.authHttp.put(url, body) 33 return this.userCache[userId]
52 .pipe(catchError(err => this.restExtractor.handleError(err)))
53 } 34 }
54 35
55 changeEmail (password: string, newEmail: string) { 36 getUser (userId: number, withStats = false) {
56 const url = UserService.BASE_USERS_URL + 'me' 37 const params = new HttpParams().append('withStats', withStats + '')
57 const body: UserUpdateMe = {
58 currentPassword: password,
59 email: newEmail
60 }
61 38
62 return this.authHttp.put(url, body) 39 return this.authHttp.get<UserServerModel>(UserService.BASE_USERS_URL + userId, { params })
63 .pipe(catchError(err => this.restExtractor.handleError(err))) 40 .pipe(catchError(err => this.restExtractor.handleError(err)))
64 } 41 }
65 42
66 // --------------------------------------------------------------------------- 43 // ---------------------------------------------------------------------------
67 44
45 setSignupInThisSession (value: boolean) {
46 this.signupInThisSession = value
47 }
48
49 hasSignupInThisSession () {
50 return this.signupInThisSession
51 }
52
53 // ---------------------------------------------------------------------------
54
68 updateMyAnonymousProfile (profile: UserUpdateMe) { 55 updateMyAnonymousProfile (profile: UserUpdateMe) {
69 this.userLocalStorageService.setUserInfo(profile) 56 this.userLocalStorageService.setUserInfo(profile)
70 } 57 }
@@ -78,8 +65,42 @@ export class UserService {
78 return new User(this.userLocalStorageService.getUserInfo()) 65 return new User(this.userLocalStorageService.getUserInfo())
79 } 66 }
80 67
68 getAnonymousOrLoggedUser () {
69 if (!this.authService.isLoggedIn()) {
70 return of(this.getAnonymousUser())
71 }
72
73 return this.authService.userInformationLoaded
74 .pipe(
75 first(),
76 map(() => this.authService.getUser())
77 )
78 }
79
81 // --------------------------------------------------------------------------- 80 // ---------------------------------------------------------------------------
82 81
82 changePassword (currentPassword: string, newPassword: string) {
83 const url = UserService.BASE_USERS_URL + 'me'
84 const body: UserUpdateMe = {
85 currentPassword,
86 password: newPassword
87 }
88
89 return this.authHttp.put(url, body)
90 .pipe(catchError(err => this.restExtractor.handleError(err)))
91 }
92
93 changeEmail (password: string, newEmail: string) {
94 const url = UserService.BASE_USERS_URL + 'me'
95 const body: UserUpdateMe = {
96 currentPassword: password,
97 email: newEmail
98 }
99
100 return this.authHttp.put(url, body)
101 .pipe(catchError(err => this.restExtractor.handleError(err)))
102 }
103
83 updateMyProfile (profile: UserUpdateMe) { 104 updateMyProfile (profile: UserUpdateMe) {
84 const url = UserService.BASE_USERS_URL + 'me' 105 const url = UserService.BASE_USERS_URL + 'me'
85 106
@@ -108,14 +129,6 @@ export class UserService {
108 .pipe(catchError(err => this.restExtractor.handleError(err))) 129 .pipe(catchError(err => this.restExtractor.handleError(err)))
109 } 130 }
110 131
111 signup (userCreate: UserRegister) {
112 return this.authHttp.post(UserService.BASE_USERS_URL + 'register', userCreate)
113 .pipe(
114 tap(() => this.signupInThisSession = true),
115 catchError(err => this.restExtractor.handleError(err))
116 )
117 }
118
119 getMyVideoQuotaUsed () { 132 getMyVideoQuotaUsed () {
120 const url = UserService.BASE_USERS_URL + 'me/video-quota-used' 133 const url = UserService.BASE_USERS_URL + 'me/video-quota-used'
121 134
@@ -141,24 +154,6 @@ export class UserService {
141 .pipe(catchError(res => this.restExtractor.handleError(res))) 154 .pipe(catchError(res => this.restExtractor.handleError(res)))
142 } 155 }
143 156
144 verifyEmail (userId: number, verificationString: string, isPendingEmail: boolean) {
145 const url = `${UserService.BASE_USERS_URL}/${userId}/verify-email`
146 const body = {
147 verificationString,
148 isPendingEmail
149 }
150
151 return this.authHttp.post(url, body)
152 .pipe(catchError(res => this.restExtractor.handleError(res)))
153 }
154
155 askSendVerifyEmail (email: string) {
156 const url = UserService.BASE_USERS_URL + '/ask-send-verify-email'
157
158 return this.authHttp.post(url, { email })
159 .pipe(catchError(err => this.restExtractor.handleError(err)))
160 }
161
162 autocomplete (search: string): Observable<string[]> { 157 autocomplete (search: string): Observable<string[]> {
163 const url = UserService.BASE_USERS_URL + 'autocomplete' 158 const url = UserService.BASE_USERS_URL + 'autocomplete'
164 const params = new HttpParams().append('search', search) 159 const params = new HttpParams().append('search', search)
@@ -167,169 +162,4 @@ export class UserService {
167 .get<string[]>(url, { params }) 162 .get<string[]>(url, { params })
168 .pipe(catchError(res => this.restExtractor.handleError(res))) 163 .pipe(catchError(res => this.restExtractor.handleError(res)))
169 } 164 }
170
171 getNewUsername (oldDisplayName: string, newDisplayName: string, currentUsername: string) {
172 // Don't update display name, the user seems to have changed it
173 if (this.displayNameToUsername(oldDisplayName) !== currentUsername) return currentUsername
174
175 return this.displayNameToUsername(newDisplayName)
176 }
177
178 displayNameToUsername (displayName: string) {
179 if (!displayName) return ''
180
181 return displayName
182 .toLowerCase()
183 .replace(/\s/g, '_')
184 .replace(/[^a-z0-9_.]/g, '')
185 }
186
187 /* ###### Admin methods ###### */
188
189 addUser (userCreate: UserCreate) {
190 return this.authHttp.post(UserService.BASE_USERS_URL, userCreate)
191 .pipe(catchError(err => this.restExtractor.handleError(err)))
192 }
193
194 updateUser (userId: number, userUpdate: UserUpdate) {
195 return this.authHttp.put(UserService.BASE_USERS_URL + userId, userUpdate)
196 .pipe(catchError(err => this.restExtractor.handleError(err)))
197 }
198
199 updateUsers (users: UserServerModel[], userUpdate: UserUpdate) {
200 return from(users)
201 .pipe(
202 concatMap(u => this.authHttp.put(UserService.BASE_USERS_URL + u.id, userUpdate)),
203 toArray(),
204 catchError(err => this.restExtractor.handleError(err))
205 )
206 }
207
208 getUserWithCache (userId: number) {
209 if (!this.userCache[userId]) {
210 this.userCache[userId] = this.getUser(userId).pipe(shareReplay())
211 }
212
213 return this.userCache[userId]
214 }
215
216 getUser (userId: number, withStats = false) {
217 const params = new HttpParams().append('withStats', withStats + '')
218 return this.authHttp.get<UserServerModel>(UserService.BASE_USERS_URL + userId, { params })
219 .pipe(catchError(err => this.restExtractor.handleError(err)))
220 }
221
222 getUsers (parameters: {
223 pagination: RestPagination
224 sort: SortMeta
225 search?: string
226 }): Observable<ResultList<UserServerModel>> {
227 const { pagination, sort, search } = parameters
228
229 let params = new HttpParams()
230 params = this.restService.addRestGetParams(params, pagination, sort)
231
232 if (search) {
233 const filters = this.restService.parseQueryStringFilter(search, {
234 blocked: {
235 prefix: 'banned:',
236 isBoolean: true
237 }
238 })
239
240 params = this.restService.addObjectParams(params, filters)
241 }
242
243 return this.authHttp.get<ResultList<UserServerModel>>(UserService.BASE_USERS_URL, { params })
244 .pipe(
245 map(res => this.restExtractor.convertResultListDateToHuman(res)),
246 map(res => this.restExtractor.applyToResultListData(res, this.formatUser.bind(this))),
247 catchError(err => this.restExtractor.handleError(err))
248 )
249 }
250
251 removeUser (usersArg: UserServerModel | UserServerModel[]) {
252 const users = Array.isArray(usersArg) ? usersArg : [ usersArg ]
253
254 return from(users)
255 .pipe(
256 concatMap(u => this.authHttp.delete(UserService.BASE_USERS_URL + u.id)),
257 toArray(),
258 catchError(err => this.restExtractor.handleError(err))
259 )
260 }
261
262 banUsers (usersArg: UserServerModel | UserServerModel[], reason?: string) {
263 const body = reason ? { reason } : {}
264 const users = Array.isArray(usersArg) ? usersArg : [ usersArg ]
265
266 return from(users)
267 .pipe(
268 concatMap(u => this.authHttp.post(UserService.BASE_USERS_URL + u.id + '/block', body)),
269 toArray(),
270 catchError(err => this.restExtractor.handleError(err))
271 )
272 }
273
274 unbanUsers (usersArg: UserServerModel | UserServerModel[]) {
275 const users = Array.isArray(usersArg) ? usersArg : [ usersArg ]
276
277 return from(users)
278 .pipe(
279 concatMap(u => this.authHttp.post(UserService.BASE_USERS_URL + u.id + '/unblock', {})),
280 toArray(),
281 catchError(err => this.restExtractor.handleError(err))
282 )
283 }
284
285 getAnonymousOrLoggedUser () {
286 if (!this.authService.isLoggedIn()) {
287 return of(this.getAnonymousUser())
288 }
289
290 return this.authService.userInformationLoaded
291 .pipe(
292 first(),
293 map(() => this.authService.getUser())
294 )
295 }
296
297 private formatUser (user: UserServerModel) {
298 let videoQuota
299 if (user.videoQuota === -1) {
300 videoQuota = '∞'
301 } else {
302 videoQuota = getBytes(user.videoQuota, 0)
303 }
304
305 const videoQuotaUsed = getBytes(user.videoQuotaUsed, 0)
306
307 let videoQuotaDaily: string
308 let videoQuotaUsedDaily: string
309 if (user.videoQuotaDaily === -1) {
310 videoQuotaDaily = '∞'
311 videoQuotaUsedDaily = getBytes(0, 0) + ''
312 } else {
313 videoQuotaDaily = getBytes(user.videoQuotaDaily, 0) + ''
314 videoQuotaUsedDaily = getBytes(user.videoQuotaUsedDaily || 0, 0) + ''
315 }
316
317 const roleLabels: { [ id in UserRole ]: string } = {
318 [UserRole.USER]: $localize`User`,
319 [UserRole.ADMINISTRATOR]: $localize`Administrator`,
320 [UserRole.MODERATOR]: $localize`Moderator`
321 }
322
323 return Object.assign(user, {
324 roleLabel: roleLabels[user.role],
325 videoQuota,
326 videoQuotaUsed,
327 rawVideoQuota: user.videoQuota,
328 rawVideoQuotaUsed: user.videoQuotaUsed,
329 videoQuotaDaily,
330 videoQuotaUsedDaily,
331 rawVideoQuotaDaily: user.videoQuotaDaily,
332 rawVideoQuotaUsedDaily: user.videoQuotaUsedDaily
333 })
334 }
335} 165}