From 47587812b809fee2a95c76266d9d0e42fc4ac1ca Mon Sep 17 00:00:00 2001 From: crupest Date: Tue, 15 Jun 2021 14:14:28 +0800 Subject: ... --- FrontEnd/src/app/http/bookmark.ts | 49 -------- FrontEnd/src/app/http/common.ts | 214 --------------------------------- FrontEnd/src/app/http/highlight.ts | 49 -------- FrontEnd/src/app/http/search.ts | 36 ------ FrontEnd/src/app/http/timeline.ts | 234 ------------------------------------- FrontEnd/src/app/http/token.ts | 71 ----------- FrontEnd/src/app/http/user.ts | 161 ------------------------- 7 files changed, 814 deletions(-) delete mode 100644 FrontEnd/src/app/http/bookmark.ts delete mode 100644 FrontEnd/src/app/http/common.ts delete mode 100644 FrontEnd/src/app/http/highlight.ts delete mode 100644 FrontEnd/src/app/http/search.ts delete mode 100644 FrontEnd/src/app/http/timeline.ts delete mode 100644 FrontEnd/src/app/http/token.ts delete mode 100644 FrontEnd/src/app/http/user.ts (limited to 'FrontEnd/src/app/http') diff --git a/FrontEnd/src/app/http/bookmark.ts b/FrontEnd/src/app/http/bookmark.ts deleted file mode 100644 index 3e5be229..00000000 --- a/FrontEnd/src/app/http/bookmark.ts +++ /dev/null @@ -1,49 +0,0 @@ -import { axios, apiBaseUrl, extractResponseData } from "./common"; - -import { HttpTimelineInfo } from "./timeline"; - -export interface HttpHighlightMoveRequest { - timeline: string; - newPosition: number; -} - -export interface IHttpBookmarkClient { - list(): Promise; - put(timeline: string): Promise; - delete(timeline: string): Promise; - move(req: HttpHighlightMoveRequest): Promise; -} - -export class HttpHighlightClient implements IHttpBookmarkClient { - list(): Promise { - return axios - .get(`${apiBaseUrl}/bookmarks`) - .then(extractResponseData); - } - - put(timeline: string): Promise { - return axios.put(`${apiBaseUrl}/bookmarks/${timeline}`).then(); - } - - delete(timeline: string): Promise { - return axios.delete(`${apiBaseUrl}/bookmarks/${timeline}`).then(); - } - - move(req: HttpHighlightMoveRequest): Promise { - return axios.post(`${apiBaseUrl}/bookmarkop/move`, req).then(); - } -} - -let client: IHttpBookmarkClient = new HttpHighlightClient(); - -export function getHttpBookmarkClient(): IHttpBookmarkClient { - return client; -} - -export function setHttpBookmarkClient( - newClient: IHttpBookmarkClient -): IHttpBookmarkClient { - const old = client; - client = newClient; - return old; -} diff --git a/FrontEnd/src/app/http/common.ts b/FrontEnd/src/app/http/common.ts deleted file mode 100644 index e1672985..00000000 --- a/FrontEnd/src/app/http/common.ts +++ /dev/null @@ -1,214 +0,0 @@ -import rawAxios, { AxiosError, AxiosResponse } from "axios"; -import { Base64 } from "js-base64"; -import { BehaviorSubject, Observable } from "rxjs"; - -export const apiBaseUrl = "/api"; - -export const axios = rawAxios.create(); - -function convertToNetworkError(error: AxiosError): never { - if (error.isAxiosError && error.response == null) { - throw new HttpNetworkError(error); - } else { - throw error; - } -} - -function convertToForbiddenError(error: AxiosError): never { - if ( - error.isAxiosError && - error.response != null && - (error.response.status == 401 || error.response.status == 403) - ) { - throw new HttpForbiddenError(error); - } else { - throw error; - } -} - -function convertToNotFoundError(error: AxiosError): never { - if ( - error.isAxiosError && - error.response != null && - error.response.status == 404 - ) { - throw new HttpNotFoundError(error); - } else { - throw error; - } -} - -rawAxios.interceptors.response.use(undefined, convertToNetworkError); -rawAxios.interceptors.response.use(undefined, convertToForbiddenError); -rawAxios.interceptors.response.use(undefined, convertToNotFoundError); -axios.interceptors.response.use(undefined, convertToNetworkError); -axios.interceptors.response.use(undefined, convertToForbiddenError); -axios.interceptors.response.use(undefined, convertToNotFoundError); - -const tokenSubject = new BehaviorSubject(null); - -export function getHttpToken(): string | null { - return tokenSubject.value; -} - -export function setHttpToken(token: string | null): void { - tokenSubject.next(token); - - if (token == null) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access - delete axios.defaults.headers.common["Authorization"]; - } else { - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access - axios.defaults.headers.common["Authorization"] = `Bearer ${token}`; - } -} - -export const token$: Observable = tokenSubject.asObservable(); - -export function base64(blob: Blob | string): Promise { - if (typeof blob === "string") { - return Promise.resolve(Base64.encode(blob)); - } - - return new Promise((resolve) => { - const reader = new FileReader(); - reader.onload = function () { - resolve((reader.result as string).replace(/^data:.*;base64,/, "")); - }; - reader.readAsDataURL(blob); - }); -} - -export function extractStatusCode(error: AxiosError): number | null { - if (error.isAxiosError) { - const code = error?.response?.status; - if (typeof code === "number") { - return code; - } - } - return null; -} - -export interface CommonErrorResponse { - code: number; - message: string; -} - -export function extractErrorCode( - error: AxiosError -): number | null { - if (error.isAxiosError) { - const code = error.response?.data?.code; - if (typeof code === "number") { - return code; - } - } - return null; -} - -export class HttpNetworkError extends Error { - constructor(public innerError?: AxiosError) { - super(); - } -} - -export class HttpForbiddenError extends Error { - constructor(public innerError?: AxiosError) { - super(); - } -} - -export class HttpNotFoundError extends Error { - constructor(public innerError?: AxiosError) { - super(); - } -} - -export class NotModified {} - -export interface BlobWithEtag { - data: Blob; - etag: string; -} - -export function extractResponseData(res: AxiosResponse): T { - return res.data; -} - -export function catchIfStatusCodeIs< - TResult, - TErrorHandlerResult extends TResult | PromiseLike | null | undefined ->( - statusCode: number, - errorHandler: (error: AxiosError) => TErrorHandlerResult -): (error: AxiosError) => TErrorHandlerResult { - return (error: AxiosError) => { - if (extractStatusCode(error) == statusCode) { - return errorHandler(error); - } else { - throw error; - } - }; -} - -export function convertToIfStatusCodeIs( - statusCode: number, - newErrorType: { - new (innerError: AxiosError): NewError; - } -): (error: AxiosError) => never { - return catchIfStatusCodeIs(statusCode, (error) => { - throw new newErrorType(error); - }); -} - -export function catchIfErrorCodeIs< - TResult, - TErrorHandlerResult extends TResult | PromiseLike | null | undefined ->( - errorCode: number, - errorHandler: (error: AxiosError) => TErrorHandlerResult -): (error: AxiosError) => TErrorHandlerResult { - return (error: AxiosError) => { - if (extractErrorCode(error) == errorCode) { - return errorHandler(error); - } else { - throw error; - } - }; -} -export function convertToIfErrorCodeIs( - errorCode: number, - newErrorType: { - new (innerError: AxiosError): NewError; - } -): (error: AxiosError) => never { - return catchIfErrorCodeIs(errorCode, (error) => { - throw new newErrorType(error); - }); -} - -export function convertToNotModified( - error: AxiosError -): NotModified { - if ( - error.isAxiosError && - error.response != null && - error.response.status == 304 - ) { - return new NotModified(); - } else { - throw error; - } -} - -export function convertToBlobWithEtag(res: AxiosResponse): BlobWithEtag { - return { - data: res.data, - etag: (res.headers as Record<"etag", string>)["etag"], - }; -} - -export function extractEtag(res: AxiosResponse): string { - return (res.headers as Record<"etag", string>)["etag"]; -} diff --git a/FrontEnd/src/app/http/highlight.ts b/FrontEnd/src/app/http/highlight.ts deleted file mode 100644 index fddf0729..00000000 --- a/FrontEnd/src/app/http/highlight.ts +++ /dev/null @@ -1,49 +0,0 @@ -import { axios, apiBaseUrl, extractResponseData } from "./common"; - -import { HttpTimelineInfo } from "./timeline"; - -export interface HttpHighlightMoveRequest { - timeline: string; - newPosition: number; -} - -export interface IHttpHighlightClient { - list(): Promise; - put(timeline: string): Promise; - delete(timeline: string): Promise; - move(req: HttpHighlightMoveRequest): Promise; -} - -export class HttpHighlightClient implements IHttpHighlightClient { - list(): Promise { - return axios - .get(`${apiBaseUrl}/highlights`) - .then(extractResponseData); - } - - put(timeline: string): Promise { - return axios.put(`${apiBaseUrl}/highlights/${timeline}`).then(); - } - - delete(timeline: string): Promise { - return axios.delete(`${apiBaseUrl}/highlights/${timeline}`).then(); - } - - move(req: HttpHighlightMoveRequest): Promise { - return axios.post(`${apiBaseUrl}/highlightop/move`, req).then(); - } -} - -let client: IHttpHighlightClient = new HttpHighlightClient(); - -export function getHttpHighlightClient(): IHttpHighlightClient { - return client; -} - -export function setHttpHighlightClient( - newClient: IHttpHighlightClient -): IHttpHighlightClient { - const old = client; - client = newClient; - return old; -} diff --git a/FrontEnd/src/app/http/search.ts b/FrontEnd/src/app/http/search.ts deleted file mode 100644 index 8ca48fe9..00000000 --- a/FrontEnd/src/app/http/search.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { apiBaseUrl, axios, extractResponseData } from "./common"; -import { HttpTimelineInfo } from "./timeline"; -import { HttpUser } from "./user"; - -export interface IHttpSearchClient { - searchTimelines(query: string): Promise; - searchUsers(query: string): Promise; -} - -export class HttpSearchClient implements IHttpSearchClient { - searchTimelines(query: string): Promise { - return axios - .get(`${apiBaseUrl}/search/timelines?q=${query}`) - .then(extractResponseData); - } - - searchUsers(query: string): Promise { - return axios - .get(`${apiBaseUrl}/search/users?q=${query}`) - .then(extractResponseData); - } -} - -let client: IHttpSearchClient = new HttpSearchClient(); - -export function getHttpSearchClient(): IHttpSearchClient { - return client; -} - -export function setHttpSearchClient( - newClient: IHttpSearchClient -): IHttpSearchClient { - const old = client; - client = newClient; - return old; -} diff --git a/FrontEnd/src/app/http/timeline.ts b/FrontEnd/src/app/http/timeline.ts deleted file mode 100644 index 9697c1a0..00000000 --- a/FrontEnd/src/app/http/timeline.ts +++ /dev/null @@ -1,234 +0,0 @@ -import { AxiosError } from "axios"; - -import { applyQueryParameters } from "../utilities/url"; - -import { - axios, - apiBaseUrl, - extractResponseData, - convertToIfErrorCodeIs, - getHttpToken, -} from "./common"; -import { HttpUser } from "./user"; - -export const kTimelineVisibilities = ["Public", "Register", "Private"] as const; - -export type TimelineVisibility = typeof kTimelineVisibilities[number]; - -export interface HttpTimelineInfo { - uniqueId: string; - title: string; - name: string; - description: string; - owner: HttpUser; - visibility: TimelineVisibility; - color: string; - lastModified: string; - members: HttpUser[]; - isHighlight: boolean; - isBookmark: boolean; - manageable: boolean; - postable: boolean; -} - -export interface HttpTimelineListQuery { - visibility?: TimelineVisibility; - relate?: string; - relateType?: "own" | "join"; -} - -export interface HttpTimelinePostRequest { - name: string; -} - -export interface HttpTimelinePostDataDigest { - kind: string; - eTag: string; - lastUpdated: string; -} - -export interface HttpTimelinePostInfo { - id: number; - time: string; - author: HttpUser; - dataList: HttpTimelinePostDataDigest[]; - color: string; - lastUpdated: string; - timelineName: string; - editable: boolean; -} - -export interface HttpTimelinePostPostRequestData { - contentType: string; - data: string; -} - -export interface HttpTimelinePostPostRequest { - time?: string; - color?: string; - dataList: HttpTimelinePostPostRequestData[]; -} - -export interface HttpTimelinePatchRequest { - name?: string; - title?: string; - color?: string; - visibility?: TimelineVisibility; - description?: string; -} - -export interface HttpTimelinePostPatchRequest { - time?: string; - color?: string; -} - -export class HttpTimelineNameConflictError extends Error { - constructor(public innerError?: AxiosError) { - super(); - } -} - -export interface IHttpTimelineClient { - listTimeline(query: HttpTimelineListQuery): Promise; - getTimeline(timelineName: string): Promise; - postTimeline(req: HttpTimelinePostRequest): Promise; - patchTimeline( - timelineName: string, - req: HttpTimelinePatchRequest - ): Promise; - deleteTimeline(timelineName: string): Promise; - memberPut(timelineName: string, username: string): Promise; - memberDelete(timelineName: string, username: string): Promise; - listPost(timelineName: string): Promise; - generatePostDataUrl(timelineName: string, postId: number): string; - getPostDataAsString(timelineName: string, postId: number): Promise; - postPost( - timelineName: string, - req: HttpTimelinePostPostRequest - ): Promise; - patchPost( - timelineName: string, - postId: number, - req: HttpTimelinePostPatchRequest - ): Promise; - deletePost(timelineName: string, postId: number): Promise; -} - -export class HttpTimelineClient implements IHttpTimelineClient { - listTimeline(query: HttpTimelineListQuery): Promise { - return axios - .get( - applyQueryParameters(`${apiBaseUrl}/timelines`, query) - ) - .then(extractResponseData); - } - - getTimeline(timelineName: string): Promise { - return axios - .get(`${apiBaseUrl}/timelines/${timelineName}`) - .then(extractResponseData); - } - - postTimeline(req: HttpTimelinePostRequest): Promise { - return axios - .post(`${apiBaseUrl}/timelines`, req) - .then(extractResponseData) - .catch(convertToIfErrorCodeIs(11040101, HttpTimelineNameConflictError)); - } - - patchTimeline( - timelineName: string, - req: HttpTimelinePatchRequest - ): Promise { - return axios - .patch(`${apiBaseUrl}/timelines/${timelineName}`, req) - .then(extractResponseData); - } - - deleteTimeline(timelineName: string): Promise { - return axios.delete(`${apiBaseUrl}/timelines/${timelineName}`).then(); - } - - memberPut(timelineName: string, username: string): Promise { - return axios - .put(`${apiBaseUrl}/timelines/${timelineName}/members/${username}`) - .then(); - } - - memberDelete(timelineName: string, username: string): Promise { - return axios - .delete(`${apiBaseUrl}/timelines/${timelineName}/members/${username}`) - .then(); - } - - listPost(timelineName: string): Promise { - return axios - .get( - `${apiBaseUrl}/timelines/${timelineName}/posts` - ) - .then(extractResponseData); - } - - generatePostDataUrl(timelineName: string, postId: number): string { - return applyQueryParameters( - `${apiBaseUrl}/timelines/${timelineName}/posts/${postId}/data`, - { token: getHttpToken() } - ); - } - - getPostDataAsString(timelineName: string, postId: number): Promise { - return axios - .get( - `${apiBaseUrl}/timelines/${timelineName}/posts/${postId}/data`, - { - responseType: "text", - } - ) - .then(extractResponseData); - } - - postPost( - timelineName: string, - req: HttpTimelinePostPostRequest - ): Promise { - return axios - .post( - `${apiBaseUrl}/timelines/${timelineName}/posts`, - req - ) - .then(extractResponseData); - } - - patchPost( - timelineName: string, - postId: number, - req: HttpTimelinePostPatchRequest - ): Promise { - return axios - .patch( - `${apiBaseUrl}/timelines/${timelineName}/posts/${postId}`, - req - ) - .then(extractResponseData); - } - - deletePost(timelineName: string, postId: number): Promise { - return axios - .delete(`${apiBaseUrl}/timelines/${timelineName}/posts/${postId}`) - .then(); - } -} - -let client: IHttpTimelineClient = new HttpTimelineClient(); - -export function getHttpTimelineClient(): IHttpTimelineClient { - return client; -} - -export function setHttpTimelineClient( - newClient: IHttpTimelineClient -): IHttpTimelineClient { - const old = client; - client = newClient; - return old; -} diff --git a/FrontEnd/src/app/http/token.ts b/FrontEnd/src/app/http/token.ts deleted file mode 100644 index f8b09d63..00000000 --- a/FrontEnd/src/app/http/token.ts +++ /dev/null @@ -1,71 +0,0 @@ -// Don't use axios in common because it will contains -// authorization header, which shouldn't be used in token apis. -import axios, { AxiosError } from "axios"; - -import { - apiBaseUrl, - convertToIfErrorCodeIs, - extractResponseData, -} from "./common"; -import { HttpUser } from "./user"; - -export interface HttpCreateTokenRequest { - username: string; - password: string; - expire: number; -} - -export interface HttpCreateTokenResponse { - token: string; - user: HttpUser; -} - -export interface HttpVerifyTokenRequest { - token: string; -} - -export interface HttpVerifyTokenResponse { - user: HttpUser; -} - -export class HttpCreateTokenBadCredentialError extends Error { - constructor(public innerError?: AxiosError) { - super(); - } -} - -export interface IHttpTokenClient { - create(req: HttpCreateTokenRequest): Promise; - verify(req: HttpVerifyTokenRequest): Promise; -} - -export class HttpTokenClient implements IHttpTokenClient { - create(req: HttpCreateTokenRequest): Promise { - return axios - .post(`${apiBaseUrl}/token/create`, req) - .then(extractResponseData) - .catch( - convertToIfErrorCodeIs(11010101, HttpCreateTokenBadCredentialError) - ); - } - - verify(req: HttpVerifyTokenRequest): Promise { - return axios - .post(`${apiBaseUrl}/token/verify`, req) - .then(extractResponseData); - } -} - -let client: IHttpTokenClient = new HttpTokenClient(); - -export function getHttpTokenClient(): IHttpTokenClient { - return client; -} - -export function setHttpTokenClient( - newClient: IHttpTokenClient -): IHttpTokenClient { - const old = client; - client = newClient; - return old; -} diff --git a/FrontEnd/src/app/http/user.ts b/FrontEnd/src/app/http/user.ts deleted file mode 100644 index dcf24cba..00000000 --- a/FrontEnd/src/app/http/user.ts +++ /dev/null @@ -1,161 +0,0 @@ -import { AxiosError } from "axios"; - -import { - axios, - apiBaseUrl, - extractResponseData, - convertToIfStatusCodeIs, - convertToIfErrorCodeIs, - extractEtag, -} from "./common"; - -export const kUserManagement = "UserManagement"; -export const kAllTimelineManagement = "AllTimelineManagement"; -export const kHighlightTimelineManagement = "HighlightTimelineManagement"; - -export const kUserPermissionList = [ - kUserManagement, - kAllTimelineManagement, - kHighlightTimelineManagement, -] as const; - -export type UserPermission = typeof kUserPermissionList[number]; - -export interface HttpUser { - uniqueId: string; - username: string; - permissions: UserPermission[]; - nickname: string; -} - -export interface HttpUserPatchRequest { - username?: string; - password?: string; - nickname?: string; -} - -export interface HttpChangePasswordRequest { - oldPassword: string; - newPassword: string; -} - -export interface HttpCreateUserRequest { - username: string; - password: string; -} - -export class HttpUserNotExistError extends Error { - constructor(public innerError?: AxiosError) { - super(); - } -} - -export class HttpChangePasswordBadCredentialError extends Error { - constructor(public innerError?: AxiosError) { - super(); - } -} - -export interface IHttpUserClient { - list(): Promise; - get(username: string): Promise; - post(req: HttpCreateUserRequest): Promise; - patch(username: string, req: HttpUserPatchRequest): Promise; - delete(username: string): Promise; - generateAvatarUrl(username: string): string; - putAvatar(username: string, data: Blob): Promise; - changePassword(req: HttpChangePasswordRequest): Promise; - putUserPermission( - username: string, - permission: UserPermission - ): Promise; - deleteUserPermission( - username: string, - permission: UserPermission - ): Promise; -} - -export class HttpUserClient implements IHttpUserClient { - list(): Promise { - return axios - .get(`${apiBaseUrl}/users`) - .then(extractResponseData); - } - - get(username: string): Promise { - return axios - .get(`${apiBaseUrl}/users/${username}`) - .then(extractResponseData) - .catch(convertToIfStatusCodeIs(404, HttpUserNotExistError)); - } - - post(req: HttpCreateUserRequest): Promise { - return axios - .post(`${apiBaseUrl}/users`, req) - .then(extractResponseData) - .then(); - } - - patch(username: string, req: HttpUserPatchRequest): Promise { - return axios - .patch(`${apiBaseUrl}/users/${username}`, req) - .then(extractResponseData); - } - - delete(username: string): Promise { - return axios.delete(`${apiBaseUrl}/users/${username}`).then(); - } - - generateAvatarUrl(username: string): string { - return `${apiBaseUrl}/users/${username}/avatar`; - } - - putAvatar(username: string, data: Blob): Promise { - return axios - .put(`${apiBaseUrl}/users/${username}/avatar`, data, { - headers: { - "Content-Type": data.type, - }, - }) - .then(extractEtag); - } - - changePassword(req: HttpChangePasswordRequest): Promise { - return axios - .post(`${apiBaseUrl}/userop/changepassword`, req) - .catch( - convertToIfErrorCodeIs(11020201, HttpChangePasswordBadCredentialError) - ) - .then(); - } - - putUserPermission( - username: string, - permission: UserPermission - ): Promise { - return axios - .put(`${apiBaseUrl}/users/${username}/permissions/${permission}`) - .then(); - } - - deleteUserPermission( - username: string, - permission: UserPermission - ): Promise { - return axios - .delete(`${apiBaseUrl}/users/${username}/permissions/${permission}`) - .then(); - } -} - -let client: IHttpUserClient = new HttpUserClient(); - -export function getHttpUserClient(): IHttpUserClient { - return client; -} - -export function setHttpUserClient(newClient: IHttpUserClient): IHttpUserClient { - const old = client; - client = newClient; - return old; -} -- cgit v1.2.3