import { useEffect, useState } from "react"; import { toast } from "react-hot-toast"; import { Button, Divider, Input, Radio, RadioGroup, Typography } from "@mui/joy"; import * as api from "@/helpers/api"; import { UNKNOWN_ID } from "@/helpers/consts"; import { absolutifyLink } from "@/helpers/utils"; import { generateDialog } from "./Dialog"; import Icon from "./Icon"; interface Props extends DialogProps { identityProvider?: IdentityProvider; confirmCallback?: () => void; } const templateList: IdentityProvider[] = [ { id: UNKNOWN_ID, name: "GitHub", type: "OAUTH2", identifierFilter: "", config: { oauth2Config: { clientId: "", clientSecret: "", authUrl: "https://github.com/login/oauth/authorize", tokenUrl: "https://github.com/login/oauth/access_token", userInfoUrl: "https://api.github.com/user", scopes: ["user"], fieldMapping: { identifier: "login", displayName: "name", email: "email", }, }, }, }, { id: UNKNOWN_ID, name: "GitLab", type: "OAUTH2", identifierFilter: "", config: { oauth2Config: { clientId: "", clientSecret: "", authUrl: "https://gitlab.com/oauth/authorize", tokenUrl: "https://gitlab.com/oauth/token", userInfoUrl: "https://gitlab.com/oauth/userinfo", scopes: ["openid"], fieldMapping: { identifier: "name", displayName: "name", email: "email", }, }, }, }, { id: UNKNOWN_ID, name: "Google", type: "OAUTH2", identifierFilter: "", config: { oauth2Config: { clientId: "", clientSecret: "", authUrl: "https://accounts.google.com/o/oauth2/v2/auth", tokenUrl: "https://oauth2.googleapis.com/token", userInfoUrl: "https://www.googleapis.com/oauth2/v2/userinfo", scopes: ["https://www.googleapis.com/auth/userinfo.email", "https://www.googleapis.com/auth/userinfo.profile"], fieldMapping: { identifier: "email", displayName: "name", email: "email", }, }, }, }, { id: UNKNOWN_ID, name: "Custom", type: "OAUTH2", identifierFilter: "", config: { oauth2Config: { clientId: "", clientSecret: "", authUrl: "", tokenUrl: "", userInfoUrl: "", scopes: [], fieldMapping: { identifier: "", displayName: "", email: "", }, }, }, }, ]; const CreateIdentityProviderDialog: React.FC = (props: Props) => { const { confirmCallback, destroy, identityProvider } = props; const [basicInfo, setBasicInfo] = useState({ name: "", identifierFilter: "", }); const [type, setType] = useState("OAUTH2"); const [oauth2Config, setOAuth2Config] = useState({ clientId: "", clientSecret: "", authUrl: "", tokenUrl: "", userInfoUrl: "", scopes: [], fieldMapping: { identifier: "", displayName: "", email: "", }, }); const [oauth2Scopes, setOAuth2Scopes] = useState(""); const [seletedTemplate, setSelectedTemplate] = useState("GitHub"); const isCreating = identityProvider === undefined; useEffect(() => { if (identityProvider) { setBasicInfo({ name: identityProvider.name, identifierFilter: identityProvider.identifierFilter, }); setType(identityProvider.type); if (identityProvider.type === "OAUTH2") { setOAuth2Config(identityProvider.config.oauth2Config); setOAuth2Scopes(identityProvider.config.oauth2Config.scopes.join(" ")); } } }, []); useEffect(() => { if (!isCreating) { return; } const template = templateList.find((t) => t.name === seletedTemplate); if (template) { setBasicInfo({ name: template.name, identifierFilter: template.identifierFilter, }); setType(template.type); if (template.type === "OAUTH2") { setOAuth2Config(template.config.oauth2Config); setOAuth2Scopes(template.config.oauth2Config.scopes.join(" ")); } } }, [seletedTemplate]); const handleCloseBtnClick = () => { destroy(); }; const allowConfirmAction = () => { if (basicInfo.name === "") { return false; } if (type === "OAUTH2") { if ( oauth2Config.clientId === "" || oauth2Config.clientSecret === "" || oauth2Config.authUrl === "" || oauth2Config.tokenUrl === "" || oauth2Config.userInfoUrl === "" || oauth2Scopes === "" || oauth2Config.fieldMapping.identifier === "" ) { return false; } } return true; }; const handleConfirmBtnClick = async () => { try { if (isCreating) { await api.createIdentityProvider({ ...basicInfo, type: type, config: { oauth2Config: { ...oauth2Config, scopes: oauth2Scopes.split(" "), }, }, }); toast.success(`SSO ${basicInfo.name} created`); } else { await api.patchIdentityProvider({ id: identityProvider?.id, type: type, ...basicInfo, config: { oauth2Config: { ...oauth2Config, scopes: oauth2Scopes.split(" "), }, }, }); toast.success(`SSO ${basicInfo.name} updated`); } } catch (error: any) { console.error(error); toast.error(error.response.data.message); } if (confirmCallback) { confirmCallback(); } destroy(); }; const setPartialOAuth2Config = (state: Partial) => { setOAuth2Config({ ...oauth2Config, ...state, }); }; return ( <>

{isCreating ? "Create SSO" : "Update SSO"}

{isCreating && ( <> Type
Template
{templateList.map((template) => ( setSelectedTemplate(e.target.value)} /> ))}
)} Name* setBasicInfo({ ...basicInfo, name: e.target.value, }) } fullWidth /> Identifier filter setBasicInfo({ ...basicInfo, identifierFilter: e.target.value, }) } fullWidth /> {type === "OAUTH2" && ( <> {isCreating && (

Redirect URL: {absolutifyLink("/auth/callback")}

)} Client ID* setPartialOAuth2Config({ clientId: e.target.value })} fullWidth /> Client secret* setPartialOAuth2Config({ clientSecret: e.target.value })} fullWidth /> Authorization endpoint* setPartialOAuth2Config({ authUrl: e.target.value })} fullWidth /> Token endpoint* setPartialOAuth2Config({ tokenUrl: e.target.value })} fullWidth /> User info endpoint* setPartialOAuth2Config({ userInfoUrl: e.target.value })} fullWidth /> Scopes* setOAuth2Scopes(e.target.value)} fullWidth /> Identifier* setPartialOAuth2Config({ fieldMapping: { ...oauth2Config.fieldMapping, identifier: e.target.value } })} fullWidth /> Display name setPartialOAuth2Config({ fieldMapping: { ...oauth2Config.fieldMapping, displayName: e.target.value } })} fullWidth /> Email setPartialOAuth2Config({ fieldMapping: { ...oauth2Config.fieldMapping, email: e.target.value } })} fullWidth /> )}
); }; function showCreateIdentityProviderDialog(identityProvider?: IdentityProvider, confirmCallback?: () => void) { generateDialog( { className: "create-identity-provider-dialog", dialogName: "create-identity-provider-dialog", }, CreateIdentityProviderDialog, { identityProvider, confirmCallback } ); } export default showCreateIdentityProviderDialog;