From 5a90a7d0de9ae8410ef8c23a6994fdba7657666d Mon Sep 17 00:00:00 2001 From: crupest Date: Thu, 30 Jul 2020 23:57:13 +0800 Subject: ... --- Timeline/ClientApp/src/app/data/common.ts | 6 ++++ Timeline/ClientApp/src/app/data/timeline.ts | 51 ++++++++++++++++++++++++++--- 2 files changed, 52 insertions(+), 5 deletions(-) (limited to 'Timeline/ClientApp/src/app/data') diff --git a/Timeline/ClientApp/src/app/data/common.ts b/Timeline/ClientApp/src/app/data/common.ts index e9b56970..9f985ce6 100644 --- a/Timeline/ClientApp/src/app/data/common.ts +++ b/Timeline/ClientApp/src/app/data/common.ts @@ -10,3 +10,9 @@ export interface BlobWithUrl { blob: Blob; url: string; } + +export class ForbiddenError extends Error { + constructor(message?: string) { + super(message); + } +} diff --git a/Timeline/ClientApp/src/app/data/timeline.ts b/Timeline/ClientApp/src/app/data/timeline.ts index 50d45aa5..88a13381 100644 --- a/Timeline/ClientApp/src/app/data/timeline.ts +++ b/Timeline/ClientApp/src/app/data/timeline.ts @@ -6,7 +6,7 @@ import { pull } from 'lodash'; import { convertError } from '../utilities/rxjs'; -import { BlobWithUrl, dataStorage } from './common'; +import { BlobWithUrl, dataStorage, ForbiddenError } from './common'; import { SubscriptionHub, ISubscriptionHub } from './SubscriptionHub'; import { UserAuthInfo, checkLogin, userService } from './user'; @@ -69,6 +69,7 @@ export interface PostKey { export interface TimelinePostListState { state: | 'loading' // Loading posts from cache. `posts` is empty array. + | 'forbid' // The list is forbidden to see. | 'syncing' // Cache loaded and syncing now. | 'synced' // Sync succeeded. | 'offline'; // Sync failed and use cache. @@ -177,6 +178,12 @@ export class TimelineService { timelineName: string ): Promise { const timeline = await this.getTimeline(timelineName).toPromise(); + if (!this.hasReadPermission(userService.currentUser, timeline)) { + throw new ForbiddenError( + 'You are not allowed to get posts of this timeline.' + ); + } + const postListInfo = await dataStorage.getItem( this.getPostListInfoKey(timeline.uniqueId) ); @@ -197,6 +204,18 @@ export class TimelineService { async syncPostList(timelineName: string): Promise { const timeline = await this.getTimeline(timelineName).toPromise(); + if (!this.hasReadPermission(userService.currentUser, timeline)) { + this._postListSubscriptionHub.update(timelineName, () => + Promise.resolve({ + state: 'forbid', + posts: [], + }) + ); + throw new ForbiddenError( + 'You are not allowed to get posts of this timeline.' + ); + } + const postListInfoKey = this.getPostListInfoKey(timeline.uniqueId); const postListInfo = await dataStorage.getItem( postListInfoKey @@ -325,10 +344,7 @@ export class TimelineService { } ); - get postListSubscriptionHub(): ISubscriptionHub< - string, - TimelinePostListState - > { + get postListHub(): ISubscriptionHub { return this._postListSubscriptionHub; } @@ -513,6 +529,31 @@ export function validateTimelineName(name: string): boolean { return timelineNameReg.test(name); } +export function usePostList( + timelineName: string | null | undefined +): TimelinePostListState | undefined { + const [state, setState] = React.useState( + undefined + ); + React.useEffect(() => { + if (timelineName == null) { + setState(undefined); + return; + } + + const subscription = timelineService.postListHub.subscribe( + timelineName, + (data) => { + setState(data); + } + ); + return () => { + subscription.unsubscribe(); + }; + }, [timelineName]); + return state; +} + export function usePostDataUrl( enable: boolean, timelineName: string, -- cgit v1.2.3