Просмотр исходного кода

Merge pull request #5542 from weseek/fix/put-user-ui-settings-when-guest-user

fix: Put user UI settings when guest user
Yuki Takei 4 лет назад
Родитель
Сommit
822b5dcd66

+ 16 - 1
packages/app/src/client/services/user-ui-settings.ts

@@ -5,6 +5,7 @@ import { debounce } from 'throttle-debounce';
 
 import { apiv3Put } from '~/client/util/apiv3-client';
 import { IUserUISettings } from '~/interfaces/user-ui-settings';
+import { useIsGuestUser } from '~/stores/context';
 
 let settingsForBulk: Partial<IUserUISettings> = {};
 const _putUserUISettingsInBulk = (): Promise<AxiosResponse<IUserUISettings>> => {
@@ -18,7 +19,8 @@ const _putUserUISettingsInBulk = (): Promise<AxiosResponse<IUserUISettings>> =>
 
 const _putUserUISettingsInBulkDebounced = debounce(1500, false, _putUserUISettingsInBulk);
 
-export const scheduleToPutUserUISettings = (settings: Partial<IUserUISettings>): Promise<AxiosResponse<IUserUISettings>> => {
+type ScheduleToPutFunction = (settings: Partial<IUserUISettings>) => Promise<AxiosResponse<IUserUISettings>>;
+const scheduleToPut: ScheduleToPutFunction = (settings: Partial<IUserUISettings>): Promise<AxiosResponse<IUserUISettings>> => {
   settingsForBulk = {
     ...settingsForBulk,
     ...settings,
@@ -26,3 +28,16 @@ export const scheduleToPutUserUISettings = (settings: Partial<IUserUISettings>):
 
   return _putUserUISettingsInBulkDebounced();
 };
+
+type UserUISettingsUtil = {
+  scheduleToPut: ScheduleToPutFunction | (() => void),
+}
+export const useUserUISettings = (): UserUISettingsUtil => {
+  const { data: isGuestUser } = useIsGuestUser();
+
+  return {
+    scheduleToPut: isGuestUser
+      ? () => {}
+      : scheduleToPut,
+  };
+};

+ 6 - 5
packages/app/src/components/Navbar/PersonalDropdown.jsx

@@ -7,7 +7,7 @@ import { UncontrolledTooltip } from 'reactstrap';
 
 import { UserPicture } from '@growi/ui';
 
-import { scheduleToPutUserUISettings } from '~/client/services/user-ui-settings';
+import { useUserUISettings } from '~/client/services/user-ui-settings';
 import AppContainer from '~/client/services/AppContainer';
 
 import { withUnstatedContainers } from '../UnstatedUtils';
@@ -39,6 +39,7 @@ const PersonalDropdown = (props) => {
 
   const { data: isPreferDrawerMode, mutate: mutatePreferDrawerMode } = usePreferDrawerModeByUser();
   const { data: isPreferDrawerModeOnEdit, mutate: mutatePreferDrawerModeOnEdit } = usePreferDrawerModeOnEditByUser();
+  const { scheduleToPut } = useUserUISettings();
 
   const logoutHandler = () => {
     const { interceptorManager } = appContainer;
@@ -54,13 +55,13 @@ const PersonalDropdown = (props) => {
 
   const preferDrawerModeSwitchModifiedHandler = useCallback((bool) => {
     mutatePreferDrawerMode(bool);
-    scheduleToPutUserUISettings({ preferDrawerModeByUser: bool });
-  }, [mutatePreferDrawerMode]);
+    scheduleToPut({ preferDrawerModeByUser: bool });
+  }, [mutatePreferDrawerMode, scheduleToPut]);
 
   const preferDrawerModeOnEditSwitchModifiedHandler = useCallback((bool) => {
     mutatePreferDrawerModeOnEdit(bool);
-    scheduleToPutUserUISettings({ preferDrawerModeOnEditByUser: bool });
-  }, [mutatePreferDrawerModeOnEdit]);
+    scheduleToPut({ preferDrawerModeOnEditByUser: bool });
+  }, [mutatePreferDrawerModeOnEdit, scheduleToPut]);
 
   const followOsCheckboxModifiedHandler = (bool) => {
     if (bool) {

+ 12 - 8
packages/app/src/components/Sidebar.tsx

@@ -2,7 +2,7 @@ import React, {
   FC, useCallback, useEffect, useRef, useState,
 } from 'react';
 
-import { scheduleToPutUserUISettings } from '~/client/services/user-ui-settings';
+import { useUserUISettings } from '~/client/services/user-ui-settings';
 import {
   useDrawerMode, useDrawerOpened,
   useSidebarCollapsed,
@@ -29,6 +29,8 @@ const GlobalNavigation = () => {
   const { data: currentContents } = useCurrentSidebarContents();
   const { data: isCollapsed, mutate: mutateSidebarCollapsed } = useSidebarCollapsed();
 
+  const { scheduleToPut } = useUserUISettings();
+
   const itemSelectedHandler = useCallback((selectedContents) => {
     if (isDrawerMode) {
       return;
@@ -43,9 +45,9 @@ const GlobalNavigation = () => {
     }
 
     mutateSidebarCollapsed(newValue, false);
-    scheduleToPutUserUISettings({ isSidebarCollapsed: newValue });
+    scheduleToPut({ isSidebarCollapsed: newValue });
 
-  }, [currentContents, isCollapsed, isDrawerMode, mutateSidebarCollapsed]);
+  }, [currentContents, isCollapsed, isDrawerMode, mutateSidebarCollapsed, scheduleToPut]);
 
   return <SidebarNav onItemSelected={itemSelectedHandler} />;
 };
@@ -88,6 +90,8 @@ const Sidebar: FC<Props> = (props: Props) => {
   const { data: isCollapsed, mutate: mutateSidebarCollapsed } = useSidebarCollapsed();
   const { data: isResizeDisabled, mutate: mutateSidebarResizeDisabled } = useSidebarResizeDisabled();
 
+  const { scheduleToPut } = useUserUISettings();
+
   const [isTransitionEnabled, setTransitionEnabled] = useState(false);
 
   const [isHover, setHover] = useState(false);
@@ -165,8 +169,8 @@ const Sidebar: FC<Props> = (props: Props) => {
   const toggleNavigationBtnClickHandler = useCallback(() => {
     const newValue = !isCollapsed;
     mutateSidebarCollapsed(newValue, false);
-    scheduleToPutUserUISettings({ isSidebarCollapsed: newValue });
-  }, [isCollapsed, mutateSidebarCollapsed]);
+    scheduleToPut({ isSidebarCollapsed: newValue });
+  }, [isCollapsed, mutateSidebarCollapsed, scheduleToPut]);
 
   useEffect(() => {
     if (isCollapsed) {
@@ -199,18 +203,18 @@ const Sidebar: FC<Props> = (props: Props) => {
       // force collapsed
       mutateSidebarCollapsed(true);
       mutateProductNavWidth(sidebarMinWidth, false);
-      scheduleToPutUserUISettings({ isSidebarCollapsed: true, currentProductNavWidth: sidebarMinWidth });
+      scheduleToPut({ isSidebarCollapsed: true, currentProductNavWidth: sidebarMinWidth });
     }
     else {
       const newWidth = resizableContainer.current.clientWidth;
       mutateSidebarCollapsed(false);
       mutateProductNavWidth(newWidth, false);
-      scheduleToPutUserUISettings({ isSidebarCollapsed: false, currentProductNavWidth: newWidth });
+      scheduleToPut({ isSidebarCollapsed: false, currentProductNavWidth: newWidth });
     }
 
     resizableContainer.current.classList.remove('dragging');
 
-  }, [mutateProductNavWidth, mutateSidebarCollapsed]);
+  }, [mutateProductNavWidth, mutateSidebarCollapsed, scheduleToPut]);
 
   const dragableAreaMouseDownHandler = useCallback((event: React.MouseEvent) => {
     if (!isResizableByDrag) {

+ 13 - 11
packages/app/src/components/Sidebar/SidebarNav.tsx

@@ -1,8 +1,8 @@
 import React, { FC, memo, useCallback } from 'react';
 
-import { scheduleToPutUserUISettings } from '~/client/services/user-ui-settings';
+import { useUserUISettings } from '~/client/services/user-ui-settings';
 import { SidebarContentsType } from '~/interfaces/ui';
-import { useCurrentUser, useIsSharedUser } from '~/stores/context';
+import { useCurrentUser, useIsGuestUser } from '~/stores/context';
 import { useCurrentSidebarContents } from '~/stores/ui';
 
 
@@ -19,6 +19,7 @@ const PrimaryItem: FC<PrimaryItemProps> = (props: PrimaryItemProps) => {
   } = props;
 
   const { data: currentContents, mutate } = useCurrentSidebarContents();
+  const { scheduleToPut } = useUserUISettings();
 
   const isSelected = contents === currentContents;
 
@@ -28,8 +29,9 @@ const PrimaryItem: FC<PrimaryItemProps> = (props: PrimaryItemProps) => {
     }
 
     mutate(contents, false);
-    scheduleToPutUserUISettings({ currentSidebarContents: contents });
-  }, [contents, mutate, onItemSelected]);
+
+    scheduleToPut({ currentSidebarContents: contents });
+  }, [contents, mutate, onItemSelected, scheduleToPut]);
 
   const labelForTestId = label.toLowerCase().replace(' ', '-');
 
@@ -69,28 +71,28 @@ type Props = {
 
 const SidebarNav: FC<Props> = (props: Props) => {
 
-  const { data: isSharedUser } = useIsSharedUser();
   const { data: currentUser } = useCurrentUser();
 
   const isAdmin = currentUser?.admin;
-  const isLoggedIn = currentUser != null;
 
   const { onItemSelected } = props;
 
   return (
     <div className="grw-sidebar-nav">
       <div className="grw-sidebar-nav-primary-container">
-        {!isSharedUser && <PrimaryItem contents={SidebarContentsType.CUSTOM} label="Custom Sidebar" iconName="code" onItemSelected={onItemSelected} />}
-        {!isSharedUser && <PrimaryItem contents={SidebarContentsType.RECENT} label="Recent Changes" iconName="update" onItemSelected={onItemSelected} />}
-        {!isSharedUser && <PrimaryItem contents={SidebarContentsType.TREE} label="Page Tree" iconName="format_list_bulleted" onItemSelected={onItemSelected} />}
+        {/* eslint-disable max-len */}
+        <PrimaryItem contents={SidebarContentsType.CUSTOM} label="Custom Sidebar" iconName="code" onItemSelected={onItemSelected} />
+        <PrimaryItem contents={SidebarContentsType.RECENT} label="Recent Changes" iconName="update" onItemSelected={onItemSelected} />
+        <PrimaryItem contents={SidebarContentsType.TREE} label="Page Tree" iconName="format_list_bulleted" onItemSelected={onItemSelected} />
         {/* <PrimaryItem id="tag" label="Tags" iconName="icon-tag" /> */}
         {/* <PrimaryItem id="favorite" label="Favorite" iconName="fa fa-bookmark-o" /> */}
-        {!isSharedUser && <PrimaryItem contents={SidebarContentsType.TAG} label="Tags" iconName="tag" onItemSelected={onItemSelected} /> }
+        <PrimaryItem contents={SidebarContentsType.TAG} label="Tags" iconName="tag" onItemSelected={onItemSelected} />
         {/* <PrimaryItem id="favorite" label="Favorite" iconName="icon-star" /> */}
+        {/* eslint-enable max-len */}
       </div>
       <div className="grw-sidebar-nav-secondary-container">
         {isAdmin && <SecondaryItem label="Admin" iconName="settings" href="/admin" />}
-        {isLoggedIn && <SecondaryItem label="Draft" iconName="file_copy" href="/me/drafts" />}
+        <SecondaryItem label="Draft" iconName="file_copy" href="/me/drafts" />
         <SecondaryItem label="Help" iconName="help" href="https://docs.growi.org" isBlank />
         <SecondaryItem label="Trash" iconName="delete" href="/trash" />
       </div>

+ 2 - 2
packages/app/src/server/middlewares/login-required.js

@@ -44,8 +44,8 @@ module.exports = (crowi, isGuestAllowed = false, fallback = null) => {
     }
 
     // is api path
-    const path = req.path || '';
-    if (path.match(/^\/_api\/.+$/)) {
+    const baseUrl = req.baseUrl || '';
+    if (baseUrl.match(/^\/_api\/.+$/)) {
       if (fallback != null) {
         return fallback(req, res, next);
       }

+ 4 - 4
packages/app/test/integration/middlewares/login-required.test.js

@@ -98,8 +98,8 @@ describe('loginRequired', () => {
       isGuestAllowedToReadSpy = jest.spyOn(crowi.aclService, 'isGuestAllowedToRead');
     });
 
-    test('send status 403 when \'req.path\' starts with \'_api\'', () => {
-      req.path = '/_api/someapi';
+    test('send status 403 when \'req.baseUrl\' starts with \'_api\'', () => {
+      req.baseUrl = '/_api/someapi';
 
       const result = loginRequiredStrictly(req, res, next);
 
@@ -113,7 +113,7 @@ describe('loginRequired', () => {
     });
 
     test('redirect to \'/login\' when the user does not loggedin', () => {
-      req.path = '/path/that/requires/loggedin';
+      req.baseUrl = '/path/that/requires/loggedin';
 
       const result = loginRequiredStrictly(req, res, next);
 
@@ -174,7 +174,7 @@ describe('loginRequired', () => {
     test('redirect to \'/login\' when user.status is \'STATUS_DELETED\'', () => {
       const User = crowi.model('User');
 
-      req.path = '/path/that/requires/loggedin';
+      req.baseUrl = '/path/that/requires/loggedin';
       req.user = {
         _id: 'user id',
         status: User.STATUS_DELETED,