diff --git a/api/v1/system.go b/api/v1/system.go index 44d9d831..51a26c11 100644 --- a/api/v1/system.go +++ b/api/v1/system.go @@ -5,9 +5,7 @@ import ( "net/http" "github.com/labstack/echo/v4" - "go.uber.org/zap" - "github.com/usememos/memos/internal/log" "github.com/usememos/memos/server/profile" "github.com/usememos/memos/store" ) @@ -18,18 +16,12 @@ type SystemStatus struct { DBSize int64 `json:"dbSize"` // System settings - // Allow sign up. - AllowSignUp bool `json:"allowSignUp"` // Disable password login. DisablePasswordLogin bool `json:"disablePasswordLogin"` // Disable public memos. DisablePublicMemos bool `json:"disablePublicMemos"` // Max upload size. MaxUploadSizeMiB int `json:"maxUploadSizeMiB"` - // Additional style. - AdditionalStyle string `json:"additionalStyle"` - // Additional script. - AdditionalScript string `json:"additionalScript"` // Customized server profile, including server name and external url. CustomizedProfile CustomizedProfile `json:"customizedProfile"` // Storage service ID. @@ -74,8 +66,6 @@ func (s *APIV1Service) GetSystemStatus(c echo.Context) error { Mode: s.Profile.Mode, Version: s.Profile.Version, }, - // Allow sign up by default. - AllowSignUp: true, MaxUploadSizeMiB: 32, CustomizedProfile: CustomizedProfile{ Name: "Memos", @@ -101,10 +91,7 @@ func (s *APIV1Service) GetSystemStatus(c echo.Context) error { if err != nil { return echo.NewHTTPError(http.StatusInternalServerError, "Failed to find workspace general setting").SetInternal(err) } - systemStatus.AllowSignUp = !workspaceGeneralSetting.DisallowSignup systemStatus.DisablePasswordLogin = workspaceGeneralSetting.DisallowPasswordLogin - systemStatus.AdditionalStyle = workspaceGeneralSetting.AdditionalStyle - systemStatus.AdditionalScript = workspaceGeneralSetting.AdditionalScript systemSettingList, err := s.Store.ListWorkspaceSettings(ctx, &store.FindWorkspaceSetting{}) if err != nil { @@ -140,7 +127,7 @@ func (s *APIV1Service) GetSystemStatus(c echo.Context) error { case SystemSettingMemoDisplayWithUpdatedTsName.String(): systemStatus.MemoDisplayWithUpdatedTs = baseValue.(bool) default: - log.Warn("Unknown system setting name", zap.String("setting name", systemSetting.Name)) + // Skip unknown system setting. } } diff --git a/api/v2/acl_config.go b/api/v2/acl_config.go index 12bff738..0ed4fbaa 100644 --- a/api/v2/acl_config.go +++ b/api/v2/acl_config.go @@ -3,20 +3,20 @@ package v2 import "strings" var authenticationAllowlistMethods = map[string]bool{ - "/memos.api.v2.WorkspaceService/GetWorkspaceProfile": true, - "/memos.api.v2.WorkspaceService/GetWorkspaceSetting": true, - "/memos.api.v2.AuthService/GetAuthStatus": true, - "/memos.api.v2.AuthService/SignIn": true, - "/memos.api.v2.AuthService/SignInWithSSO": true, - "/memos.api.v2.AuthService/SignOut": true, - "/memos.api.v2.AuthService/SignUp": true, - "/memos.api.v2.UserService/GetUser": true, - "/memos.api.v2.MemoService/ListMemos": true, - "/memos.api.v2.MemoService/GetMemo": true, - "/memos.api.v2.MemoService/GetMemoByName": true, - "/memos.api.v2.MemoService/ListMemoResources": true, - "/memos.api.v2.MemoService/ListMemoRelations": true, - "/memos.api.v2.MemoService/ListMemoComments": true, + "/memos.api.v2.WorkspaceService/GetWorkspaceProfile": true, + "/memos.api.v2.WorkspaceSettingService/GetWorkspaceSetting": true, + "/memos.api.v2.AuthService/GetAuthStatus": true, + "/memos.api.v2.AuthService/SignIn": true, + "/memos.api.v2.AuthService/SignInWithSSO": true, + "/memos.api.v2.AuthService/SignOut": true, + "/memos.api.v2.AuthService/SignUp": true, + "/memos.api.v2.UserService/GetUser": true, + "/memos.api.v2.MemoService/ListMemos": true, + "/memos.api.v2.MemoService/GetMemo": true, + "/memos.api.v2.MemoService/GetMemoByName": true, + "/memos.api.v2.MemoService/ListMemoResources": true, + "/memos.api.v2.MemoService/ListMemoRelations": true, + "/memos.api.v2.MemoService/ListMemoComments": true, } // isUnauthorizeAllowedMethod returns whether the method is exempted from authentication. diff --git a/web/src/App.tsx b/web/src/App.tsx index 2fcf40ee..efd8a800 100644 --- a/web/src/App.tsx +++ b/web/src/App.tsx @@ -1,5 +1,4 @@ import { useColorScheme } from "@mui/joy"; -import mermaid from "mermaid"; import { useEffect, useState } from "react"; import { useTranslation } from "react-i18next"; import { Outlet } from "react-router-dom"; @@ -7,19 +6,22 @@ import storage from "./helpers/storage"; import { getSystemColorScheme } from "./helpers/utils"; import useNavigateTo from "./hooks/useNavigateTo"; import { useGlobalStore } from "./store/module"; -import { useUserStore } from "./store/v1"; +import { useUserStore, useWorkspaceSettingStore } from "./store/v1"; +import { WorkspaceGeneralSetting, WorkspaceSettingKey } from "./types/proto/store/workspace_setting"; const App = () => { const { i18n } = useTranslation(); const navigateTo = useNavigateTo(); const { mode, setMode } = useColorScheme(); const globalStore = useGlobalStore(); + const workspaceSettingStore = useWorkspaceSettingStore(); const userStore = useUserStore(); const [loading, setLoading] = useState(true); const { appearance, locale, systemStatus } = globalStore.state; const userSetting = userStore.userSetting; - - mermaid.initialize({ startOnLoad: false, theme: mode }); + const workspaceGeneralSetting = + workspaceSettingStore.getWorkspaceSettingByKey(WorkspaceSettingKey.WORKSPACE_SETTING_GENERAL).generalSetting || + WorkspaceGeneralSetting.fromPartial({}); // Redirect to sign up page if no host. useEffect(() => { @@ -30,6 +32,7 @@ const App = () => { useEffect(() => { const initialState = async () => { + await workspaceSettingStore.fetchWorkspaceSetting(WorkspaceSettingKey.WORKSPACE_SETTING_GENERAL); try { await userStore.fetchCurrentUser(); } catch (error) { @@ -61,21 +64,21 @@ const App = () => { }, []); useEffect(() => { - if (systemStatus.additionalStyle) { + if (workspaceGeneralSetting.additionalStyle) { const styleEl = document.createElement("style"); - styleEl.innerHTML = systemStatus.additionalStyle; + styleEl.innerHTML = workspaceGeneralSetting.additionalStyle; styleEl.setAttribute("type", "text/css"); document.body.insertAdjacentElement("beforeend", styleEl); } - }, [systemStatus.additionalStyle]); + }, [workspaceGeneralSetting.additionalStyle]); useEffect(() => { - if (systemStatus.additionalScript) { + if (workspaceGeneralSetting.additionalScript) { const scriptEl = document.createElement("script"); - scriptEl.innerHTML = systemStatus.additionalScript; + scriptEl.innerHTML = workspaceGeneralSetting.additionalScript; document.head.appendChild(scriptEl); } - }, [systemStatus.additionalScript]); + }, [workspaceGeneralSetting.additionalScript]); // Dynamic update metadata with customized profile. useEffect(() => { diff --git a/web/src/components/MemoContent/MermaidBlock.tsx b/web/src/components/MemoContent/MermaidBlock.tsx index 30d9a18d..4d52d266 100644 --- a/web/src/components/MemoContent/MermaidBlock.tsx +++ b/web/src/components/MemoContent/MermaidBlock.tsx @@ -1,3 +1,4 @@ +import { useColorScheme } from "@mui/joy"; import mermaid from "mermaid"; import { useEffect, useRef } from "react"; @@ -6,14 +7,16 @@ interface Props { } const MermaidBlock: React.FC = ({ content }: Props) => { + const { mode } = useColorScheme(); const mermaidDockBlock = useRef(null); + mermaid.initialize({ startOnLoad: false, theme: mode }); useEffect(() => { if (!mermaidDockBlock.current) { return; } - // Render mermaid when mounted + // Render mermaid when mounted. mermaid.run({ nodes: [mermaidDockBlock.current], }); diff --git a/web/src/components/Settings/SystemSection.tsx b/web/src/components/Settings/SystemSection.tsx index 6eb65ca7..02c4b29b 100644 --- a/web/src/components/Settings/SystemSection.tsx +++ b/web/src/components/Settings/SystemSection.tsx @@ -72,13 +72,14 @@ const SystemSection = () => { }; const handleDisablePasswordLoginChanged = async (value: boolean) => { - setWorkspaceGeneralSetting({ ...workspaceGeneralSetting, disallowPasswordLogin: value }); + const setting = { ...workspaceGeneralSetting, disallowPasswordLogin: value }; await workspaceSettingServiceClient.setWorkspaceSetting({ setting: { name: `${WorkspaceSettingPrefix}${WorkspaceSettingKey.WORKSPACE_SETTING_GENERAL}`, - generalSetting: workspaceGeneralSetting, + generalSetting: setting, }, }); + setWorkspaceGeneralSetting(setting); }; const handleUpdateCustomizedProfileButtonClick = () => { @@ -223,7 +224,7 @@ const SystemSection = () => {

{t("common.settings")}

{t("setting.system-section.allow-user-signup")} - handleAllowSignUpChanged(event.target.checked)} /> + handleAllowSignUpChanged(event.target.checked)} />
{t("setting.system-section.disable-password-login")} diff --git a/web/src/pages/SignIn.tsx b/web/src/pages/SignIn.tsx index d73b10fe..882d0585 100644 --- a/web/src/pages/SignIn.tsx +++ b/web/src/pages/SignIn.tsx @@ -11,13 +11,16 @@ import { absolutifyLink } from "@/helpers/utils"; import useLoading from "@/hooks/useLoading"; import useNavigateTo from "@/hooks/useNavigateTo"; import { useGlobalStore } from "@/store/module"; -import { useUserStore } from "@/store/v1"; +import { useUserStore, useWorkspaceSettingStore } from "@/store/v1"; +import { WorkspaceGeneralSetting } from "@/types/proto/api/v2/workspace_setting_service"; +import { WorkspaceSettingKey } from "@/types/proto/store/workspace_setting"; import { useTranslate } from "@/utils/i18n"; const SignIn = () => { const t = useTranslate(); const navigateTo = useNavigateTo(); const globalStore = useGlobalStore(); + const workspaceSettingStore = useWorkspaceSettingStore(); const userStore = useUserStore(); const actionBtnLoadingState = useLoading(false); const { appearance, locale, systemStatus } = globalStore.state; @@ -25,8 +28,12 @@ const SignIn = () => { const [username, setUsername] = useState(""); const [password, setPassword] = useState(""); const [remember, setRemember] = useState(true); - const disablePasswordLogin = systemStatus.disablePasswordLogin; const [identityProviderList, setIdentityProviderList] = useState([]); + const workspaceGeneralSetting = + workspaceSettingStore.getWorkspaceSettingByKey(WorkspaceSettingKey.WORKSPACE_SETTING_GENERAL).generalSetting || + WorkspaceGeneralSetting.fromPartial({}); + + console.log("workspaceGeneralSetting", workspaceGeneralSetting); useEffect(() => { const fetchIdentityProviderList = async () => { @@ -112,7 +119,7 @@ const SignIn = () => {

{systemStatus.customizedProfile.name}

- {!disablePasswordLogin && ( + {!workspaceGeneralSetting.disallowPasswordLogin && ( <>
@@ -164,7 +171,7 @@ const SignIn = () => {
- {systemStatus.allowSignUp && ( + {!workspaceGeneralSetting.disallowSignup && (

{t("auth.sign-up-tip")} @@ -176,7 +183,7 @@ const SignIn = () => { )} {identityProviderList.length > 0 && ( <> - {!disablePasswordLogin && {t("common.or")}} + {!workspaceGeneralSetting.disallowPasswordLogin && {t("common.or")}}

{identityProviderList.map((identityProvider) => (