2024-05-08 17:31:20 +00:00
|
|
|
"use client";
|
|
|
|
|
|
|
|
import { useState } from "react";
|
2024-05-14 15:24:49 +00:00
|
|
|
import { observer } from "mobx-react-lite";
|
2024-05-08 17:31:20 +00:00
|
|
|
import Image from "next/image";
|
|
|
|
import { useTheme } from "next-themes";
|
|
|
|
import useSWR from "swr";
|
|
|
|
import { Mails, KeyRound } from "lucide-react";
|
|
|
|
import { TInstanceConfigurationKeys } from "@plane/types";
|
2024-06-04 10:05:20 +00:00
|
|
|
import { Loader, ToggleSwitch, setPromiseToast } from "@plane/ui";
|
2024-05-08 17:31:20 +00:00
|
|
|
// components
|
|
|
|
import { PageHeader } from "@/components/core";
|
|
|
|
// hooks
|
|
|
|
// helpers
|
2024-06-04 10:05:20 +00:00
|
|
|
import { cn, resolveGeneralTheme } from "@/helpers/common.helper";
|
2024-05-14 15:24:49 +00:00
|
|
|
import { useInstance } from "@/hooks/store";
|
2024-05-08 17:31:20 +00:00
|
|
|
// images
|
|
|
|
import githubLightModeImage from "@/public/logos/github-black.png";
|
|
|
|
import githubDarkModeImage from "@/public/logos/github-white.png";
|
2024-05-14 15:24:49 +00:00
|
|
|
import GoogleLogo from "@/public/logos/google-logo.svg";
|
|
|
|
// local components
|
|
|
|
import {
|
|
|
|
AuthenticationMethodCard,
|
|
|
|
EmailCodesConfiguration,
|
|
|
|
PasswordLoginConfiguration,
|
|
|
|
GithubConfiguration,
|
|
|
|
GoogleConfiguration,
|
|
|
|
} from "./components";
|
2024-05-08 17:31:20 +00:00
|
|
|
|
|
|
|
type TInstanceAuthenticationMethodCard = {
|
|
|
|
key: string;
|
|
|
|
name: string;
|
|
|
|
description: string;
|
|
|
|
icon: JSX.Element;
|
|
|
|
config: JSX.Element;
|
|
|
|
};
|
|
|
|
|
|
|
|
const InstanceAuthenticationPage = observer(() => {
|
|
|
|
// store
|
|
|
|
const { fetchInstanceConfigurations, formattedConfig, updateInstanceConfigurations } = useInstance();
|
|
|
|
|
|
|
|
useSWR("INSTANCE_CONFIGURATIONS", () => fetchInstanceConfigurations());
|
|
|
|
|
|
|
|
// state
|
|
|
|
const [isSubmitting, setIsSubmitting] = useState<boolean>(false);
|
|
|
|
// theme
|
|
|
|
const { resolvedTheme } = useTheme();
|
2024-06-04 10:05:20 +00:00
|
|
|
// derived values
|
|
|
|
const enableSignUpConfig = formattedConfig?.ENABLE_SIGNUP ?? "";
|
2024-05-08 17:31:20 +00:00
|
|
|
|
|
|
|
const updateConfig = async (key: TInstanceConfigurationKeys, value: string) => {
|
|
|
|
setIsSubmitting(true);
|
|
|
|
|
|
|
|
const payload = {
|
|
|
|
[key]: value,
|
|
|
|
};
|
|
|
|
|
|
|
|
const updateConfigPromise = updateInstanceConfigurations(payload);
|
|
|
|
|
|
|
|
setPromiseToast(updateConfigPromise, {
|
|
|
|
loading: "Saving Configuration...",
|
|
|
|
success: {
|
|
|
|
title: "Success",
|
|
|
|
message: () => "Configuration saved successfully",
|
|
|
|
},
|
|
|
|
error: {
|
|
|
|
title: "Error",
|
|
|
|
message: () => "Failed to save configuration",
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
|
|
|
await updateConfigPromise
|
|
|
|
.then(() => {
|
|
|
|
setIsSubmitting(false);
|
|
|
|
})
|
|
|
|
.catch((err) => {
|
|
|
|
console.error(err);
|
|
|
|
setIsSubmitting(false);
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
// Authentication methods
|
|
|
|
const authenticationMethodsCard: TInstanceAuthenticationMethodCard[] = [
|
|
|
|
{
|
|
|
|
key: "email-codes",
|
|
|
|
name: "Email codes",
|
|
|
|
description: "Login or sign up using codes sent via emails. You need to have email setup here and enabled.",
|
|
|
|
icon: <Mails className="h-6 w-6 p-0.5 text-custom-text-300/80" />,
|
|
|
|
config: <EmailCodesConfiguration disabled={isSubmitting} updateConfig={updateConfig} />,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
key: "password-login",
|
|
|
|
name: "Password based login",
|
|
|
|
description: "Allow members to create accounts with passwords for emails to sign in.",
|
|
|
|
icon: <KeyRound className="h-6 w-6 p-0.5 text-custom-text-300/80" />,
|
|
|
|
config: <PasswordLoginConfiguration disabled={isSubmitting} updateConfig={updateConfig} />,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
key: "google",
|
|
|
|
name: "Google",
|
|
|
|
description: "Allow members to login or sign up to plane with their Google accounts.",
|
|
|
|
icon: <Image src={GoogleLogo} height={20} width={20} alt="Google Logo" />,
|
|
|
|
config: <GoogleConfiguration disabled={isSubmitting} updateConfig={updateConfig} />,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
key: "github",
|
|
|
|
name: "Github",
|
|
|
|
description: "Allow members to login or sign up to plane with their Github accounts.",
|
|
|
|
icon: (
|
|
|
|
<Image
|
|
|
|
src={resolveGeneralTheme(resolvedTheme) === "dark" ? githubDarkModeImage : githubLightModeImage}
|
|
|
|
height={20}
|
|
|
|
width={20}
|
|
|
|
alt="GitHub Logo"
|
|
|
|
/>
|
|
|
|
),
|
|
|
|
config: <GithubConfiguration disabled={isSubmitting} updateConfig={updateConfig} />,
|
|
|
|
},
|
|
|
|
];
|
|
|
|
|
|
|
|
return (
|
|
|
|
<>
|
|
|
|
<PageHeader title="Authentication - God Mode" />
|
2024-05-24 15:45:24 +00:00
|
|
|
<div className="relative container mx-auto w-full h-full p-4 py-4 space-y-6 flex flex-col">
|
|
|
|
<div className="border-b border-custom-border-100 mx-4 py-4 space-y-1 flex-shrink-0">
|
2024-05-08 17:31:20 +00:00
|
|
|
<div className="text-xl font-medium text-custom-text-100">Manage authentication for your instance</div>
|
|
|
|
<div className="text-sm font-normal text-custom-text-300">
|
|
|
|
Configure authentication modes for your team and restrict sign ups to be invite only.
|
|
|
|
</div>
|
|
|
|
</div>
|
2024-05-24 15:45:24 +00:00
|
|
|
<div className="flex-grow overflow-hidden overflow-y-scroll vertical-scrollbar scrollbar-md px-4">
|
2024-05-08 17:31:20 +00:00
|
|
|
{formattedConfig ? (
|
|
|
|
<div className="space-y-3">
|
2024-06-04 10:05:20 +00:00
|
|
|
<div className="text-lg font-medium pb-1">Sign-up configuration</div>
|
|
|
|
<div className={cn("w-full flex items-center gap-14 rounded")}>
|
|
|
|
<div className="flex grow items-center gap-4">
|
|
|
|
<div className="grow">
|
|
|
|
<div className={cn("font-medium leading-5 text-custom-text-100 text-sm")}>
|
|
|
|
Allow anyone to sign up without invite
|
|
|
|
</div>
|
|
|
|
<div className={cn("font-normal leading-5 text-custom-text-300 text-xs")}>
|
|
|
|
Toggling this off will disable self sign ups.
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div className={`shrink-0 pr-4 ${isSubmitting && "opacity-70"}`}>
|
|
|
|
<div className="flex items-center gap-4">
|
|
|
|
<ToggleSwitch
|
|
|
|
value={Boolean(parseInt(enableSignUpConfig))}
|
|
|
|
onChange={() => {
|
|
|
|
Boolean(parseInt(enableSignUpConfig)) === true
|
|
|
|
? updateConfig("ENABLE_SIGNUP", "0")
|
|
|
|
: updateConfig("ENABLE_SIGNUP", "1");
|
|
|
|
}}
|
|
|
|
size="sm"
|
|
|
|
disabled={isSubmitting}
|
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div className="text-lg font-medium pt-6">Authentication modes</div>
|
2024-05-08 17:31:20 +00:00
|
|
|
{authenticationMethodsCard.map((method) => (
|
|
|
|
<AuthenticationMethodCard
|
|
|
|
key={method.key}
|
|
|
|
name={method.name}
|
|
|
|
description={method.description}
|
|
|
|
icon={method.icon}
|
|
|
|
config={method.config}
|
|
|
|
disabled={isSubmitting}
|
|
|
|
/>
|
|
|
|
))}
|
|
|
|
</div>
|
|
|
|
) : (
|
|
|
|
<Loader className="space-y-10">
|
|
|
|
<Loader.Item height="50px" width="75%" />
|
|
|
|
<Loader.Item height="50px" width="75%" />
|
|
|
|
<Loader.Item height="50px" width="40%" />
|
|
|
|
<Loader.Item height="50px" width="40%" />
|
|
|
|
<Loader.Item height="50px" width="20%" />
|
|
|
|
</Loader>
|
|
|
|
)}
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</>
|
|
|
|
);
|
|
|
|
});
|
|
|
|
|
|
|
|
export default InstanceAuthenticationPage;
|