diff --git a/src/client/web/src/client/index.ts b/src/client/web/src/client/index.ts index 0a56327..14b701a 100644 --- a/src/client/web/src/client/index.ts +++ b/src/client/web/src/client/index.ts @@ -3,6 +3,10 @@ import axios, { AxiosRequestConfig } from "axios"; export const defaultTimeout = 10000; export const userIDParam = "uid"; +export const roleAdmin = "admin"; +export const roleUser = "user"; +export const roleVisitor = "visitor"; + export interface Quota { spaceLimit: string; uploadSpeedLimit: number; diff --git a/src/client/web/src/components/__test__/state_mgr.test.tsx b/src/client/web/src/components/__test__/state_mgr.test.tsx index 6052721..c510e15 100644 --- a/src/client/web/src/components/__test__/state_mgr.test.tsx +++ b/src/client/web/src/components/__test__/state_mgr.test.tsx @@ -9,7 +9,7 @@ import { ICoreState, newWithWorker } from "../core_state"; import { MockWorker, UploadState, UploadEntry } from "../../worker/interface"; describe("State Manager", () => { - test("initUpdater", async () => { + test("initUpdater for admin", async () => { const usersCl = new MockUsersClient(""); const filesCl = new MockFilesClient(""); @@ -36,16 +36,18 @@ describe("State Manager", () => { ); expect(coreState.browser.uploadings).toEqual( List( - filesResps.listUploadingsMockResp.data.uploadInfos.map((info: UploadInfo) => { - return { - file: undefined, - filePath: info.realFilePath, - size: info.size, - uploaded: info.uploaded, - state: UploadState.Ready, - err: "", - }; - }) + filesResps.listUploadingsMockResp.data.uploadInfos.map( + (info: UploadInfo) => { + return { + file: undefined, + filePath: info.realFilePath, + size: info.size, + uploaded: info.uploaded, + state: UploadState.Ready, + err: "", + }; + } + ) ) ); @@ -71,7 +73,7 @@ describe("State Manager", () => { downloadSpeedLimit: 3, }, authed: true, - captchaID: "mockCaptchaID", + captchaID: "", }); // admin @@ -90,4 +92,77 @@ describe("State Manager", () => { roles: roles, }); }); + + test("initUpdater for visitor in sharing mode", async () => { + const usersCl = new MockUsersClient(""); + const filesCl = new MockFilesClient(""); + const mockSelfResp = { + status: 200, + statusText: "", + data: { + id: "-1", + name: "visitor", + role: "visitor", + usedSpace: "0", + quota: { + spaceLimit: "0", + uploadSpeedLimit: 0, + downloadSpeedLimit: 0, + }, + }, + }; + const mockIsAuthedResp = { status: 401, statusText: "", data: {} }; + const mockUserResps = { + ...usersResps, + isAuthedMockResp: mockIsAuthedResp, + selfMockResp: mockSelfResp, + }; + usersCl.setMock(mockUserResps); + + const mockWorkerClass = mock(MockWorker); + const mockWorker = instance(mockWorkerClass); + const coreState = newWithWorker(mockWorker); + + const mgr = new StateMgr({}); // it will call initUpdater + mgr.setUsersClient(usersCl); + mgr.setFilesClient(filesCl); + // TODO: depress warning + mgr.update = (apply: (prevState: ICoreState) => ICoreState): void => { + // no op + }; + await mgr.initUpdater(coreState); + + // browser + // TODO: mock query to get dir parm + expect(coreState.browser.dirPath.join("/")).toEqual("mock_home/files"); + expect(coreState.browser.isSharing).toEqual(true); + expect(coreState.browser.sharings).toEqual(List([])); + expect(coreState.browser.uploadings).toEqual(List([])); + expect(coreState.browser.items).toEqual( + List(filesResps.listHomeMockResp.data.metadatas) + ); + + // panes + expect(coreState.panes).toEqual({ + displaying: "", + paneNames: Set(["settings", "login", "admin"]), + }); + + // login + expect(coreState.login).toEqual({ + userID: mockSelfResp.data.id, + userName: mockSelfResp.data.name, + userRole: mockSelfResp.data.role, + quota: mockSelfResp.data.quota, + usedSpace: mockSelfResp.data.usedSpace, + authed: false, + captchaID: "", + }); + + // admin + expect(coreState.admin).toEqual({ + users: Map({}), + roles: Set(), + }); + }); }); diff --git a/src/client/web/src/components/panes.tsx b/src/client/web/src/components/panes.tsx index 91151ce..8cc56a5 100644 --- a/src/client/web/src/components/panes.tsx +++ b/src/client/web/src/components/panes.tsx @@ -2,6 +2,7 @@ import * as React from "react"; import { Set, Map } from "immutable"; import { updater } from "./state_updater"; +import { roleAdmin, roleVisitor } from "../client"; import { ICoreState, MsgProps } from "./core_state"; import { PaneSettings } from "./pane_settings"; import { AdminPane, AdminProps } from "./pane_admin"; @@ -40,23 +41,25 @@ export class Panes extends React.Component { displaying = "login"; } - let panesMap: Map = Map({ - settings: ( + let panesMap: Map = Map({}); + if (this.props.login.userRole !== roleVisitor) { + panesMap = panesMap.set( + "settings", - ), - login: ( + ); + panesMap = panesMap.set( + "login", - ), - }); - + ); + } if (this.props.login.userRole === "admin") { panesMap = panesMap.set( "admin", diff --git a/src/client/web/src/components/state_mgr.tsx b/src/client/web/src/components/state_mgr.tsx index 56bcc9f..f3d9f81 100644 --- a/src/client/web/src/components/state_mgr.tsx +++ b/src/client/web/src/components/state_mgr.tsx @@ -6,7 +6,7 @@ import { ICoreState, newState } from "./core_state"; import { RootFrame } from "./root_frame"; import { FilesClient } from "../client/files"; import { UsersClient } from "../client/users"; -import { IUsersClient, IFilesClient } from "../client"; +import { IUsersClient, IFilesClient, roleAdmin, roleVisitor } from "../client"; import { alertMsg } from "../common/env"; export interface Props {} @@ -39,30 +39,11 @@ export class StateMgr extends React.Component { updater().setClients(this.usersClient, this.filesClient); const params = new URLSearchParams(document.location.search.substring(1)); + return updater() .initIsAuthed() .then(() => { - this.update(updater().updateLogin); - }) - .then(() => { - if (updater().props.login.authed) { - updater().displayPane(""); - } else { - updater().displayPane("login"); - } - }) - .then(() => { - return updater().getCaptchaID(); - }) - .then((ok: boolean) => { - if (!ok) { - alertMsg(this.state.msg.pkg.get("stateMgr.cap.fail")); - } else { - this.update(updater().updateLogin); - } - }) - .then(() => { - return updater().refreshUploadings(); + return updater().self(); }) .then(() => { const dir = params.get("dir"); @@ -73,34 +54,39 @@ export class StateMgr extends React.Component { return updater().setHomeItems(); } }) - .then(() => { - return updater().initUploads(); - }) .then(() => { return updater().isSharing(updater().props.browser.dirPath.join("/")); }) .then(() => { - return updater().listSharings(); + // init browser content + if (updater().props.login.userRole === roleVisitor) { + if (updater().props.browser.isSharing) { + // sharing with visitor + updater().displayPane(""); + return Promise.all([]); + } + + // redirect to login + updater().displayPane("login"); + return Promise.all([updater().getCaptchaID()]); + } + + updater().displayPane(""); + return Promise.all([ + updater().refreshUploadings(), + updater().initUploads(), + updater().listSharings(), + ]); + }) + .then(() => { + // init admin content + if (updater().props.login.userRole === roleAdmin) { + return Promise.all([updater().listRoles(), updater().listUsers()]); + } + return; }) .then(() => { this.update(updater().updateBrowser); - }) - .then(() => { - return updater().self(); - }) - .then(() => { - if (updater().props.login.userRole === "admin") { - // TODO: remove hardcode - return updater().listRoles(); - } - }) - .then(() => { - if (updater().props.login.userRole === "admin") { - // TODO: remove hardcode - return updater().listUsers(); - } - }) - .then(() => { this.update(updater().updateLogin); this.update(updater().updatePanes); this.update(updater().updateAdmin);