aboutsummaryrefslogtreecommitdiffhomepage
path: root/client/src/app/shared
diff options
context:
space:
mode:
authorChocobozzz <me@florianbigard.com>2020-06-16 11:00:35 +0200
committerChocobozzz <me@florianbigard.com>2020-06-16 11:26:46 +0200
commit5c20a45518c3afc40c9494cad4a78def92e5e288 (patch)
treed4f6894b37394f3a40e6c58d34012bc55c05f55e /client/src/app/shared
parent64e0f8cf12c804a7a2fa582fd954f686cea9a45b (diff)
downloadPeerTube-5c20a45518c3afc40c9494cad4a78def92e5e288.tar.gz
PeerTube-5c20a45518c3afc40c9494cad4a78def92e5e288.tar.zst
PeerTube-5c20a45518c3afc40c9494cad4a78def92e5e288.zip
Fix anonymous nsfw policy
Diffstat (limited to 'client/src/app/shared')
-rw-r--r--client/src/app/shared/users/user.service.ts51
-rw-r--r--client/src/app/shared/video/abstract-video-list.html2
-rw-r--r--client/src/app/shared/video/abstract-video-list.ts69
-rw-r--r--client/src/app/shared/video/video.service.ts50
4 files changed, 102 insertions, 70 deletions
diff --git a/client/src/app/shared/users/user.service.ts b/client/src/app/shared/users/user.service.ts
index 7c1ae5799..de1c8ec94 100644
--- a/client/src/app/shared/users/user.service.ts
+++ b/client/src/app/shared/users/user.service.ts
@@ -1,19 +1,20 @@
1import { from, Observable } from 'rxjs' 1import { has } from 'lodash-es'
2import { catchError, concatMap, map, shareReplay, toArray } from 'rxjs/operators' 2import { BytesPipe } from 'ngx-pipes'
3import { SortMeta } from 'primeng/api'
4import { from, Observable, of } from 'rxjs'
5import { catchError, concatMap, first, map, shareReplay, toArray, throttleTime, filter } from 'rxjs/operators'
3import { HttpClient, HttpParams } from '@angular/common/http' 6import { HttpClient, HttpParams } from '@angular/common/http'
4import { Injectable } from '@angular/core' 7import { Injectable } from '@angular/core'
5import { ResultList, User as UserServerModel, UserCreate, UserRole, UserUpdate, UserUpdateMe, UserVideoQuota } from '../../../../../shared' 8import { AuthService } from '@app/core/auth'
6import { environment } from '../../../environments/environment'
7import { RestExtractor, RestPagination, RestService } from '../rest'
8import { Avatar } from '../../../../../shared/models/avatars/avatar.model'
9import { SortMeta } from 'primeng/api'
10import { BytesPipe } from 'ngx-pipes'
11import { I18n } from '@ngx-translate/i18n-polyfill' 9import { I18n } from '@ngx-translate/i18n-polyfill'
12import { UserRegister } from '@shared/models/users/user-register.model' 10import { UserRegister } from '@shared/models/users/user-register.model'
13import { User } from './user.model'
14import { NSFWPolicyType } from '@shared/models/videos/nsfw-policy.type' 11import { NSFWPolicyType } from '@shared/models/videos/nsfw-policy.type'
15import { has } from 'lodash-es' 12import { ResultList, User as UserServerModel, UserCreate, UserRole, UserUpdate, UserUpdateMe, UserVideoQuota } from '../../../../../shared'
13import { Avatar } from '../../../../../shared/models/avatars/avatar.model'
14import { environment } from '../../../environments/environment'
16import { LocalStorageService, SessionStorageService } from '../misc/storage.service' 15import { LocalStorageService, SessionStorageService } from '../misc/storage.service'
16import { RestExtractor, RestPagination, RestService } from '../rest'
17import { User } from './user.model'
17 18
18@Injectable() 19@Injectable()
19export class UserService { 20export class UserService {
@@ -25,6 +26,7 @@ export class UserService {
25 26
26 constructor ( 27 constructor (
27 private authHttp: HttpClient, 28 private authHttp: HttpClient,
29 private authService: AuthService,
28 private restExtractor: RestExtractor, 30 private restExtractor: RestExtractor,
29 private restService: RestService, 31 private restService: RestService,
30 private localStorageService: LocalStorageService, 32 private localStorageService: LocalStorageService,
@@ -94,6 +96,21 @@ export class UserService {
94 } 96 }
95 } 97 }
96 98
99 listenAnonymousUpdate () {
100 return this.localStorageService.watch([
101 User.KEYS.NSFW_POLICY,
102 User.KEYS.WEBTORRENT_ENABLED,
103 User.KEYS.AUTO_PLAY_VIDEO,
104 User.KEYS.AUTO_PLAY_VIDEO_PLAYLIST,
105 User.KEYS.THEME,
106 User.KEYS.VIDEO_LANGUAGES
107 ]).pipe(
108 throttleTime(200),
109 filter(() => this.authService.isLoggedIn() !== true),
110 map(() => this.getAnonymousUser())
111 )
112 }
113
97 deleteMe () { 114 deleteMe () {
98 const url = UserService.BASE_USERS_URL + 'me' 115 const url = UserService.BASE_USERS_URL + 'me'
99 116
@@ -241,7 +258,7 @@ export class UserService {
241 } 258 }
242 259
243 getAnonymousUser () { 260 getAnonymousUser () {
244 let videoLanguages 261 let videoLanguages: string[]
245 262
246 try { 263 try {
247 videoLanguages = JSON.parse(this.localStorageService.getItem(User.KEYS.VIDEO_LANGUAGES)) 264 videoLanguages = JSON.parse(this.localStorageService.getItem(User.KEYS.VIDEO_LANGUAGES))
@@ -313,6 +330,18 @@ export class UserService {
313 ) 330 )
314 } 331 }
315 332
333 getAnonymousOrLoggedUser () {
334 if (!this.authService.isLoggedIn()) {
335 return of(this.getAnonymousUser())
336 }
337
338 return this.authService.userInformationLoaded
339 .pipe(
340 first(),
341 map(() => this.authService.getUser())
342 )
343 }
344
316 private formatUser (user: UserServerModel) { 345 private formatUser (user: UserServerModel) {
317 let videoQuota 346 let videoQuota
318 if (user.videoQuota === -1) { 347 if (user.videoQuota === -1) {
diff --git a/client/src/app/shared/video/abstract-video-list.html b/client/src/app/shared/video/abstract-video-list.html
index 548370843..1e919ee72 100644
--- a/client/src/app/shared/video/abstract-video-list.html
+++ b/client/src/app/shared/video/abstract-video-list.html
@@ -38,7 +38,7 @@
38 <div class="video-wrapper"> 38 <div class="video-wrapper">
39 <my-video-miniature 39 <my-video-miniature
40 [fitWidth]="true" 40 [fitWidth]="true"
41 [video]="video" [user]="user" [ownerDisplayType]="ownerDisplayType" 41 [video]="video" [user]="userMiniature" [ownerDisplayType]="ownerDisplayType"
42 [displayVideoActions]="displayVideoActions" [displayOptions]="displayOptions" 42 [displayVideoActions]="displayVideoActions" [displayOptions]="displayOptions"
43 (videoBlocked)="removeVideoFromArray(video)" (videoRemoved)="removeVideoFromArray(video)" 43 (videoBlocked)="removeVideoFromArray(video)" (videoRemoved)="removeVideoFromArray(video)"
44 > 44 >
diff --git a/client/src/app/shared/video/abstract-video-list.ts b/client/src/app/shared/video/abstract-video-list.ts
index 76aa683fc..0bc339ff6 100644
--- a/client/src/app/shared/video/abstract-video-list.ts
+++ b/client/src/app/shared/video/abstract-video-list.ts
@@ -1,22 +1,23 @@
1import { debounceTime, first, tap, throttleTime } from 'rxjs/operators' 1import { fromEvent, Observable, of, Subject, Subscription } from 'rxjs'
2import { debounceTime, tap, throttleTime, switchMap } from 'rxjs/operators'
2import { OnDestroy, OnInit } from '@angular/core' 3import { OnDestroy, OnInit } from '@angular/core'
3import { ActivatedRoute, Router } from '@angular/router' 4import { ActivatedRoute, Router } from '@angular/router'
4import { fromEvent, Observable, of, Subject, Subscription } from 'rxjs'
5import { AuthService } from '../../core/auth'
6import { ComponentPaginationLight } from '../rest/component-pagination.model'
7import { VideoSortField } from './sort-field.type'
8import { Video } from './video.model'
9import { ScreenService } from '@app/shared/misc/screen.service'
10import { MiniatureDisplayOptions, OwnerDisplayType } from '@app/shared/video/video-miniature.component'
11import { Syndication } from '@app/shared/video/syndication.model'
12import { Notifier, ServerService } from '@app/core' 5import { Notifier, ServerService } from '@app/core'
13import { DisableForReuseHook } from '@app/core/routing/disable-for-reuse-hook' 6import { DisableForReuseHook } from '@app/core/routing/disable-for-reuse-hook'
7import { GlobalIconName } from '@app/shared/images/global-icon.component'
8import { ScreenService } from '@app/shared/misc/screen.service'
9import { Syndication } from '@app/shared/video/syndication.model'
10import { MiniatureDisplayOptions, OwnerDisplayType } from '@app/shared/video/video-miniature.component'
14import { I18n } from '@ngx-translate/i18n-polyfill' 11import { I18n } from '@ngx-translate/i18n-polyfill'
15import { isLastMonth, isLastWeek, isToday, isYesterday } from '@shared/core-utils/miscs/date' 12import { isLastMonth, isLastWeek, isToday, isYesterday } from '@shared/core-utils/miscs/date'
16import { ServerConfig } from '@shared/models' 13import { ServerConfig } from '@shared/models'
17import { GlobalIconName } from '@app/shared/images/global-icon.component' 14import { NSFWPolicyType } from '@shared/models/videos/nsfw-policy.type'
18import { UserService, User } from '../users' 15import { AuthService } from '../../core/auth'
19import { LocalStorageService } from '../misc/storage.service' 16import { LocalStorageService } from '../misc/storage.service'
17import { ComponentPaginationLight } from '../rest/component-pagination.model'
18import { User, UserService } from '../users'
19import { VideoSortField } from './sort-field.type'
20import { Video } from './video.model'
20 21
21enum GroupDate { 22enum GroupDate {
22 UNKNOWN = 0, 23 UNKNOWN = 0,
@@ -34,14 +35,15 @@ export abstract class AbstractVideoList implements OnInit, OnDestroy, DisableFor
34 } 35 }
35 sort: VideoSortField = '-publishedAt' 36 sort: VideoSortField = '-publishedAt'
36 37
37 categoryOneOf?: number 38 categoryOneOf?: number[]
38 languageOneOf?: string[] 39 languageOneOf?: string[]
40 nsfwPolicy?: NSFWPolicyType
39 defaultSort: VideoSortField = '-publishedAt' 41 defaultSort: VideoSortField = '-publishedAt'
40 42
41 syndicationItems: Syndication[] = [] 43 syndicationItems: Syndication[] = []
42 44
43 loadOnInit = true 45 loadOnInit = true
44 useUserVideoLanguagePreferences = false 46 useUserVideoPreferences = false
45 ownerDisplayType: OwnerDisplayType = 'account' 47 ownerDisplayType: OwnerDisplayType = 'account'
46 displayModerationBlock = false 48 displayModerationBlock = false
47 titleTooltip: string 49 titleTooltip: string
@@ -71,6 +73,8 @@ export abstract class AbstractVideoList implements OnInit, OnDestroy, DisableFor
71 73
72 onDataSubject = new Subject<any[]>() 74 onDataSubject = new Subject<any[]>()
73 75
76 userMiniature: User
77
74 protected serverConfig: ServerConfig 78 protected serverConfig: ServerConfig
75 79
76 protected abstract notifier: Notifier 80 protected abstract notifier: Notifier
@@ -96,10 +100,6 @@ export abstract class AbstractVideoList implements OnInit, OnDestroy, DisableFor
96 100
97 abstract generateSyndicationList (): void 101 abstract generateSyndicationList (): void
98 102
99 get user () {
100 return this.authService.getUser()
101 }
102
103 ngOnInit () { 103 ngOnInit () {
104 this.serverConfig = this.serverService.getTmpConfig() 104 this.serverConfig = this.serverService.getTmpConfig()
105 this.serverService.getConfig() 105 this.serverService.getConfig()
@@ -124,21 +124,17 @@ export abstract class AbstractVideoList implements OnInit, OnDestroy, DisableFor
124 124
125 this.calcPageSizes() 125 this.calcPageSizes()
126 126
127 const loadUserObservable = this.loadUserVideoLanguagesIfNeeded() 127 const loadUserObservable = this.loadUserAndSettings()
128 128
129 if (this.loadOnInit === true) { 129 if (this.loadOnInit === true) {
130 loadUserObservable.subscribe(() => this.loadMoreVideos()) 130 loadUserObservable.subscribe(() => this.loadMoreVideos())
131 } 131 }
132 132
133 this.storageService.watch([ 133 this.userService.listenAnonymousUpdate()
134 User.KEYS.NSFW_POLICY, 134 .pipe(switchMap(() => this.loadUserAndSettings()))
135 User.KEYS.VIDEO_LANGUAGES 135 .subscribe(() => {
136 ]).pipe(throttleTime(200)).subscribe(
137 () => {
138 this.loadUserVideoLanguagesIfNeeded()
139 if (this.hasDoneFirstQuery) this.reloadVideos() 136 if (this.hasDoneFirstQuery) this.reloadVideos()
140 } 137 })
141 )
142 138
143 // Display avatar in mobile view 139 // Display avatar in mobile view
144 if (this.screenService.isInMobileView()) { 140 if (this.screenService.isInMobileView()) {
@@ -298,20 +294,15 @@ export abstract class AbstractVideoList implements OnInit, OnDestroy, DisableFor
298 this.router.navigate([ path ], { queryParams, replaceUrl: true, queryParamsHandling: 'merge' }) 294 this.router.navigate([ path ], { queryParams, replaceUrl: true, queryParamsHandling: 'merge' })
299 } 295 }
300 296
301 private loadUserVideoLanguagesIfNeeded () { 297 private loadUserAndSettings () {
302 if (!this.useUserVideoLanguagePreferences) { 298 return this.userService.getAnonymousOrLoggedUser()
303 return of(true) 299 .pipe(tap(user => {
304 } 300 this.userMiniature = user
305 301
306 if (!this.authService.isLoggedIn()) { 302 if (!this.useUserVideoPreferences) return
307 this.languageOneOf = this.userService.getAnonymousUser().videoLanguages
308 return of(true)
309 }
310 303
311 return this.authService.userInformationLoaded 304 this.languageOneOf = user.videoLanguages
312 .pipe( 305 this.nsfwPolicy = user.nsfwPolicy
313 first(), 306 }))
314 tap(() => this.languageOneOf = this.user.videoLanguages)
315 )
316 } 307 }
317} 308}
diff --git a/client/src/app/shared/video/video.service.ts b/client/src/app/shared/video/video.service.ts
index 3aaf14990..d66a1f809 100644
--- a/client/src/app/shared/video/video.service.ts
+++ b/client/src/app/shared/video/video.service.ts
@@ -39,8 +39,9 @@ export interface VideosProvider {
39 videoPagination: ComponentPaginationLight, 39 videoPagination: ComponentPaginationLight,
40 sort: VideoSortField, 40 sort: VideoSortField,
41 filter?: VideoFilter, 41 filter?: VideoFilter,
42 categoryOneOf?: number, 42 categoryOneOf?: number[],
43 languageOneOf?: string[] 43 languageOneOf?: string[]
44 nsfwPolicy: NSFWPolicyType
44 }): Observable<ResultList<Video>> 45 }): Observable<ResultList<Video>>
45} 46}
46 47
@@ -161,13 +162,18 @@ export class VideoService implements VideosProvider {
161 getVideoChannelVideos ( 162 getVideoChannelVideos (
162 videoChannel: VideoChannel, 163 videoChannel: VideoChannel,
163 videoPagination: ComponentPaginationLight, 164 videoPagination: ComponentPaginationLight,
164 sort: VideoSortField 165 sort: VideoSortField,
166 nsfwPolicy?: NSFWPolicyType
165 ): Observable<ResultList<Video>> { 167 ): Observable<ResultList<Video>> {
166 const pagination = this.restService.componentPaginationToRestPagination(videoPagination) 168 const pagination = this.restService.componentPaginationToRestPagination(videoPagination)
167 169
168 let params = new HttpParams() 170 let params = new HttpParams()
169 params = this.restService.addRestGetParams(params, pagination, sort) 171 params = this.restService.addRestGetParams(params, pagination, sort)
170 172
173 if (nsfwPolicy) {
174 params = params.set('nsfw', this.nsfwPolicyToParam(nsfwPolicy))
175 }
176
171 return this.authHttp 177 return this.authHttp
172 .get<ResultList<Video>>(VideoChannelService.BASE_VIDEO_CHANNEL_URL + videoChannel.nameWithHost + '/videos', { params }) 178 .get<ResultList<Video>>(VideoChannelService.BASE_VIDEO_CHANNEL_URL + videoChannel.nameWithHost + '/videos', { params })
173 .pipe( 179 .pipe(
@@ -201,12 +207,12 @@ export class VideoService implements VideosProvider {
201 videoPagination: ComponentPaginationLight, 207 videoPagination: ComponentPaginationLight,
202 sort: VideoSortField, 208 sort: VideoSortField,
203 filter?: VideoFilter, 209 filter?: VideoFilter,
204 categoryOneOf?: number, 210 categoryOneOf?: number[],
205 languageOneOf?: string[], 211 languageOneOf?: string[],
206 skipCount?: boolean, 212 skipCount?: boolean,
207 nsfw?: boolean 213 nsfwPolicy?: NSFWPolicyType
208 }): Observable<ResultList<Video>> { 214 }): Observable<ResultList<Video>> {
209 const { videoPagination, sort, filter, categoryOneOf, languageOneOf, skipCount, nsfw } = parameters 215 const { videoPagination, sort, filter, categoryOneOf, languageOneOf, skipCount, nsfwPolicy } = parameters
210 216
211 const pagination = this.restService.componentPaginationToRestPagination(videoPagination) 217 const pagination = this.restService.componentPaginationToRestPagination(videoPagination)
212 218
@@ -214,16 +220,10 @@ export class VideoService implements VideosProvider {
214 params = this.restService.addRestGetParams(params, pagination, sort) 220 params = this.restService.addRestGetParams(params, pagination, sort)
215 221
216 if (filter) params = params.set('filter', filter) 222 if (filter) params = params.set('filter', filter)
217 if (categoryOneOf) params = params.set('categoryOneOf', categoryOneOf + '')
218 if (skipCount) params = params.set('skipCount', skipCount + '') 223 if (skipCount) params = params.set('skipCount', skipCount + '')
219 224
220 if (nsfw) { 225 if (nsfwPolicy) {
221 params = params.set('nsfw', nsfw + '') 226 params = params.set('nsfw', this.nsfwPolicyToParam(nsfwPolicy))
222 } else {
223 const nsfwPolicy = this.authService.isLoggedIn()
224 ? this.authService.getUser().nsfwPolicy
225 : this.userService.getAnonymousUser().nsfwPolicy
226 if (this.nsfwPolicyToFilter(nsfwPolicy)) params.set('nsfw', 'false')
227 } 227 }
228 228
229 if (languageOneOf) { 229 if (languageOneOf) {
@@ -232,6 +232,12 @@ export class VideoService implements VideosProvider {
232 } 232 }
233 } 233 }
234 234
235 if (categoryOneOf) {
236 for (const c of categoryOneOf) {
237 params = params.append('categoryOneOf[]', c + '')
238 }
239 }
240
235 return this.authHttp 241 return this.authHttp
236 .get<ResultList<Video>>(VideoService.BASE_VIDEO_URL, { params }) 242 .get<ResultList<Video>>(VideoService.BASE_VIDEO_URL, { params })
237 .pipe( 243 .pipe(
@@ -268,12 +274,16 @@ export class VideoService implements VideosProvider {
268 return feeds 274 return feeds
269 } 275 }
270 276
271 getVideoFeedUrls (sort: VideoSortField, filter?: VideoFilter, categoryOneOf?: number) { 277 getVideoFeedUrls (sort: VideoSortField, filter?: VideoFilter, categoryOneOf?: number[]) {
272 let params = this.restService.addRestGetParams(new HttpParams(), undefined, sort) 278 let params = this.restService.addRestGetParams(new HttpParams(), undefined, sort)
273 279
274 if (filter) params = params.set('filter', filter) 280 if (filter) params = params.set('filter', filter)
275 281
276 if (categoryOneOf) params = params.set('categoryOneOf', categoryOneOf + '') 282 if (categoryOneOf) {
283 for (const c of categoryOneOf) {
284 params = params.append('categoryOneOf[]', c + '')
285 }
286 }
277 287
278 return this.buildBaseFeedUrls(params) 288 return this.buildBaseFeedUrls(params)
279 } 289 }
@@ -377,6 +387,12 @@ export class VideoService implements VideosProvider {
377 return base.filter(o => !!privacies.find(p => p.id === o.id)) 387 return base.filter(o => !!privacies.find(p => p.id === o.id))
378 } 388 }
379 389
390 nsfwPolicyToParam (nsfwPolicy: NSFWPolicyType) {
391 return nsfwPolicy === 'do_not_list'
392 ? 'false'
393 : 'both'
394 }
395
380 private setVideoRate (id: number, rateType: UserVideoRateType) { 396 private setVideoRate (id: number, rateType: UserVideoRateType) {
381 const url = VideoService.BASE_VIDEO_URL + id + '/rate' 397 const url = VideoService.BASE_VIDEO_URL + id + '/rate'
382 const body: UserVideoRateUpdate = { 398 const body: UserVideoRateUpdate = {
@@ -390,8 +406,4 @@ export class VideoService implements VideosProvider {
390 catchError(err => this.restExtractor.handleError(err)) 406 catchError(err => this.restExtractor.handleError(err))
391 ) 407 )
392 } 408 }
393
394 private nsfwPolicyToFilter (policy: NSFWPolicyType) {
395 return policy === 'do_not_list'
396 }
397} 409}