From 98a15a901ec17c38c9312ce0e5196b45524475ba Mon Sep 17 00:00:00 2001 From: Sheen Capadngan Date: Wed, 26 Jun 2024 22:45:14 +0800 Subject: [PATCH 01/13] feat: allowed toggling login options as admin --- ...0240626115035_admin-login-method-config.ts | 19 ++ backend/src/db/schemas/super-admin.ts | 3 +- backend/src/server/routes/v1/admin-router.ts | 10 +- .../services/super-admin/super-admin-types.ts | 10 + frontend/src/hooks/api/admin/types.ts | 11 + .../components/InitialStep/InitialStep.tsx | 321 ++++++++++-------- .../views/admin/DashboardPage/AuthPanel.tsx | 251 ++++++++++++++ .../admin/DashboardPage/DashboardPage.tsx | 9 +- 8 files changed, 488 insertions(+), 146 deletions(-) create mode 100644 backend/src/db/migrations/20240626115035_admin-login-method-config.ts create mode 100644 frontend/src/views/admin/DashboardPage/AuthPanel.tsx diff --git a/backend/src/db/migrations/20240626115035_admin-login-method-config.ts b/backend/src/db/migrations/20240626115035_admin-login-method-config.ts new file mode 100644 index 0000000000..8748fe753e --- /dev/null +++ b/backend/src/db/migrations/20240626115035_admin-login-method-config.ts @@ -0,0 +1,19 @@ +import { Knex } from "knex"; + +import { TableName } from "../schemas"; + +export async function up(knex: Knex): Promise { + if (!(await knex.schema.hasColumn(TableName.SuperAdmin, "enabledLoginMethods"))) { + await knex.schema.alterTable(TableName.SuperAdmin, (tb) => { + tb.specificType("enabledLoginMethods", "text[]"); + }); + } +} + +export async function down(knex: Knex): Promise { + if (await knex.schema.hasColumn(TableName.SuperAdmin, "enabledLoginMethods")) { + await knex.schema.alterTable(TableName.SuperAdmin, (t) => { + t.dropColumn("enabledLoginMethods"); + }); + } +} diff --git a/backend/src/db/schemas/super-admin.ts b/backend/src/db/schemas/super-admin.ts index 29e41c78ef..b676b81a80 100644 --- a/backend/src/db/schemas/super-admin.ts +++ b/backend/src/db/schemas/super-admin.ts @@ -18,7 +18,8 @@ export const SuperAdminSchema = z.object({ trustSamlEmails: z.boolean().default(false).nullable().optional(), trustLdapEmails: z.boolean().default(false).nullable().optional(), trustOidcEmails: z.boolean().default(false).nullable().optional(), - defaultAuthOrgId: z.string().uuid().nullable().optional() + defaultAuthOrgId: z.string().uuid().nullable().optional(), + enabledLoginMethods: z.string().array().nullable().optional() }); export type TSuperAdmin = z.infer; diff --git a/backend/src/server/routes/v1/admin-router.ts b/backend/src/server/routes/v1/admin-router.ts index 24c7e2a6e4..4557152bdb 100644 --- a/backend/src/server/routes/v1/admin-router.ts +++ b/backend/src/server/routes/v1/admin-router.ts @@ -8,6 +8,7 @@ import { verifySuperAdmin } from "@app/server/plugins/auth/superAdmin"; import { verifyAuth } from "@app/server/plugins/auth/verify-auth"; import { AuthMode } from "@app/services/auth/auth-type"; import { getServerCfg } from "@app/services/super-admin/super-admin-service"; +import { LoginMethod } from "@app/services/super-admin/super-admin-types"; import { PostHogEventTypes } from "@app/services/telemetry/telemetry-types"; export const registerAdminRouter = async (server: FastifyZodProvider) => { @@ -54,7 +55,14 @@ export const registerAdminRouter = async (server: FastifyZodProvider) => { trustSamlEmails: z.boolean().optional(), trustLdapEmails: z.boolean().optional(), trustOidcEmails: z.boolean().optional(), - defaultAuthOrgId: z.string().optional().nullable() + defaultAuthOrgId: z.string().optional().nullable(), + enabledLoginMethods: z + .nativeEnum(LoginMethod) + .array() + .optional() + .refine((methods) => !methods || methods.length > 0, { + message: "At least one login method should be enabled." + }) }), response: { 200: z.object({ diff --git a/backend/src/services/super-admin/super-admin-types.ts b/backend/src/services/super-admin/super-admin-types.ts index e444c8843a..f622c8f174 100644 --- a/backend/src/services/super-admin/super-admin-types.ts +++ b/backend/src/services/super-admin/super-admin-types.ts @@ -15,3 +15,13 @@ export type TAdminSignUpDTO = { ip: string; userAgent: string; }; + +export enum LoginMethod { + EMAIL = "email", + GOOGLE = "google", + GITHUB = "github", + GITLAB = "gitlab", + SAML = "saml", + LDAP = "ldap", + OIDC = "oidc" +} diff --git a/frontend/src/hooks/api/admin/types.ts b/frontend/src/hooks/api/admin/types.ts index 524bc6ace0..4d5add1e0e 100644 --- a/frontend/src/hooks/api/admin/types.ts +++ b/frontend/src/hooks/api/admin/types.ts @@ -1,3 +1,13 @@ +export enum LoginMethod { + EMAIL = "email", + GOOGLE = "google", + GITHUB = "github", + GITLAB = "gitlab", + SAML = "saml", + LDAP = "ldap", + OIDC = "oidc" +} + export type TServerConfig = { initialized: boolean; allowSignUp: boolean; @@ -9,6 +19,7 @@ export type TServerConfig = { isSecretScanningDisabled: boolean; defaultAuthOrgSlug: string | null; defaultAuthOrgId: string | null; + enabledLoginMethods: LoginMethod[]; }; export type TCreateAdminUserDTO = { diff --git a/frontend/src/views/Login/components/InitialStep/InitialStep.tsx b/frontend/src/views/Login/components/InitialStep/InitialStep.tsx index 0616ee58d1..83615ccf56 100644 --- a/frontend/src/views/Login/components/InitialStep/InitialStep.tsx +++ b/frontend/src/views/Login/components/InitialStep/InitialStep.tsx @@ -15,6 +15,7 @@ import { CAPTCHA_SITE_KEY } from "@app/components/utilities/config"; import { Button, Input } from "@app/components/v2"; import { useServerConfig } from "@app/context"; import { useFetchServerStatus } from "@app/hooks/api"; +import { LoginMethod } from "@app/hooks/api/admin/types"; import { useNavigateToSelectOrganization } from "../../Login.utils"; @@ -162,154 +163,188 @@ export const InitialStep = ({ setStep, email, setEmail, password, setPassword }:

Login to Infisical

-
- -
-
- +
+ ))} + {!config.enabledLoginMethods || + (config.enabledLoginMethods.includes(LoginMethod.GITHUB) && ( +
+ -
-
- +
+ ))} + {!config.enabledLoginMethods || + (config.enabledLoginMethods.includes(LoginMethod.GITLAB) && ( +
+ -
-
- -
-
- -
-
- -
-
-
- or -
-
-
- setEmail(e.target.value)} - type="email" - placeholder="Enter your email..." - isRequired - autoComplete="username" - className="h-10" - /> -
-
- setPassword(e.target.value)} - type="password" - placeholder="Enter your password..." - isRequired - autoComplete="current-password" - id="current-password" - className="select:-webkit-autofill:focus h-10" - /> -
- {shouldShowCaptcha && ( -
- setCaptchaToken(token)} - ref={captchaRef} - /> -
- )} -
- -
+ window.close(); + }} + leftIcon={} + className="mx-0 h-10 w-full" + > + Continue with GitLab + +
+ ))} + {!config.enabledLoginMethods || + (config.enabledLoginMethods.includes(LoginMethod.SAML) && ( +
+ +
+ ))} + {!config.enabledLoginMethods || + (config.enabledLoginMethods.includes(LoginMethod.OIDC) && ( +
+ +
+ ))} + {!config.enabledLoginMethods || + (config.enabledLoginMethods.includes(LoginMethod.LDAP) && ( +
+ +
+ ))} + + {!config.enabledLoginMethods || + (config.enabledLoginMethods.length > 1 && + config.enabledLoginMethods.includes(LoginMethod.EMAIL) && ( +
+
+ or +
+
+ ))} + {!config.enabledLoginMethods || + (config.enabledLoginMethods.includes(LoginMethod.EMAIL) && ( + <> +
+ setEmail(e.target.value)} + type="email" + placeholder="Enter your email..." + isRequired + autoComplete="username" + className="h-10" + /> +
+
+ setPassword(e.target.value)} + type="password" + placeholder="Enter your password..." + isRequired + autoComplete="current-password" + id="current-password" + className="select:-webkit-autofill:focus h-10" + /> +
+ {shouldShowCaptcha && ( +
+ setCaptchaToken(token)} + ref={captchaRef} + /> +
+ )} +
+ +
+ + ))} {!isLoading && loginError && } {config.allowSignUp ? (
diff --git a/frontend/src/views/admin/DashboardPage/AuthPanel.tsx b/frontend/src/views/admin/DashboardPage/AuthPanel.tsx new file mode 100644 index 0000000000..0060cb095a --- /dev/null +++ b/frontend/src/views/admin/DashboardPage/AuthPanel.tsx @@ -0,0 +1,251 @@ +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), + 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 available to users +
+ { + 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/src/views/admin/DashboardPage/DashboardPage.tsx b/frontend/src/views/admin/DashboardPage/DashboardPage.tsx index 134a67f8cd..bf8a5a4a9e 100644 --- a/frontend/src/views/admin/DashboardPage/DashboardPage.tsx +++ b/frontend/src/views/admin/DashboardPage/DashboardPage.tsx @@ -24,10 +24,12 @@ import { import { useOrganization, useServerConfig, useUser } from "@app/context"; import { useGetOrganizations, useUpdateServerConfig } from "@app/hooks/api"; +import { AuthPanel } from "./AuthPanel"; import { RateLimitPanel } from "./RateLimitPanel"; enum TabSections { Settings = "settings", + Auth = "auth", RateLimit = "rate-limit" } @@ -131,6 +133,7 @@ export const AdminDashboardPage = () => {
General + Auth Rate Limit
@@ -203,7 +206,8 @@ export const AdminDashboardPage = () => { Default organization
- Select the default organization you want to set for SAML/LDAP based logins. When selected, user logins will be automatically scoped to the selected organization. + Select the default organization you want to set for SAML/LDAP based logins. When + selected, user logins will be automatically scoped to the selected organization.
{ + + + From e1ed37c7135caf3e916bcbd9d56e182bdb44ab4d Mon Sep 17 00:00:00 2001 From: Sheen Capadngan Date: Thu, 27 Jun 2024 01:07:28 +0800 Subject: [PATCH 02/13] misc: adjusted OrgSettingsPage and PersonalSettingsPage to include toggle --- .../components/OrgAuthTab/OrgAuthTab.tsx | 26 +++++++++++++++---- .../OrgAuthTab/OrgGeneralAuthSection.tsx | 2 +- .../components/OrgAuthTab/OrgLDAPSection.tsx | 2 +- .../components/OrgAuthTab/OrgOIDCSection.tsx | 2 +- .../components/OrgAuthTab/OrgSSOSection.tsx | 3 ++- .../AuthMethodSection/AuthMethodSection.tsx | 23 +++++++++++----- 6 files changed, 42 insertions(+), 16 deletions(-) diff --git a/frontend/src/views/Settings/OrgSettingsPage/components/OrgAuthTab/OrgAuthTab.tsx b/frontend/src/views/Settings/OrgSettingsPage/components/OrgAuthTab/OrgAuthTab.tsx index 31d6987bd8..b1a079922f 100644 --- a/frontend/src/views/Settings/OrgSettingsPage/components/OrgAuthTab/OrgAuthTab.tsx +++ b/frontend/src/views/Settings/OrgSettingsPage/components/OrgAuthTab/OrgAuthTab.tsx @@ -1,5 +1,8 @@ -import { OrgPermissionActions, OrgPermissionSubjects } from "@app/context"; +import { useCallback } from "react"; + +import { OrgPermissionActions, OrgPermissionSubjects, useServerConfig } from "@app/context"; import { withPermission } from "@app/hoc"; +import { LoginMethod } from "@app/hooks/api/admin/types"; import { OrgGeneralAuthSection } from "./OrgGeneralAuthSection"; import { OrgLDAPSection } from "./OrgLDAPSection"; @@ -9,12 +12,25 @@ import { OrgSSOSection } from "./OrgSSOSection"; export const OrgAuthTab = withPermission( () => { + const { + config: { enabledLoginMethods } + } = useServerConfig(); + + const shouldDisplaySection = useCallback( + (method: LoginMethod) => !enabledLoginMethods || enabledLoginMethods.includes(method), + [enabledLoginMethods] + ); + return (
- - - - + {shouldDisplaySection(LoginMethod.SAML) && ( + <> + + + + )} + {shouldDisplaySection(LoginMethod.OIDC) && } + {shouldDisplaySection(LoginMethod.LDAP) && }
); diff --git a/frontend/src/views/Settings/OrgSettingsPage/components/OrgAuthTab/OrgGeneralAuthSection.tsx b/frontend/src/views/Settings/OrgSettingsPage/components/OrgAuthTab/OrgGeneralAuthSection.tsx index 7c3af9493f..6e4eca456b 100644 --- a/frontend/src/views/Settings/OrgSettingsPage/components/OrgAuthTab/OrgGeneralAuthSection.tsx +++ b/frontend/src/views/Settings/OrgSettingsPage/components/OrgAuthTab/OrgGeneralAuthSection.tsx @@ -11,7 +11,6 @@ import { useLogoutUser, useUpdateOrg } from "@app/hooks/api"; import { usePopUp } from "@app/hooks/usePopUp"; export const OrgGeneralAuthSection = () => { - const { currentOrg } = useOrganization(); const { subscription } = useSubscription(); const { popUp, handlePopUpOpen, handlePopUpToggle } = usePopUp(["upgradePlan"] as const); @@ -88,6 +87,7 @@ export const OrgGeneralAuthSection = () => { Enforce members to authenticate via SAML to access this organization

+
handlePopUpToggle("upgradePlan", isOpen)} diff --git a/frontend/src/views/Settings/OrgSettingsPage/components/OrgAuthTab/OrgLDAPSection.tsx b/frontend/src/views/Settings/OrgSettingsPage/components/OrgAuthTab/OrgLDAPSection.tsx index 87d0f28aff..0d34fcefc0 100644 --- a/frontend/src/views/Settings/OrgSettingsPage/components/OrgAuthTab/OrgLDAPSection.tsx +++ b/frontend/src/views/Settings/OrgSettingsPage/components/OrgAuthTab/OrgLDAPSection.tsx @@ -94,7 +94,6 @@ export const OrgLDAPSection = (): JSX.Element => { return ( <> -

LDAP

@@ -151,6 +150,7 @@ export const OrgLDAPSection = (): JSX.Element => {

)} +
{ return ( <> -

OIDC

@@ -103,6 +102,7 @@ export const OrgOIDCSection = (): JSX.Element => {

)} +
{ const { currentOrg } = useOrganization(); const { subscription } = useSubscription(); - + const { data, isLoading } = useGetSSOConfig(currentOrg?.id ?? ""); const { mutateAsync } = useUpdateSSOConfig(); const { popUp, handlePopUpOpen, handlePopUpClose, handlePopUpToggle } = usePopUp([ @@ -115,6 +115,7 @@ export const OrgSSOSection = (): JSX.Element => { Allow members to authenticate into Infisical with SAML

+
; export const AuthMethodSection = () => { - const { user } = useUser(); + const { config } = useServerConfig(); const { mutateAsync } = useUpdateUserAuthMethods(); const { reset, setValue, watch } = useForm({ @@ -102,6 +103,14 @@ export const AuthMethodSection = () => {
{user && authMethodOpts.map((authMethodOpt) => { + // only filter when enabledLoginMethods is explicitly configured by admin + if ( + config.enabledLoginMethods && + !config.enabledLoginMethods.includes(authMethodOpt.loginMethod) + ) { + return null; + } + return (
From 9daa5badec8657f8fd0b8e3f8f129824e30bcd65 Mon Sep 17 00:00:00 2001 From: Sheen Capadngan Date: Thu, 27 Jun 2024 01:15:50 +0800 Subject: [PATCH 03/13] misc: made reusable helper for login page --- .../components/InitialStep/InitialStep.tsx | 329 +++++++++--------- 1 file changed, 160 insertions(+), 169 deletions(-) diff --git a/frontend/src/views/Login/components/InitialStep/InitialStep.tsx b/frontend/src/views/Login/components/InitialStep/InitialStep.tsx index 83615ccf56..d97126f671 100644 --- a/frontend/src/views/Login/components/InitialStep/InitialStep.tsx +++ b/frontend/src/views/Login/components/InitialStep/InitialStep.tsx @@ -62,6 +62,12 @@ export const InitialStep = ({ setStep, email, setEmail, password, setPassword }: } }, []); + const shouldDisplayLoginMethod = useCallback( + (method: LoginMethod) => + !config.enabledLoginMethods || config.enabledLoginMethods.includes(method), + [config] + ); + const handleLogin = async (e: FormEvent) => { e.preventDefault(); try { @@ -163,188 +169,173 @@ export const InitialStep = ({ setStep, email, setEmail, password, setPassword }:

Login to Infisical

- {!config.enabledLoginMethods || - (config.enabledLoginMethods.includes(LoginMethod.GOOGLE) && ( -
- -
- ))} - {!config.enabledLoginMethods || - (config.enabledLoginMethods.includes(LoginMethod.GITHUB) && ( -
- +
+ )} + {shouldDisplayLoginMethod(LoginMethod.GITHUB) && ( +
+ -
- ))} - {!config.enabledLoginMethods || - (config.enabledLoginMethods.includes(LoginMethod.GITLAB) && ( -
- +
+ )} + {shouldDisplayLoginMethod(LoginMethod.GITLAB) && ( +
+ -
- ))} - {!config.enabledLoginMethods || - (config.enabledLoginMethods.includes(LoginMethod.SAML) && ( -
- + window.close(); + }} + leftIcon={} + className="mx-0 h-10 w-full" + > + Continue with GitLab + +
+ )} + {shouldDisplayLoginMethod(LoginMethod.SAML) && ( +
+ +
+ )} + {shouldDisplayLoginMethod(LoginMethod.OIDC) && ( +
+ +
+ )} + {shouldDisplayLoginMethod(LoginMethod.LDAP) && ( +
+ +
+ )} + + {shouldDisplayLoginMethod(LoginMethod.EMAIL) && config.enabledLoginMethods.length > 1 && ( +
+
+ or +
+
+ )} + {shouldDisplayLoginMethod(LoginMethod.EMAIL) && ( + <> +
+ setEmail(e.target.value)} + type="email" + placeholder="Enter your email..." + isRequired + autoComplete="username" + className="h-10" + />
- ))} - {!config.enabledLoginMethods || - (config.enabledLoginMethods.includes(LoginMethod.OIDC) && (
- + setPassword(e.target.value)} + type="password" + placeholder="Enter your password..." + isRequired + autoComplete="current-password" + id="current-password" + className="select:-webkit-autofill:focus h-10" + />
- ))} - {!config.enabledLoginMethods || - (config.enabledLoginMethods.includes(LoginMethod.LDAP) && ( -
+ {shouldShowCaptcha && ( +
+ setCaptchaToken(token)} + ref={captchaRef} + /> +
+ )} +
- ))} - - {!config.enabledLoginMethods || - (config.enabledLoginMethods.length > 1 && - config.enabledLoginMethods.includes(LoginMethod.EMAIL) && ( -
-
- or -
-
- ))} - {!config.enabledLoginMethods || - (config.enabledLoginMethods.includes(LoginMethod.EMAIL) && ( - <> -
- setEmail(e.target.value)} - type="email" - placeholder="Enter your email..." - isRequired - autoComplete="username" - className="h-10" - /> -
-
- setPassword(e.target.value)} - type="password" - placeholder="Enter your password..." - isRequired - autoComplete="current-password" - id="current-password" - className="select:-webkit-autofill:focus h-10" - /> -
- {shouldShowCaptcha && ( -
- setCaptchaToken(token)} - ref={captchaRef} - /> -
- )} -
- -
- - ))} + + )} {!isLoading && loginError && } {config.allowSignUp ? (
From db39d03713403206725d1e2d0344020ab648074f Mon Sep 17 00:00:00 2001 From: Sheen Capadngan Date: Thu, 27 Jun 2024 01:59:02 +0800 Subject: [PATCH 04/13] misc: added check to backend --- .../src/services/auth/auth-login-service.ts | 35 +++++++++++++++++++ .../components/InitialStep/InitialStep.tsx | 4 +-- 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/backend/src/services/auth/auth-login-service.ts b/backend/src/services/auth/auth-login-service.ts index 8090b937ab..8207e4bec6 100644 --- a/backend/src/services/auth/auth-login-service.ts +++ b/backend/src/services/auth/auth-login-service.ts @@ -17,6 +17,7 @@ import { TAuthTokenServiceFactory } from "../auth-token/auth-token-service"; import { TokenType } from "../auth-token/auth-token-types"; import { TOrgDALFactory } from "../org/org-dal"; import { SmtpTemplates, TSmtpService } from "../smtp/smtp-service"; +import { LoginMethod } from "../super-admin/super-admin-types"; import { TUserDALFactory } from "../user/user-dal"; import { enforceUserLockStatus, validateProviderAuthToken } from "./auth-fns"; import { @@ -507,6 +508,40 @@ export const authLoginServiceFactory = ({ let user = await userDAL.findUserByUsername(email); const serverCfg = await getServerCfg(); + if (serverCfg.enabledLoginMethods) { + switch (authMethod) { + case AuthMethod.GITHUB: { + if (!serverCfg.enabledLoginMethods.includes(LoginMethod.GITHUB)) { + throw new BadRequestError({ + message: "Login with Github is disabled.", + name: "Oauth 2 login" + }); + } + break; + } + case AuthMethod.GOOGLE: { + if (!serverCfg.enabledLoginMethods.includes(LoginMethod.GOOGLE)) { + throw new BadRequestError({ + message: "Login with Google is disabled.", + name: "Oauth 2 login" + }); + } + break; + } + case AuthMethod.GITLAB: { + if (!serverCfg.enabledLoginMethods.includes(LoginMethod.GITLAB)) { + throw new BadRequestError({ + message: "Login with Gitlab is disabled.", + name: "Oauth 2 login" + }); + } + break; + } + default: + break; + } + } + const appCfg = getConfig(); if (!user) { diff --git a/frontend/src/views/Login/components/InitialStep/InitialStep.tsx b/frontend/src/views/Login/components/InitialStep/InitialStep.tsx index d97126f671..99e80048af 100644 --- a/frontend/src/views/Login/components/InitialStep/InitialStep.tsx +++ b/frontend/src/views/Login/components/InitialStep/InitialStep.tsx @@ -276,8 +276,8 @@ export const InitialStep = ({ setStep, email, setEmail, password, setPassword }:
)} - - {shouldDisplayLoginMethod(LoginMethod.EMAIL) && config.enabledLoginMethods.length > 1 && ( + {(!config.enabledLoginMethods || + (shouldDisplayLoginMethod(LoginMethod.EMAIL) && config.enabledLoginMethods.length > 1)) && (
or From c460f226650313ad1ff271d2113829d9cc14966f Mon Sep 17 00:00:00 2001 From: Sheen Capadngan Date: Thu, 27 Jun 2024 12:40:56 +0800 Subject: [PATCH 05/13] misc: added backend disable checks --- .../ee/services/ldap-config/ldap-config-service.ts | 8 ++++++++ backend/src/ee/services/oidc/oidc-config-service.ts | 8 ++++++++ .../ee/services/saml-config/saml-config-service.ts | 8 ++++++++ backend/src/services/auth/auth-login-service.ts | 13 +++++++++++++ 4 files changed, 37 insertions(+) diff --git a/backend/src/ee/services/ldap-config/ldap-config-service.ts b/backend/src/ee/services/ldap-config/ldap-config-service.ts index 63565d94c2..7434862fc7 100644 --- a/backend/src/ee/services/ldap-config/ldap-config-service.ts +++ b/backend/src/ee/services/ldap-config/ldap-config-service.ts @@ -34,6 +34,7 @@ import { TProjectBotDALFactory } from "@app/services/project-bot/project-bot-dal import { TProjectKeyDALFactory } from "@app/services/project-key/project-key-dal"; import { SmtpTemplates, TSmtpService } from "@app/services/smtp/smtp-service"; import { getServerCfg } from "@app/services/super-admin/super-admin-service"; +import { LoginMethod } from "@app/services/super-admin/super-admin-types"; import { TUserDALFactory } from "@app/services/user/user-dal"; import { normalizeUsername } from "@app/services/user/user-fns"; import { TUserAliasDALFactory } from "@app/services/user-alias/user-alias-dal"; @@ -411,6 +412,13 @@ export const ldapConfigServiceFactory = ({ }: TLdapLoginDTO) => { const appCfg = getConfig(); const serverCfg = await getServerCfg(); + + if (serverCfg.enabledLoginMethods && !serverCfg.enabledLoginMethods.includes(LoginMethod.LDAP)) { + throw new BadRequestError({ + message: "Login with LDAP is disabled." + }); + } + let userAlias = await userAliasDAL.findOne({ externalId, orgId, diff --git a/backend/src/ee/services/oidc/oidc-config-service.ts b/backend/src/ee/services/oidc/oidc-config-service.ts index b983492bc2..58b098522c 100644 --- a/backend/src/ee/services/oidc/oidc-config-service.ts +++ b/backend/src/ee/services/oidc/oidc-config-service.ts @@ -26,6 +26,7 @@ import { TOrgDALFactory } from "@app/services/org/org-dal"; import { TOrgMembershipDALFactory } from "@app/services/org-membership/org-membership-dal"; import { SmtpTemplates, TSmtpService } from "@app/services/smtp/smtp-service"; import { getServerCfg } from "@app/services/super-admin/super-admin-service"; +import { LoginMethod } from "@app/services/super-admin/super-admin-types"; import { TUserDALFactory } from "@app/services/user/user-dal"; import { normalizeUsername } from "@app/services/user/user-fns"; import { TUserAliasDALFactory } from "@app/services/user-alias/user-alias-dal"; @@ -157,6 +158,13 @@ export const oidcConfigServiceFactory = ({ const oidcLogin = async ({ externalId, email, firstName, lastName, orgId, callbackPort }: TOidcLoginDTO) => { const serverCfg = await getServerCfg(); + + if (serverCfg.enabledLoginMethods && !serverCfg.enabledLoginMethods.includes(LoginMethod.OIDC)) { + throw new BadRequestError({ + message: "Login with OIDC is disabled." + }); + } + const appCfg = getConfig(); const userAlias = await userAliasDAL.findOne({ externalId, diff --git a/backend/src/ee/services/saml-config/saml-config-service.ts b/backend/src/ee/services/saml-config/saml-config-service.ts index 3cc51e1c20..286a85746d 100644 --- a/backend/src/ee/services/saml-config/saml-config-service.ts +++ b/backend/src/ee/services/saml-config/saml-config-service.ts @@ -28,6 +28,7 @@ import { TOrgDALFactory } from "@app/services/org/org-dal"; import { TOrgMembershipDALFactory } from "@app/services/org-membership/org-membership-dal"; import { SmtpTemplates, TSmtpService } from "@app/services/smtp/smtp-service"; import { getServerCfg } from "@app/services/super-admin/super-admin-service"; +import { LoginMethod } from "@app/services/super-admin/super-admin-types"; import { TUserDALFactory } from "@app/services/user/user-dal"; import { normalizeUsername } from "@app/services/user/user-fns"; import { TUserAliasDALFactory } from "@app/services/user-alias/user-alias-dal"; @@ -335,6 +336,13 @@ export const samlConfigServiceFactory = ({ }: TSamlLoginDTO) => { const appCfg = getConfig(); const serverCfg = await getServerCfg(); + + if (serverCfg.enabledLoginMethods && !serverCfg.enabledLoginMethods.includes(LoginMethod.SAML)) { + throw new BadRequestError({ + message: "Login with SAML is disabled." + }); + } + const userAlias = await userAliasDAL.findOne({ externalId, orgId, diff --git a/backend/src/services/auth/auth-login-service.ts b/backend/src/services/auth/auth-login-service.ts index 8207e4bec6..24ae087b7a 100644 --- a/backend/src/services/auth/auth-login-service.ts +++ b/backend/src/services/auth/auth-login-service.ts @@ -159,9 +159,22 @@ export const authLoginServiceFactory = ({ const userEnc = await userDAL.findUserEncKeyByUsername({ username: email }); + const serverCfg = await getServerCfg(); + + if ( + serverCfg.enabledLoginMethods && + !serverCfg.enabledLoginMethods.includes(LoginMethod.EMAIL) && + !providerAuthToken + ) { + throw new BadRequestError({ + message: "Login with email is disabled." + }); + } + if (!userEnc || (userEnc && !userEnc.isAccepted)) { throw new Error("Failed to find user"); } + if (!userEnc.authMethods?.includes(AuthMethod.EMAIL)) { validateProviderAuthToken(providerAuthToken as string, email); } From b3463e0d0fe563ccc8f5c4a744aaf618d1c0020f Mon Sep 17 00:00:00 2001 From: Sheen Capadngan Date: Thu, 27 Jun 2024 12:55:39 +0800 Subject: [PATCH 06/13] misc: added explicit comment of intent --- frontend/src/views/admin/DashboardPage/AuthPanel.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/frontend/src/views/admin/DashboardPage/AuthPanel.tsx b/frontend/src/views/admin/DashboardPage/AuthPanel.tsx index 0060cb095a..f2fab83ec1 100644 --- a/frontend/src/views/admin/DashboardPage/AuthPanel.tsx +++ b/frontend/src/views/admin/DashboardPage/AuthPanel.tsx @@ -31,6 +31,7 @@ export const AuthPanel = () => { 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), From 92a663a17d3f1f3879ea45e3c80d1778148c041c Mon Sep 17 00:00:00 2001 From: Sheen Capadngan Date: Thu, 27 Jun 2024 13:24:26 +0800 Subject: [PATCH 07/13] misc: design change to finalize scim section in org settings --- .../OrgSettingsPage/components/OrgAuthTab/OrgSCIMSection.tsx | 2 -- 1 file changed, 2 deletions(-) diff --git a/frontend/src/views/Settings/OrgSettingsPage/components/OrgAuthTab/OrgSCIMSection.tsx b/frontend/src/views/Settings/OrgSettingsPage/components/OrgAuthTab/OrgSCIMSection.tsx index 601643db80..ffec3f3558 100644 --- a/frontend/src/views/Settings/OrgSettingsPage/components/OrgAuthTab/OrgSCIMSection.tsx +++ b/frontend/src/views/Settings/OrgSettingsPage/components/OrgAuthTab/OrgSCIMSection.tsx @@ -13,7 +13,6 @@ import { usePopUp } from "@app/hooks/usePopUp"; import { ScimTokenModal } from "./ScimTokenModal"; export const OrgScimSection = () => { - const { currentOrg } = useOrganization(); const { subscription } = useSubscription(); const { popUp, handlePopUpOpen, handlePopUpToggle } = usePopUp([ @@ -59,7 +58,6 @@ export const OrgScimSection = () => { return ( <> -

SCIM

From d6881e2e6831429ded24526e21ff210812e71af9 Mon Sep 17 00:00:00 2001 From: Sheen Capadngan Date: Thu, 27 Jun 2024 13:53:12 +0800 Subject: [PATCH 08/13] misc: added signup option filtering --- .../components/signup/InitialSignupStep.tsx | 129 ++++++++++-------- 1 file changed, 74 insertions(+), 55 deletions(-) diff --git a/frontend/src/components/signup/InitialSignupStep.tsx b/frontend/src/components/signup/InitialSignupStep.tsx index e5c23f3334..8df6759132 100644 --- a/frontend/src/components/signup/InitialSignupStep.tsx +++ b/frontend/src/components/signup/InitialSignupStep.tsx @@ -1,9 +1,13 @@ +import { useCallback } from "react"; import { useTranslation } from "react-i18next"; import Link from "next/link"; import { faGithub, faGitlab, faGoogle } from "@fortawesome/free-brands-svg-icons"; import { faEnvelope } from "@fortawesome/free-regular-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { useServerConfig } from "@app/context"; +import { LoginMethod } from "@app/hooks/api/admin/types"; + import { Button } from "../v2"; export default function InitialSignupStep({ @@ -12,67 +16,82 @@ export default function InitialSignupStep({ setIsSignupWithEmail: (value: boolean) => void; }) { const { t } = useTranslation(); + const { config } = useServerConfig(); + + const shouldDisplaySignupMethod = useCallback( + (method: LoginMethod) => + !config.enabledLoginMethods || config.enabledLoginMethods.includes(method), + [config] + ); return (

{t("signup.initial-title")}

-
- -
-
- -
-
- -
-
- -
+ {shouldDisplaySignupMethod(LoginMethod.GOOGLE) && ( +
+ +
+ )} + {shouldDisplaySignupMethod(LoginMethod.GITHUB) && ( +
+ +
+ )} + {shouldDisplaySignupMethod(LoginMethod.GITLAB) && ( +
+ +
+ )} + {shouldDisplaySignupMethod(LoginMethod.EMAIL) && ( +
+ +
+ )}
{t("signup.create-policy")}
From 59fc34412dde33add0068a73d2e93af344e3bdbe Mon Sep 17 00:00:00 2001 From: Maidul Islam Date: Thu, 27 Jun 2024 20:35:15 -0400 Subject: [PATCH 09/13] small nits for admin login toggle pr --- .../src/ee/services/ldap-config/ldap-config-service.ts | 2 +- backend/src/ee/services/oidc/oidc-config-service.ts | 2 +- .../src/ee/services/saml-config/saml-config-service.ts | 2 +- backend/src/services/auth/auth-login-service.ts | 8 ++++---- frontend/src/views/admin/DashboardPage/AuthPanel.tsx | 2 +- frontend/src/views/admin/DashboardPage/DashboardPage.tsx | 4 ++-- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/backend/src/ee/services/ldap-config/ldap-config-service.ts b/backend/src/ee/services/ldap-config/ldap-config-service.ts index 7434862fc7..55129ca025 100644 --- a/backend/src/ee/services/ldap-config/ldap-config-service.ts +++ b/backend/src/ee/services/ldap-config/ldap-config-service.ts @@ -415,7 +415,7 @@ export const ldapConfigServiceFactory = ({ if (serverCfg.enabledLoginMethods && !serverCfg.enabledLoginMethods.includes(LoginMethod.LDAP)) { throw new BadRequestError({ - message: "Login with LDAP is disabled." + message: "Login with LDAP is disabled by administrator." }); } diff --git a/backend/src/ee/services/oidc/oidc-config-service.ts b/backend/src/ee/services/oidc/oidc-config-service.ts index 58b098522c..55c929b9a9 100644 --- a/backend/src/ee/services/oidc/oidc-config-service.ts +++ b/backend/src/ee/services/oidc/oidc-config-service.ts @@ -161,7 +161,7 @@ export const oidcConfigServiceFactory = ({ if (serverCfg.enabledLoginMethods && !serverCfg.enabledLoginMethods.includes(LoginMethod.OIDC)) { throw new BadRequestError({ - message: "Login with OIDC is disabled." + message: "Login with OIDC is disabled by administrator." }); } diff --git a/backend/src/ee/services/saml-config/saml-config-service.ts b/backend/src/ee/services/saml-config/saml-config-service.ts index 286a85746d..9ac6c9c5ed 100644 --- a/backend/src/ee/services/saml-config/saml-config-service.ts +++ b/backend/src/ee/services/saml-config/saml-config-service.ts @@ -339,7 +339,7 @@ export const samlConfigServiceFactory = ({ if (serverCfg.enabledLoginMethods && !serverCfg.enabledLoginMethods.includes(LoginMethod.SAML)) { throw new BadRequestError({ - message: "Login with SAML is disabled." + message: "Login with SAML is disabled by administrator." }); } diff --git a/backend/src/services/auth/auth-login-service.ts b/backend/src/services/auth/auth-login-service.ts index 24ae087b7a..2ce900b471 100644 --- a/backend/src/services/auth/auth-login-service.ts +++ b/backend/src/services/auth/auth-login-service.ts @@ -167,7 +167,7 @@ export const authLoginServiceFactory = ({ !providerAuthToken ) { throw new BadRequestError({ - message: "Login with email is disabled." + message: "Login with email is disabled by administrator." }); } @@ -526,7 +526,7 @@ export const authLoginServiceFactory = ({ case AuthMethod.GITHUB: { if (!serverCfg.enabledLoginMethods.includes(LoginMethod.GITHUB)) { throw new BadRequestError({ - message: "Login with Github is disabled.", + message: "Login with Github is disabled by administrator.", name: "Oauth 2 login" }); } @@ -535,7 +535,7 @@ export const authLoginServiceFactory = ({ case AuthMethod.GOOGLE: { if (!serverCfg.enabledLoginMethods.includes(LoginMethod.GOOGLE)) { throw new BadRequestError({ - message: "Login with Google is disabled.", + message: "Login with Google is disabled by administrator.", name: "Oauth 2 login" }); } @@ -544,7 +544,7 @@ export const authLoginServiceFactory = ({ case AuthMethod.GITLAB: { if (!serverCfg.enabledLoginMethods.includes(LoginMethod.GITLAB)) { throw new BadRequestError({ - message: "Login with Gitlab is disabled.", + message: "Login with Gitlab is disabled by administrator.", name: "Oauth 2 login" }); } diff --git a/frontend/src/views/admin/DashboardPage/AuthPanel.tsx b/frontend/src/views/admin/DashboardPage/AuthPanel.tsx index f2fab83ec1..84e48ea0f6 100644 --- a/frontend/src/views/admin/DashboardPage/AuthPanel.tsx +++ b/frontend/src/views/admin/DashboardPage/AuthPanel.tsx @@ -117,7 +117,7 @@ export const AuthPanel = () => {
Login Methods
- Select the login methods available to users + Select the login methods you wish to allow for all users of this instance.
{

Admin Dashboard

-

Manage your Infisical instance.

+

Manage your instance level configurations.

{isUserLoading || isNotAllowed ? ( @@ -133,7 +133,7 @@ export const AdminDashboardPage = () => {
General - Auth + Authentication Rate Limit
From 04f54479cd6a968f2fd1e6e5bcc5459ddfa98fbd Mon Sep 17 00:00:00 2001 From: Sheen Capadngan Date: Sat, 29 Jun 2024 01:58:27 +0800 Subject: [PATCH 10/13] misc: implemented review comments --- backend/src/server/routes/v1/admin-router.ts | 2 +- .../super-admin/super-admin-service.ts | 37 +++++++++++++++++-- .../components/InitialStep/InitialStep.tsx | 6 ++- 3 files changed, 40 insertions(+), 5 deletions(-) diff --git a/backend/src/server/routes/v1/admin-router.ts b/backend/src/server/routes/v1/admin-router.ts index 4557152bdb..73d6cc7e78 100644 --- a/backend/src/server/routes/v1/admin-router.ts +++ b/backend/src/server/routes/v1/admin-router.ts @@ -78,7 +78,7 @@ export const registerAdminRouter = async (server: FastifyZodProvider) => { }); }, handler: async (req) => { - const config = await server.services.superAdmin.updateServerCfg(req.body); + const config = await server.services.superAdmin.updateServerCfg(req.body, req.permission.id); return { config }; } }); diff --git a/backend/src/services/super-admin/super-admin-service.ts b/backend/src/services/super-admin/super-admin-service.ts index 41b97efa42..a51282db6f 100644 --- a/backend/src/services/super-admin/super-admin-service.ts +++ b/backend/src/services/super-admin/super-admin-service.ts @@ -12,7 +12,7 @@ import { AuthMethod } from "../auth/auth-type"; import { TOrgServiceFactory } from "../org/org-service"; import { TUserDALFactory } from "../user/user-dal"; import { TSuperAdminDALFactory } from "./super-admin-dal"; -import { TAdminSignUpDTO } from "./super-admin-types"; +import { LoginMethod, TAdminSignUpDTO } from "./super-admin-types"; type TSuperAdminServiceFactoryDep = { serverCfgDAL: TSuperAdminDALFactory; @@ -79,7 +79,38 @@ export const superAdminServiceFactory = ({ return newCfg; }; - const updateServerCfg = async (data: TSuperAdminUpdate) => { + const updateServerCfg = async (data: TSuperAdminUpdate, userId: string) => { + if (data.enabledLoginMethods) { + const superAdminUser = await userDAL.findById(userId); + const loginMethodToAuthMethod = { + [LoginMethod.EMAIL]: [AuthMethod.EMAIL], + [LoginMethod.GOOGLE]: [AuthMethod.GOOGLE], + [LoginMethod.GITLAB]: [AuthMethod.GITLAB], + [LoginMethod.GITHUB]: [AuthMethod.GITHUB], + [LoginMethod.LDAP]: [AuthMethod.LDAP], + [LoginMethod.OIDC]: [AuthMethod.OIDC], + [LoginMethod.SAML]: [ + AuthMethod.AZURE_SAML, + AuthMethod.GOOGLE_SAML, + AuthMethod.JUMPCLOUD_SAML, + AuthMethod.KEYCLOAK_SAML, + AuthMethod.OKTA_SAML + ] + }; + + if ( + !data.enabledLoginMethods.some((loginMethod) => + loginMethodToAuthMethod[loginMethod as LoginMethod].some( + (authMethod) => superAdminUser.authMethods?.includes(authMethod) + ) + ) + ) { + throw new BadRequestError({ + message: + "Admin has insufficient authentication methods for update operation to complete without getting locked out." + }); + } + } const updatedServerCfg = await serverCfgDAL.updateById(ADMIN_CONFIG_DB_UUID, data); await keyStore.setItemWithExpiry(ADMIN_CONFIG_KEY, ADMIN_CONFIG_KEY_EXP, JSON.stringify(updatedServerCfg)); @@ -167,7 +198,7 @@ export const superAdminServiceFactory = ({ orgName: initialOrganizationName }); - await updateServerCfg({ initialized: true }); + await updateServerCfg({ initialized: true }, userInfo.user.id); const token = await authService.generateUserTokens({ user: userInfo.user, authMethod: AuthMethod.EMAIL, diff --git a/frontend/src/views/Login/components/InitialStep/InitialStep.tsx b/frontend/src/views/Login/components/InitialStep/InitialStep.tsx index 99e80048af..69a4188270 100644 --- a/frontend/src/views/Login/components/InitialStep/InitialStep.tsx +++ b/frontend/src/views/Login/components/InitialStep/InitialStep.tsx @@ -337,7 +337,11 @@ export const InitialStep = ({ setStep, email, setEmail, password, setPassword }: )} {!isLoading && loginError && } - {config.allowSignUp ? ( + {config.allowSignUp && + (shouldDisplayLoginMethod(LoginMethod.EMAIL) || + shouldDisplayLoginMethod(LoginMethod.GOOGLE) || + shouldDisplayLoginMethod(LoginMethod.GITHUB) || + shouldDisplayLoginMethod(LoginMethod.GITLAB)) ? (
From 5a1e43be4448fe2d1b069a9338a701414ae521c4 Mon Sep 17 00:00:00 2001 From: Sheen Capadngan Date: Sat, 29 Jun 2024 02:12:09 +0800 Subject: [PATCH 11/13] misc: only display recover when email login is enabled --- .../Login/components/InitialStep/InitialStep.tsx | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/frontend/src/views/Login/components/InitialStep/InitialStep.tsx b/frontend/src/views/Login/components/InitialStep/InitialStep.tsx index 69a4188270..06c4df835b 100644 --- a/frontend/src/views/Login/components/InitialStep/InitialStep.tsx +++ b/frontend/src/views/Login/components/InitialStep/InitialStep.tsx @@ -352,13 +352,15 @@ export const InitialStep = ({ setStep, email, setEmail, password, setPassword }: ) : (
)} -
- - - Forgot password? Recover your account - - -
+ {shouldDisplayLoginMethod(LoginMethod.EMAIL) && ( +
+ + + Forgot password? Recover your account + + +
+ )} ); }; From 9e9b9a7b942dca579496cd276545c64e515f318a Mon Sep 17 00:00:00 2001 From: Maidul Islam Date: Tue, 2 Jul 2024 10:53:36 -0400 Subject: [PATCH 12/13] update self lock out msg --- backend/src/services/super-admin/super-admin-service.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/backend/src/services/super-admin/super-admin-service.ts b/backend/src/services/super-admin/super-admin-service.ts index a51282db6f..70330c4ef7 100644 --- a/backend/src/services/super-admin/super-admin-service.ts +++ b/backend/src/services/super-admin/super-admin-service.ts @@ -106,8 +106,7 @@ export const superAdminServiceFactory = ({ ) ) { throw new BadRequestError({ - message: - "Admin has insufficient authentication methods for update operation to complete without getting locked out." + message: "You must configure at least one auth method to prevent account lockout" }); } } From b12de3e4f5901a3c2c6de931707bf0e9f8eb2cf4 Mon Sep 17 00:00:00 2001 From: Sheen Capadngan Date: Wed, 3 Jul 2024 01:57:24 +0800 Subject: [PATCH 13/13] misc: removed usecallback --- frontend/src/components/signup/InitialSignupStep.tsx | 8 ++------ .../views/Login/components/InitialStep/InitialStep.tsx | 7 ++----- .../OrgSettingsPage/components/OrgAuthTab/OrgAuthTab.tsx | 8 ++------ 3 files changed, 6 insertions(+), 17 deletions(-) diff --git a/frontend/src/components/signup/InitialSignupStep.tsx b/frontend/src/components/signup/InitialSignupStep.tsx index 8df6759132..3a7c6db045 100644 --- a/frontend/src/components/signup/InitialSignupStep.tsx +++ b/frontend/src/components/signup/InitialSignupStep.tsx @@ -1,4 +1,3 @@ -import { useCallback } from "react"; import { useTranslation } from "react-i18next"; import Link from "next/link"; import { faGithub, faGitlab, faGoogle } from "@fortawesome/free-brands-svg-icons"; @@ -18,11 +17,8 @@ export default function InitialSignupStep({ const { t } = useTranslation(); const { config } = useServerConfig(); - const shouldDisplaySignupMethod = useCallback( - (method: LoginMethod) => - !config.enabledLoginMethods || config.enabledLoginMethods.includes(method), - [config] - ); + const shouldDisplaySignupMethod = (method: LoginMethod) => + !config.enabledLoginMethods || config.enabledLoginMethods.includes(method); return (
diff --git a/frontend/src/views/Login/components/InitialStep/InitialStep.tsx b/frontend/src/views/Login/components/InitialStep/InitialStep.tsx index 06c4df835b..b2df75865b 100644 --- a/frontend/src/views/Login/components/InitialStep/InitialStep.tsx +++ b/frontend/src/views/Login/components/InitialStep/InitialStep.tsx @@ -62,11 +62,8 @@ export const InitialStep = ({ setStep, email, setEmail, password, setPassword }: } }, []); - const shouldDisplayLoginMethod = useCallback( - (method: LoginMethod) => - !config.enabledLoginMethods || config.enabledLoginMethods.includes(method), - [config] - ); + const shouldDisplayLoginMethod = (method: LoginMethod) => + !config.enabledLoginMethods || config.enabledLoginMethods.includes(method); const handleLogin = async (e: FormEvent) => { e.preventDefault(); diff --git a/frontend/src/views/Settings/OrgSettingsPage/components/OrgAuthTab/OrgAuthTab.tsx b/frontend/src/views/Settings/OrgSettingsPage/components/OrgAuthTab/OrgAuthTab.tsx index b1a079922f..d344b8a28e 100644 --- a/frontend/src/views/Settings/OrgSettingsPage/components/OrgAuthTab/OrgAuthTab.tsx +++ b/frontend/src/views/Settings/OrgSettingsPage/components/OrgAuthTab/OrgAuthTab.tsx @@ -1,5 +1,3 @@ -import { useCallback } from "react"; - import { OrgPermissionActions, OrgPermissionSubjects, useServerConfig } from "@app/context"; import { withPermission } from "@app/hoc"; import { LoginMethod } from "@app/hooks/api/admin/types"; @@ -16,10 +14,8 @@ export const OrgAuthTab = withPermission( config: { enabledLoginMethods } } = useServerConfig(); - const shouldDisplaySection = useCallback( - (method: LoginMethod) => !enabledLoginMethods || enabledLoginMethods.includes(method), - [enabledLoginMethods] - ); + const shouldDisplaySection = (method: LoginMethod) => + !enabledLoginMethods || enabledLoginMethods.includes(method); return (