diff --git a/backend/src/db/migrations/20240205200732_invite-only.ts b/backend/src/db/migrations/20240205200732_invite-only.ts index d242623c8..4bebab17f 100644 --- a/backend/src/db/migrations/20240205200732_invite-only.ts +++ b/backend/src/db/migrations/20240205200732_invite-only.ts @@ -7,7 +7,7 @@ export async function up(knex: Knex): Promise { if (isTablePresent) { await knex.schema.alterTable(TableName.SuperAdmin, (t) => { t.boolean("inviteOnlySignUp").defaultTo(false); - t.string("allowSpecificDomainSignUp"); + t.string("allowedSignUpDomain"); }); } } @@ -19,9 +19,9 @@ export async function down(knex: Knex): Promise { }); } - if (await knex.schema.hasColumn(TableName.SuperAdmin, "allowSpecificDomainSignUp")) { + if (await knex.schema.hasColumn(TableName.SuperAdmin, "allowedSignUpDomain")) { await knex.schema.alterTable(TableName.SuperAdmin, (t) => { - t.dropColumn("allowSpecificDomainSignUp"); + t.dropColumn("allowedSignUpDomain"); }); } } diff --git a/backend/src/db/schemas/super-admin.ts b/backend/src/db/schemas/super-admin.ts index fb373e19b..4b410d88b 100644 --- a/backend/src/db/schemas/super-admin.ts +++ b/backend/src/db/schemas/super-admin.ts @@ -12,7 +12,7 @@ export const SuperAdminSchema = z.object({ initialized: z.boolean().default(false).nullable().optional(), allowSignUp: z.boolean().default(true).nullable().optional(), inviteOnlySignUp: z.boolean().default(false).nullable().optional(), - allowSpecificDomainSignUp: z.string().nullable().optional(), + allowedSignUpDomain: z.string().nullable().optional(), createdAt: z.date(), updatedAt: z.date() }); diff --git a/backend/src/server/routes/v1/admin-router.ts b/backend/src/server/routes/v1/admin-router.ts index ddd95522f..221014ccc 100644 --- a/backend/src/server/routes/v1/admin-router.ts +++ b/backend/src/server/routes/v1/admin-router.ts @@ -33,7 +33,7 @@ export const registerAdminRouter = async (server: FastifyZodProvider) => { body: z.object({ allowSignUp: z.boolean().optional(), inviteOnlySignUp: z.boolean().optional(), - allowSpecificDomainSignUp: z.string().optional() + allowedSignUpDomain: z.string().optional() }), response: { 200: z.object({ diff --git a/backend/src/server/routes/v3/signup-router.ts b/backend/src/server/routes/v3/signup-router.ts index e0ce21006..45434412e 100644 --- a/backend/src/server/routes/v3/signup-router.ts +++ b/backend/src/server/routes/v3/signup-router.ts @@ -28,9 +28,9 @@ export const registerSignupRouter = async (server: FastifyZodProvider) => { const { email } = req.body; const serverCfg = await getServerCfg(); - if (serverCfg?.allowSpecificDomainSignUp) { + if (serverCfg?.allowedSignUpDomain) { const domain = email.split("@")[1]; - const allowedDomains = serverCfg.allowSpecificDomainSignUp.split(",").map((e) => e.trim()); + const allowedDomains = serverCfg.allowedSignUpDomain.split(",").map((e) => e.trim()); if (!allowedDomains.includes(domain)) { throw new BadRequestError({ message: `Email with a domain (@${domain}) is not supported` diff --git a/backend/src/services/auth/auth-login-service.ts b/backend/src/services/auth/auth-login-service.ts index f43fe063c..e78b4080e 100644 --- a/backend/src/services/auth/auth-login-service.ts +++ b/backend/src/services/auth/auth-login-service.ts @@ -273,9 +273,9 @@ export const authLoginServiceFactory = ({ userDAL, tokenService, smtpService }: if (!serverCfg?.allowSignUp) throw new BadRequestError({ message: "User signup disabled", name: "Oauth 2 login" }); - if (serverCfg?.allowSpecificDomainSignUp) { + if (serverCfg?.allowedSignUpDomain) { const domain = email.split("@")[1]; - const allowedDomains = serverCfg.allowSpecificDomainSignUp.split(",").map((e) => e.trim()); + const allowedDomains = serverCfg.allowedSignUpDomain.split(",").map((e) => e.trim()); if (!allowedDomains.includes(domain)) throw new BadRequestError({ message: `Email with a domain (@${domain}) is not supported`, diff --git a/frontend/src/hooks/api/admin/types.ts b/frontend/src/hooks/api/admin/types.ts index 145f22072..e28e7f972 100644 --- a/frontend/src/hooks/api/admin/types.ts +++ b/frontend/src/hooks/api/admin/types.ts @@ -2,7 +2,7 @@ export type TServerConfig = { initialized: boolean; allowSignUp: boolean; inviteOnlySignUp: boolean; - allowSpecificDomainSignUp?: string; + allowedSignUpDomain?: string; isMigrationModeOn?: boolean; }; diff --git a/frontend/src/pages/signupinvite.tsx b/frontend/src/pages/signupinvite.tsx index 5ede3126c..a3b643e29 100644 --- a/frontend/src/pages/signupinvite.tsx +++ b/frontend/src/pages/signupinvite.tsx @@ -2,7 +2,7 @@ /* eslint-disable @typescript-eslint/no-unused-vars */ import crypto from "crypto"; -import { useEffect,useState } from "react"; +import { useEffect, useState } from "react"; import Head from "next/head"; import Image from "next/image"; import Link from "next/link"; diff --git a/frontend/src/views/Login/components/InitialStep/InitialStep.tsx b/frontend/src/views/Login/components/InitialStep/InitialStep.tsx index bbef55751..16541c9a0 100644 --- a/frontend/src/views/Login/components/InitialStep/InitialStep.tsx +++ b/frontend/src/views/Login/components/InitialStep/InitialStep.tsx @@ -226,7 +226,7 @@ export const InitialStep = ({ setStep, email, setEmail, password, setPassword }: {!isLoading && loginError && } - {config.allowSignUp ? ( + {config.allowSignUp && !config.inviteOnlySignUp ? (
diff --git a/frontend/src/views/admin/DashboardPage/DashboardPage.tsx b/frontend/src/views/admin/DashboardPage/DashboardPage.tsx index 340c1662a..912a60c18 100644 --- a/frontend/src/views/admin/DashboardPage/DashboardPage.tsx +++ b/frontend/src/views/admin/DashboardPage/DashboardPage.tsx @@ -1,7 +1,10 @@ -import { useEffect, useState } from "react"; +import { useEffect } from "react"; +import { Controller, useForm } from "react-hook-form"; import { useRouter } from "next/router"; import { faAt } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { yupResolver } from "@hookform/resolvers/yup"; +import * as yup from "yup"; import { useNotificationContext } from "@app/components/context/Notifications/NotificationProvider"; import { @@ -23,15 +26,37 @@ enum TabSections { Settings = "settings" } -type SignUpMode = "disabled" | "invite-only" | "anyone"; +const formSchema = yup.object({ + signUpMode: yup + .string() + .oneOf(["disabled", "invite-only", "anyone"]) + .required(), + allowedSignUpDomain: yup.string().optional() +}); + +type TDashboardForm = yup.InferType; export const AdminDashboardPage = () => { const router = useRouter(); const data = useServerConfig(); - const [signUpMode, setSignUpMode] = useState("invite-only"); - const [allowSpecificDomain, setAllowSpecificDomain] = useState(); - const { config } = data; + + const signUpStatus = config.allowSignUp + ? config.inviteOnlySignUp && "invite-only" + : "disabled"; + + const signUpType = signUpStatus || "anyone"; + + const { control, handleSubmit, watch } = useForm({ + resolver: yupResolver(formSchema), + defaultValues: { + signUpMode: signUpType, + allowedSignUpDomain: config.allowedSignUpDomain + } + }); + + const signupMode = watch("signUpMode"); + const { user, isLoading: isUserLoading } = useUser(); const { orgs } = useOrganization(); const { mutate: updateServerConfig } = useUpdateServerConfig(); @@ -49,29 +74,15 @@ export const AdminDashboardPage = () => { } }, [isNotAllowed, isUserLoading]); - useEffect(() => { - if (!config.allowSignUp) { - setSignUpMode("disabled"); - return; - } - if (config.inviteOnlySignUp) { - setSignUpMode("invite-only"); - } else { - setSignUpMode("anyone"); - } - - if (config.allowSpecificDomainSignUp) { - setAllowSpecificDomain(config.allowSpecificDomainSignUp); - } - }, [config]); - - const handleSubmit = async () => { + const onFormSubmit = async (formData: TDashboardForm) => { try { - config.allowSignUp = signUpMode !== "disabled"; - config.inviteOnlySignUp = signUpMode === "invite-only"; - config.allowSpecificDomainSignUp = signUpMode === "anyone" ? allowSpecificDomain : ""; + const { signUpMode, allowedSignUpDomain } = formData; - await updateServerConfig(config); + await updateServerConfig({ + allowSignUp: signUpMode !== "disabled", + inviteOnlySignUp: signUpMode === "invite-only", + allowedSignUpDomain: signUpMode === "anyone" ? allowedSignUpDomain : "" + }); createNotification({ text: "Successfully changed sign up setting.", @@ -86,6 +97,8 @@ export const AdminDashboardPage = () => { } }; + + return (
@@ -105,46 +118,70 @@ export const AdminDashboardPage = () => {
-
+
Allow user to Sign Up
- + ( + + + + )} + />
- {signUpMode === "anyone" && ( + {signupMode === "anyone" && (
Allow email with only specific domain(s)
- -
- } - value={allowSpecificDomain} - onChange={(ev) => setAllowSpecificDomain(ev.target.value)} - /> -
-
+ ( + + } + /> + + )} + />
)} - -
+