diff --git a/frontend-v2/src/components/navigation/NavHeader.tsx b/frontend-v2/src/components/navigation/NavHeader.tsx index 310894f8a..f87afb5f3 100644 --- a/frontend-v2/src/components/navigation/NavHeader.tsx +++ b/frontend-v2/src/components/navigation/NavHeader.tsx @@ -4,6 +4,7 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { Link, useParams } from "@tanstack/react-router"; import { twMerge } from "tailwind-merge"; +import { ROUTE_PATHS } from "@app/const/routes"; import { useOrganization, useWorkspace } from "@app/context"; import { useToggle } from "@app/hooks"; import { ProjectType } from "@app/hooks/api/workspace/types"; @@ -59,7 +60,7 @@ export default function NavHeader({ const [isHoveringCopyButton, setIsHoveringCopyButton] = useState(false); const routerEnvSlug = useParams({ - from: "/_authenticate/_ctx-org-details/secret-manager/$projectId/_layout-secret-manager/secrets/$envSlug/", + from: ROUTE_PATHS.SecretDashboardPage.id, select: (el) => el.envSlug }); diff --git a/frontend-v2/src/components/secrets/SecretReferenceDetails/index.tsx b/frontend-v2/src/components/secrets/SecretReferenceDetails/index.tsx index 6238ff612..98cb65c62 100644 --- a/frontend-v2/src/components/secrets/SecretReferenceDetails/index.tsx +++ b/frontend-v2/src/components/secrets/SecretReferenceDetails/index.tsx @@ -1 +1 @@ -export { hasSecretReference,SecretReferenceTree } from "./SecretReferenceDetails"; +export { hasSecretReference, SecretReferenceTree } from "./SecretReferenceDetails"; diff --git a/frontend-v2/src/const/routes.ts b/frontend-v2/src/const/routes.ts index f40ad3329..7b2555b79 100644 --- a/frontend-v2/src/const/routes.ts +++ b/frontend-v2/src/const/routes.ts @@ -6,12 +6,36 @@ const setRoute = ({ full, id }) as const; export const ROUTE_PATHS = Object.freeze({ + Auth: { + LoginSSO: setRoute("/login/sso", "/_restrict-login-signup/login/sso") + }, + Organization: { + SecretScanning: setRoute( + "/organization/secret-scanning", + "/_authenticate/_inject-org-details/organization/_layout/secret-scanning" + ), + SettingsPage: setRoute( + "/organization/settings", + "/_authenticate/_inject-org-details/organization/_layout/settings" + ) + }, + SecretManager: { + ApprovalPage: setRoute( + "/secret-manager/$projectId/approval", + "/_authenticate/_inject-org-details/secret-manager/$projectId/_secret-manager-layout/approval" + ), + SecretDashboardPage: setRoute( + "/secret-manager/$projectId/secrets/$envSlug", + "/_authenticate/_inject-org-details/secret-manager/$projectId/_secret-manager-layout/secrets/$envSlug" + ) + }, ProviderSuccessPage: setRoute( "/login/provider/success", "/_restrict-login-signup/login/provider/success" ), SignUpSsoPage: setRoute("/signup/sso", "/_restrict-login-signup/signup/sso"), PasswordResetPage: setRoute("/password-reset", "/_restrict-login-signup/password-reset"), + ViewSharedSecretByIDPage: setRoute("/shared/secret/$secretId", "/shared/secret/$secretId"), OrgGroupDetailsByIDPage: setRoute( "/organization/groups/$groupId", "/_authenticate/_inject-org-details/organization/_layout/groups/$groupId" diff --git a/frontend-v2/src/context/OrgPermissionContext/OrgPermissionContext.tsx b/frontend-v2/src/context/OrgPermissionContext/OrgPermissionContext.tsx index b58c0e1f5..dbbc4a806 100644 --- a/frontend-v2/src/context/OrgPermissionContext/OrgPermissionContext.tsx +++ b/frontend-v2/src/context/OrgPermissionContext/OrgPermissionContext.tsx @@ -13,7 +13,7 @@ import { OrgPermissionSet } from "./types"; export const useOrgPermission = () => { const organizationId = useRouteContext({ - from: "/_authenticate/_ctx-org-details", + from: "/_authenticate/_inject-org-details", select: (el) => el.organizationId }); diff --git a/frontend-v2/src/context/OrganizationContext/OrganizationContext.tsx b/frontend-v2/src/context/OrganizationContext/OrganizationContext.tsx index 47f0912e8..26865b5bf 100644 --- a/frontend-v2/src/context/OrganizationContext/OrganizationContext.tsx +++ b/frontend-v2/src/context/OrganizationContext/OrganizationContext.tsx @@ -5,7 +5,7 @@ import { fetchOrganizationById, organizationKeys } from "@app/hooks/api/organiza export const useOrganization = () => { const organizationId = useRouteContext({ - from: "/_authenticate/_ctx-org-details", + from: "/_authenticate/_inject-org-details", select: (el) => el.organizationId }); diff --git a/frontend-v2/src/context/SubscriptionContext/SubscriptionContext.tsx b/frontend-v2/src/context/SubscriptionContext/SubscriptionContext.tsx index 8722ff4f8..de52e5f18 100644 --- a/frontend-v2/src/context/SubscriptionContext/SubscriptionContext.tsx +++ b/frontend-v2/src/context/SubscriptionContext/SubscriptionContext.tsx @@ -5,7 +5,7 @@ import { fetchOrgSubscription, subscriptionQueryKeys } from "@app/hooks/api/subs export const useSubscription = () => { const organizationId = useRouteContext({ - from: "/_authenticate/_ctx-org-details", + from: "/_authenticate/_inject-org-details", select: (el) => el.organizationId }); diff --git a/frontend-v2/src/layouts/AdminLayout/AdminLayout.tsx b/frontend-v2/src/layouts/AdminLayout/AdminLayout.tsx new file mode 100644 index 000000000..f74c9103b --- /dev/null +++ b/frontend-v2/src/layouts/AdminLayout/AdminLayout.tsx @@ -0,0 +1,89 @@ +import { useTranslation } from "react-i18next"; +import { faArrowLeft, faInfo, faMobile, faQuestion } from "@fortawesome/free-solid-svg-icons"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { Link, Outlet } from "@tanstack/react-router"; + +import { WishForm } from "@app/components/features/WishForm"; +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuTrigger +} from "@app/components/v2"; +import { ProjectType } from "@app/hooks/api/workspace/types"; + +import { InsecureConnectionBanner } from "../OrganizationLayout/components/InsecureConnectionBanner"; +import { INFISICAL_SUPPORT_OPTIONS } from "../OrganizationLayout/components/SidebarFooter/SidebarFooter"; + +export const AdminLayout = () => { + const { t } = useTranslation(); + + const infisicalPlatformVersion = import.meta.env.VITE_INFISICAL_PLATFORM_VERSION; + + return ( + <> +
+ {!window.isSecureContext && } +
+ +
+ +
+
+
+
+ +

+ {` ${t("common.no-mobile")} `} +

+
+ + ); +}; diff --git a/frontend-v2/src/layouts/AdminLayout/index.tsx b/frontend-v2/src/layouts/AdminLayout/index.tsx new file mode 100644 index 000000000..1a136d62f --- /dev/null +++ b/frontend-v2/src/layouts/AdminLayout/index.tsx @@ -0,0 +1 @@ +export { AdminLayout } from "./AdminLayout"; diff --git a/frontend-v2/src/layouts/OrganizationLayout/OrganizationLayout.tsx b/frontend-v2/src/layouts/OrganizationLayout/OrganizationLayout.tsx index 36f7d6177..e0a596d77 100644 --- a/frontend-v2/src/layouts/OrganizationLayout/OrganizationLayout.tsx +++ b/frontend-v2/src/layouts/OrganizationLayout/OrganizationLayout.tsx @@ -92,7 +92,7 @@ export const OrganizationLayout = () => { )} - + {({ isActive }) => ( Access Control diff --git a/frontend-v2/src/layouts/OrganizationLayout/components/SidebarFooter/SidebarFooter.tsx b/frontend-v2/src/layouts/OrganizationLayout/components/SidebarFooter/SidebarFooter.tsx index 9c7d55fcf..8b4db193f 100644 --- a/frontend-v2/src/layouts/OrganizationLayout/components/SidebarFooter/SidebarFooter.tsx +++ b/frontend-v2/src/layouts/OrganizationLayout/components/SidebarFooter/SidebarFooter.tsx @@ -62,7 +62,7 @@ export const SidebarFooter = () => { {(window.location.origin.includes("https://app.infisical.com") || window.location.origin.includes("https://gamma.infisical.com")) && } { )} { return (
- +
diff --git a/frontend-v2/src/pages/admin/OverviewPage/OverviewPage.tsx b/frontend-v2/src/pages/admin/OverviewPage/OverviewPage.tsx new file mode 100644 index 000000000..67c1bef18 --- /dev/null +++ b/frontend-v2/src/pages/admin/OverviewPage/OverviewPage.tsx @@ -0,0 +1,357 @@ +import { Helmet } from "react-helmet"; +import { Controller, useForm } from "react-hook-form"; +import { useTranslation } from "react-i18next"; +import { faAt } from "@fortawesome/free-solid-svg-icons"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { zodResolver } from "@hookform/resolvers/zod"; +import { z } from "zod"; + +import { createNotification } from "@app/components/notifications"; +import { + Button, + ContentLoader, + FormControl, + Input, + Select, + SelectClear, + SelectItem, + Switch, + Tab, + TabList, + TabPanel, + Tabs +} from "@app/components/v2"; +import { useServerConfig, useUser } from "@app/context"; +import { + useGetOrganizations, + useGetServerRootKmsEncryptionDetails, + useUpdateServerConfig +} from "@app/hooks/api"; + +import { AuthPanel } from "./components/AuthPanel"; +import { EncryptionPanel } from "./components/EncryptionPanel"; +import { IntegrationPanel } from "./components/IntegrationPanel"; +import { RateLimitPanel } from "./components/RateLimitPanel"; +import { UserPanel } from "./components/UserPanel"; + +enum TabSections { + Settings = "settings", + Encryption = "encryption", + Auth = "auth", + RateLimit = "rate-limit", + Integrations = "integrations", + Users = "users" +} + +enum SignUpModes { + Disabled = "disabled", + Anyone = "anyone" +} + +const formSchema = z.object({ + signUpMode: z.nativeEnum(SignUpModes), + allowedSignUpDomain: z.string().optional().nullable(), + trustSamlEmails: z.boolean(), + trustLdapEmails: z.boolean(), + trustOidcEmails: z.boolean(), + defaultAuthOrgId: z.string() +}); + +type TDashboardForm = z.infer; + +export const OverviewPage = () => { + const { t } = useTranslation(); + const data = useServerConfig(); + const { data: serverRootKmsDetails } = useGetServerRootKmsEncryptionDetails(); + const { config } = data; + + const { + control, + handleSubmit, + watch, + formState: { isSubmitting, isDirty } + } = useForm({ + resolver: zodResolver(formSchema), + values: { + // eslint-disable-next-line + signUpMode: config.allowSignUp ? SignUpModes.Anyone : SignUpModes.Disabled, + allowedSignUpDomain: config.allowedSignUpDomain, + trustSamlEmails: config.trustSamlEmails, + trustLdapEmails: config.trustLdapEmails, + trustOidcEmails: config.trustOidcEmails, + defaultAuthOrgId: config.defaultAuthOrgId ?? "" + } + }); + + const signUpMode = watch("signUpMode"); + const defaultAuthOrgId = watch("defaultAuthOrgId"); + + const { user } = useUser(); + const { mutateAsync: updateServerConfig } = useUpdateServerConfig(); + + const organizations = useGetOrganizations(); + + const isNotAllowed = !user?.superAdmin; + const onFormSubmit = async (formData: TDashboardForm) => { + try { + const { allowedSignUpDomain, trustSamlEmails, trustLdapEmails, trustOidcEmails } = formData; + + await updateServerConfig({ + defaultAuthOrgId: defaultAuthOrgId || null, + allowSignUp: signUpMode !== SignUpModes.Disabled, + allowedSignUpDomain: signUpMode === SignUpModes.Anyone ? allowedSignUpDomain : null, + trustSamlEmails, + trustLdapEmails, + trustOidcEmails + }); + createNotification({ + text: "Successfully changed sign up setting.", + type: "success" + }); + } catch (e) { + console.error(e); + createNotification({ + type: "error", + text: "Failed to update sign up setting." + }); + } + }; + + return ( + <> + + {t("common.head-title", { title: t("admin.dashboard") })} + + + + + +
+
+
+
+

Server Admin Console

+

+ Manage your instance level configurations. +

+
+
+ {isNotAllowed ? ( + + ) : ( +
+ + +
+ General + Encryption + Authentication + Rate Limit + Integrations + Users +
+
+ +
+
+
+ Allow user signups +
+
+ Select if you want users to be able to signup freely into your Infisical + instance. +
+ ( + + + + )} + /> +
+ {signUpMode === "anyone" && ( +
+
+ Restrict signup by email domain(s) +
+ ( + + } + /> + + )} + /> +
+ )} + +
+
+ Default organization +
+
+ Select the default organization you want to set for SAML/LDAP/OIDC based + logins. When selected, user logins will be automatically scoped to the + selected organization. +
+ ( + + + + )} + /> +
+ +
+
+ Trust emails +
+
+ Select if you want Infisical to trust external emails from SAML/LDAP/OIDC + identity providers. If set to false, then Infisical will prompt + SAML/LDAP/OIDC provisioned users to verify their email upon their first + login. +
+ { + return ( + + field.onChange(value)} + isChecked={field.value} + > +

Trust SAML emails

+
+
+ ); + }} + /> + { + return ( + + field.onChange(value)} + isChecked={field.value} + > +

Trust LDAP emails

+
+
+ ); + }} + /> + { + return ( + + field.onChange(value)} + isChecked={field.value} + > +

Trust OIDC emails

+
+
+ ); + }} + /> +
+ +
+
+ + + + + + + + + + + + + + + +
+
+ )} +
+
+ + ); +}; diff --git a/frontend-v2/src/pages/admin/OverviewPage/components/AuthPanel.tsx b/frontend-v2/src/pages/admin/OverviewPage/components/AuthPanel.tsx new file mode 100644 index 000000000..84e48ea0f --- /dev/null +++ b/frontend-v2/src/pages/admin/OverviewPage/components/AuthPanel.tsx @@ -0,0 +1,252 @@ +import { Controller, useForm } from "react-hook-form"; +import { zodResolver } from "@hookform/resolvers/zod"; +import { z } from "zod"; + +import { createNotification } from "@app/components/notifications"; +import { Button, FormControl, Switch } from "@app/components/v2"; +import { useServerConfig } from "@app/context"; +import { useUpdateServerConfig } from "@app/hooks/api"; +import { LoginMethod } from "@app/hooks/api/admin/types"; + +const formSchema = z.object({ + isEmailEnabled: z.boolean(), + isGoogleEnabled: z.boolean(), + isGithubEnabled: z.boolean(), + isGitlabEnabled: z.boolean(), + isSamlEnabled: z.boolean(), + isLdapEnabled: z.boolean(), + isOidcEnabled: z.boolean() +}); + +type TAuthForm = z.infer; + +export const AuthPanel = () => { + const { config } = useServerConfig(); + const { enabledLoginMethods } = config; + const { mutateAsync: updateServerConfig } = useUpdateServerConfig(); + + const { + control, + handleSubmit, + formState: { isSubmitting, isDirty } + } = useForm({ + resolver: zodResolver(formSchema), + // if not yet explicitly defined by the admin, all login methods should be enabled by default + values: enabledLoginMethods + ? { + isEmailEnabled: enabledLoginMethods.includes(LoginMethod.EMAIL), + isGoogleEnabled: enabledLoginMethods.includes(LoginMethod.GOOGLE), + isGithubEnabled: enabledLoginMethods.includes(LoginMethod.GITHUB), + isGitlabEnabled: enabledLoginMethods.includes(LoginMethod.GITLAB), + isSamlEnabled: enabledLoginMethods.includes(LoginMethod.SAML), + isLdapEnabled: enabledLoginMethods.includes(LoginMethod.LDAP), + isOidcEnabled: enabledLoginMethods.includes(LoginMethod.OIDC) + } + : { + isEmailEnabled: true, + isGoogleEnabled: true, + isGithubEnabled: true, + isGitlabEnabled: true, + isSamlEnabled: true, + isLdapEnabled: true, + isOidcEnabled: true + } + }); + + const onAuthFormSubmit = async (formData: TAuthForm) => { + try { + const enabledMethods: LoginMethod[] = []; + if (formData.isEmailEnabled) { + enabledMethods.push(LoginMethod.EMAIL); + } + + if (formData.isGoogleEnabled) { + enabledMethods.push(LoginMethod.GOOGLE); + } + + if (formData.isGithubEnabled) { + enabledMethods.push(LoginMethod.GITHUB); + } + + if (formData.isGitlabEnabled) { + enabledMethods.push(LoginMethod.GITLAB); + } + + if (formData.isSamlEnabled) { + enabledMethods.push(LoginMethod.SAML); + } + + if (formData.isLdapEnabled) { + enabledMethods.push(LoginMethod.LDAP); + } + + if (formData.isOidcEnabled) { + enabledMethods.push(LoginMethod.OIDC); + } + + if (!enabledMethods.length) { + createNotification({ + type: "error", + text: "At least one login method should be enabled." + }); + return; + } + + await updateServerConfig({ + enabledLoginMethods: enabledMethods + }); + + createNotification({ + text: "Login methods have been successfully updated.", + type: "success" + }); + } catch (e) { + console.error(e); + createNotification({ + type: "error", + text: "Failed to update login methods." + }); + } + }; + + return ( +
+
+
Login Methods
+
+ Select the login methods you wish to allow for all users of this instance. +
+ { + return ( + + field.onChange(value)} + isChecked={field.value} + > +

Email

+
+
+ ); + }} + /> + { + return ( + + field.onChange(value)} + isChecked={field.value} + > +

Google SSO

+
+
+ ); + }} + /> + { + return ( + + field.onChange(value)} + isChecked={field.value} + > +

Github SSO

+
+
+ ); + }} + /> + { + return ( + + field.onChange(value)} + isChecked={field.value} + > +

Gitlab SSO

+
+
+ ); + }} + /> + { + return ( + + field.onChange(value)} + isChecked={field.value} + > +

SAML SSO

+
+
+ ); + }} + /> + { + return ( + + field.onChange(value)} + isChecked={field.value} + > +

OIDC SSO

+
+
+ ); + }} + /> +
+ { + return ( + + field.onChange(value)} + isChecked={field.value} + > +

LDAP

+
+
+ ); + }} + /> + + + ); +}; diff --git a/frontend-v2/src/pages/admin/OverviewPage/components/EncryptionPanel.tsx b/frontend-v2/src/pages/admin/OverviewPage/components/EncryptionPanel.tsx new file mode 100644 index 000000000..bb6e55d8c --- /dev/null +++ b/frontend-v2/src/pages/admin/OverviewPage/components/EncryptionPanel.tsx @@ -0,0 +1,138 @@ +import { useCallback } from "react"; +import { Controller, useForm } from "react-hook-form"; +import { zodResolver } from "@hookform/resolvers/zod"; +import { z } from "zod"; + +import { UpgradePlanModal } from "@app/components/license/UpgradePlanModal"; +import { createNotification } from "@app/components/notifications"; +import { Button, FormControl, Select, SelectItem } from "@app/components/v2"; +import { useSubscription } from "@app/context"; +import { usePopUp } from "@app/hooks"; +import { useUpdateServerEncryptionStrategy } from "@app/hooks/api"; +import { + RootKeyEncryptionStrategy, + TGetServerRootKmsEncryptionDetails +} from "@app/hooks/api/admin/types"; + +const formSchema = z.object({ + encryptionStrategy: z.nativeEnum(RootKeyEncryptionStrategy) +}); + +const strategies: Record = { + [RootKeyEncryptionStrategy.Software]: "Software-based Encryption", + [RootKeyEncryptionStrategy.HSM]: "Hardware Security Module (HSM)" +}; + +type TForm = z.infer; + +type Props = { + rootKmsDetails?: TGetServerRootKmsEncryptionDetails; +}; + +export const EncryptionPanel = ({ rootKmsDetails }: Props) => { + const { mutateAsync: updateEncryptionStrategy } = useUpdateServerEncryptionStrategy(); + const { subscription } = useSubscription(); + + const { popUp, handlePopUpOpen, handlePopUpToggle } = usePopUp(["upgradePlan"] as const); + + const { + control, + handleSubmit, + formState: { isSubmitting, isDirty } + } = useForm({ + resolver: zodResolver(formSchema), + values: { + encryptionStrategy: + rootKmsDetails?.strategies?.find((s) => s.enabled)?.strategy ?? + RootKeyEncryptionStrategy.Software + } + }); + + const onSubmit = useCallback(async (formData: TForm) => { + if (!subscription) return; + + if (!subscription.hsm) { + handlePopUpOpen("upgradePlan", { + description: "Hardware Security Module's (HSM's), are only available on Enterprise plans." + }); + return; + } + + try { + await updateEncryptionStrategy(formData.encryptionStrategy); + + createNotification({ + type: "success", + text: "Encryption strategy updated successfully" + }); + } catch { + createNotification({ + type: "error", + text: "Failed to update encryption strategy" + }); + } + }, []); + + return ( + <> +
+
+
+
+ KMS Encryption Strategy +
+
+
+ Select which type of encryption strategy you want to use for your KMS root key. HSM is + supported on Enterprise plans. +
+ + {!!rootKmsDetails && ( + ( + + + + )} + /> + )} +
+ + +
+ handlePopUpToggle("upgradePlan", isOpen)} + text={(popUp.upgradePlan?.data as { description: string })?.description} + /> + + ); +}; diff --git a/frontend-v2/src/pages/admin/OverviewPage/components/IntegrationPanel.tsx b/frontend-v2/src/pages/admin/OverviewPage/components/IntegrationPanel.tsx new file mode 100644 index 000000000..9bb005ce4 --- /dev/null +++ b/frontend-v2/src/pages/admin/OverviewPage/components/IntegrationPanel.tsx @@ -0,0 +1,166 @@ +import { useEffect } from "react"; +import { Controller, useForm } from "react-hook-form"; +import { zodResolver } from "@hookform/resolvers/zod"; +import { z } from "zod"; + +import { createNotification } from "@app/components/notifications"; +import { Button, FormControl, Input } from "@app/components/v2"; +import { useToggle } from "@app/hooks"; +import { useGetAdminSlackConfig, useUpdateServerConfig } from "@app/hooks/api"; + +const slackFormSchema = z.object({ + clientId: z.string(), + clientSecret: z.string() +}); + +type TSlackForm = z.infer; + +const getCustomSlackAppCreationUrl = () => + `https://api.slack.com/apps?new_app=1&manifest_json=${encodeURIComponent( + JSON.stringify({ + display_information: { + name: "Infisical", + description: "Get real-time Infisical updates in Slack", + background_color: "#c2d62b", + long_description: `This Slack application is designed specifically for use with your self-hosted Infisical instance, allowing seamless integration between your Infisical projects and your Slack workspace. With this integration, your team can stay up-to-date with the latest events, changes, and notifications directly inside Slack. + - Notifications: Receive real-time updates and alerts about critical events in your Infisical projects. Whether it's a new project being created, updates to secrets, or changes to your team's configuration, you will be promptly notified within the designated Slack channels of your choice. + - Customization: Tailor the notifications to your team's specific needs by configuring which types of events trigger alerts and in which channels they are sent. + - Collaboration: Keep your entire team in the loop with notifications that help facilitate more efficient collaboration by ensuring that everyone is aware of important developments in your Infisical projects. + + By integrating Infisical with Slack, you can enhance your workflow by combining the power of secure secrets management with the communication capabilities of Slack.` + }, + features: { + app_home: { + home_tab_enabled: false, + messages_tab_enabled: false, + messages_tab_read_only_enabled: true + }, + bot_user: { + display_name: "Infisical", + always_online: true + } + }, + oauth_config: { + redirect_urls: [`${window.origin}/api/v1/workflow-integrations/slack/oauth_redirect`], + scopes: { + bot: ["chat:write.public", "chat:write", "channels:read", "groups:read"] + } + }, + settings: { + org_deploy_enabled: false, + socket_mode_enabled: false, + token_rotation_enabled: false + } + }) + )}`; + +export const IntegrationPanel = () => { + const { + control, + handleSubmit, + setValue, + formState: { isSubmitting, isDirty } + } = useForm({ + resolver: zodResolver(slackFormSchema) + }); + + const { data: adminSlackConfig } = useGetAdminSlackConfig(); + const { mutateAsync: updateAdminServerConfig } = useUpdateServerConfig(); + const [isSlackClientIdFocused, setIsSlackClientIdFocused] = useToggle(); + const [isSlackClientSecretFocused, setIsSlackClientSecretFocused] = useToggle(); + + useEffect(() => { + if (adminSlackConfig) { + setValue("clientId", adminSlackConfig.clientId); + setValue("clientSecret", adminSlackConfig.clientSecret); + } + }, [adminSlackConfig]); + + const onSlackFormSubmit = async (data: TSlackForm) => { + await updateAdminServerConfig({ + slackClientId: data.clientId, + slackClientSecret: data.clientSecret + }); + + createNotification({ + text: "Updated admin slack configuration", + type: "success" + }); + }; + + return ( +
+
+
Slack Integration
+
+ Step 1: Create your Infisical Slack App +
+
+ +
+
+ Step 2: Configure your instance-wide settings to enable integration with Slack. Copy the + values from the App Credentials page of your custom Slack App. +
+ ( + + setIsSlackClientIdFocused.on()} + onBlur={() => setIsSlackClientIdFocused.off()} + onChange={(e) => field.onChange(e.target.value)} + /> + + )} + /> + ( + + setIsSlackClientSecretFocused.on()} + onBlur={() => setIsSlackClientSecretFocused.off()} + onChange={(e) => field.onChange(e.target.value)} + /> + + )} + /> +
+ +
+ ); +}; diff --git a/frontend-v2/src/pages/admin/OverviewPage/components/RateLimitPanel.tsx b/frontend-v2/src/pages/admin/OverviewPage/components/RateLimitPanel.tsx new file mode 100644 index 000000000..74264132e --- /dev/null +++ b/frontend-v2/src/pages/admin/OverviewPage/components/RateLimitPanel.tsx @@ -0,0 +1,240 @@ +import { Controller, useForm } from "react-hook-form"; +import { zodResolver } from "@hookform/resolvers/zod"; +import { z } from "zod"; + +import { UpgradePlanModal } from "@app/components/license/UpgradePlanModal"; +import { createNotification } from "@app/components/notifications"; +import { Button, ContentLoader, FormControl, Input } from "@app/components/v2"; +import { useSubscription } from "@app/context"; +import { usePopUp } from "@app/hooks"; +import { useGetRateLimit, useUpdateRateLimit } from "@app/hooks/api"; + +const formSchema = z.object({ + readRateLimit: z.number(), + writeRateLimit: z.number(), + secretsRateLimit: z.number(), + authRateLimit: z.number(), + inviteUserRateLimit: z.number(), + mfaRateLimit: z.number(), + publicEndpointLimit: z.number() +}); + +type TRateLimitForm = z.infer; + +export const RateLimitPanel = () => { + const { data: rateLimit, isPending } = useGetRateLimit(); + const { subscription } = useSubscription(); + const { mutateAsync: updateRateLimit } = useUpdateRateLimit(); + const { handlePopUpToggle, handlePopUpOpen, popUp } = usePopUp(["upgradePlan"] as const); + + const { + control, + handleSubmit, + formState: { isSubmitting, isDirty } + } = useForm({ + resolver: zodResolver(formSchema), + values: { + // eslint-disable-next-line + readRateLimit: rateLimit?.readRateLimit ?? 600, + writeRateLimit: rateLimit?.writeRateLimit ?? 200, + secretsRateLimit: rateLimit?.secretsRateLimit ?? 60, + authRateLimit: rateLimit?.authRateLimit ?? 60, + inviteUserRateLimit: rateLimit?.inviteUserRateLimit ?? 30, + mfaRateLimit: rateLimit?.mfaRateLimit ?? 20, + publicEndpointLimit: rateLimit?.publicEndpointLimit ?? 30 + } + }); + + const onRateLimitFormSubmit = async (formData: TRateLimitForm) => { + try { + if (subscription && !subscription.customRateLimits) { + handlePopUpOpen("upgradePlan"); + return; + } + + const { + readRateLimit, + writeRateLimit, + secretsRateLimit, + authRateLimit, + inviteUserRateLimit, + mfaRateLimit, + publicEndpointLimit + } = formData; + + await updateRateLimit({ + readRateLimit, + writeRateLimit, + secretsRateLimit, + authRateLimit, + inviteUserRateLimit, + mfaRateLimit, + publicEndpointLimit + }); + createNotification({ + text: "Rate limits have been successfully updated. Please allow at least 10 minutes for the changes to take effect.", + type: "success" + }); + } catch (e) { + console.error(e); + createNotification({ + type: "error", + text: "Failed to update rate limiting setting." + }); + } + }; + + return isPending ? ( + + ) : ( +
+
+
Configure rate limits
+ ( + + field.onChange(Number(e.target.value))} + /> + + )} + /> + ( + + field.onChange(Number(e.target.value))} + /> + + )} + /> + ( + + field.onChange(Number(e.target.value))} + /> + + )} + /> + ( + + field.onChange(Number(e.target.value))} + /> + + )} + /> + ( + + field.onChange(Number(e.target.value))} + /> + + )} + /> + ( + + field.onChange(Number(e.target.value))} + /> + + )} + /> + ( + + field.onChange(Number(e.target.value))} + /> + + )} + /> +
+ + handlePopUpToggle("upgradePlan", isOpen)} + text="You can configure custom rate limits if you switch to Infisical's Enterprise plan." + /> + + ); +}; diff --git a/frontend-v2/src/pages/admin/OverviewPage/components/UserPanel.tsx b/frontend-v2/src/pages/admin/OverviewPage/components/UserPanel.tsx new file mode 100644 index 000000000..889420a73 --- /dev/null +++ b/frontend-v2/src/pages/admin/OverviewPage/components/UserPanel.tsx @@ -0,0 +1,183 @@ +import { useState } from "react"; +import { faMagnifyingGlass, faUsers, faXmark } from "@fortawesome/free-solid-svg-icons"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; + +import { UpgradePlanModal } from "@app/components/license/UpgradePlanModal"; +import { createNotification } from "@app/components/notifications"; +import { + Badge, + Button, + DeleteActionModal, + EmptyState, + IconButton, + Input, + Table, + TableContainer, + TableSkeleton, + TBody, + Td, + Th, + THead, + Tr +} from "@app/components/v2"; +import { useSubscription, useUser } from "@app/context"; +import { useDebounce, usePopUp } from "@app/hooks"; +import { useAdminDeleteUser, useAdminGetUsers } from "@app/hooks/api"; +import { UsePopUpState } from "@app/hooks/usePopUp"; + +const UserPanelTable = ({ + handlePopUpOpen +}: { + handlePopUpOpen: ( + popUpName: keyof UsePopUpState<["removeUser", "upgradePlan"]>, + data?: { + username: string; + id: string; + } + ) => void; +}) => { + const [searchUserFilter, setSearchUserFilter] = useState(""); + const { user } = useUser(); + const userId = user?.id || ""; + const [debounedSearchTerm] = useDebounce(searchUserFilter, 500); + const { subscription } = useSubscription(); + + const { data, isPending, isFetchingNextPage, hasNextPage, fetchNextPage } = useAdminGetUsers({ + limit: 20, + searchTerm: debounedSearchTerm + }); + + const isEmpty = !isPending && !data?.pages?.[0].length; + return ( + <> + setSearchUserFilter(e.target.value)} + leftIcon={} + placeholder="Search users..." + /> +
+ + + + + + + + + + {isPending && } + {!isPending && + data?.pages?.map((users) => + users.map(({ username, email, firstName, lastName, id, superAdmin }) => { + const name = firstName || lastName ? `${firstName} ${lastName}` : "-"; + + return ( + + + + + + ); + }) + )} + +
NameUsername +
+ {name} + {superAdmin && ( + + Server Admin + + )} + {email} + {userId !== id && ( +
+ { + if (!subscription?.instanceUserManagement) { + handlePopUpOpen("upgradePlan"); + return; + } + handlePopUpOpen("removeUser", { username, id }); + }} + > + + +
+ )} +
+ {!isPending && isEmpty && } +
+ {!isEmpty && ( + + )} +
+ + ); +}; + +export const UserPanel = () => { + const { handlePopUpToggle, popUp, handlePopUpOpen, handlePopUpClose } = usePopUp([ + "removeUser", + "upgradePlan" + ] as const); + + const { mutateAsync: deleteUser } = useAdminDeleteUser(); + + const handleRemoveUser = async () => { + const { id } = popUp?.removeUser?.data as { id: string; username: string }; + + try { + await deleteUser(id); + createNotification({ + type: "success", + text: "Successfully deleted user" + }); + } catch { + createNotification({ + type: "error", + text: "Error deleting user" + }); + } + + handlePopUpClose("removeUser"); + }; + + return ( +
+
+

Users

+
+ + handlePopUpToggle("removeUser", isOpen)} + onDeleteApproved={handleRemoveUser} + /> + handlePopUpToggle("upgradePlan", isOpen)} + text="Deleting users via Admin UI is only available on Infisical's Pro plan and above." + /> +
+ ); +}; diff --git a/frontend-v2/src/pages/admin/OverviewPage/route.tsx b/frontend-v2/src/pages/admin/OverviewPage/route.tsx new file mode 100644 index 000000000..45704f831 --- /dev/null +++ b/frontend-v2/src/pages/admin/OverviewPage/route.tsx @@ -0,0 +1,7 @@ +import { createFileRoute } from "@tanstack/react-router"; + +import { OverviewPage } from "./OverviewPage"; + +export const Route = createFileRoute("/_authenticate/admin/_admin-layout/")({ + component: OverviewPage +}); diff --git a/frontend-v2/src/pages/admin/SignUpPage/SignUpPage.tsx b/frontend-v2/src/pages/admin/SignUpPage/SignUpPage.tsx new file mode 100644 index 000000000..42cd7746c --- /dev/null +++ b/frontend-v2/src/pages/admin/SignUpPage/SignUpPage.tsx @@ -0,0 +1,255 @@ +import { useState } from "react"; +import { Helmet } from "react-helmet"; +import { Controller, useForm } from "react-hook-form"; +import { useTranslation } from "react-i18next"; +import { zodResolver } from "@hookform/resolvers/zod"; +import { useNavigate } from "@tanstack/react-router"; +import { AnimatePresence, motion } from "framer-motion"; +import { z } from "zod"; + +import { createNotification } from "@app/components/notifications"; +import { generateBackupPDFAsync } from "@app/components/utilities/generateBackupPDF"; +// TODO(akhilmhdh): rewrite this into module functions in lib +import { saveTokenToLocalStorage } from "@app/components/utilities/saveTokenToLocalStorage"; +import SecurityClient from "@app/components/utilities/SecurityClient"; +import { Button, ContentLoader, FormControl, Input } from "@app/components/v2"; +import { useServerConfig } from "@app/context"; +import { useCreateAdminUser, useSelectOrganization } from "@app/hooks/api"; +import { generateUserBackupKey, generateUserPassKey } from "@app/lib/crypto"; + +import { DownloadBackupKeys } from "./components/DownloadBackupKeys"; + +const formSchema = z + .object({ + email: z.string().email().trim(), + firstName: z.string().trim(), + lastName: z.string().trim().optional(), + password: z.string().trim().min(14).max(100), + confirmPassword: z.string().trim() + }) + .refine((data) => data.password === data.confirmPassword, { + message: "Password don't match", + path: ["confirmPassword"] + }); + +type TFormSchema = z.infer; + +enum SignupSteps { + DetailsForm = "details-form", + BackupKey = "backup-key" +} + +export const SignUpPage = () => { + const { t } = useTranslation(); + const navigate = useNavigate(); + const { + control, + handleSubmit, + getValues, + formState: { isSubmitting } + } = useForm({ + resolver: zodResolver(formSchema) + }); + + const [step, setStep] = useState(SignupSteps.DetailsForm); + + const { config } = useServerConfig(); + + // TODO(rbr): do this is layout + // useEffect(() => { + // if (config?.initialized) { + // if (isLoggedIn()) { + // navigate.push("/admin"); + // } else { + // navigate.push("/login"); + // } + // } + // }, []); + + const { mutateAsync: createAdminUser } = useCreateAdminUser(); + const { mutateAsync: selectOrganization } = useSelectOrganization(); + + const handleFormSubmit = async ({ email, password, firstName, lastName }: TFormSchema) => { + // avoid multi submission + if (isSubmitting) return; + try { + const { privateKey, ...userPass } = await generateUserPassKey(email, password); + const res = await createAdminUser({ + email, + password, + firstName, + lastName, + ...userPass + }); + + SecurityClient.setToken(res.token); + saveTokenToLocalStorage({ + publicKey: userPass.publicKey, + encryptedPrivateKey: userPass.encryptedPrivateKey, + iv: userPass.encryptedPrivateKeyIV, + tag: userPass.encryptedPrivateKeyTag, + privateKey + }); + await selectOrganization({ organizationId: res.organization.id }); + + // TODO(akhilmhdh): This is such a confusing pattern and too unreliable + // Will be refactored in next iteration to make it url based rather than local storage ones + // Part of migration to nextjs 14 + localStorage.setItem("orgData.id", res.organization.id); + setStep(SignupSteps.BackupKey); + } catch (err) { + console.log(err); + createNotification({ + type: "error", + text: "Failed to create admin" + }); + } + }; + + const handleBackupKeyGenerate = async () => { + try { + const { email, password, firstName, lastName } = getValues(); + const generatedKey = await generateUserBackupKey(email, password); + await generateBackupPDFAsync({ + generatedKey, + personalEmail: email, + personalName: `${firstName} ${lastName}` + }); + navigate({ to: "/admin" }); + } catch (err) { + console.log(err); + createNotification({ + type: "error", + text: "Failed to generate backup" + }); + } + }; + + if (config?.initialized && step === SignupSteps.DetailsForm) + return ; + + return ( +
+ + {t("common.head-title", { title: t("signup.title") })} + + + + + +
+ + {step === SignupSteps.DetailsForm && ( + +
+ Infisical logo +
Welcome to Infisical
+
Create your first Super Admin Account
+
+
+
+
+ ( + + + + )} + /> + ( + + + + )} + /> +
+ ( + + + + )} + /> + ( + + + + )} + /> + ( + + + + )} + /> +
+ +
+
+ )} + {step === SignupSteps.BackupKey && ( + + + + )} +
+
+
+ ); +}; diff --git a/frontend-v2/src/pages/admin/SignUpPage/components/DownloadBackupKeys/DownloadBackupKeys.tsx b/frontend-v2/src/pages/admin/SignUpPage/components/DownloadBackupKeys/DownloadBackupKeys.tsx new file mode 100644 index 000000000..253031a91 --- /dev/null +++ b/frontend-v2/src/pages/admin/SignUpPage/components/DownloadBackupKeys/DownloadBackupKeys.tsx @@ -0,0 +1,56 @@ +import { useTranslation } from "react-i18next"; +import { faWarning } from "@fortawesome/free-solid-svg-icons"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; + +import { Button } from "@app/components/v2"; +import { useToggle } from "@app/hooks"; + +type Props = { + onGenerate: () => Promise; +}; + +export const DownloadBackupKeys = ({ onGenerate }: Props): JSX.Element => { + const { t } = useTranslation(); + const [isLoading, setIsLoading] = useToggle(); + + return ( +
+

+ + {t("signup.step4-message")} +

+
+
+ + {t("signup.step4-description1")} {t("signup.step4-description3")} + +
+
+
+ +
+
+
+
+ ); +}; diff --git a/frontend-v2/src/pages/admin/SignUpPage/components/DownloadBackupKeys/index.tsx b/frontend-v2/src/pages/admin/SignUpPage/components/DownloadBackupKeys/index.tsx new file mode 100644 index 000000000..bbbd9aad9 --- /dev/null +++ b/frontend-v2/src/pages/admin/SignUpPage/components/DownloadBackupKeys/index.tsx @@ -0,0 +1 @@ +export { DownloadBackupKeys } from "./DownloadBackupKeys"; diff --git a/frontend-v2/src/pages/admin/SignUpPage/route.tsx b/frontend-v2/src/pages/admin/SignUpPage/route.tsx new file mode 100644 index 000000000..b5f3cf44a --- /dev/null +++ b/frontend-v2/src/pages/admin/SignUpPage/route.tsx @@ -0,0 +1,14 @@ +import { createFileRoute, redirect } from "@tanstack/react-router"; + +import { SignUpPage } from "./SignUpPage"; + +export const Route = createFileRoute("/_restrict-login-signup/admin/signup")({ + component: SignUpPage, + beforeLoad: ({ context }) => { + if (context.serverConfig.initialized) { + throw redirect({ + to: "/login" + }); + } + } +}); diff --git a/frontend-v2/src/pages/admin/layout.tsx b/frontend-v2/src/pages/admin/layout.tsx new file mode 100644 index 000000000..dfe4f6b17 --- /dev/null +++ b/frontend-v2/src/pages/admin/layout.tsx @@ -0,0 +1,14 @@ +import { createFileRoute, redirect } from "@tanstack/react-router"; + +import { AdminLayout } from "@app/layouts/AdminLayout"; + +export const Route = createFileRoute("/_authenticate/admin/_admin-layout")({ + component: AdminLayout, + beforeLoad: ({ context }) => { + if (!context.user.superAdmin) { + throw redirect({ + to: "/organization/secret-manager/overview" + }); + } + } +}); diff --git a/frontend-v2/src/pages/auth/CliRedirectPage/route.tsx b/frontend-v2/src/pages/auth/CliRedirectPage/route.tsx index db8b032d3..e9c4e5750 100644 --- a/frontend-v2/src/pages/auth/CliRedirectPage/route.tsx +++ b/frontend-v2/src/pages/auth/CliRedirectPage/route.tsx @@ -2,6 +2,6 @@ import { createFileRoute } from "@tanstack/react-router"; import { CliRedirectPage } from "./CliRedirectPage"; -export const Route = createFileRoute("/_authenticate/cli-redirect")({ +export const Route = createFileRoute("/_restrict-login-signup/cli-redirect")({ component: CliRedirectPage }); diff --git a/frontend-v2/src/pages/auth/EmailNotVerifiedPage/route.tsx b/frontend-v2/src/pages/auth/EmailNotVerifiedPage/route.tsx index 034880d09..420ce3c10 100644 --- a/frontend-v2/src/pages/auth/EmailNotVerifiedPage/route.tsx +++ b/frontend-v2/src/pages/auth/EmailNotVerifiedPage/route.tsx @@ -1,4 +1,5 @@ import { createFileRoute } from "@tanstack/react-router"; + import { EmailNotVerifiedPage } from "./EmailNotVerifiedPage"; export const Route = createFileRoute("/_restrict-login-signup/email-not-verified")({ diff --git a/frontend-v2/src/pages/auth/LoginPage/route.tsx b/frontend-v2/src/pages/auth/LoginPage/route.tsx index 08b2fe07c..dd0dadccd 100644 --- a/frontend-v2/src/pages/auth/LoginPage/route.tsx +++ b/frontend-v2/src/pages/auth/LoginPage/route.tsx @@ -1,7 +1,7 @@ -import { createFileRoute } from '@tanstack/react-router' +import { createFileRoute } from "@tanstack/react-router"; -import { LoginPage } from './LoginPage' +import { LoginPage } from "./LoginPage"; -export const Route = createFileRoute('/_restrict-login-signup/login/')({ - component: LoginPage, -}) +export const Route = createFileRoute("/_restrict-login-signup/login/")({ + component: LoginPage +}); diff --git a/frontend-v2/src/pages/auth/LoginSsoPage/LoginSsoPage.tsx b/frontend-v2/src/pages/auth/LoginSsoPage/LoginSsoPage.tsx index 6ec6e2c9d..f4d1ea856 100644 --- a/frontend-v2/src/pages/auth/LoginSsoPage/LoginSsoPage.tsx +++ b/frontend-v2/src/pages/auth/LoginSsoPage/LoginSsoPage.tsx @@ -4,11 +4,13 @@ import { useTranslation } from "react-i18next"; import { Link, useSearch } from "@tanstack/react-router"; import { jwtDecode } from "jwt-decode"; +import { ROUTE_PATHS } from "@app/const/routes"; + import { PasswordStep } from "../LoginPage/components"; export const LoginSsoPage = () => { const { t } = useTranslation(); - const search = useSearch({ from: "/_restrict-login-signup/login/sso/" }); + const search = useSearch({ from: ROUTE_PATHS.Auth.LoginSSO.id }); const token = search.token as string; const [step, setStep] = useState(0); const [password, setPassword] = useState(""); diff --git a/frontend-v2/src/pages/auth/ProviderErrorPage/route.tsx b/frontend-v2/src/pages/auth/ProviderErrorPage/route.tsx index 339d546fb..6df6a07a3 100644 --- a/frontend-v2/src/pages/auth/ProviderErrorPage/route.tsx +++ b/frontend-v2/src/pages/auth/ProviderErrorPage/route.tsx @@ -1,9 +1,7 @@ -import { createFileRoute } from '@tanstack/react-router' +import { createFileRoute } from "@tanstack/react-router"; -import { LoginProviderErrorPage } from './ProviderErrorPage' +import { LoginProviderErrorPage } from "./ProviderErrorPage"; -export const Route = createFileRoute( - '/_restrict-login-signup/login/provider/error', -)({ - component: LoginProviderErrorPage, -}) +export const Route = createFileRoute("/_restrict-login-signup/login/provider/error")({ + component: LoginProviderErrorPage +}); diff --git a/frontend-v2/src/pages/auth/ProviderSuccessPage/route.tsx b/frontend-v2/src/pages/auth/ProviderSuccessPage/route.tsx index 21e0a101c..df71b2cb4 100644 --- a/frontend-v2/src/pages/auth/ProviderSuccessPage/route.tsx +++ b/frontend-v2/src/pages/auth/ProviderSuccessPage/route.tsx @@ -1,16 +1,14 @@ -import { createFileRoute } from '@tanstack/react-router' -import { zodValidator } from '@tanstack/zod-adapter' -import { z } from 'zod' +import { createFileRoute } from "@tanstack/react-router"; +import { zodValidator } from "@tanstack/zod-adapter"; +import { z } from "zod"; -import { LoginProviderSuccessPage } from './ProviderSuccessPage' +import { LoginProviderSuccessPage } from "./ProviderSuccessPage"; const LoginProviderSuccessQuerySchema = z.object({ - token: z.string(), -}) + token: z.string() +}); -export const Route = createFileRoute( - '/_restrict-login-signup/login/provider/success', -)({ +export const Route = createFileRoute("/_restrict-login-signup/login/provider/success")({ component: LoginProviderSuccessPage, - validateSearch: zodValidator(LoginProviderSuccessQuerySchema), -}) + validateSearch: zodValidator(LoginProviderSuccessQuerySchema) +}); diff --git a/frontend-v2/src/pages/auth/SelectOrgPage/route.tsx b/frontend-v2/src/pages/auth/SelectOrgPage/route.tsx index 7d4dd44b6..0267cd530 100644 --- a/frontend-v2/src/pages/auth/SelectOrgPage/route.tsx +++ b/frontend-v2/src/pages/auth/SelectOrgPage/route.tsx @@ -1,9 +1,7 @@ -import { createFileRoute } from '@tanstack/react-router' +import { createFileRoute } from "@tanstack/react-router"; -import { SelectOrganizationPage } from './SelectOrgPage' +import { SelectOrganizationPage } from "./SelectOrgPage"; -export const Route = createFileRoute( - '/_restrict-login-signup/login/select-organization', -)({ - component: SelectOrganizationPage, -}) +export const Route = createFileRoute("/_restrict-login-signup/login/select-organization")({ + component: SelectOrganizationPage +}); diff --git a/frontend-v2/src/pages/auth/SignUpSsoPage/route.tsx b/frontend-v2/src/pages/auth/SignUpSsoPage/route.tsx index 504f47783..a255efaf6 100644 --- a/frontend-v2/src/pages/auth/SignUpSsoPage/route.tsx +++ b/frontend-v2/src/pages/auth/SignUpSsoPage/route.tsx @@ -1,14 +1,14 @@ -import { createFileRoute } from '@tanstack/react-router' -import { zodValidator } from '@tanstack/zod-adapter' -import { z } from 'zod' +import { createFileRoute } from "@tanstack/react-router"; +import { zodValidator } from "@tanstack/zod-adapter"; +import { z } from "zod"; -import { SignupSsoPage } from './SignUpSsoPage' +import { SignupSsoPage } from "./SignUpSsoPage"; const SignupSSOPageQueryParamsSchema = z.object({ - token: z.string(), -}) + token: z.string() +}); -export const Route = createFileRoute('/_restrict-login-signup/signup/sso')({ +export const Route = createFileRoute("/_restrict-login-signup/signup/sso")({ component: SignupSsoPage, - validateSearch: zodValidator(SignupSSOPageQueryParamsSchema), -}) + validateSearch: zodValidator(SignupSSOPageQueryParamsSchema) +}); diff --git a/frontend-v2/src/pages/auth/VerifyEmailPage/route.tsx b/frontend-v2/src/pages/auth/VerifyEmailPage/route.tsx index 8019554f8..b5150364c 100644 --- a/frontend-v2/src/pages/auth/VerifyEmailPage/route.tsx +++ b/frontend-v2/src/pages/auth/VerifyEmailPage/route.tsx @@ -1,4 +1,5 @@ import { createFileRoute } from "@tanstack/react-router"; + import { VerifyEmailPage } from "./VerifyEmailPage"; export const Route = createFileRoute("/_restrict-login-signup/verify-email")({ diff --git a/frontend-v2/src/pages/cert-manager/CertAuthDetailsByIDPage/CertAuthDetailsByIDPage.tsx b/frontend-v2/src/pages/cert-manager/CertAuthDetailsByIDPage/CertAuthDetailsByIDPage.tsx index 2552a57c6..d7a2b4360 100644 --- a/frontend-v2/src/pages/cert-manager/CertAuthDetailsByIDPage/CertAuthDetailsByIDPage.tsx +++ b/frontend-v2/src/pages/cert-manager/CertAuthDetailsByIDPage/CertAuthDetailsByIDPage.tsx @@ -63,7 +63,12 @@ const Page = () => { }); handlePopUpClose("deleteCa"); - navigate({ to: `/${ProjectType.CertificateManager}/${projectId}/certificates` as const }); + navigate({ + to: `/${ProjectType.CertificateManager}/$projectId/overview` as const, + params: { + projectId + } + }); } catch { createNotification({ text: "Failed to delete CA", @@ -82,7 +87,10 @@ const Page = () => { leftIcon={} onClick={() => navigate({ - to: `/${ProjectType.CertificateManager}/${projectId}/certificates` as const + to: `/${ProjectType.CertificateManager}/${projectId}/overview` as const, + params: { + projectId + } }) } className="mb-4" diff --git a/frontend-v2/src/pages/cert-manager/CertAuthDetailsByIDPage/route.tsx b/frontend-v2/src/pages/cert-manager/CertAuthDetailsByIDPage/route.tsx index 145ec5057..112d0c4c1 100644 --- a/frontend-v2/src/pages/cert-manager/CertAuthDetailsByIDPage/route.tsx +++ b/frontend-v2/src/pages/cert-manager/CertAuthDetailsByIDPage/route.tsx @@ -1,9 +1,9 @@ -import { createFileRoute } from '@tanstack/react-router' +import { createFileRoute } from "@tanstack/react-router"; -import { CertAuthDetailsByIDPage } from './CertAuthDetailsByIDPage' +import { CertAuthDetailsByIDPage } from "./CertAuthDetailsByIDPage"; export const Route = createFileRoute( - '/_authenticate/_inject-org-details/cert-manager/$projectId/_cert-manager-layout/ca/$caId', + "/_authenticate/_inject-org-details/cert-manager/$projectId/_cert-manager-layout/ca/$caId" )({ - component: CertAuthDetailsByIDPage, -}) + component: CertAuthDetailsByIDPage +}); diff --git a/frontend-v2/src/pages/cert-manager/CertificatesPage/components/CaTab/components/CaInstallCertModal/ExternalCaInstallForm.tsx b/frontend-v2/src/pages/cert-manager/CertificatesPage/components/CaTab/components/CaInstallCertModal/ExternalCaInstallForm.tsx index 8b3ddd0cf..9ff62ff2e 100644 --- a/frontend-v2/src/pages/cert-manager/CertificatesPage/components/CaTab/components/CaInstallCertModal/ExternalCaInstallForm.tsx +++ b/frontend-v2/src/pages/cert-manager/CertificatesPage/components/CaTab/components/CaInstallCertModal/ExternalCaInstallForm.tsx @@ -65,7 +65,7 @@ export const ExternalCaInstallForm = ({ caId, handlePopUpToggle }: Props) => { type: "success" }); handlePopUpToggle("installCaCert", false); - } catch (err) { + } catch { createNotification({ text: "Failed to install certificate for CA", type: "error" diff --git a/frontend-v2/src/pages/cert-manager/CertificatesPage/components/CaTab/components/CaInstallCertModal/InternalCaInstallForm.tsx b/frontend-v2/src/pages/cert-manager/CertificatesPage/components/CaTab/components/CaInstallCertModal/InternalCaInstallForm.tsx index ddde187cb..4d0aa4a8e 100644 --- a/frontend-v2/src/pages/cert-manager/CertificatesPage/components/CaTab/components/CaInstallCertModal/InternalCaInstallForm.tsx +++ b/frontend-v2/src/pages/cert-manager/CertificatesPage/components/CaTab/components/CaInstallCertModal/InternalCaInstallForm.tsx @@ -126,7 +126,7 @@ export const InternalCaInstallForm = ({ caId, handlePopUpToggle }: Props) => { type: "success" }); handlePopUpToggle("installCaCert", false); - } catch (err) { + } catch { createNotification({ text: "Failed to install certificate for CA", type: "error" diff --git a/frontend-v2/src/pages/cert-manager/CertificatesPage/components/CaTab/components/CaTable.tsx b/frontend-v2/src/pages/cert-manager/CertificatesPage/components/CaTab/components/CaTable.tsx index 8acf45e81..295b7c319 100644 --- a/frontend-v2/src/pages/cert-manager/CertificatesPage/components/CaTab/components/CaTable.tsx +++ b/frontend-v2/src/pages/cert-manager/CertificatesPage/components/CaTab/components/CaTable.tsx @@ -78,7 +78,11 @@ export const CaTable = ({ handlePopUpOpen }: Props) => { key={`ca-${ca.id}`} onClick={() => navigate({ - to: `/${ProjectType.CertificateManager}/${currentWorkspace?.id}/ca/${ca.id}` as const + to: `/${ProjectType.CertificateManager}/$projectId/ca/$caId` as const, + params: { + projectId: currentWorkspace.id, + caId: ca.id + } }) } > diff --git a/frontend-v2/src/pages/cert-manager/CertificatesPage/components/CertificatesTab/components/CertificateTemplateModal.tsx b/frontend-v2/src/pages/cert-manager/CertificatesPage/components/CertificatesTab/components/CertificateTemplateModal.tsx index c7fba88b7..28faa5970 100644 --- a/frontend-v2/src/pages/cert-manager/CertificatesPage/components/CertificatesTab/components/CertificateTemplateModal.tsx +++ b/frontend-v2/src/pages/cert-manager/CertificatesPage/components/CertificatesTab/components/CertificateTemplateModal.tsx @@ -407,7 +407,7 @@ export const CertificateTemplateModal = ({ popUp, handlePopUpToggle, caId }: Pro errorText={error?.message} isError={Boolean(error)} > -
+
{KEY_USAGES_OPTIONS.map(({ label, value: optionValue }) => { return ( -
+
{EXTENDED_KEY_USAGES_OPTIONS.map(({ label, value: optionValue }) => { return ( { }); } else { // create - const { id: createdId } = await createPkiCollection({ + const { id: collectionId } = await createPkiCollection({ name, description, projectId }); navigate({ - to: `/${ProjectType.CertificateManager}/${projectId}/pki-collections/${createdId}` as const + to: `/${ProjectType.CertificateManager}/$projectId/pki-collections/$collectionId` as const, + params: { + projectId, + collectionId + } }); } diff --git a/frontend-v2/src/pages/cert-manager/CertificatesPage/components/PkiAlertsTab/components/PkiCollectionTable.tsx b/frontend-v2/src/pages/cert-manager/CertificatesPage/components/PkiAlertsTab/components/PkiCollectionTable.tsx index e8e7d50b2..8a3e6ffe5 100644 --- a/frontend-v2/src/pages/cert-manager/CertificatesPage/components/PkiAlertsTab/components/PkiCollectionTable.tsx +++ b/frontend-v2/src/pages/cert-manager/CertificatesPage/components/PkiAlertsTab/components/PkiCollectionTable.tsx @@ -61,7 +61,11 @@ export const PkiCollectionTable = ({ handlePopUpOpen }: Props) => { key={`pki-collection-${pkiCollection.id}`} onClick={() => navigate({ - to: `/${ProjectType.CertificateManager}/${projectId}/pki-collections/${pkiCollection.id}` as const + to: `/${ProjectType.CertificateManager}/$projectId/pki-collections/$collectionId` as const, + params: { + projectId, + collectionId: pkiCollection.id + } }) } > diff --git a/frontend-v2/src/pages/cert-manager/CertificatesPage/route.tsx b/frontend-v2/src/pages/cert-manager/CertificatesPage/route.tsx index 8fdecba6f..eec2b6007 100644 --- a/frontend-v2/src/pages/cert-manager/CertificatesPage/route.tsx +++ b/frontend-v2/src/pages/cert-manager/CertificatesPage/route.tsx @@ -1,9 +1,9 @@ -import { createFileRoute } from '@tanstack/react-router' +import { createFileRoute } from "@tanstack/react-router"; -import { CertificatesPage } from './CertificatesPage' +import { CertificatesPage } from "./CertificatesPage"; export const Route = createFileRoute( - '/_authenticate/_inject-org-details/cert-manager/$projectId/_cert-manager-layout/overview', + "/_authenticate/_inject-org-details/cert-manager/$projectId/_cert-manager-layout/overview" )({ - component: CertificatesPage, -}) + component: CertificatesPage +}); diff --git a/frontend-v2/src/pages/cert-manager/PkiCollectionDetailsByIDPage/PkiCollectionDetailsByIDPage.tsx b/frontend-v2/src/pages/cert-manager/PkiCollectionDetailsByIDPage/PkiCollectionDetailsByIDPage.tsx index ba47a0d4e..c2dc3b13b 100644 --- a/frontend-v2/src/pages/cert-manager/PkiCollectionDetailsByIDPage/PkiCollectionDetailsByIDPage.tsx +++ b/frontend-v2/src/pages/cert-manager/PkiCollectionDetailsByIDPage/PkiCollectionDetailsByIDPage.tsx @@ -58,7 +58,10 @@ export const PkiCollectionPage = () => { }); handlePopUpClose("deletePkiCollection"); navigate({ - to: `/${ProjectType.CertificateManager}/${projectId}/certificates` as const + to: `/${ProjectType.CertificateManager}/$projectId/overview` as const, + params: { + projectId + } }); } catch { createNotification({ @@ -78,7 +81,10 @@ export const PkiCollectionPage = () => { leftIcon={} onClick={() => { navigate({ - to: `/${ProjectType.CertificateManager}/${projectId}/certificates` as const + to: `/${ProjectType.CertificateManager}/$projectId/overview` as const, + params: { + projectId + } }); }} className="mb-4" diff --git a/frontend-v2/src/pages/cert-manager/PkiCollectionDetailsByIDPage/routes.tsx b/frontend-v2/src/pages/cert-manager/PkiCollectionDetailsByIDPage/routes.tsx index 0409aec2f..8f02182f5 100644 --- a/frontend-v2/src/pages/cert-manager/PkiCollectionDetailsByIDPage/routes.tsx +++ b/frontend-v2/src/pages/cert-manager/PkiCollectionDetailsByIDPage/routes.tsx @@ -1,9 +1,9 @@ -import { createFileRoute } from '@tanstack/react-router' +import { createFileRoute } from "@tanstack/react-router"; -import { PkiCollectionDetailsByIDPage } from './PkiCollectionDetailsByIDPage' +import { PkiCollectionDetailsByIDPage } from "./PkiCollectionDetailsByIDPage"; export const Route = createFileRoute( - '/_authenticate/_inject-org-details/cert-manager/$projectId/_cert-manager-layout/pki-collections/$collectionId', + "/_authenticate/_inject-org-details/cert-manager/$projectId/_cert-manager-layout/pki-collections/$collectionId" )({ - component: PkiCollectionDetailsByIDPage, -}) + component: PkiCollectionDetailsByIDPage +}); diff --git a/frontend-v2/src/pages/cert-manager/SettingsPage/components/index.tsx b/frontend-v2/src/pages/cert-manager/SettingsPage/components/index.tsx index 6fb72e4c4..2f355dc94 100644 --- a/frontend-v2/src/pages/cert-manager/SettingsPage/components/index.tsx +++ b/frontend-v2/src/pages/cert-manager/SettingsPage/components/index.tsx @@ -1,6 +1,2 @@ -export { AutoCapitalizationSection } from "./AutoCapitalizationSection"; -export { BackfillSecretReferenceSecretion } from "./BackfillSecretReferenceSection"; export { DeleteProjectSection } from "./DeleteProjectSection"; -export { EnvironmentSection } from "./EnvironmentSection"; export { ProjectOverviewChangeSection } from "./ProjectOverviewChangeSection"; -export { SecretTagsSection } from "./SecretTagsSection"; diff --git a/frontend-v2/src/pages/cert-manager/SettingsPage/route.tsx b/frontend-v2/src/pages/cert-manager/SettingsPage/route.tsx index f0ead96f4..bf769e482 100644 --- a/frontend-v2/src/pages/cert-manager/SettingsPage/route.tsx +++ b/frontend-v2/src/pages/cert-manager/SettingsPage/route.tsx @@ -1,9 +1,9 @@ -import { createFileRoute } from '@tanstack/react-router' +import { createFileRoute } from "@tanstack/react-router"; -import { SettingsPage } from './SettingsPage' +import { SettingsPage } from "./SettingsPage"; export const Route = createFileRoute( - '/_authenticate/_inject-org-details/cert-manager/$projectId/_cert-manager-layout/settings', + "/_authenticate/_inject-org-details/cert-manager/$projectId/_cert-manager-layout/settings" )({ - component: SettingsPage, -}) + component: SettingsPage +}); diff --git a/frontend-v2/src/pages/kms/OverviewPage/route.tsx b/frontend-v2/src/pages/kms/OverviewPage/route.tsx index 060042fff..76f356245 100644 --- a/frontend-v2/src/pages/kms/OverviewPage/route.tsx +++ b/frontend-v2/src/pages/kms/OverviewPage/route.tsx @@ -1,9 +1,9 @@ -import { createFileRoute } from '@tanstack/react-router' +import { createFileRoute } from "@tanstack/react-router"; -import { OverviewPage } from './OverviewPage' +import { OverviewPage } from "./OverviewPage"; export const Route = createFileRoute( - '/_authenticate/_inject-org-details/kms/$projectId/_kms-layout/overview', + "/_authenticate/_inject-org-details/kms/$projectId/_kms-layout/overview" )({ - component: OverviewPage, -}) + component: OverviewPage +}); diff --git a/frontend-v2/src/pages/kms/SettingsPage/components/index.tsx b/frontend-v2/src/pages/kms/SettingsPage/components/index.tsx index 6fb72e4c4..2f355dc94 100644 --- a/frontend-v2/src/pages/kms/SettingsPage/components/index.tsx +++ b/frontend-v2/src/pages/kms/SettingsPage/components/index.tsx @@ -1,6 +1,2 @@ -export { AutoCapitalizationSection } from "./AutoCapitalizationSection"; -export { BackfillSecretReferenceSecretion } from "./BackfillSecretReferenceSection"; export { DeleteProjectSection } from "./DeleteProjectSection"; -export { EnvironmentSection } from "./EnvironmentSection"; export { ProjectOverviewChangeSection } from "./ProjectOverviewChangeSection"; -export { SecretTagsSection } from "./SecretTagsSection"; diff --git a/frontend-v2/src/pages/kms/SettingsPage/route.tsx b/frontend-v2/src/pages/kms/SettingsPage/route.tsx index 9420da46c..c5578c700 100644 --- a/frontend-v2/src/pages/kms/SettingsPage/route.tsx +++ b/frontend-v2/src/pages/kms/SettingsPage/route.tsx @@ -1,9 +1,9 @@ -import { createFileRoute } from '@tanstack/react-router' +import { createFileRoute } from "@tanstack/react-router"; -import { SettingsPage } from './SettingsPage' +import { SettingsPage } from "./SettingsPage"; export const Route = createFileRoute( - '/_authenticate/_inject-org-details/kms/$projectId/_kms-layout/settings', + "/_authenticate/_inject-org-details/kms/$projectId/_kms-layout/settings" )({ - component: SettingsPage, -}) + component: SettingsPage +}); diff --git a/frontend-v2/src/pages/kms/layout.tsx b/frontend-v2/src/pages/kms/layout.tsx index 359652410..7a8cfe7e3 100644 --- a/frontend-v2/src/pages/kms/layout.tsx +++ b/frontend-v2/src/pages/kms/layout.tsx @@ -1,29 +1,25 @@ -import { createFileRoute } from '@tanstack/react-router' +import { createFileRoute } from "@tanstack/react-router"; -import { workspaceKeys } from '@app/hooks/api' -import { - fetchUserProjectPermissions, - roleQueryKeys, -} from '@app/hooks/api/roles/queries' -import { fetchWorkspaceById } from '@app/hooks/api/workspace/queries' -import { ProjectLayout } from '@app/layouts/ProjectLayout' +import { workspaceKeys } from "@app/hooks/api"; +import { fetchUserProjectPermissions, roleQueryKeys } from "@app/hooks/api/roles/queries"; +import { fetchWorkspaceById } from "@app/hooks/api/workspace/queries"; +import { ProjectLayout } from "@app/layouts/ProjectLayout"; export const Route = createFileRoute( - '/_authenticate/_inject-org-details/kms/$projectId/_kms-layout', + "/_authenticate/_inject-org-details/kms/$projectId/_kms-layout" )({ component: ProjectLayout, beforeLoad: async ({ params, context }) => { await context.queryClient.ensureQueryData({ queryKey: workspaceKeys.getWorkspaceById(params.projectId), - queryFn: () => fetchWorkspaceById(params.projectId), - }) + queryFn: () => fetchWorkspaceById(params.projectId) + }); await context.queryClient.ensureQueryData({ queryKey: roleQueryKeys.getUserProjectPermissions({ - workspaceId: params.projectId, + workspaceId: params.projectId }), - queryFn: () => - fetchUserProjectPermissions({ workspaceId: params.projectId }), - }) - }, -}) + queryFn: () => fetchUserProjectPermissions({ workspaceId: params.projectId }) + }); + } +}); diff --git a/frontend-v2/src/pages/middlewares/inject-org-details.tsx b/frontend-v2/src/pages/middlewares/inject-org-details.tsx index aab0f36ff..d2f3e97ab 100644 --- a/frontend-v2/src/pages/middlewares/inject-org-details.tsx +++ b/frontend-v2/src/pages/middlewares/inject-org-details.tsx @@ -1,36 +1,27 @@ -import { createFileRoute } from '@tanstack/react-router' +import { createFileRoute } from "@tanstack/react-router"; -import { - fetchOrganizationById, - organizationKeys, -} from '@app/hooks/api/organization/queries' -import { - fetchUserOrgPermissions, - roleQueryKeys, -} from '@app/hooks/api/roles/queries' -import { - fetchOrgSubscription, - subscriptionQueryKeys, -} from '@app/hooks/api/subscriptions/queries' +import { fetchOrganizationById, organizationKeys } from "@app/hooks/api/organization/queries"; +import { fetchUserOrgPermissions, roleQueryKeys } from "@app/hooks/api/roles/queries"; +import { fetchOrgSubscription, subscriptionQueryKeys } from "@app/hooks/api/subscriptions/queries"; // Route context to fill in organization's data like details, subscription etc -export const Route = createFileRoute('/_authenticate/_inject-org-details')({ +export const Route = createFileRoute("/_authenticate/_inject-org-details")({ beforeLoad: async ({ context }) => { - const organizationId = context.organizationId! + const organizationId = context.organizationId!; await context.queryClient.ensureQueryData({ queryKey: organizationKeys.getOrgById(organizationId), - queryFn: () => fetchOrganizationById(organizationId), - }) + queryFn: () => fetchOrganizationById(organizationId) + }); await context.queryClient.ensureQueryData({ queryKey: subscriptionQueryKeys.getOrgSubsription(organizationId), - queryFn: () => fetchOrgSubscription(organizationId), - }) + queryFn: () => fetchOrgSubscription(organizationId) + }); await context.queryClient.ensureQueryData({ queryKey: roleQueryKeys.getUserOrgPermissions({ orgId: organizationId }), - queryFn: () => fetchUserOrgPermissions({ orgId: organizationId }), - }) - return { organizationId } - }, -}) + queryFn: () => fetchUserOrgPermissions({ orgId: organizationId }) + }); + return { organizationId }; + } +}); diff --git a/frontend-v2/src/pages/organization/AccessManagementPage/components/OrgMembersTab/components/OrgMembersSection/OrgMembersTable.tsx b/frontend-v2/src/pages/organization/AccessManagementPage/components/OrgMembersTab/components/OrgMembersSection/OrgMembersTable.tsx index eea58dc01..335b4cdb7 100644 --- a/frontend-v2/src/pages/organization/AccessManagementPage/components/OrgMembersTab/components/OrgMembersSection/OrgMembersTable.tsx +++ b/frontend-v2/src/pages/organization/AccessManagementPage/components/OrgMembersTab/components/OrgMembersSection/OrgMembersTable.tsx @@ -306,7 +306,7 @@ export const OrgMembersTable = ({ handlePopUpOpen, setCompleteInviteLinks }: Pro className="h-10 w-full cursor-pointer transition-colors duration-100 hover:bg-mineshaft-700" onClick={() => navigate({ - to: "/organization/memberships/$membershipId" as const, + to: "/organization/members/$membershipId" as const, params: { membershipId: orgMembershipId } @@ -401,7 +401,7 @@ export const OrgMembersTable = ({ handlePopUpOpen, setCompleteInviteLinks }: Pro onClick={(e) => { e.stopPropagation(); navigate({ - to: "/organization/memberships/$membershipId" as const, + to: "/organization/members/$membershipId" as const, params: { membershipId: orgMembershipId } diff --git a/frontend-v2/src/pages/organization/AccessManagementPage/components/OrgRoleTabSection/OrgRoleTable.tsx b/frontend-v2/src/pages/organization/AccessManagementPage/components/OrgRoleTabSection/OrgRoleTable.tsx index a1668f023..e4c7aca98 100644 --- a/frontend-v2/src/pages/organization/AccessManagementPage/components/OrgRoleTabSection/OrgRoleTable.tsx +++ b/frontend-v2/src/pages/organization/AccessManagementPage/components/OrgRoleTabSection/OrgRoleTable.tsx @@ -34,8 +34,7 @@ import { isCustomOrgRole } from "@app/helpers/roles"; import { usePopUp } from "@app/hooks"; import { useDeleteOrgRole, useGetOrgRoles, useUpdateOrg } from "@app/hooks/api"; import { TOrgRole } from "@app/hooks/api/roles/types"; - -import { RoleModal } from "../../../roles/$roleId/-components"; +import { RoleModal } from "@app/pages/organization/RoleByIDPage/components/RoleModal"; export const OrgRoleTable = () => { const navigate = useNavigate(); diff --git a/frontend-v2/src/pages/organization/AccessManagementPage/route.tsx b/frontend-v2/src/pages/organization/AccessManagementPage/route.tsx index b91ad4eee..67e18a914 100644 --- a/frontend-v2/src/pages/organization/AccessManagementPage/route.tsx +++ b/frontend-v2/src/pages/organization/AccessManagementPage/route.tsx @@ -1,19 +1,19 @@ -import { createFileRoute } from '@tanstack/react-router' -import { zodValidator } from '@tanstack/zod-adapter' -import { z } from 'zod' +import { createFileRoute } from "@tanstack/react-router"; +import { zodValidator } from "@tanstack/zod-adapter"; +import { z } from "zod"; -import { OrgAccessControlTabSections } from '@app/types/org' +import { OrgAccessControlTabSections } from "@app/types/org"; -import { AccessManagementPage } from './AccessManagementPage' +import { AccessManagementPage } from "./AccessManagementPage"; const AccessControlPageQuerySchema = z.object({ selectedTab: z.string().catch(OrgAccessControlTabSections.Member), - action: z.string().catch(''), -}) + action: z.string().catch("") +}); export const Route = createFileRoute( - '/_authenticate/_inject-org-details/organization/_layout/access-management', + "/_authenticate/_inject-org-details/organization/_layout/access-management" )({ component: AccessManagementPage, - validateSearch: zodValidator(AccessControlPageQuerySchema), -}) + validateSearch: zodValidator(AccessControlPageQuerySchema) +}); diff --git a/frontend-v2/src/pages/organization/AdminPage/route.tsx b/frontend-v2/src/pages/organization/AdminPage/route.tsx index 7eae0689d..0c660fb19 100644 --- a/frontend-v2/src/pages/organization/AdminPage/route.tsx +++ b/frontend-v2/src/pages/organization/AdminPage/route.tsx @@ -1,9 +1,9 @@ -import { createFileRoute } from '@tanstack/react-router' +import { createFileRoute } from "@tanstack/react-router"; -import { AdminPage } from './AdminPage' +import { AdminPage } from "./AdminPage"; export const Route = createFileRoute( - '/_authenticate/_inject-org-details/organization/_layout/admin', + "/_authenticate/_inject-org-details/organization/_layout/admin" )({ - component: AdminPage, -}) + component: AdminPage +}); diff --git a/frontend-v2/src/pages/organization/AuditLogsPage/route.tsx b/frontend-v2/src/pages/organization/AuditLogsPage/route.tsx index e587a113f..5123ffe64 100644 --- a/frontend-v2/src/pages/organization/AuditLogsPage/route.tsx +++ b/frontend-v2/src/pages/organization/AuditLogsPage/route.tsx @@ -1,9 +1,9 @@ -import { createFileRoute } from '@tanstack/react-router' +import { createFileRoute } from "@tanstack/react-router"; -import { AuditLogsPage } from './AuditLogsPage' +import { AuditLogsPage } from "./AuditLogsPage"; export const Route = createFileRoute( - '/_authenticate/_inject-org-details/organization/_layout/audit-logs', + "/_authenticate/_inject-org-details/organization/_layout/audit-logs" )({ - component: AuditLogsPage, -}) + component: AuditLogsPage +}); diff --git a/frontend-v2/src/pages/organization/BillingPage/route.tsx b/frontend-v2/src/pages/organization/BillingPage/route.tsx index 138a88e56..d699c39bf 100644 --- a/frontend-v2/src/pages/organization/BillingPage/route.tsx +++ b/frontend-v2/src/pages/organization/BillingPage/route.tsx @@ -1,9 +1,9 @@ -import { createFileRoute } from '@tanstack/react-router' +import { createFileRoute } from "@tanstack/react-router"; -import { BillingPage } from './BillingPage' +import { BillingPage } from "./BillingPage"; export const Route = createFileRoute( - '/_authenticate/_inject-org-details/organization/_layout/billing', + "/_authenticate/_inject-org-details/organization/_layout/billing" )({ - component: BillingPage, -}) + component: BillingPage +}); diff --git a/frontend-v2/src/pages/organization/CertManagerOverviewPage/route.tsx b/frontend-v2/src/pages/organization/CertManagerOverviewPage/route.tsx index 612de6aca..a4e8bb63c 100644 --- a/frontend-v2/src/pages/organization/CertManagerOverviewPage/route.tsx +++ b/frontend-v2/src/pages/organization/CertManagerOverviewPage/route.tsx @@ -1,9 +1,9 @@ -import { createFileRoute } from '@tanstack/react-router' +import { createFileRoute } from "@tanstack/react-router"; -import { CertManagerOverviewPage } from './CertManagerOverviewPage' +import { CertManagerOverviewPage } from "./CertManagerOverviewPage"; export const Route = createFileRoute( - '/_authenticate/_inject-org-details/organization/_layout/cert-manager/overview', + "/_authenticate/_inject-org-details/organization/_layout/cert-manager/overview" )({ - component: CertManagerOverviewPage, -}) + component: CertManagerOverviewPage +}); diff --git a/frontend-v2/src/pages/organization/GroupDetailsByIDPage/GroupDetailsByIDPage.tsx b/frontend-v2/src/pages/organization/GroupDetailsByIDPage/GroupDetailsByIDPage.tsx index a61355c50..6f2927ed6 100644 --- a/frontend-v2/src/pages/organization/GroupDetailsByIDPage/GroupDetailsByIDPage.tsx +++ b/frontend-v2/src/pages/organization/GroupDetailsByIDPage/GroupDetailsByIDPage.tsx @@ -62,7 +62,7 @@ const Page = () => { type: "success" }); navigate({ - to: "/organization/members" as const, + to: "/organization/access-management" as const, search: { selectedTab: TabSections.Groups } @@ -90,7 +90,7 @@ const Page = () => { leftIcon={} onClick={() => { navigate({ - to: "/organization/members" as const, + to: "/organization/access-management" as const, search: { selectedTab: TabSections.Groups } diff --git a/frontend-v2/src/pages/organization/GroupDetailsByIDPage/route.tsx b/frontend-v2/src/pages/organization/GroupDetailsByIDPage/route.tsx index 4f0972c1e..7814110e6 100644 --- a/frontend-v2/src/pages/organization/GroupDetailsByIDPage/route.tsx +++ b/frontend-v2/src/pages/organization/GroupDetailsByIDPage/route.tsx @@ -1,9 +1,9 @@ -import { createFileRoute } from '@tanstack/react-router' +import { createFileRoute } from "@tanstack/react-router"; -import { GroupDetailsByIDPage } from './GroupDetailsByIDPage' +import { GroupDetailsByIDPage } from "./GroupDetailsByIDPage"; export const Route = createFileRoute( - '/_authenticate/_inject-org-details/organization/_layout/groups/$groupId', + "/_authenticate/_inject-org-details/organization/_layout/groups/$groupId" )({ - component: GroupDetailsByIDPage, -}) + component: GroupDetailsByIDPage +}); diff --git a/frontend-v2/src/pages/organization/IdentityDetailsByIDPage/IdentityDetailsByIDPage.tsx b/frontend-v2/src/pages/organization/IdentityDetailsByIDPage/IdentityDetailsByIDPage.tsx index 4e5c15978..6699fd549 100644 --- a/frontend-v2/src/pages/organization/IdentityDetailsByIDPage/IdentityDetailsByIDPage.tsx +++ b/frontend-v2/src/pages/organization/IdentityDetailsByIDPage/IdentityDetailsByIDPage.tsx @@ -1,4 +1,3 @@ -/* eslint-disable @typescript-eslint/no-unused-vars */ import { useState } from "react"; import { Helmet } from "react-helmet"; import { useTranslation } from "react-i18next"; @@ -32,6 +31,9 @@ import { Identity } from "@app/hooks/api/identities/types"; import { usePopUp } from "@app/hooks/usePopUp"; import { OrgAccessControlTabSections } from "@app/types/org"; +import { IdentityAuthMethodModal } from "../AccessManagementPage/components/OrgIdentityTab/components/IdentitySection/IdentityAuthMethodModal"; +import { IdentityModal } from "../AccessManagementPage/components/OrgIdentityTab/components/IdentitySection/IdentityModal"; +import { IdentityUniversalAuthClientSecretModal } from "../AccessManagementPage/components/OrgIdentityTab/components/IdentitySection/IdentityUniversalAuthClientSecretModal"; import { IdentityAuthenticationSection, IdentityClientSecretModal, @@ -86,7 +88,7 @@ const Page = () => { handlePopUpClose("deleteIdentity"); navigate({ - to: "/organization/members", + to: "/organization/access-management", search: { selectedTab: OrgAccessControlTabSections.Identities } @@ -170,7 +172,7 @@ const Page = () => { leftIcon={} onClick={() => { navigate({ - to: "/organization/members", + to: "/organization/access-management", search: { selectedTab: OrgAccessControlTabSections.Identities } diff --git a/frontend-v2/src/pages/organization/IdentityDetailsByIDPage/components/IdentityProjectsSection/IdentityProjectRow.tsx b/frontend-v2/src/pages/organization/IdentityDetailsByIDPage/components/IdentityProjectsSection/IdentityProjectRow.tsx index 0b3aab8b2..30861a98b 100644 --- a/frontend-v2/src/pages/organization/IdentityDetailsByIDPage/components/IdentityProjectsSection/IdentityProjectRow.tsx +++ b/frontend-v2/src/pages/organization/IdentityDetailsByIDPage/components/IdentityProjectsSection/IdentityProjectRow.tsx @@ -59,7 +59,10 @@ export const IdentityProjectRow = ({ onClick={() => { if (isAccessible) { navigate({ - to: `/${project?.type}/${project.id}/access` as const, + to: `/${project?.type}/$projectId/access-management` as const, + params: { + projectId: project.id + }, search: { selectedTab: TabSections.Identities } diff --git a/frontend-v2/src/pages/organization/IdentityDetailsByIDPage/route.tsx b/frontend-v2/src/pages/organization/IdentityDetailsByIDPage/route.tsx index aeb41e61d..de43184d3 100644 --- a/frontend-v2/src/pages/organization/IdentityDetailsByIDPage/route.tsx +++ b/frontend-v2/src/pages/organization/IdentityDetailsByIDPage/route.tsx @@ -1,9 +1,9 @@ -import { createFileRoute } from '@tanstack/react-router' +import { createFileRoute } from "@tanstack/react-router"; -import { IdentityDetailsByIDPage } from './IdentityDetailsByIDPage' +import { IdentityDetailsByIDPage } from "./IdentityDetailsByIDPage"; export const Route = createFileRoute( - '/_authenticate/_inject-org-details/organization/_layout/identities/$identityId', + "/_authenticate/_inject-org-details/organization/_layout/identities/$identityId" )({ - component: IdentityDetailsByIDPage, -}) + component: IdentityDetailsByIDPage +}); diff --git a/frontend-v2/src/pages/organization/KmsOverviewPage/route.tsx b/frontend-v2/src/pages/organization/KmsOverviewPage/route.tsx index 1ed571425..3c9f96924 100644 --- a/frontend-v2/src/pages/organization/KmsOverviewPage/route.tsx +++ b/frontend-v2/src/pages/organization/KmsOverviewPage/route.tsx @@ -1,9 +1,9 @@ -import { createFileRoute } from '@tanstack/react-router' +import { createFileRoute } from "@tanstack/react-router"; -import { KmsOverviewPage } from './KmsOverviewPage' +import { KmsOverviewPage } from "./KmsOverviewPage"; export const Route = createFileRoute( - '/_authenticate/_inject-org-details/organization/_layout/kms/overview', + "/_authenticate/_inject-org-details/organization/_layout/kms/overview" )({ - component: KmsOverviewPage, -}) + component: KmsOverviewPage +}); diff --git a/frontend-v2/src/pages/organization/NoOrgPage/route.tsx b/frontend-v2/src/pages/organization/NoOrgPage/route.tsx index b51f5af51..70c49f387 100644 --- a/frontend-v2/src/pages/organization/NoOrgPage/route.tsx +++ b/frontend-v2/src/pages/organization/NoOrgPage/route.tsx @@ -1,8 +1,9 @@ -import { createFileRoute } from '@tanstack/react-router' -import { NoOrgPage } from './NoOrgPage' +import { createFileRoute } from "@tanstack/react-router"; + +import { NoOrgPage } from "./NoOrgPage"; export const Route = createFileRoute( - '/_authenticate/_inject-org-details/organization/_layout/none', + "/_authenticate/_inject-org-details/organization/_layout/none" )({ - component: NoOrgPage, -}) + component: NoOrgPage +}); diff --git a/frontend-v2/src/pages/organization/RoleByIDPage/RoleByIDPage.tsx b/frontend-v2/src/pages/organization/RoleByIDPage/RoleByIDPage.tsx index 7ca6a3a43..ece358b71 100644 --- a/frontend-v2/src/pages/organization/RoleByIDPage/RoleByIDPage.tsx +++ b/frontend-v2/src/pages/organization/RoleByIDPage/RoleByIDPage.tsx @@ -56,7 +56,7 @@ export const Page = () => { handlePopUpClose("deleteOrgRole"); navigate({ - to: "/organization/members" as const, + to: "/organization/access-management" as const, search: { selectedTab: OrgAccessControlTabSections.Roles } @@ -85,7 +85,7 @@ export const Page = () => { leftIcon={} onClick={() => { navigate({ - to: "/organization/members" as const, + to: "/organization/access-management" as const, search: { selectedTab: OrgAccessControlTabSections.Roles } diff --git a/frontend-v2/src/pages/organization/RoleByIDPage/route.tsx b/frontend-v2/src/pages/organization/RoleByIDPage/route.tsx index c68a323dc..d0d65f661 100644 --- a/frontend-v2/src/pages/organization/RoleByIDPage/route.tsx +++ b/frontend-v2/src/pages/organization/RoleByIDPage/route.tsx @@ -1,9 +1,9 @@ -import { createFileRoute } from '@tanstack/react-router' +import { createFileRoute } from "@tanstack/react-router"; -import { RoleByIDPage } from './RoleByIDPage' +import { RoleByIDPage } from "./RoleByIDPage"; export const Route = createFileRoute( - '/_authenticate/_inject-org-details/organization/_layout/roles/$roleId', + "/_authenticate/_inject-org-details/organization/_layout/roles/$roleId" )({ - component: RoleByIDPage, -}) + component: RoleByIDPage +}); diff --git a/frontend-v2/src/pages/organization/SecretManagerOverviewPage/route.tsx b/frontend-v2/src/pages/organization/SecretManagerOverviewPage/route.tsx index 0903800f4..30320f2b3 100644 --- a/frontend-v2/src/pages/organization/SecretManagerOverviewPage/route.tsx +++ b/frontend-v2/src/pages/organization/SecretManagerOverviewPage/route.tsx @@ -1,9 +1,9 @@ -import { createFileRoute } from '@tanstack/react-router' +import { createFileRoute } from "@tanstack/react-router"; -import { SecretManagerOverviewPage } from './SecretManagerOverviewPage' +import { SecretManagerOverviewPage } from "./SecretManagerOverviewPage"; export const Route = createFileRoute( - '/_authenticate/_inject-org-details/organization/_layout/secret-manager/overview', + "/_authenticate/_inject-org-details/organization/_layout/secret-manager/overview" )({ - component: SecretManagerOverviewPage, -}) + component: SecretManagerOverviewPage +}); diff --git a/frontend-v2/src/pages/organization/SecretScanningPage/SecretScanningPage.tsx b/frontend-v2/src/pages/organization/SecretScanningPage/SecretScanningPage.tsx index 49a25bbfc..b5fae842c 100644 --- a/frontend-v2/src/pages/organization/SecretScanningPage/SecretScanningPage.tsx +++ b/frontend-v2/src/pages/organization/SecretScanningPage/SecretScanningPage.tsx @@ -4,6 +4,7 @@ import { useSearch } from "@tanstack/react-router"; import { OrgPermissionCan } from "@app/components/permissions"; import { Button, NoticeBanner } from "@app/components/v2"; +import { ROUTE_PATHS } from "@app/const/routes"; import { OrgPermissionActions, OrgPermissionSubjects, @@ -22,7 +23,7 @@ import { SecretScanningLogsTable } from "./components"; export const SecretScanningPage = withPermission( () => { const queryParams = useSearch({ - from: "/_authenticate/_ctx-org-details/organization/_layout-org/secret-scanning/" + from: ROUTE_PATHS.Organization.SecretScanning.id }); const { config } = useServerConfig(); const { currentOrg } = useOrganization(); diff --git a/frontend-v2/src/pages/organization/SecretScanningPage/route.tsx b/frontend-v2/src/pages/organization/SecretScanningPage/route.tsx index ebb9a8c24..07c562fbe 100644 --- a/frontend-v2/src/pages/organization/SecretScanningPage/route.tsx +++ b/frontend-v2/src/pages/organization/SecretScanningPage/route.tsx @@ -1,17 +1,17 @@ -import { createFileRoute } from '@tanstack/react-router' -import { zodValidator } from '@tanstack/zod-adapter' -import { z } from 'zod' +import { createFileRoute } from "@tanstack/react-router"; +import { zodValidator } from "@tanstack/zod-adapter"; +import { z } from "zod"; -import { SecretScanningPage } from './SecretScanningPage' +import { SecretScanningPage } from "./SecretScanningPage"; const SecretScanningQueryParams = z.object({ - state: z.string().catch(''), - installation_id: z.string().catch(''), -}) + state: z.string().catch(""), + installation_id: z.string().catch("") +}); export const Route = createFileRoute( - '/_authenticate/_inject-org-details/organization/_layout/secret-scanning', + "/_authenticate/_inject-org-details/organization/_layout/secret-scanning" )({ component: SecretScanningPage, - validateSearch: zodValidator(SecretScanningQueryParams), -}) + validateSearch: zodValidator(SecretScanningQueryParams) +}); diff --git a/frontend-v2/src/pages/organization/SecretSharingPage/route.tsx b/frontend-v2/src/pages/organization/SecretSharingPage/route.tsx index 9861b6f34..fec2f8925 100644 --- a/frontend-v2/src/pages/organization/SecretSharingPage/route.tsx +++ b/frontend-v2/src/pages/organization/SecretSharingPage/route.tsx @@ -1,9 +1,9 @@ -import { createFileRoute } from '@tanstack/react-router' +import { createFileRoute } from "@tanstack/react-router"; -import { SecretSharingPage } from './SecretSharingPage' +import { SecretSharingPage } from "./SecretSharingPage"; export const Route = createFileRoute( - '/_authenticate/_inject-org-details/organization/_layout/secret-sharing', + "/_authenticate/_inject-org-details/organization/_layout/secret-sharing" )({ - component: SecretSharingPage, -}) + component: SecretSharingPage +}); diff --git a/frontend-v2/src/pages/organization/SettingsPage/components/OrgAuthTab/LDAPGroupMapModal.tsx b/frontend-v2/src/pages/organization/SettingsPage/components/OrgAuthTab/LDAPGroupMapModal.tsx index 6f23ae245..8e6877cad 100644 --- a/frontend-v2/src/pages/organization/SettingsPage/components/OrgAuthTab/LDAPGroupMapModal.tsx +++ b/frontend-v2/src/pages/organization/SettingsPage/components/OrgAuthTab/LDAPGroupMapModal.tsx @@ -279,7 +279,7 @@ export const LDAPGroupMapModal = ({ popUp, handlePopUpOpen, handlePopUpToggle }: size="sm" onClick={() => navigate({ - to: "/organization/members" + to: "/organization/access-management" }) } > diff --git a/frontend-v2/src/pages/organization/SettingsPage/components/OrgDeleteSection/OrgDeleteSection.tsx b/frontend-v2/src/pages/organization/SettingsPage/components/OrgDeleteSection/OrgDeleteSection.tsx index 0d5d63551..9cd59c0ad 100644 --- a/frontend-v2/src/pages/organization/SettingsPage/components/OrgDeleteSection/OrgDeleteSection.tsx +++ b/frontend-v2/src/pages/organization/SettingsPage/components/OrgDeleteSection/OrgDeleteSection.tsx @@ -5,7 +5,7 @@ import { Button, DeleteActionModal } from "@app/components/v2"; import { useOrganization, useOrgPermission } from "@app/context"; import { useDeleteOrgById } from "@app/hooks/api"; import { usePopUp } from "@app/hooks/usePopUp"; -import { navigateUserToOrg } from "@app/routes/_restrict-login-signup/login/-components/Login.utils"; +import { navigateUserToOrg } from "@app/pages/auth/LoginPage/Login.utils"; export const OrgDeleteSection = () => { const navigate = useNavigate(); diff --git a/frontend-v2/src/pages/organization/SettingsPage/components/OrgTabGroup/OrgTabGroup.tsx b/frontend-v2/src/pages/organization/SettingsPage/components/OrgTabGroup/OrgTabGroup.tsx index a68e8ca47..799067da0 100644 --- a/frontend-v2/src/pages/organization/SettingsPage/components/OrgTabGroup/OrgTabGroup.tsx +++ b/frontend-v2/src/pages/organization/SettingsPage/components/OrgTabGroup/OrgTabGroup.tsx @@ -3,6 +3,7 @@ import { useSearch } from "@tanstack/react-router"; import { OrgPermissionCan } from "@app/components/permissions"; import { Tab, TabList, TabPanel, Tabs } from "@app/components/v2"; +import { ROUTE_PATHS } from "@app/const/routes"; import { OrgPermissionActions, OrgPermissionSubjects } from "@app/context"; import { AuditLogStreamsTab } from "../AuditLogStreamTab"; @@ -24,7 +25,7 @@ const tabs = [ ]; export const OrgTabGroup = () => { const search = useSearch({ - from: "/_authenticate/_ctx-org-details/organization/_layout-org/settings/" + from: ROUTE_PATHS.Organization.SettingsPage.id }); const [selectedTab, setSelectedTab] = useState(search.selectedTab || tabs[0].key); diff --git a/frontend-v2/src/pages/organization/SettingsPage/components/ProjectTemplatesTab/components/EditProjectTemplateSection/components/ProjectTemplateEditRoleForm.tsx b/frontend-v2/src/pages/organization/SettingsPage/components/ProjectTemplatesTab/components/EditProjectTemplateSection/components/ProjectTemplateEditRoleForm.tsx index c1af760ee..b1a639e89 100644 --- a/frontend-v2/src/pages/organization/SettingsPage/components/ProjectTemplatesTab/components/EditProjectTemplateSection/components/ProjectTemplateEditRoleForm.tsx +++ b/frontend-v2/src/pages/organization/SettingsPage/components/ProjectTemplatesTab/components/EditProjectTemplateSection/components/ProjectTemplateEditRoleForm.tsx @@ -6,22 +6,22 @@ import { twMerge } from "tailwind-merge"; import { z } from "zod"; import { createNotification } from "@app/components/notifications"; -import { GeneralPermissionPolicies } from "@app/components/permissions/ProjectRolePermissionsSection/components/GeneralPermissionPolicies"; -import { NewPermissionRule } from "@app/components/permissions/ProjectRolePermissionsSection/components/NewPermissionRule"; -import { PermissionEmptyState } from "@app/components/permissions/ProjectRolePermissionsSection/PermissionEmptyState"; -import { - formRolePermission2API, - PROJECT_PERMISSION_OBJECT, - projectRoleFormSchema, - rolePermission2Form -} from "@app/components/permissions/ProjectRolePermissionsSection/ProjectRoleModifySection.utils"; -import { renderConditionalComponents } from "@app/components/permissions/ProjectRolePermissionsSection/RolePermissionsSection"; import { Button, FormControl, Input, Modal, ModalContent, ModalTrigger } from "@app/components/v2"; import { ProjectPermissionSub } from "@app/context"; import { isCustomProjectRole } from "@app/helpers/roles"; import { usePopUp } from "@app/hooks"; import { TProjectTemplate, useUpdateProjectTemplate } from "@app/hooks/api/projectTemplates"; import { slugSchema } from "@app/lib/schemas"; +import { GeneralPermissionPolicies } from "@app/pages/project/RoleDetailsBySlugPage/components/GeneralPermissionPolicies"; +import { NewPermissionRule } from "@app/pages/project/RoleDetailsBySlugPage/components/NewPermissionRule"; +import { PermissionEmptyState } from "@app/pages/project/RoleDetailsBySlugPage/components/PermissionEmptyState"; +import { + formRolePermission2API, + PROJECT_PERMISSION_OBJECT, + projectRoleFormSchema, + rolePermission2Form +} from "@app/pages/project/RoleDetailsBySlugPage/components/ProjectRoleModifySection.utils"; +import { renderConditionalComponents } from "@app/pages/project/RoleDetailsBySlugPage/components/RolePermissionsSection"; type Props = { projectTemplate: TProjectTemplate; diff --git a/frontend-v2/src/pages/organization/SettingsPage/route.tsx b/frontend-v2/src/pages/organization/SettingsPage/route.tsx index ecbfb39d3..ed6da9cd9 100644 --- a/frontend-v2/src/pages/organization/SettingsPage/route.tsx +++ b/frontend-v2/src/pages/organization/SettingsPage/route.tsx @@ -1,16 +1,16 @@ -import { createFileRoute } from '@tanstack/react-router' -import { zodValidator } from '@tanstack/zod-adapter' -import { z } from 'zod' +import { createFileRoute } from "@tanstack/react-router"; +import { zodValidator } from "@tanstack/zod-adapter"; +import { z } from "zod"; -import { SettingsPage } from './SettingsPage' +import { SettingsPage } from "./SettingsPage"; const SettingsPageQueryParams = z.object({ - selectedTab: z.string().catch(''), -}) + selectedTab: z.string().catch("") +}); export const Route = createFileRoute( - '/_authenticate/_inject-org-details/organization/_layout/settings', + "/_authenticate/_inject-org-details/organization/_layout/settings" )({ component: SettingsPage, - validateSearch: zodValidator(SettingsPageQueryParams), -}) + validateSearch: zodValidator(SettingsPageQueryParams) +}); diff --git a/frontend-v2/src/pages/organization/UserDetailsByIDPage/UserDetailsByIDPage.tsx b/frontend-v2/src/pages/organization/UserDetailsByIDPage/UserDetailsByIDPage.tsx index 7172a9db9..80990280d 100644 --- a/frontend-v2/src/pages/organization/UserDetailsByIDPage/UserDetailsByIDPage.tsx +++ b/frontend-v2/src/pages/organization/UserDetailsByIDPage/UserDetailsByIDPage.tsx @@ -99,7 +99,7 @@ const Page = withPermission( handlePopUpClose("removeMember"); navigate({ - to: "/organization/members" as const, + to: "/organization/access-management" as const, search: { selectedTab: OrgAccessControlTabSections.Member } @@ -125,7 +125,7 @@ const Page = withPermission( leftIcon={} onClick={() => { navigate({ - to: "/organization/members" as const, + to: "/organization/access-management" as const, search: { selectedTab: OrgAccessControlTabSections.Member } diff --git a/frontend-v2/src/pages/organization/UserDetailsByIDPage/components/UserProjectsSection/UserAuditLogsSection.tsx b/frontend-v2/src/pages/organization/UserDetailsByIDPage/components/UserProjectsSection/UserAuditLogsSection.tsx index bf3e194c3..d03cf3af7 100644 --- a/frontend-v2/src/pages/organization/UserDetailsByIDPage/components/UserProjectsSection/UserAuditLogsSection.tsx +++ b/frontend-v2/src/pages/organization/UserDetailsByIDPage/components/UserProjectsSection/UserAuditLogsSection.tsx @@ -6,8 +6,7 @@ import { IconButton, Tooltip } from "@app/components/v2"; import { OrgPermissionActions, OrgPermissionSubjects, useSubscription } from "@app/context"; import { withPermission } from "@app/hoc"; import { OrgUser } from "@app/hooks/api/types"; - -import { LogsSection } from "../../../../audit-logs/-components"; +import { LogsSection } from "@app/pages/organization/AuditLogsPage/components"; type Props = { orgMembership: OrgUser; diff --git a/frontend-v2/src/pages/organization/UserDetailsByIDPage/components/UserProjectsSection/UserProjectRow.tsx b/frontend-v2/src/pages/organization/UserDetailsByIDPage/components/UserProjectsSection/UserProjectRow.tsx index 2a879f0fb..0fbf4d216 100644 --- a/frontend-v2/src/pages/organization/UserDetailsByIDPage/components/UserProjectsSection/UserProjectRow.tsx +++ b/frontend-v2/src/pages/organization/UserDetailsByIDPage/components/UserProjectsSection/UserProjectRow.tsx @@ -52,7 +52,7 @@ export const UserProjectRow = ({ onClick={() => { if (isAccessible) { navigate({ - to: `/${project.type}/$projectId/access` as const, + to: `/${project.type}/$projectId/access-management` as const, params: { projectId: project.id }, diff --git a/frontend-v2/src/pages/organization/UserDetailsByIDPage/route.tsx b/frontend-v2/src/pages/organization/UserDetailsByIDPage/route.tsx index d50598a73..37bac8f73 100644 --- a/frontend-v2/src/pages/organization/UserDetailsByIDPage/route.tsx +++ b/frontend-v2/src/pages/organization/UserDetailsByIDPage/route.tsx @@ -1,9 +1,9 @@ -import { createFileRoute } from '@tanstack/react-router' +import { createFileRoute } from "@tanstack/react-router"; -import { UserDetailsByIDPage } from './UserDetailsByIDPage' +import { UserDetailsByIDPage } from "./UserDetailsByIDPage"; export const Route = createFileRoute( - '/_authenticate/_inject-org-details/organization/_layout/members/$membershipId', + "/_authenticate/_inject-org-details/organization/_layout/members/$membershipId" )({ - component: UserDetailsByIDPage, -}) + component: UserDetailsByIDPage +}); diff --git a/frontend-v2/src/pages/organization/layout.tsx b/frontend-v2/src/pages/organization/layout.tsx index 547974117..646a27ff3 100644 --- a/frontend-v2/src/pages/organization/layout.tsx +++ b/frontend-v2/src/pages/organization/layout.tsx @@ -1,9 +1,7 @@ -import { createFileRoute } from '@tanstack/react-router' +import { createFileRoute } from "@tanstack/react-router"; -import { OrganizationLayout } from '@app/layouts/OrganizationLayout' +import { OrganizationLayout } from "@app/layouts/OrganizationLayout"; -export const Route = createFileRoute( - '/_authenticate/_inject-org-details/organization/_layout', -)({ - component: OrganizationLayout, -}) +export const Route = createFileRoute("/_authenticate/_inject-org-details/organization/_layout")({ + component: OrganizationLayout +}); diff --git a/frontend-v2/src/pages/project/AccessControlPage/AccessControlPage.tsx b/frontend-v2/src/pages/project/AccessControlPage/AccessControlPage.tsx index cb0205180..2fbc9e67a 100644 --- a/frontend-v2/src/pages/project/AccessControlPage/AccessControlPage.tsx +++ b/frontend-v2/src/pages/project/AccessControlPage/AccessControlPage.tsx @@ -28,7 +28,7 @@ const Page = withProjectPermission( const updateSelectedTab = (tab: string) => { navigate({ - to: `/${currentWorkspace.type}/$projectId/access` as const, + to: `/${currentWorkspace.type}/$projectId/access-management` as const, search: (prev) => ({ ...prev, selectedTab: tab }), params: { projectId: currentWorkspace.id diff --git a/frontend-v2/src/pages/project/AccessControlPage/components/GroupsTab/GroupsTab.tsx b/frontend-v2/src/pages/project/AccessControlPage/components/GroupsTab/GroupsTab.tsx index 19fb35773..e3f040375 100644 --- a/frontend-v2/src/pages/project/AccessControlPage/components/GroupsTab/GroupsTab.tsx +++ b/frontend-v2/src/pages/project/AccessControlPage/components/GroupsTab/GroupsTab.tsx @@ -15,4 +15,3 @@ export const GroupsTab = () => { ); }; - diff --git a/frontend-v2/src/pages/project/AccessControlPage/components/GroupsTab/components/GroupsSection/GroupModal.tsx b/frontend-v2/src/pages/project/AccessControlPage/components/GroupsTab/components/GroupsSection/GroupModal.tsx index bd150a6a1..f909f92b4 100644 --- a/frontend-v2/src/pages/project/AccessControlPage/components/GroupsTab/components/GroupsSection/GroupModal.tsx +++ b/frontend-v2/src/pages/project/AccessControlPage/components/GroupsTab/components/GroupsSection/GroupModal.tsx @@ -147,7 +147,7 @@ const Content = ({ popUp, handlePopUpToggle }: Props) => {
All groups in your organization have already been added to this project.
- +
diff --git a/frontend-v2/src/pages/project/AccessControlPage/components/GroupsTab/components/GroupsSection/index.tsx b/frontend-v2/src/pages/project/AccessControlPage/components/GroupsTab/components/GroupsSection/index.tsx index 7726fd170..a08c82739 100644 --- a/frontend-v2/src/pages/project/AccessControlPage/components/GroupsTab/components/GroupsSection/index.tsx +++ b/frontend-v2/src/pages/project/AccessControlPage/components/GroupsTab/components/GroupsSection/index.tsx @@ -1 +1 @@ -export { GroupsSection } from "./GroupsSection"; \ No newline at end of file +export { GroupsSection } from "./GroupsSection"; diff --git a/frontend-v2/src/pages/project/AccessControlPage/components/GroupsTab/components/index.tsx b/frontend-v2/src/pages/project/AccessControlPage/components/GroupsTab/components/index.tsx index 7726fd170..a08c82739 100644 --- a/frontend-v2/src/pages/project/AccessControlPage/components/GroupsTab/components/index.tsx +++ b/frontend-v2/src/pages/project/AccessControlPage/components/GroupsTab/components/index.tsx @@ -1 +1 @@ -export { GroupsSection } from "./GroupsSection"; \ No newline at end of file +export { GroupsSection } from "./GroupsSection"; diff --git a/frontend-v2/src/pages/project/AccessControlPage/components/GroupsTab/index.tsx b/frontend-v2/src/pages/project/AccessControlPage/components/GroupsTab/index.tsx index 419579efc..a4cb0c27a 100644 --- a/frontend-v2/src/pages/project/AccessControlPage/components/GroupsTab/index.tsx +++ b/frontend-v2/src/pages/project/AccessControlPage/components/GroupsTab/index.tsx @@ -1 +1 @@ -export { GroupsTab } from "./GroupsTab"; \ No newline at end of file +export { GroupsTab } from "./GroupsTab"; diff --git a/frontend-v2/src/pages/project/AccessControlPage/components/IdentityTab/components/IdentityModal.tsx b/frontend-v2/src/pages/project/AccessControlPage/components/IdentityTab/components/IdentityModal.tsx index bd161a5ec..1baf80b9b 100644 --- a/frontend-v2/src/pages/project/AccessControlPage/components/IdentityTab/components/IdentityModal.tsx +++ b/frontend-v2/src/pages/project/AccessControlPage/components/IdentityTab/components/IdentityModal.tsx @@ -182,7 +182,7 @@ const Content = ({ popUp, handlePopUpToggle }: Props) => {
All identities in your organization have already been added to this project.
- + diff --git a/frontend-v2/src/pages/project/AccessControlPage/components/MembersTab/components/AddMemberModal.tsx b/frontend-v2/src/pages/project/AccessControlPage/components/MembersTab/components/AddMemberModal.tsx index b448200d8..492df2aaa 100644 --- a/frontend-v2/src/pages/project/AccessControlPage/components/MembersTab/components/AddMemberModal.tsx +++ b/frontend-v2/src/pages/project/AccessControlPage/components/MembersTab/components/AddMemberModal.tsx @@ -211,7 +211,7 @@ export const AddMemberModal = ({ popUp, handlePopUpToggle }: Props) => { ) : (
All the users in your organization are already invited.
- +
diff --git a/frontend-v2/src/pages/project/AccessControlPage/components/ProjectRoleListTab/components/ProjectRoleList/ProjectRoleList.tsx b/frontend-v2/src/pages/project/AccessControlPage/components/ProjectRoleListTab/components/ProjectRoleList/ProjectRoleList.tsx index 312de70ac..cf00be0de 100644 --- a/frontend-v2/src/pages/project/AccessControlPage/components/ProjectRoleListTab/components/ProjectRoleList/ProjectRoleList.tsx +++ b/frontend-v2/src/pages/project/AccessControlPage/components/ProjectRoleListTab/components/ProjectRoleList/ProjectRoleList.tsx @@ -25,7 +25,7 @@ import { ProjectPermissionActions, ProjectPermissionSub, useWorkspace } from "@a import { usePopUp } from "@app/hooks"; import { useDeleteProjectRole, useGetProjectRoles } from "@app/hooks/api"; import { TProjectRole } from "@app/hooks/api/roles/types"; -import { RoleModal } from "@app/routes/_authenticate/_ctx-org-details/organization/_layout-org/roles/$roleId/-components"; +import { RoleModal } from "@app/pages/organization/RoleByIDPage/components"; export const ProjectRoleList = () => { const navigate = useNavigate(); diff --git a/frontend-v2/src/pages/project/AccessControlPage/components/ServiceTokenTab/components/ServiceTokenSection/ServiceTokenSection.tsx b/frontend-v2/src/pages/project/AccessControlPage/components/ServiceTokenTab/components/ServiceTokenSection/ServiceTokenSection.tsx index 46e9e2ceb..e66ad17cd 100644 --- a/frontend-v2/src/pages/project/AccessControlPage/components/ServiceTokenTab/components/ServiceTokenSection/ServiceTokenSection.tsx +++ b/frontend-v2/src/pages/project/AccessControlPage/components/ServiceTokenTab/components/ServiceTokenSection/ServiceTokenSection.tsx @@ -18,7 +18,7 @@ type DeleteModalData = { name: string; id: string }; export const ServiceTokenSection = withProjectPermission( () => { const { t } = useTranslation(); - + const deleteServiceToken = useDeleteServiceToken(); const { popUp, handlePopUpToggle, handlePopUpClose, handlePopUpOpen } = usePopUp([ diff --git a/frontend-v2/src/pages/project/AccessControlPage/route-cert-manager.tsx b/frontend-v2/src/pages/project/AccessControlPage/route-cert-manager.tsx index 4bb75c967..1bea9fc9e 100644 --- a/frontend-v2/src/pages/project/AccessControlPage/route-cert-manager.tsx +++ b/frontend-v2/src/pages/project/AccessControlPage/route-cert-manager.tsx @@ -1,20 +1,18 @@ -import { createFileRoute } from '@tanstack/react-router' -import { zodValidator } from '@tanstack/zod-adapter' -import { z } from 'zod' +import { createFileRoute } from "@tanstack/react-router"; +import { zodValidator } from "@tanstack/zod-adapter"; +import { z } from "zod"; -import { ProjectAccessControlTabs } from '@app/types/project' +import { ProjectAccessControlTabs } from "@app/types/project"; -import { AccessControlPage } from './AccessControlPage' +import { AccessControlPage } from "./AccessControlPage"; const AccessControlPageQuerySchema = z.object({ - selectedTab: z - .nativeEnum(ProjectAccessControlTabs) - .catch(ProjectAccessControlTabs.Member), -}) + selectedTab: z.nativeEnum(ProjectAccessControlTabs).catch(ProjectAccessControlTabs.Member) +}); export const Route = createFileRoute( - '/_authenticate/_inject-org-details/cert-manager/$projectId/_cert-manager-layout/access-management', + "/_authenticate/_inject-org-details/cert-manager/$projectId/_cert-manager-layout/access-management" )({ component: AccessControlPage, - validateSearch: zodValidator(AccessControlPageQuerySchema), -}) + validateSearch: zodValidator(AccessControlPageQuerySchema) +}); diff --git a/frontend-v2/src/pages/project/AccessControlPage/route-kms.tsx b/frontend-v2/src/pages/project/AccessControlPage/route-kms.tsx index 9c62ebbd4..1262dda77 100644 --- a/frontend-v2/src/pages/project/AccessControlPage/route-kms.tsx +++ b/frontend-v2/src/pages/project/AccessControlPage/route-kms.tsx @@ -1,20 +1,18 @@ -import { createFileRoute } from '@tanstack/react-router' -import { zodValidator } from '@tanstack/zod-adapter' -import { z } from 'zod' +import { createFileRoute } from "@tanstack/react-router"; +import { zodValidator } from "@tanstack/zod-adapter"; +import { z } from "zod"; -import { ProjectAccessControlTabs } from '@app/types/project' +import { ProjectAccessControlTabs } from "@app/types/project"; -import { AccessControlPage } from './AccessControlPage' +import { AccessControlPage } from "./AccessControlPage"; const AccessControlPageQuerySchema = z.object({ - selectedTab: z - .nativeEnum(ProjectAccessControlTabs) - .catch(ProjectAccessControlTabs.Member), -}) + selectedTab: z.nativeEnum(ProjectAccessControlTabs).catch(ProjectAccessControlTabs.Member) +}); export const Route = createFileRoute( - '/_authenticate/_inject-org-details/kms/$projectId/_kms-layout/access-management', + "/_authenticate/_inject-org-details/kms/$projectId/_kms-layout/access-management" )({ component: AccessControlPage, - validateSearch: zodValidator(AccessControlPageQuerySchema), -}) + validateSearch: zodValidator(AccessControlPageQuerySchema) +}); diff --git a/frontend-v2/src/pages/project/AccessControlPage/route-secret-manager.tsx b/frontend-v2/src/pages/project/AccessControlPage/route-secret-manager.tsx index 0824160f2..4b9bb1b9d 100644 --- a/frontend-v2/src/pages/project/AccessControlPage/route-secret-manager.tsx +++ b/frontend-v2/src/pages/project/AccessControlPage/route-secret-manager.tsx @@ -1,20 +1,18 @@ -import { createFileRoute } from '@tanstack/react-router' -import { zodValidator } from '@tanstack/zod-adapter' -import { z } from 'zod' +import { createFileRoute } from "@tanstack/react-router"; +import { zodValidator } from "@tanstack/zod-adapter"; +import { z } from "zod"; -import { ProjectAccessControlTabs } from '@app/types/project' +import { ProjectAccessControlTabs } from "@app/types/project"; -import { AccessControlPage } from './AccessControlPage' +import { AccessControlPage } from "./AccessControlPage"; const AccessControlPageQuerySchema = z.object({ - selectedTab: z - .nativeEnum(ProjectAccessControlTabs) - .catch(ProjectAccessControlTabs.Member), -}) + selectedTab: z.nativeEnum(ProjectAccessControlTabs).catch(ProjectAccessControlTabs.Member) +}); export const Route = createFileRoute( - '/_authenticate/_inject-org-details/secret-manager/$projectId/_secret-manager-layout/access-management', + "/_authenticate/_inject-org-details/secret-manager/$projectId/_secret-manager-layout/access-management" )({ component: AccessControlPage, - validateSearch: zodValidator(AccessControlPageQuerySchema), -}) + validateSearch: zodValidator(AccessControlPageQuerySchema) +}); diff --git a/frontend-v2/src/pages/project/IdentityDetailsByIDPage/IdentityDetailsByIDPage.tsx b/frontend-v2/src/pages/project/IdentityDetailsByIDPage/IdentityDetailsByIDPage.tsx index 61faa8d4c..865a79206 100644 --- a/frontend-v2/src/pages/project/IdentityDetailsByIDPage/IdentityDetailsByIDPage.tsx +++ b/frontend-v2/src/pages/project/IdentityDetailsByIDPage/IdentityDetailsByIDPage.tsx @@ -53,7 +53,7 @@ const Page = () => { }); handlePopUpClose("deleteIdentity"); navigate({ - to: `/${currentWorkspace.type}/$projectId/access` as const, + to: `/${currentWorkspace.type}/$projectId/access-management` as const, params: { projectId: workspaceId }, @@ -90,7 +90,7 @@ const Page = () => { leftIcon={} onClick={() => { navigate({ - to: `/${currentWorkspace.type}/$projectId/access` as const, + to: `/${currentWorkspace.type}/$projectId/access-management` as const, params: { projectId: workspaceId }, diff --git a/frontend-v2/src/pages/project/IdentityDetailsByIDPage/route-cert-manager.tsx b/frontend-v2/src/pages/project/IdentityDetailsByIDPage/route-cert-manager.tsx index 30b1ca685..479cb32b7 100644 --- a/frontend-v2/src/pages/project/IdentityDetailsByIDPage/route-cert-manager.tsx +++ b/frontend-v2/src/pages/project/IdentityDetailsByIDPage/route-cert-manager.tsx @@ -1,8 +1,9 @@ -import { createFileRoute } from '@tanstack/react-router' -import { IdentityDetailsByIDPage } from './IdentityDetailsByIDPage' +import { createFileRoute } from "@tanstack/react-router"; + +import { IdentityDetailsByIDPage } from "./IdentityDetailsByIDPage"; export const Route = createFileRoute( - '/_authenticate/_inject-org-details/cert-manager/$projectId/_cert-manager-layout/identities/$identityId', + "/_authenticate/_inject-org-details/cert-manager/$projectId/_cert-manager-layout/identities/$identityId" )({ - component: IdentityDetailsByIDPage, -}) + component: IdentityDetailsByIDPage +}); diff --git a/frontend-v2/src/pages/project/IdentityDetailsByIDPage/route-kms.tsx b/frontend-v2/src/pages/project/IdentityDetailsByIDPage/route-kms.tsx index c4aea57c5..77f0e3d44 100644 --- a/frontend-v2/src/pages/project/IdentityDetailsByIDPage/route-kms.tsx +++ b/frontend-v2/src/pages/project/IdentityDetailsByIDPage/route-kms.tsx @@ -1,8 +1,9 @@ -import { createFileRoute } from '@tanstack/react-router' -import { IdentityDetailsByIDPage } from './IdentityDetailsByIDPage' +import { createFileRoute } from "@tanstack/react-router"; + +import { IdentityDetailsByIDPage } from "./IdentityDetailsByIDPage"; export const Route = createFileRoute( - '/_authenticate/_inject-org-details/kms/$projectId/_kms-layout/identities/$identityId', + "/_authenticate/_inject-org-details/kms/$projectId/_kms-layout/identities/$identityId" )({ - component: IdentityDetailsByIDPage, -}) + component: IdentityDetailsByIDPage +}); diff --git a/frontend-v2/src/pages/project/IdentityDetailsByIDPage/route-secret-manager.tsx b/frontend-v2/src/pages/project/IdentityDetailsByIDPage/route-secret-manager.tsx index b57179480..66e1245e2 100644 --- a/frontend-v2/src/pages/project/IdentityDetailsByIDPage/route-secret-manager.tsx +++ b/frontend-v2/src/pages/project/IdentityDetailsByIDPage/route-secret-manager.tsx @@ -1,8 +1,9 @@ -import { createFileRoute } from '@tanstack/react-router' -import { IdentityDetailsByIDPage } from './IdentityDetailsByIDPage' +import { createFileRoute } from "@tanstack/react-router"; + +import { IdentityDetailsByIDPage } from "./IdentityDetailsByIDPage"; export const Route = createFileRoute( - '/_authenticate/_inject-org-details/secret-manager/$projectId/_secret-manager-layout/identities/$identityId', + "/_authenticate/_inject-org-details/secret-manager/$projectId/_secret-manager-layout/identities/$identityId" )({ - component: IdentityDetailsByIDPage, -}) + component: IdentityDetailsByIDPage +}); diff --git a/frontend-v2/src/pages/project/MemberDetailsByIDPage/MemberDetailsByIDPage.tsx b/frontend-v2/src/pages/project/MemberDetailsByIDPage/MemberDetailsByIDPage.tsx index 2f104e707..c3a714ba9 100644 --- a/frontend-v2/src/pages/project/MemberDetailsByIDPage/MemberDetailsByIDPage.tsx +++ b/frontend-v2/src/pages/project/MemberDetailsByIDPage/MemberDetailsByIDPage.tsx @@ -58,7 +58,7 @@ export const Page = () => { type: "success" }); navigate({ - to: `/${currentWorkspace.type}/$projectId/access` as const, + to: `/${currentWorkspace.type}/$projectId/access-management` as const, params: { projectId: currentWorkspace.id } @@ -90,7 +90,7 @@ export const Page = () => { leftIcon={} onClick={() => { navigate({ - to: `/${currentWorkspace.type}/$projectId/access` as const, + to: `/${currentWorkspace.type}/$projectId/access-management` as const, params: { projectId: currentWorkspace.id } diff --git a/frontend-v2/src/pages/project/MemberDetailsByIDPage/components/MemberProjectAdditionalPrivilegeSection/MembershipProjectAdditionalPrivilegeModifySection.tsx b/frontend-v2/src/pages/project/MemberDetailsByIDPage/components/MemberProjectAdditionalPrivilegeSection/MembershipProjectAdditionalPrivilegeModifySection.tsx index e6ccda691..4ea443ccc 100644 --- a/frontend-v2/src/pages/project/MemberDetailsByIDPage/components/MemberProjectAdditionalPrivilegeSection/MembershipProjectAdditionalPrivilegeModifySection.tsx +++ b/frontend-v2/src/pages/project/MemberDetailsByIDPage/components/MemberProjectAdditionalPrivilegeSection/MembershipProjectAdditionalPrivilegeModifySection.tsx @@ -15,16 +15,6 @@ import { z } from "zod"; import { TtlFormLabel } from "@app/components/features"; import { createNotification } from "@app/components/notifications"; -import { GeneralPermissionPolicies } from "@app/components/permissions/ProjectRolePermissionsSection/components/GeneralPermissionPolicies"; -import { PermissionEmptyState } from "@app/components/permissions/ProjectRolePermissionsSection/PermissionEmptyState"; -import { - formRolePermission2API, - isConditionalSubjects, - PROJECT_PERMISSION_OBJECT, - projectRoleFormSchema, - rolePermission2Form -} from "@app/components/permissions/ProjectRolePermissionsSection/ProjectRoleModifySection.utils"; -import { renderConditionalComponents } from "@app/components/permissions/ProjectRolePermissionsSection/RolePermissionsSection"; import { Button, DropdownMenu, @@ -52,6 +42,16 @@ import { useUpdateProjectUserAdditionalPrivilege } from "@app/hooks/api"; import { ProjectUserAdditionalPrivilegeTemporaryMode } from "@app/hooks/api/projectUserAdditionalPrivilege/types"; +import { GeneralPermissionPolicies } from "@app/pages/project/RoleDetailsBySlugPage/components/GeneralPermissionPolicies"; +import { PermissionEmptyState } from "@app/pages/project/RoleDetailsBySlugPage/components/PermissionEmptyState"; +import { + formRolePermission2API, + isConditionalSubjects, + PROJECT_PERMISSION_OBJECT, + projectRoleFormSchema, + rolePermission2Form +} from "@app/pages/project/RoleDetailsBySlugPage/components/ProjectRoleModifySection.utils"; +import { renderConditionalComponents } from "@app/pages/project/RoleDetailsBySlugPage/components/RolePermissionsSection"; type Props = { privilegeId?: string; diff --git a/frontend-v2/src/pages/project/MemberDetailsByIDPage/route-cert-manager.tsx b/frontend-v2/src/pages/project/MemberDetailsByIDPage/route-cert-manager.tsx index cf60aed50..0f52ffc4c 100644 --- a/frontend-v2/src/pages/project/MemberDetailsByIDPage/route-cert-manager.tsx +++ b/frontend-v2/src/pages/project/MemberDetailsByIDPage/route-cert-manager.tsx @@ -1,9 +1,9 @@ -import { createFileRoute } from '@tanstack/react-router' +import { createFileRoute } from "@tanstack/react-router"; -import { MemberDetailsByIDPage } from './MemberDetailsByIdPage' +import { MemberDetailsByIDPage } from "./MemberDetailsByIdPage"; export const Route = createFileRoute( - '/_authenticate/_inject-org-details/cert-manager/$projectId/_cert-manager-layout/members/$membershipId', + "/_authenticate/_inject-org-details/cert-manager/$projectId/_cert-manager-layout/members/$membershipId" )({ - component: MemberDetailsByIDPage, -}) + component: MemberDetailsByIDPage +}); diff --git a/frontend-v2/src/pages/project/MemberDetailsByIDPage/route-kms.tsx b/frontend-v2/src/pages/project/MemberDetailsByIDPage/route-kms.tsx index 989487a88..7f01f9e52 100644 --- a/frontend-v2/src/pages/project/MemberDetailsByIDPage/route-kms.tsx +++ b/frontend-v2/src/pages/project/MemberDetailsByIDPage/route-kms.tsx @@ -1,9 +1,9 @@ -import { createFileRoute } from '@tanstack/react-router' +import { createFileRoute } from "@tanstack/react-router"; -import { MemberDetailsByIDPage } from './MemberDetailsByIdPage' +import { MemberDetailsByIDPage } from "./MemberDetailsByIdPage"; export const Route = createFileRoute( - '/_authenticate/_inject-org-details/kms/$projectId/_kms-layout/members/$membershipId', + "/_authenticate/_inject-org-details/kms/$projectId/_kms-layout/members/$membershipId" )({ - component: MemberDetailsByIDPage, -}) + component: MemberDetailsByIDPage +}); diff --git a/frontend-v2/src/pages/project/MemberDetailsByIDPage/route-secret-manager.tsx b/frontend-v2/src/pages/project/MemberDetailsByIDPage/route-secret-manager.tsx index 8f7c00752..f5d826e20 100644 --- a/frontend-v2/src/pages/project/MemberDetailsByIDPage/route-secret-manager.tsx +++ b/frontend-v2/src/pages/project/MemberDetailsByIDPage/route-secret-manager.tsx @@ -1,9 +1,9 @@ -import { createFileRoute } from '@tanstack/react-router' +import { createFileRoute } from "@tanstack/react-router"; -import { MemberDetailsByIDPage } from './MemberDetailsByIdPage' +import { MemberDetailsByIDPage } from "./MemberDetailsByIDPage"; export const Route = createFileRoute( - '/_authenticate/_inject-org-details/secret-manager/$projectId/_secret-manager-layout/members/$membershipId', + "/_authenticate/_inject-org-details/secret-manager/$projectId/_secret-manager-layout/members/$membershipId" )({ - component: MemberDetailsByIDPage, -}) + component: MemberDetailsByIDPage +}); diff --git a/frontend-v2/src/pages/project/RoleDetailsBySlugPage/RoleDetailsBySlugPage.tsx b/frontend-v2/src/pages/project/RoleDetailsBySlugPage/RoleDetailsBySlugPage.tsx index 3d2bbc3aa..522ac4434 100644 --- a/frontend-v2/src/pages/project/RoleDetailsBySlugPage/RoleDetailsBySlugPage.tsx +++ b/frontend-v2/src/pages/project/RoleDetailsBySlugPage/RoleDetailsBySlugPage.tsx @@ -29,7 +29,7 @@ const Page = () => { const navigate = useNavigate(); const roleSlug = useParams({ strict: false, - select: (el) => el.roleSlug + select: (el) => el.roleSlug as string }); const { currentWorkspace } = useWorkspace(); const projectId = currentWorkspace?.id || ""; @@ -58,7 +58,7 @@ const Page = () => { }); handlePopUpClose("deleteRole"); navigate({ - to: `/${currentWorkspace?.type}/$projectId/access` as const, + to: `/${currentWorkspace?.type}/$projectId/access-management` as const, params: { projectId }, @@ -90,7 +90,7 @@ const Page = () => { leftIcon={} onClick={() => navigate({ - to: `/${currentWorkspace?.type}/$projectId/access` as const, + to: `/${currentWorkspace?.type}/$projectId/access-management` as const, params: { projectId }, diff --git a/frontend-v2/src/pages/project/RoleDetailsBySlugPage/components/GeneralPermissionConditions.tsx b/frontend-v2/src/pages/project/RoleDetailsBySlugPage/components/GeneralPermissionConditions.tsx index 2ac518038..8617fe7d1 100644 --- a/frontend-v2/src/pages/project/RoleDetailsBySlugPage/components/GeneralPermissionConditions.tsx +++ b/frontend-v2/src/pages/project/RoleDetailsBySlugPage/components/GeneralPermissionConditions.tsx @@ -16,11 +16,11 @@ import { ProjectPermissionSub } from "@app/context/ProjectPermissionContext/types"; -import { TFormSchema } from "../ProjectRoleModifySection.utils"; import { getConditionOperatorHelperInfo, renderOperatorSelectItems } from "./PermissionConditionHelpers"; +import { TFormSchema } from "./ProjectRoleModifySection.utils"; type Props = { position?: number; diff --git a/frontend-v2/src/pages/project/RoleDetailsBySlugPage/components/GeneralPermissionPolicies.tsx b/frontend-v2/src/pages/project/RoleDetailsBySlugPage/components/GeneralPermissionPolicies.tsx index 15d819fc8..de2231fc9 100644 --- a/frontend-v2/src/pages/project/RoleDetailsBySlugPage/components/GeneralPermissionPolicies.tsx +++ b/frontend-v2/src/pages/project/RoleDetailsBySlugPage/components/GeneralPermissionPolicies.tsx @@ -18,7 +18,7 @@ import { isConditionalSubjects, TFormSchema, TProjectPermissionObject -} from "../ProjectRoleModifySection.utils"; +} from "./ProjectRoleModifySection.utils"; type Props = { title: string; @@ -47,7 +47,7 @@ export const GeneralPermissionPolicies =
setIsOpen.toggle()} @@ -74,7 +74,7 @@ export const GeneralPermissionPolicies = (
{isConditionalSubjects(subject) && ( -
+
Permission
void; diff --git a/frontend-v2/src/pages/project/RoleDetailsBySlugPage/components/RolePermissionsSection.tsx b/frontend-v2/src/pages/project/RoleDetailsBySlugPage/components/RolePermissionsSection.tsx index 16397ac24..efa800dcb 100644 --- a/frontend-v2/src/pages/project/RoleDetailsBySlugPage/components/RolePermissionsSection.tsx +++ b/frontend-v2/src/pages/project/RoleDetailsBySlugPage/components/RolePermissionsSection.tsx @@ -15,10 +15,9 @@ import { import { ProjectPermissionSub, useWorkspace } from "@app/context"; import { useGetProjectRoleBySlug, useUpdateProjectRole } from "@app/hooks/api"; -import { GeneralPermissionConditions } from "./components/GeneralPermissionConditions"; -import { GeneralPermissionPolicies } from "./components/GeneralPermissionPolicies"; -import { IdentityManagementPermissionConditions } from "./components/IdentityManagementPermissionConditions"; -import { SecretPermissionConditions } from "./components/SecretPermissionConditions"; +import { GeneralPermissionConditions } from "./GeneralPermissionConditions"; +import { GeneralPermissionPolicies } from "./GeneralPermissionPolicies"; +import { IdentityManagementPermissionConditions } from "./IdentityManagementPermissionConditions"; import { PermissionEmptyState } from "./PermissionEmptyState"; import { formRolePermission2API, @@ -28,6 +27,7 @@ import { rolePermission2Form, TFormSchema } from "./ProjectRoleModifySection.utils"; +import { SecretPermissionConditions } from "./SecretPermissionConditions"; type Props = { roleSlug: string; diff --git a/frontend-v2/src/pages/project/RoleDetailsBySlugPage/components/SecretPermissionConditions.tsx b/frontend-v2/src/pages/project/RoleDetailsBySlugPage/components/SecretPermissionConditions.tsx index b742b829d..0956ab958 100644 --- a/frontend-v2/src/pages/project/RoleDetailsBySlugPage/components/SecretPermissionConditions.tsx +++ b/frontend-v2/src/pages/project/RoleDetailsBySlugPage/components/SecretPermissionConditions.tsx @@ -13,11 +13,11 @@ import { } from "@app/components/v2"; import { PermissionConditionOperators } from "@app/context/ProjectPermissionContext/types"; -import { TFormSchema } from "../ProjectRoleModifySection.utils"; import { getConditionOperatorHelperInfo, renderOperatorSelectItems } from "./PermissionConditionHelpers"; +import { TFormSchema } from "./ProjectRoleModifySection.utils"; type Props = { position?: number; diff --git a/frontend-v2/src/pages/project/RoleDetailsBySlugPage/route-cert-manager.tsx b/frontend-v2/src/pages/project/RoleDetailsBySlugPage/route-cert-manager.tsx index a18830f85..7f9ec6791 100644 --- a/frontend-v2/src/pages/project/RoleDetailsBySlugPage/route-cert-manager.tsx +++ b/frontend-v2/src/pages/project/RoleDetailsBySlugPage/route-cert-manager.tsx @@ -1,9 +1,9 @@ -import { createFileRoute } from '@tanstack/react-router' +import { createFileRoute } from "@tanstack/react-router"; -import { RoleDetailsBySlugPage } from './RoleDetailsBySlugPage' +import { RoleDetailsBySlugPage } from "./RoleDetailsBySlugPage"; export const Route = createFileRoute( - '/_authenticate/_inject-org-details/cert-manager/$projectId/_cert-manager-layout/roles/$roleSlug', + "/_authenticate/_inject-org-details/cert-manager/$projectId/_cert-manager-layout/roles/$roleSlug" )({ - component: RoleDetailsBySlugPage, -}) + component: RoleDetailsBySlugPage +}); diff --git a/frontend-v2/src/pages/project/RoleDetailsBySlugPage/route-kms.tsx b/frontend-v2/src/pages/project/RoleDetailsBySlugPage/route-kms.tsx index 14b952f12..1677d9401 100644 --- a/frontend-v2/src/pages/project/RoleDetailsBySlugPage/route-kms.tsx +++ b/frontend-v2/src/pages/project/RoleDetailsBySlugPage/route-kms.tsx @@ -1,9 +1,9 @@ -import { createFileRoute } from '@tanstack/react-router' +import { createFileRoute } from "@tanstack/react-router"; -import { RoleDetailsBySlugPage } from './RoleDetailsBySlugPage' +import { RoleDetailsBySlugPage } from "./RoleDetailsBySlugPage"; export const Route = createFileRoute( - '/_authenticate/_inject-org-details/kms/$projectId/_kms-layout/roles/$roleSlug', + "/_authenticate/_inject-org-details/kms/$projectId/_kms-layout/roles/$roleSlug" )({ - component: RoleDetailsBySlugPage, -}) + component: RoleDetailsBySlugPage +}); diff --git a/frontend-v2/src/pages/project/RoleDetailsBySlugPage/route-secret-manager.tsx b/frontend-v2/src/pages/project/RoleDetailsBySlugPage/route-secret-manager.tsx index d35d28bb7..4a2f18750 100644 --- a/frontend-v2/src/pages/project/RoleDetailsBySlugPage/route-secret-manager.tsx +++ b/frontend-v2/src/pages/project/RoleDetailsBySlugPage/route-secret-manager.tsx @@ -1,9 +1,9 @@ -import { createFileRoute } from '@tanstack/react-router' +import { createFileRoute } from "@tanstack/react-router"; -import { RoleDetailsBySlugPage } from './RoleDetailsBySlugPage' +import { RoleDetailsBySlugPage } from "./RoleDetailsBySlugPage"; export const Route = createFileRoute( - '/_authenticate/_inject-org-details/secret-manager/$projectId/_secret-manager-layout/roles/$roleSlug', + "/_authenticate/_inject-org-details/secret-manager/$projectId/_secret-manager-layout/roles/$roleSlug" )({ - component: RoleDetailsBySlugPage, -}) + component: RoleDetailsBySlugPage +}); diff --git a/frontend-v2/src/pages/public/ShareSecretPage/ShareSecretPage.tsx b/frontend-v2/src/pages/public/ShareSecretPage/ShareSecretPage.tsx new file mode 100644 index 000000000..186949722 --- /dev/null +++ b/frontend-v2/src/pages/public/ShareSecretPage/ShareSecretPage.tsx @@ -0,0 +1,101 @@ +import { Helmet } from "react-helmet"; +import { faArrowRight } from "@fortawesome/free-solid-svg-icons"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; + +import { ShareSecretForm } from "./components"; + +export const ShareSecretPage = () => { + return ( + <> + + Securely Share Secrets | Infisical + + + + + +
+
+
+
+
+
+ + Infisical logo + +
+

+ Share a secret +

+

+ Powered by{" "} + + Infisical → + +

+
+
+ +
+
+
+
+
+

+ Open source{" "} + + secret management + {" "} + for developers +

+
+

+ + Infisical + {" "} + is the all-in-one secret management platform to securely manage secrets, configs, + and certificates across your team and infrastructure. +

+ +
+
+
+ +
+

+ Made with ❤️ by{" "} + + Infisical + +
+ 156 2nd st, 3rd Floor, San Francisco, California, 94105, United States. 🇺🇸 +

+
+
+
+ + ); +}; diff --git a/frontend-v2/src/pages/public/ShareSecretPage/components/ShareSecretForm.tsx b/frontend-v2/src/pages/public/ShareSecretPage/components/ShareSecretForm.tsx new file mode 100644 index 000000000..2fb470517 --- /dev/null +++ b/frontend-v2/src/pages/public/ShareSecretPage/components/ShareSecretForm.tsx @@ -0,0 +1,264 @@ +import { useState } from "react"; +import { Controller, useForm } from "react-hook-form"; +import { faCheck, faCopy, faRedo } from "@fortawesome/free-solid-svg-icons"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { zodResolver } from "@hookform/resolvers/zod"; +import { z } from "zod"; + +import { createNotification } from "@app/components/notifications"; +import { Button, FormControl, IconButton, Input, Select, SelectItem } from "@app/components/v2"; +import { useTimedReset } from "@app/hooks"; +import { useCreatePublicSharedSecret, useCreateSharedSecret } from "@app/hooks/api"; +import { SecretSharingAccessType } from "@app/hooks/api/secretSharing"; + +// values in ms +const expiresInOptions = [ + { label: "5 min", value: 5 * 60 * 1000 }, + { label: "30 min", value: 30 * 60 * 1000 }, + { label: "1 hour", value: 60 * 60 * 1000 }, + { label: "1 day", value: 24 * 60 * 60 * 1000 }, + { label: "7 days", value: 7 * 24 * 60 * 60 * 1000 }, + { label: "14 days", value: 14 * 24 * 60 * 60 * 1000 }, + { label: "30 days", value: 30 * 24 * 60 * 60 * 1000 } +]; + +const viewLimitOptions = [ + { label: "1", value: 1 }, + { label: "Unlimited", value: -1 } +]; + +const schema = z.object({ + name: z.string().optional(), + password: z.string().optional(), + secret: z.string().min(1), + expiresIn: z.string(), + viewLimit: z.string(), + accessType: z.nativeEnum(SecretSharingAccessType).optional() +}); + +export type FormData = z.infer; + +type Props = { + isPublic: boolean; // whether or not this is a public (non-authenticated) secret sharing form + value?: string; +}; + +export const ShareSecretForm = ({ isPublic, value }: Props) => { + const [secretLink, setSecretLink] = useState(""); + const [, isCopyingSecret, setCopyTextSecret] = useTimedReset({ + initialState: "Copy to clipboard" + }); + + const publicSharedSecretCreator = useCreatePublicSharedSecret(); + const privateSharedSecretCreator = useCreateSharedSecret(); + const createSharedSecret = isPublic ? publicSharedSecretCreator : privateSharedSecretCreator; + + const { + control, + reset, + handleSubmit, + formState: { isSubmitting } + } = useForm({ + resolver: zodResolver(schema), + defaultValues: { + secret: value || "" + } + }); + + const onFormSubmit = async ({ + name, + password, + secret, + expiresIn, + viewLimit, + accessType + }: FormData) => { + try { + const expiresAt = new Date(new Date().getTime() + Number(expiresIn)); + + const { id } = await createSharedSecret.mutateAsync({ + name, + password, + secretValue: secret, + expiresAt, + expiresAfterViews: viewLimit === "-1" ? undefined : Number(viewLimit), + accessType + }); + + const link = `${window.location.origin}/shared/secret/${id}`; + + setSecretLink(link); + reset(); + + navigator.clipboard.writeText(link); + setCopyTextSecret("secret"); + + createNotification({ + text: "Shared secret link copied to clipboard.", + type: "success" + }); + } catch (error) { + console.error(error); + createNotification({ + text: "Failed to create a shared secret.", + type: "error" + }); + } + }; + + const hasSecretLink = Boolean(secretLink); + + return !hasSecretLink ? ( +
+ {!isPublic && ( + ( + + + + )} + /> + )} + ( + +