diff --git a/apps/web/app/(all)/settings/profile/[profileTabId]/page.tsx b/apps/web/app/(all)/settings/profile/[profileTabId]/page.tsx index d7df27ccbcd..9ece9e80b28 100644 --- a/apps/web/app/(all)/settings/profile/[profileTabId]/page.tsx +++ b/apps/web/app/(all)/settings/profile/[profileTabId]/page.tsx @@ -5,6 +5,7 @@ */ import { observer } from "mobx-react"; +import { Navigate } from "react-router"; // plane imports import { PROFILE_SETTINGS_TABS } from "@plane/constants"; import { useTranslation } from "@plane/i18n"; @@ -17,6 +18,8 @@ import { ProfileSettingsSidebarRoot } from "@/components/settings/profile/sideba // hooks import { useUser } from "@/hooks/store/user"; import { useAppRouter } from "@/hooks/use-app-router"; +// helpers +import { isSsoAuth } from "@/helpers/auth-config.helper"; // local imports import type { Route } from "../+types/layout"; @@ -31,6 +34,10 @@ function ProfileSettingsPage(props: Route.ComponentProps) { // derived values const isAValidTab = PROFILE_SETTINGS_TABS.includes(profileTabId as TProfileSettingsTabs); + if (isSsoAuth() && profileTabId === "security") { + return ; + } + if (!currentUser || !isAValidTab) return (
diff --git a/apps/web/core/components/onboarding/profile-setup.tsx b/apps/web/core/components/onboarding/profile-setup.tsx index c466e1f0478..d0cf8842e1e 100644 --- a/apps/web/core/components/onboarding/profile-setup.tsx +++ b/apps/web/core/components/onboarding/profile-setup.tsx @@ -21,6 +21,8 @@ import { cn, getFileURL, getPasswordStrength, validatePersonName } from "@plane/ import { UserImageUploadModal } from "@/components/core/modals/user-image-upload-modal"; // hooks import { useUser, useUserProfile } from "@/hooks/store/user"; +// helpers +import { isSsoAuth } from "@/helpers/auth-config.helper"; // services import { AuthService } from "@/services/auth.service"; @@ -220,8 +222,7 @@ export const ProfileSetup = observer(function ProfileSetup(props: Props) { // derived values const isPasswordAlreadySetup = !user?.is_password_autoset; - const isSsoAuth = (import.meta.env.VITE_AUTH_TYPE?.toString() ?? "").trim().toUpperCase() === "SSO"; - const showOptionalPassword = !isSsoAuth && !isPasswordAlreadySetup; + const showOptionalPassword = !isSsoAuth() && !isPasswordAlreadySetup; const currentPassword = watch("password") || undefined; const currentConfirmPassword = watch("confirm_password") || undefined; diff --git a/apps/web/core/components/onboarding/steps/profile/root.tsx b/apps/web/core/components/onboarding/steps/profile/root.tsx index bde25779a68..90b53325308 100644 --- a/apps/web/core/components/onboarding/steps/profile/root.tsx +++ b/apps/web/core/components/onboarding/steps/profile/root.tsx @@ -20,6 +20,8 @@ import { UserImageUploadModal } from "@/components/core/modals/user-image-upload // hooks import { useInstance } from "@/hooks/store/use-instance"; import { useUser, useUserProfile } from "@/hooks/store/user"; +// helpers +import { isSsoAuth } from "@/helpers/auth-config.helper"; // services import { AuthService } from "@/services/auth.service"; // local components @@ -121,9 +123,7 @@ export const ProfileSetupStep = observer(function ProfileSetupStep({ handleStepC // derived values const isPasswordAlreadySetup = !user?.is_password_autoset; - // Hide optional password on SSO builds only (VITE_AUTH_TYPE baked at build time). - const isSsoAuth = (import.meta.env.VITE_AUTH_TYPE ?? "").trim().toUpperCase() === "SSO"; - const showOptionalPassword = !isSsoAuth && !isPasswordAlreadySetup; + const showOptionalPassword = !isSsoAuth() && !isPasswordAlreadySetup; const currentPassword = watch("password") || undefined; const currentConfirmPassword = watch("confirm_password") || undefined; diff --git a/apps/web/core/components/settings/profile/content/pages/general/form.tsx b/apps/web/core/components/settings/profile/content/pages/general/form.tsx index e20245f8352..71075e63c66 100644 --- a/apps/web/core/components/settings/profile/content/pages/general/form.tsx +++ b/apps/web/core/components/settings/profile/content/pages/general/form.tsx @@ -30,6 +30,8 @@ import { useInstance } from "@/hooks/store/use-instance"; import { useUser, useUserProfile } from "@/hooks/store/user"; // utils import { validatePersonName, validateDisplayName } from "@plane/utils"; +// helpers +import { isSsoAuth } from "@/helpers/auth-config.helper"; type TUserProfileForm = { avatar_url: string; @@ -56,6 +58,7 @@ export const GeneralProfileSettingsForm = observer(function GeneralProfileSettin const [isLoading, setIsLoading] = useState(false); const [isImageUploadModalOpen, setIsImageUploadModalOpen] = useState(false); const [deactivateAccountModal, setDeactivateAccountModal] = useState(false); + const hideDeactivateAccount = isSsoAuth(); const [isChangeEmailModalOpen, setIsChangeEmailModalOpen] = useState(false); // language support const { t } = useTranslation(); @@ -190,7 +193,9 @@ export const GeneralProfileSettingsForm = observer(function GeneralProfileSettin return ( <> - setDeactivateAccountModal(false)} /> + {!hideDeactivateAccount && ( + setDeactivateAccountModal(false)} /> + )} setIsChangeEmailModalOpen(false)} />
-
- setDeactivateAccountModal(true)}> - {t("deactivate_account")} - - } - /> -
+ {!hideDeactivateAccount && ( +
+ setDeactivateAccountModal(true)}> + {t("deactivate_account")} + + } + /> +
+ )} ); }); diff --git a/apps/web/core/components/settings/profile/modal.tsx b/apps/web/core/components/settings/profile/modal.tsx index 43abd90afbf..99a88038d33 100644 --- a/apps/web/core/components/settings/profile/modal.tsx +++ b/apps/web/core/components/settings/profile/modal.tsx @@ -12,6 +12,8 @@ import { IconButton } from "@plane/propel/icon-button"; import { EModalPosition, EModalWidth, ModalCore } from "@plane/ui"; // hooks import { useCommandPalette } from "@/hooks/store/use-command-palette"; +// helpers +import { isSsoAuth } from "@/helpers/auth-config.helper"; // local imports import { ProfileSettingsContent } from "./content"; import { ProfileSettingsSidebarRoot } from "./sidebar"; @@ -20,7 +22,8 @@ export const ProfileSettingsModal = observer(function ProfileSettingsModal() { // store hooks const { profileSettingsModal, toggleProfileSettingsModal } = useCommandPalette(); // derived values - const activeTab = profileSettingsModal.activeTab ?? "general"; + const requestedTab = profileSettingsModal.activeTab ?? "general"; + const activeTab = isSsoAuth() && requestedTab === "security" ? "general" : requestedTab; const handleClose = useCallback(() => { toggleProfileSettingsModal({ diff --git a/apps/web/core/components/settings/profile/sidebar/item-categories.tsx b/apps/web/core/components/settings/profile/sidebar/item-categories.tsx index d1ee973f3ee..b4e9f4c13c1 100644 --- a/apps/web/core/components/settings/profile/sidebar/item-categories.tsx +++ b/apps/web/core/components/settings/profile/sidebar/item-categories.tsx @@ -14,6 +14,8 @@ import { GROUPED_PROFILE_SETTINGS, PROFILE_SETTINGS_CATEGORIES } from "@plane/co import { useTranslation } from "@plane/i18n"; import type { ISvgIcons } from "@plane/propel/icons"; import type { TProfileSettingsTabs } from "@plane/types"; +// helpers +import { isSsoAuth } from "@/helpers/auth-config.helper"; // local imports import { SettingsSidebarItem } from "../../sidebar/item"; import { ProfileSettingsSidebarWorkspaceOptions } from "./workspace-options"; @@ -40,11 +42,14 @@ export const ProfileSettingsSidebarItemCategories = observer(function ProfileSet const { profileTabId } = useParams(); // translation const { t } = useTranslation(); + const hideSecurityTab = isSsoAuth(); return (
{PROFILE_SETTINGS_CATEGORIES.map((category) => { - const categoryItems = GROUPED_PROFILE_SETTINGS[category]; + const categoryItems = GROUPED_PROFILE_SETTINGS[category].filter( + (item) => !(hideSecurityTab && item.key === "security") + ); if (categoryItems.length === 0) return null; diff --git a/apps/web/helpers/auth-config.helper.ts b/apps/web/helpers/auth-config.helper.ts new file mode 100644 index 00000000000..1ada1eb8ba8 --- /dev/null +++ b/apps/web/helpers/auth-config.helper.ts @@ -0,0 +1,9 @@ +/** + * Copyright (c) 2023-present Plane Software, Inc. and contributors + * SPDX-License-Identifier: AGPL-3.0-only + * See the LICENSE file for details. + */ + +/** True when the web build is configured for SSO auth (VITE_AUTH_TYPE=SSO). */ +export const isSsoAuth = (): boolean => + (import.meta.env.VITE_AUTH_TYPE?.toString() ?? "").trim().toUpperCase() === "SSO"; diff --git a/apps/web/vite-process-env.d.ts b/apps/web/vite-process-env.d.ts new file mode 100644 index 00000000000..1889ad76191 --- /dev/null +++ b/apps/web/vite-process-env.d.ts @@ -0,0 +1,8 @@ +// `process.env` is replaced at build time in apps/web/vite.config.ts (`define`). +export {}; + +declare global { + const process: { + env: Record; + }; +}