From 764e08140cb57684bdb5f0dd6fce1daee4c7aff0 Mon Sep 17 00:00:00 2001 From: Prateek Shourya Date: Tue, 2 Jul 2024 12:58:45 +0530 Subject: [PATCH] [WEB-1814] chore: admin app UI & UX improvements. (#4999) --- admin/app/authentication/github/form.tsx | 19 ++-- admin/app/authentication/github/page.tsx | 2 +- admin/app/authentication/gitlab/form.tsx | 18 ++-- admin/app/authentication/gitlab/page.tsx | 2 +- admin/app/authentication/google/form.tsx | 19 ++-- admin/app/authentication/google/page.tsx | 2 +- .../authentication/authentication-modes.tsx | 85 ++++++------------ admin/core/components/admin-sidebar/root.tsx | 8 +- .../authentication-method-card.tsx | 9 +- admin/core/components/common/code-block.tsx | 21 +++++ .../components/common/controller-input.tsx | 4 +- admin/core/components/common/index.ts | 2 + .../core/components/common/upgrade-button.tsx | 16 ++++ admin/helpers/authentication.helper.tsx | 69 +++++++++++++- admin/public/logos/oidc-logo.png | Bin 0 -> 19925 bytes admin/public/logos/saml-logo.svg | 16 ++++ packages/types/src/instance/auth.d.ts | 7 ++ 17 files changed, 203 insertions(+), 96 deletions(-) create mode 100644 admin/core/components/common/code-block.tsx create mode 100644 admin/core/components/common/upgrade-button.tsx create mode 100644 admin/public/logos/oidc-logo.png create mode 100644 admin/public/logos/saml-logo.svg diff --git a/admin/app/authentication/github/form.tsx b/admin/app/authentication/github/form.tsx index e9359a68b..afab9a3c5 100644 --- a/admin/app/authentication/github/form.tsx +++ b/admin/app/authentication/github/form.tsx @@ -10,6 +10,7 @@ import { IFormattedInstanceConfiguration, TInstanceGithubAuthenticationConfigura import { Button, TOAST_TYPE, getButtonStyling, setToast } from "@plane/ui"; // components import { + CodeBlock, ConfirmDiscardModal, ControllerInput, CopyField, @@ -102,7 +103,8 @@ export const InstanceGithubConfigForm: FC = (props) => { url: originURL, description: ( <> - We will auto-generate this. Paste this into the Authorized origin URL field{" "} + We will auto-generate this. Paste this into the{" "} + Authorized origin URL field{" "} = (props) => { url: `${originURL}/auth/github/callback/`, description: ( <> - We will auto-generate this. Paste this into your Authorized Callback URI field{" "} + We will auto-generate this. Paste this into your{" "} + Authorized Callback URI field{" "} = (props) => { .then((response = []) => { setToast({ type: TOAST_TYPE.SUCCESS, - title: "Success", - message: "Github Configuration Settings updated successfully", + title: "Done!", + message: "Your GitHub authentication is configured. You should test it now.", }); reset({ GITHUB_CLIENT_ID: response.find((item) => item.key === "GITHUB_CLIENT_ID")?.value, @@ -170,8 +173,8 @@ export const InstanceGithubConfigForm: FC = (props) => { />
-
-
Configuration
+
+
GitHub-provided details for Plane
{GITHUB_FORM_FIELDS.map((field) => ( = (props) => {
-
-
Service provider details
+
+
Plane-provided details for GitHub
{GITHUB_SERVICE_FIELD.map((field) => ( ))} diff --git a/admin/app/authentication/github/page.tsx b/admin/app/authentication/github/page.tsx index b00def973..7991fb95f 100644 --- a/admin/app/authentication/github/page.tsx +++ b/admin/app/authentication/github/page.tsx @@ -93,7 +93,7 @@ const InstanceGithubAuthenticationPage = observer(() => { withBorder={false} />
-
+
{formattedConfig ? ( ) : ( diff --git a/admin/app/authentication/gitlab/form.tsx b/admin/app/authentication/gitlab/form.tsx index 2cb46baf9..2d5782e10 100644 --- a/admin/app/authentication/gitlab/form.tsx +++ b/admin/app/authentication/gitlab/form.tsx @@ -8,6 +8,7 @@ import { IFormattedInstanceConfiguration, TInstanceGitlabAuthenticationConfigura import { Button, TOAST_TYPE, getButtonStyling, setToast } from "@plane/ui"; // components import { + CodeBlock, ConfirmDiscardModal, ControllerInput, CopyField, @@ -54,7 +55,7 @@ export const InstanceGitlabConfigForm: FC = (props) => { label: "Host", description: ( <> - This is the GitLab host to use for login, including scheme. + This is either https://gitlab.com or the domain.tld where you host GitLab. ), placeholder: "https://gitlab.com", @@ -116,7 +117,8 @@ export const InstanceGitlabConfigForm: FC = (props) => { url: `${originURL}/auth/gitlab/callback/`, description: ( <> - We will auto-generate this. Paste this into the Redirect URI field of your{" "} + We will auto-generate this. Paste this into the{" "} + Redirect URI field of your{" "} = (props) => { .then((response = []) => { setToast({ type: TOAST_TYPE.SUCCESS, - title: "Success", - message: "GitLab Configuration Settings updated successfully", + title: "Done!", + message: "Your GitLab authentication is configured. You should test it now.", }); reset({ GITLAB_HOST: response.find((item) => item.key === "GITLAB_HOST")?.value, @@ -167,8 +169,8 @@ export const InstanceGitlabConfigForm: FC = (props) => { />
-
-
Configuration
+
+
GitLab-provided details for Plane
{GITLAB_FORM_FIELDS.map((field) => ( = (props) => {
-
-
Service provider details
+
+
Plane-provided details for GitLab
{GITLAB_SERVICE_FIELD.map((field) => ( ))} diff --git a/admin/app/authentication/gitlab/page.tsx b/admin/app/authentication/gitlab/page.tsx index b6441d9b7..7a4d8248e 100644 --- a/admin/app/authentication/gitlab/page.tsx +++ b/admin/app/authentication/gitlab/page.tsx @@ -80,7 +80,7 @@ const InstanceGitlabAuthenticationPage = observer(() => { withBorder={false} />
-
+
{formattedConfig ? ( ) : ( diff --git a/admin/app/authentication/google/form.tsx b/admin/app/authentication/google/form.tsx index 42dd15e4d..cf5797895 100644 --- a/admin/app/authentication/google/form.tsx +++ b/admin/app/authentication/google/form.tsx @@ -9,6 +9,7 @@ import { IFormattedInstanceConfiguration, TInstanceGoogleAuthenticationConfigura import { Button, TOAST_TYPE, getButtonStyling, setToast } from "@plane/ui"; // components import { + CodeBlock, ConfirmDiscardModal, ControllerInput, CopyField, @@ -101,7 +102,8 @@ export const InstanceGoogleConfigForm: FC = (props) => { url: originURL, description: (

- We will auto-generate this. Paste this into your Authorized JavaScript origins field. For this OAuth client{" "} + We will auto-generate this. Paste this into your{" "} + Authorized JavaScript origins field. For this OAuth client{" "} = (props) => { url: `${originURL}/auth/google/callback/`, description: (

- We will auto-generate this. Paste this into your Authorized Redirect URI field. For this OAuth client{" "} + We will auto-generate this. Paste this into your Authorized Redirect URI{" "} + field. For this OAuth client{" "} = (props) => { .then((response = []) => { setToast({ type: TOAST_TYPE.SUCCESS, - title: "Success", - message: "Google Configuration Settings updated successfully", + title: "Done!", + message: "Your Google authentication is configured. You should test it now.", }); reset({ GOOGLE_CLIENT_ID: response.find((item) => item.key === "GOOGLE_CLIENT_ID")?.value, @@ -167,8 +170,8 @@ export const InstanceGoogleConfigForm: FC = (props) => { />

-
-
Configuration
+
+
Google-provided details for Plane
{GOOGLE_FORM_FIELDS.map((field) => ( = (props) => {
-
-
Service provider details
+
+
Plane-provided details for Google
{GOOGLE_SERVICE_DETAILS.map((field) => ( ))} diff --git a/admin/app/authentication/google/page.tsx b/admin/app/authentication/google/page.tsx index af2005e40..992c7a8a7 100644 --- a/admin/app/authentication/google/page.tsx +++ b/admin/app/authentication/google/page.tsx @@ -81,7 +81,7 @@ const InstanceGoogleAuthenticationPage = observer(() => { withBorder={false} />
-
+
{formattedConfig ? ( ) : ( diff --git a/admin/ce/components/authentication/authentication-modes.tsx b/admin/ce/components/authentication/authentication-modes.tsx index e0b37a146..31a807cec 100644 --- a/admin/ce/components/authentication/authentication-modes.tsx +++ b/admin/ce/components/authentication/authentication-modes.tsx @@ -1,84 +1,48 @@ import { observer } from "mobx-react"; import Image from "next/image"; import { useTheme } from "next-themes"; -import { KeyRound, Mails } from "lucide-react"; // types -import { TInstanceAuthenticationMethodKeys, TInstanceAuthenticationModes } from "@plane/types"; -// components import { - AuthenticationMethodCard, - EmailCodesConfiguration, - GithubConfiguration, - GitlabConfiguration, - GoogleConfiguration, - PasswordLoginConfiguration, -} from "@/components/authentication"; + TGetBaseAuthenticationModeProps, + TInstanceAuthenticationMethodKeys, + TInstanceAuthenticationModes, +} from "@plane/types"; +// components +import { AuthenticationMethodCard } from "@/components/authentication"; // helpers -import { resolveGeneralTheme } from "@/helpers/common.helper"; +import { UpgradeButton } from "@/components/common/upgrade-button"; +import { getBaseAuthenticationModes } from "@/helpers/authentication.helper"; // images -import githubLightModeImage from "@/public/logos/github-black.png"; -import githubDarkModeImage from "@/public/logos/github-white.png"; -import GitlabLogo from "@/public/logos/gitlab-logo.svg"; -import GoogleLogo from "@/public/logos/google-logo.svg"; +import OIDCLogo from "@/public/logos/oidc-logo.png"; +import SAMLLogo from "@/public/logos/saml-logo.svg"; export type TAuthenticationModeProps = { disabled: boolean; updateConfig: (key: TInstanceAuthenticationMethodKeys, value: string) => void; }; -export type TGetAuthenticationModeProps = { - disabled: boolean; - updateConfig: (key: TInstanceAuthenticationMethodKeys, value: string) => void; - resolvedTheme: string | undefined; -}; - // Authentication methods -export const getAuthenticationModes: (props: TGetAuthenticationModeProps) => TInstanceAuthenticationModes[] = ({ +export const getAuthenticationModes: (props: TGetBaseAuthenticationModeProps) => TInstanceAuthenticationModes[] = ({ disabled, updateConfig, resolvedTheme, }) => [ + ...getBaseAuthenticationModes({ disabled, updateConfig, resolvedTheme }), { - key: "unique-codes", - name: "Unique codes", - description: "Log in or sign up for Plane using codes sent via email. You need to have set up SMTP to use this method.", - icon: , - config: , + key: "oidc", + name: "OIDC", + description: "Authenticate your users via the OpenID Connect protocol.", + icon: OIDC Logo, + config: , + unavailable: true, }, { - key: "passwords-login", - name: "Passwords", - description: "Allow members to create accounts with passwords and use it with their email addresses to sign in.", - icon: , - config: , - }, - { - key: "google", - name: "Google", - description: "Allow members to log in or sign up for Plane with their Google accounts.", - icon: Google Logo, - config: , - }, - { - key: "github", - name: "GitHub", - description: "Allow members to log in or sign up for Plane with their GitHub accounts.", - icon: ( - GitHub Logo - ), - config: , - }, - { - key: "gitlab", - name: "GitLab", - description: "Allow members to login or sign up to plane with their GitLab accounts.", - icon: GitLab Logo, - config: , + key: "saml", + name: "SAML", + description: "Authenticate your users via the Security Assertion Markup Language protocol.", + icon: SAML Logo, + config: , + unavailable: true, }, ]; @@ -97,6 +61,7 @@ export const AuthenticationModes: React.FC = observer( icon={method.icon} config={method.config} disabled={disabled} + unavailable={method.unavailable} /> ))} diff --git a/admin/core/components/admin-sidebar/root.tsx b/admin/core/components/admin-sidebar/root.tsx index 6e992b06a..c2a90daa3 100644 --- a/admin/core/components/admin-sidebar/root.tsx +++ b/admin/core/components/admin-sidebar/root.tsx @@ -41,10 +41,10 @@ export const InstanceSidebar: FC = observer(() => {
diff --git a/admin/core/components/authentication/authentication-method-card.tsx b/admin/core/components/authentication/authentication-method-card.tsx index 1346a730e..50895a459 100644 --- a/admin/core/components/authentication/authentication-method-card.tsx +++ b/admin/core/components/authentication/authentication-method-card.tsx @@ -11,10 +11,11 @@ type Props = { config: JSX.Element; disabled?: boolean; withBorder?: boolean; + unavailable?: boolean; }; export const AuthenticationMethodCard: FC = (props) => { - const { name, description, icon, config, disabled = false, withBorder = true } = props; + const { name, description, icon, config, disabled = false, withBorder = true, unavailable = false } = props; return (
= (props) => { "px-4 py-3 border border-custom-border-200": withBorder, })} > -
+
{icon}
diff --git a/admin/core/components/common/code-block.tsx b/admin/core/components/common/code-block.tsx new file mode 100644 index 000000000..55f8b4afb --- /dev/null +++ b/admin/core/components/common/code-block.tsx @@ -0,0 +1,21 @@ +import { cn } from "@/helpers/common.helper"; + +type TProps = { + children: React.ReactNode; + className?: string; + darkerShade?: boolean; +}; + +export const CodeBlock = ({ children, className, darkerShade }: TProps) => ( + + {children} + +); diff --git a/admin/core/components/common/controller-input.tsx b/admin/core/components/common/controller-input.tsx index 0eb215095..4d0eade08 100644 --- a/admin/core/components/common/controller-input.tsx +++ b/admin/core/components/common/controller-input.tsx @@ -38,7 +38,7 @@ export const ControllerInput: React.FC = (props) => { return (

- {label} {!required && "(optional)"} + {label}

= (props) => { ))}
- {description &&

{description}

} + {description &&

{description}

}
); }; diff --git a/admin/core/components/common/index.ts b/admin/core/components/common/index.ts index ef376f622..2043926ac 100644 --- a/admin/core/components/common/index.ts +++ b/admin/core/components/common/index.ts @@ -7,3 +7,5 @@ export * from "./banner"; export * from "./empty-state"; export * from "./logo-spinner"; export * from "./page-header"; +export * from "./code-block"; +export * from "./upgrade-button"; diff --git a/admin/core/components/common/upgrade-button.tsx b/admin/core/components/common/upgrade-button.tsx new file mode 100644 index 000000000..aa3c95fdb --- /dev/null +++ b/admin/core/components/common/upgrade-button.tsx @@ -0,0 +1,16 @@ +"use client"; + +import React from "react"; +// icons +import { SquareArrowOutUpRight } from "lucide-react"; +// ui +import { getButtonStyling } from "@plane/ui"; +// helpers +import { cn } from "@/helpers/common.helper"; + +export const UpgradeButton: React.FC = () => ( + + Available on One + + +); diff --git a/admin/helpers/authentication.helper.tsx b/admin/helpers/authentication.helper.tsx index cc9058611..627ff182c 100644 --- a/admin/helpers/authentication.helper.tsx +++ b/admin/helpers/authentication.helper.tsx @@ -1,7 +1,24 @@ import { ReactNode } from "react"; +import Image from "next/image"; import Link from "next/link"; +import { KeyRound, Mails } from "lucide-react"; +// types +import { TGetBaseAuthenticationModeProps, TInstanceAuthenticationModes } from "@plane/types"; +// components +import { + EmailCodesConfiguration, + GithubConfiguration, + GitlabConfiguration, + GoogleConfiguration, + PasswordLoginConfiguration, +} from "@/components/authentication"; // helpers -import { SUPPORT_EMAIL } from "./common.helper"; +import { SUPPORT_EMAIL, resolveGeneralTheme } from "@/helpers/common.helper"; +// images +import githubLightModeImage from "@/public/logos/github-black.png"; +import githubDarkModeImage from "@/public/logos/github-white.png"; +import GitlabLogo from "@/public/logos/gitlab-logo.svg"; +import GoogleLogo from "@/public/logos/google-logo.svg"; export enum EPageTypes { PUBLIC = "PUBLIC", @@ -134,3 +151,53 @@ export const authErrorHandler = ( return undefined; }; + +export const getBaseAuthenticationModes: (props: TGetBaseAuthenticationModeProps) => TInstanceAuthenticationModes[] = ({ + disabled, + updateConfig, + resolvedTheme, +}) => [ + { + key: "unique-codes", + name: "Unique codes", + description: + "Log in or sign up for Plane using codes sent via email. You need to have set up SMTP to use this method.", + icon: , + config: , + }, + { + key: "passwords-login", + name: "Passwords", + description: "Allow members to create accounts with passwords and use it with their email addresses to sign in.", + icon: , + config: , + }, + { + key: "google", + name: "Google", + description: "Allow members to log in or sign up for Plane with their Google accounts.", + icon: Google Logo, + config: , + }, + { + key: "github", + name: "GitHub", + description: "Allow members to log in or sign up for Plane with their GitHub accounts.", + icon: ( + GitHub Logo + ), + config: , + }, + { + key: "gitlab", + name: "GitLab", + description: "Allow members to log in or sign up to plane with their GitLab accounts.", + icon: GitLab Logo, + config: , + }, + ]; diff --git a/admin/public/logos/oidc-logo.png b/admin/public/logos/oidc-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..154fb9bbba201f93e759e44f828210c4768e1140 GIT binary patch literal 19925 zcmeFZXH=8R*Ef7YfFLD+fYbnrVh0qZgcd|WMF9&SQUW4P=?T3hAfSRE#{xo!7bP*FQT%@szj}HZrQgfti0)V6%s>IUg?yKlq6~jHkpYmYvsJ z@n#MSuenE;st1u>-(2yRxs2xAjEQo=>kE%Vp}d{D_Q9C*?18>rf1&mW{cg(n&cy;m z`2X#H_#Yb!yPI)#8BmP@f`1Ca zEdq~*L;RDF44DNgi~F51-EsjnEG7W4p&+~>98H8loLGn-tU{e6L_k2sxJ2oww&j)x zHHZ}n*$@>m?^NN;4>GMR|5E*@=X2zwqix~RK-I(;l=ny8rV_5uKP8(e`*_&Pf7{|so82=G;e|I3mI*gq`6$}roQ_#SPg{@0lQ4+0_S zN$C#?BL7b5N@6HalJN4YAJD(h0~!D21O#TbUC`gS*6XtU1%M4^4P@1jVu}i+1EMme z17a~h%rnuPR{&FD{vy-`y&98bg77alu&VzN#n>k?E%V5KNX?Ph3>N0>{~3fi?SJ`4 zpcL7lMVa={+^U?f|6uY5S%^6@#GEkn2dMwPkvZbOluSkZhw^_K|3LTu9T2ci(4X!9 zXB+%kR_Kr6_@73mUHE?mh#M!MXWE7TJB9uq%K!UqFQ$5i4f-{U+1>0h-)u^vFHm;R z99WzVoP59OCB9o4K(dq&VA_I##)eC)6INW0*S%ABvNkd>;=AtoEVSS*fIhQZ3q6bH zD|)i$#*m=psriE*`j=E?*6nZKG>sojx*m=juN0eGH4D7J+%~rnOXEUA%X)ay6CU#7 zuhRWrx5@+-LwB&k^S+Txj*CGLdybEtlXU9beze?nW7O>{lk1h!jifq;{nYB{j)x7+ zBXQ*s`=w% z*rE3%SLze&aGXP4mXoi$IAzs>p-I{bIP2+ZEE1sx$BM2+H@e<+hvTy01vrw=_Jh)b-O(RODm-D+a-lbkK| z2sIB1mM*t}v!T%3I$C_D%`Cm7@vYt&n`$okN1(MPS|>zE>eEwhFQ|-XZD2%-3D36h zgmhhf%1;)eLgC_~)LN2$?M^2@0S!N*)@*b=rswzs^fbDuyrCyQWMan~hkr_ZJAMl+^n42_qo|x|On(ns`C) zCUaXxrRNZ#6T?hi!TSEe3L6J*9fI5ROD!NmJ0E(}KZT>=w1eMgkUisUcOA|{BbQdE zHw%`I6pPMKczD4u!QmBExXP-aq0AX5FUkBO{gYW*_R?+@mwW`AfXK6dE*%v`e+Gl* z{DY2eANyKnHL62|X*~RW!9!aOS~(OlY2BESe|-CU@Qe(ZFa>1h@&e>&seJ1Nu22c( zgxY8z8vY0z;tUG1O(~6irCuf&b|IV^y~>v z9C77HTzMYmt)eeR4SJfixp!ULtSj7LM1Y321tQl;)ejz;g=$34C=iOdHA>rZL!)!s zrdQWh2nd(JG1W`g+(djJo7UImHBGsmBJ20->!9Tszi6jz+aEbI+6F{jvBSJzRP?uf zqoa*p$Frwb6q~dz6&@(Hr_Ge_>J*gh8)=zb@=h-@7L@5 zm6Q%ZkopD|zP@6)y7`-~UVqN6Dmd9%f~v--WJCS(exvFPE_slnyiOFW5&xfWX)Tm2 zm4%(BRXwh4rR*pnTv(ojI#jdxI-xo@Y=~lz?3<|<> zw^L=9zSH(JCSce~;o-@~HD3`LnXzZgj%)b_xHdlh?62`*W5AV1gZ_7%+prbooOqls za@V}cYEXPXIlcT@{ecuo2R$~(=H}S;NB^_{OOsvaTLr11p;su`zM55fY^WHS*1(Ow z!G$sZl;MLn(W3;JOR_l9)cOUhR7tzRRyne?>aIdHDll3@_p^!={-N!F!Sjfzb#3FYX!3wpnOweD@vi^3552c8^;pd$)hcKF-Zs?(yH zwpz_(Q=*z$1}%mvF~so)Hp?nZ?v&-laiPh{QC6g_Ja7=2<+>C;81E{_`}w&kZ?5fM0`;Z=|@M&9wrq z*rwCDp#!hbQ4Wci2LD2p{SDPdz8!vkJP zhMd4H!T;5uHt*W+bdp}WezQo5W=cM~zjeIwWVTJ`9tirrPbB?i_qMOVY5&NwQor&X zqSB4`9|aa}HNiVdLTA+D@m zg)zY>Z1!H1A94(FmLKLNv?taLa(F<{V)nA%&E*Nv_7-{Nzm!BmO|$Jr_xd*OrFwQg zO0t2eLXe+f47DVF(0y{OQq6T)r7+BJ-Ztc=Asf?4f^r|T1e>>I*ySh;SBHkW%4i*= zbyOQ;%6Cd@*(7nXu$9t$XkJK|D(?t~@F8vW4#o7OFEBwuyK4QQ(KH0v+#0J$`Jy&# zFQ`Q@G*lSQ5SnC?LYEb@V@+9yQp&|iZ9Lp)#~k9btI19JStr9yup@Ii zOCx@}I}D?G)^dY|6!)q1WUbt|4z>a&6D`dy8x$3A$KN7NP- zZEh=Kp+Ta>S-7>=){(|s-aSIXbIbap2y_b@YM`+c*-vQt`9ua&?kFiIFt=JktjY== z=Jds~*?f1XcmYQG_ zeV*n@=!7_4#GAcgEFIhO^ed^GFYtp1?NYWTQ7FCEuG z+!dc~GZ?cgD*uWQefA2S^-)pV@R?7-YaR2S-p>cRctv&cR1_ZVcJ<;uS=++-X+qLe z<*;zC!N{oWUs8b_F>1XtSE*HJCQo?hkz)9b4-mA56yxZ@R;EpLPBrhlbwVZzyorl8 zxe8Ic`emC76#}!6+L@o*(7RfZ!zA7Yk-^6JBgVk_+Oa1`fl%}HWuB$ zWs`5L!2zB-7QH#iuyId8<>M2_>3_jA#Ae&tCJnFWG}Z5*@aV%Wig5`=xnV6eHYe^p zEyp2k=(lngtab-`#dZcIIcYlE=_4wH_WPdmfBA?;W$Qf$BqMYAJ3Z}-&iQW;tD`37cq2Ia{|N5Uh~UNa|gdBy>v0D<*PBcSLLY?wAvN5FWXirij$)UR#MBo_NYUo zhRw93mQ4Tt10`%y@9tS6dsu^Sdsg|>MOo+6O;-KBugg;NGF@uH%-xzbR6wJEm!Ec_ zapTfs>|sAztW__I)A66L2jKnQ63XzB*a9mNXWUst+!~>LXwzKW5Sr^ zaI5_+6r=W2+WlCu;xR?>rDL?pNg}IewJJtzPwzmS(4;{^KFs*y`<|rlCvUuMx>fuX z7O|JM(Xb(1Youq3DYjj%|7cJSNSxj`NozD2P{v=p^n{Iy&ML{m%pWgYJx-J5T`mzD z%v6o4tPh&n@q*-prrU-nLs^Ioj!kQ}%|*{DgwMSwtFQE{mM3=|jzEbXIV#efUxcO= zL*S7%d8*p`sCj0Ir0hN4C?Ke|Ej-<`RCucGxS1XshYE#`DGJlNk{lQ#J}YOaEZ?c8 z2Gw+?4-Xp4OL1qgjvpX@Rr@71>2nv3A3Db{d|yv=*xHGf_gqkEAJ>yo8I%0NwQPR2 zcKu*Gi_NZaTw3PQePfO@d>O3%@G{|*knte%kvp)g-yMYNtRti7>Q7`p%{Ix>;*wm%kpGA8G`U zy^~ygo;_Ux91caN_XAfDr@3**X=9R`MTjJ7;%=5I93OP9GXG78{duBr*4DOxDUg3f zc+zvZ80aFj5gD*Lp`BeiYYs#qJ>gn0AVy$i`j)HJBMq!xpBb~t0>sJ@G4qUP6*DoI8{?@)A2?j-3B(i09&u%h*k$_txX`l>+!CvmWXt{PEV zs!%c1zV&j?N{`X?U0m3mbEd!;wIiU;*UOE(Bl2Net+vLjj0wT+CYyxI??#nfF&9=ibR&5oHB*tkZbORWYi#OUt3TdP*Z55B>NK;4o6x|9%D&o;dtj(XYI(g;7PZh z2k}WR#4N$S4g-AH_WRiAW37LHZ3t2xcC6x3#)l`*t%Mg|;wW=Wxj`%u81xsW`T{+E zoYo?hRXRK9gkJOMpKO<;3>m@5?& z4L1&Y8yND`v!z0z39t_zwCQ=~YMm}kL>pJjNA@gTUYO|#xptIJ%nb_+5T)EV1*S!ed9AS&KHN^A zx^!n}V04T~>b?}UjK_bt3fM}4&Jk^unNTMJM^bluFy`Qa;e|ml0f^faYc&<|nwMX0 z-;{DCW^DzTR*@cJA!5^pBM;D1s7!HEnAzpTm|fST&pkM>avK*=t=fd(=jCCk%43OJ zQnKwV_*iPn(zU9V5iRV9>-P%ykZiYT{J@A9Fi$@fwGFU_NdmA+v2nYfrd6&n=%B`p zzX5PRA~rm|w-=_Rd&VT4HnzRi`g7GJ`$EYJhR{+J$f?ZM8b;!J7Azn+n3Jc;sF6 zfyX;%^s;9PD{14=mrKkt7_f4Cz~o{Q>=WwTsx~g1HGf*2bd$NoWC6- zcV3zrERJa1ewb?jq`*ne#hLZR)#b+d7d~YlS9Y%=6(UwfUQvIEQI`|u1z8~4k>2sK znqnImDlx`|Ra0|0Xwu@GLp!)GJiS(=-HVrR%OHgT(M~w@!2|jaj@Qv2x1Q+8bO1iR z{?-i%vgYtv5azV7;Lx6uRS@Zp8ZrahHb${GiR6%*!T5Cz-1CKgIWD4&5`LWsI^Nv; zVbf;ojwpl=dsA6;rYbdDC9Tams+?VkHmos&&b8c>ijU8phRr^+g&;1zwaLOhX?Ju_ zg@zRE2N4(?Hm!j1XYolR_du+y?8nX^2d>Q~P3)*27A~zx=cLx}-@R^&T~PZ~Q`pV| zg*;gcc)>7uUEd=?KC2K1_rZ#%`tRF(dYtCjv-WC%_f=vRuLX&eRFXtMD=?O zn;N(5vn;dB*#b6?_SMnDd3y7akW8*k9JbJXw1=1WI(t@`nBf$hOH|-h6U#d)3Du~+ zVU#)+k|ajm+>bXpDEkprhA%3sQj*?MP*|V=+DbK4#IUq><$4);7F15`tVeJ0>r@||l z`HtvN>wY&;2BS;1C;eY4|h1}eS+G=uS0$gOe>{Sa1%l;fXMCLX_) zO-QvCwdUce{WK@jNI2Ji^$pS|mbp5}2#oads#vmuRzn86Uhs6_3quiW+*u_?wp|wIEKq2n)6in(F)Lm@3=I!aqm;M~SM_45iq& zS}%HMy+G$yIZKDP?59!c_+>!ag{pD9*LKD!SK&!6#h}fxuxIoWJ6&nvAUR?$?ACxN z;uHd%M7{F^VZk1_+&2q0!F_8flGLyyZAvSmH2tk3w=P}=PHb8JY{QiDGcQdeiLtTV zer?(FhieXTKr*(fkIAG)hKd7B^tZ5oHnyXZRF5l1nSS<N7i63D&%{sFCaJo8EmDY;0_5P#98A0swyBpM7XrE%hvX8^b;PefXglZAb;{KSR01Wc%onWcP&)-9ik;O7H_k+xeOfTVZn5MP;)=8#r zVqXLcNs#A+X;X)VSW~KQY3e_PDVCB>_qT3+0829!=|gh-&-o&*izqfyxxAuieWA^*}rD zYg%UP>bQM#?tS?A+(e2uyH#>$!trb>U_hH!GRx7;s@>`0z#WbY3tn5N2-1GtbLKn` zYC(Rc6aP`E@YTXTI%1{NHWNOxB6#?pZ(TOIX>C=3#H^%YikM!&$T0RA0($73m~3TA zwi-5+cFX1qbC1*ksVtC_+FYKDjF!sbA%HX&$Z)MtDKV@2mdIxlilelIlAPR+aPCw{=9QxVA|T zAPVtwY5Xn6+2z>;*5G-I^G!b^nPomjnwY)QG2WkC*;8t79&UHn1HL%K>D~GnNbTic z4p5`H8Xo#7Rv)yr_^R4vP{wU?KriZ_zAKufz0=lkwLmxKW?~(B#0sI`+qIu0A06b2 zGXsD^rLA8Z%KVGbj^BS8@`H?svbNy# z>9PLw&QMd4+_?I~J48FmZPb}ZTcitW5ZWAz%6Hotipnx2J62WVXpN6Rygt8u`9ax+ zFNNS1u3A>)a|c9+-`nj}S`n+4=icdF_(0RXUz*04%(ysQEYRpbLo69HdD)deCvn~IzH zc?m@8(__`vI}sH;{4_ozE<+v=zjl1Qynm-X&Wud87ROC6w&*>EU`CwRj!#dH4zQze z6H$U77|-dwyf_CN(xl-IWg`bu04n_8dnvrkk=Xgd;xI@uB)Yv%ie8YS8Q&$Ui-FRn zuC}jDKofM&T_Vii1u=1Bkx4sV+>rz16fi3Pbe$!!zB8cj>(Dn4Tu+y8ZJH*YN<17H z{^{o7zZRGh7*8hmSXLn0gmLO6;|D?BP4?C9WZr8x`C%)ft{KXoqwE=&&$-}4V-=BV z=_utU46!px+7KM|iaVfb!BmNC#0$4mT>|_W%)E&c6E%2Y|u zgmDF$mzclWs>knvF|2clzzusPkWpLUmHKQee!&y9=!hJYqSUi5f8Qr zuiU8DNoWAcvl<^lh@C1wxYJ#3hHl6)&m&a(1jj)iZ%saFM{!8iP5xq;7ET*&YA{k{yE4+nx+y7 z117m*ZD-#sGz3TCzH*@+dJ-40cqb4Cj|mSX>pX=CsvB|ofIdu0k0<#*D%P1Dn1U zk!MBRRXm7m0GT*1ylK1V9c1%04V6l7EjjX3^l>F{%;3D{1!vJmQ_C6{gL!1atNlPo z@@na|9M~a{%)|i$a|bCCj;=m+5J$^Fed1;E%||Q-5X<2y@*uzP&i@uh|dHz0vZmJS=jdz!Kwu zeh1TVVl@5krA}iI78h;tw|o!NH%5C|}b`h*tgI%3yDf5a@6O!hC2l*YlSeLZxxTt|E^A=Z*vk0#| zd~{3_N()CHMPN24J>B_=S8zwHCwIOo=FL1{gZ$P@oh~51^WhRoJ3mMK%l3X{gkKy)uFodN<|~jVat`jB^pNoNUk7!wvwV zeh~I}IOAS>q&$DDA*8)yY@BC=)oy?qlV&ek{YM#ONJqC*Cbej_g4nV&U%GbyfBfURYsFYRY7!u`8@WOV8Yo?2Dy65!yj zSHJ@}R~qc+ftXE^weYjh(*>&bVnOgHRkgvTo+dQCgFl~BNHpAA~EIZBRT(&`Yk z-Gy`BbjF$IJqAocxhyNgTppWcWI$l%b+FVsM@9*~Hr^JfO-&1! zvuzNbi2xGM(c4kGdl$9$90lnp)G=3ajyu)Dv1@Wam zGOQjuw%MTwLQ?2t-Af3I&0r0|l&X^*_vibK!FJ@I#G|W4q>J~dLgdK1D;2f7q}^Tro;YC~0zf zNN1&pn{s#@1<>xTvrG<0i(HNwa`xW-XGLPVZQ<3_V=nW1)|$_5ez}rctq#;U22j8G zX+|EG?Wvm#u@SAi3{bV(gY`t5LHew0$%i|>QHt^R-Zn*Iz-*oZkTf!*1IaV`pFZ*^ zz|2jX@<9N~iyP2a{K~7RsJrbeR&3yrnGfZ6FI-Oo6ZPW6;$0GiSxkR?t9gUc`m;VTHTBskk~yFRdCBe-<~%vE zGWzh~?frlZ&7hqHd$K~U6@={~>ZNvbGA}yXc(OCnx|f&%v01@M$O=W9;VXD-C?{Ws zre^?YMcoslvBdXiqnDA%JUJi6&jXkS8r0D71UKQ7D;3j4!XV@aUr`En^s7s^mSzM|8%e4akCf4q_lKKV@*V)9@Y*aHeK z>admG%Ix{|87#ifE53(5HW;|t_Mr~Do|jd~yK?ihAqT*sS!E1y;6Su-i)GkWFSKXf za^*svt>nhTIE+P9+nfk9)0gL-w}83?e|Izq9T#V1pk9XA`0~{JZSM8AyFye5+(;ht zt^Bem!Q?-%Ojfo|(B_3hWc?y;AAXwJt(#3Ct73W1G~PPcxP81^3S4Vw>b)1#Iah|y z7%F?#m-uOKb`(cR%2uLwK=ugwfe;d-871G;GHdeZI?#NqBfDotx;tw8Fvz<75}gY} zvIU5YMS9++95`L{P&()U5)#$Tiv~kk1diVIL@FngVb+!Rcd$VH(LS{Z)?n$Dywa}V zNsEY!z}b)k1OFNg<=KdG_us3^E$@BU{dhcLVx9TYg%bYc@>JvR(4E{}dY_`A+#6)s zQWxL1H}wJ)eOA+k^Eq!}(6fh}wTK~<h`F6rtYlfTs0)h$ATU`NHS(BNip|?&*|L385HzP>Zlh16?zcWI>5Ic` zD4+i8V%+hm=xN=FY!K@EgNvOHxk$YZXRR16vO!7lX;yzzim%oHJB)JFIamM<)?)jk6tP9AIw2bg(^!fu23JP_|*n- zcmZ?_UlO#4n;|PN+!bVtatvup1-?m5r@kdZo57)b{P^dt$dHx%mcF(;pxR=;smENc z^dI#1_NrEreCT2Gkp9ju$}MBaQMQsjKyFOwolz%?ogk)IrTdZkr?;U@8gzwjU+sM1 zb3<0mLJ<>SLFgGudQ0AcCY4z)=MD59z{Zg8MCP=7TeK6jc2cGH?NEY5=2f1A=X+sL z=OjfL8@eU+1K~rCxDCYNMT#F%nf@j>s9Y>xJD1}UJu}c65b@8;^arPMulz7vaS_+w z<1o5Yg(Dg0$H2a(CY@KWIN2XO$-Qza&sj3_A;}=k45MKAJC+~*4kslzpNGjylD?uy z*8j~LcTG^`Nz%qoC9mjd)vMW4^8PB1*b`^fjEcgYL}=r}W)d@3$7g5Td%NTAL?55R z@I;BiJ=}!m7GFB4^zhSkA7(#^o-X-4m&Knj^_OpXMYJb$UcG4F?BqdN-W7q6&MJ2G z@*6Mx?3-QtCm8)6oL-Q%7KzKJSE0YnT#uh7YwzfLS|WpW0hq;!83Zc9l5{LVwFaCwp~@=$^yQv6S@v8(8*W zq(;b-f`%S!u0|U<|0a6a^6wI_Ua(e<<#I> z#1?zG|4lf-nv4(F7C)2})i&On^A415v#H;en42^=B_~y7Jr$UG{@(g(T&`!Fo!~Es z)2CUhH%nDyK%LBuJVLsdg7p{FX}sI*+0*MLDo!JoK%XovghDV-n~G?fR6hery0 zuOT1?y!=+wPFV1OS}q#2XPe3gicEmmo9*`>J6%Dyh|#!Sv*5lh6RuTtKz#?3mXC}tCI#bj^qzpEYA12?Ce)1Gq0aRe0k_21`Lz1Flrm~DiV@1!< z;WTUH?x$EjVE?{9UfqPsJWJ-1;y=m;BXi!?10S?w%hnv(6UoN>`uc@8O^qxtm6x^2 zSfuKCb$dEqWDa43eH7>$Uv*k&F#%Lix_WP4LpCw_J@HPct>4KZ`ie}Yb!aQ_z_;z= zV@*KK$L^Vfkg;1%Pfkv~55mXaF2B&I_A*LCWV*O}DbQO|3;`X{{^`wL(asg19d8Za zlz$ir(5Y@0^)~H<3paYvhh!YIekTK*U5P@HumPcsaH-9k+9rE zK+mGR6Kd*@AEyl;{J8bH>Jtxph4{2-7mH0;x^>})b|G^eX}OMZrH)WhuHIu^?%CsM zwc~w|jaR;#eTpRJ8Ed5mrGCHzW!_v$Wbm?2y2Ik87_moU-r?IJ??^N8TZ4_<~P z$_c*&6H)m4-voJZVZ!(SYTJh*9L3c9;(h<2O_GP!T3BlwpVBsB;wy17kxeIWmrlLW zeTby}X!$(EmD4^U5SE z*HfNcPCeNAre61oUFC8)FDRyeubW$CcEWQZ)z{zhZQHn%1ftgpo9OdE4*-x=Irg;ddlUg)@IVY+)#{C^MkU5aQVW9 z%JRo{y|asm?nJ${`{pvvf_!$vCgl;>Sl;@*jg1*(7100Rl> zN#1wpjwnS_wK@Ti#L!$OjfT2|)H_i>acjgaj@2&jd>-JL9Qw8~wz`K615$?}Xx!bX1 zT)1e7I^!xn^JL-#0ge~oc$2x%Xhp<68!KH=(q;L0F}M1{UGNTrl@AJwf87{BJK-rE zyJERnoIR5p-!{!M=O;WPD?s`^Q)$bB_iV_>TmX^B8*6d}$l)78e)7ov8zI)3UpEg_ zYl(`3uq5ZQI&7#TruJgFfzh&YsDmm|Fh4|c#%`d!0rf{LITDf2?Dp>+4ZwgfpE#MG zs_e5Jc(>`0*4Yz~;$ZI?fqOY@s0f^p#gfJe^3bha>hvZB)J#GTN%669xqV7ByLjdI zmkowUb$|KNKD0Uh?3`KE*j>#SWx?AJHbR;+ZUD2XWR+u{V!arzpaML$?CO(}7 z9}+b~9ydv*wDD~EWjfxjHn-Xp_6dlp>bK-__d!A&d-HW)UlW;RO&LnjQ+`&(DbcJ$ z(TrZ@3G~k>#rXq@2W5&Pv=#Jg=cEahRbaa~M&I?VE_c{F`u!8d?YuVSz&QA`a7y`U zxb0Dgo@nX17j}%g#Xk|>Id#QEmy3??jASjuxp{g{6qqO-CGUPN3wb;%+Ni4w>^z@0 zrbqFW4pq)snK96;{M0~Y(V^2;vR3OjV`jO-TkK^63{AaL!d*B8)~z$Sh+z5p62@h) z1UAmS*7C%rcuEqAQSFM@2$1|B8AW>{Q_$N61$?^Li<`&IadQ{|(Lqh&%fp$%Kp4!R|F|Am0x> zDV)pnz%*`hmdteXKFs_Lc^JfGflxbZitX|CtD&!=%KC7`ZywcC9B(D(_7Ag+bQyumd3I@B*9}6JUYv2<9Y|~;J}%mBm&47$dH{c zX{;C(U$wJBv1e`f+$V0v%|( zqg<^ej>rd-)Oimh=h*M4dC9ewi_C=mLoaFsswssSdwlW{xUaRY?l)_s(|5Y3QCv-h zEFR^{&9T3?FDKKLej-OXa0D@2uVz=8Wnt9nK+bp4;vOcw33ZdPbDpg3tdZzfgHuQeSWR zD?LQCFK07;KZ~fOe&*7p95ZiO=9*L)8}(>ZKR}^(Ps%2p5}ADHO%!-pqWihStEp(# z^K}$>)WkxwPn5p!h1x9P+5RctZI6brKQYjb@ckU)s?>B7IJNOwB_|?EGdlc?-+DE`+Gb zJ?Yo295MH{kx-(MD{!*wu6J7~osGJwH{ecMt(}33_dN|I^4(04B~Qd~PDTNSzz&vI zNmEr~pqmS*pXvqb)yakr0%~(m#){#Hx#QYdsV^(jB=+Jj*9S@U@u7_x)U2L(7fz#3 zm(FP~KGSgOezqNXntjWzo~3PLjGi_=gE8Vg&qUxP=6qD_rLFBP%ywIzAbpJNzO_Sc z<3ZtWY-p@zcwCXF39i$qbbn`ZDQlDm8xVwbH$^t;6LpI-C0cwpo=l!7cqIev%xV;v z=(j8CzlX6R-&^%Nmn52`MVWi!541XF&m?uP4tszcg;rs-`ijx*ogKMqYrQYeJ6}!L z^qx2n*ti{@ZsU?}y_k&RA=Sz&gb)imT&{V(+tg_N02}9AUP-0jPL}=I_MzU16-j$> z$Fx%Q!(8iA2zFia#hNM~RzH(q44!|kobxwjsDdsGzU7sWmm!?a`ab;A;Gw7WWu+@q z57U1m7JDMuX$1SbTla(Zx9YqPM=Mm85Oj_#Kxu9P3cP#BItlq&^@G=(WxBva&v4V^ z>>Z7`)gsvMjy&k3dYnrp32Tcu2eR3Udd_>cFXgDbw0Ll65nb4RCpdB=ViZb8=;kk+ zddP~r*wN@UacI$p0G}>urnpxLPlCw@vXzM_#9Yp2tE%9xpmr0Ey%k2e+XY7gEkeJC z(Rpz;MUSmUI+fB%b<5K=JGNS+`t9?H;l>~@v#2P2hfxtAFq3Kq|6;E9h3ha=_dqXz z^{Jno8x6_{FgLE{jOGxc?=dhjm@vFdEQZC?d5x<8j(mt>KzhaZmVp8V?jOj%bN;i5k6K2>haym-H=or^Whd zjg|DEZ$;EYZ`49GB{ViSRP!wV0MIrcJ4y?cvU`VLl+6n29+c+B5m!}Gw;8|kgl2BY zK0+@Pje$B#aMBZbiB*C227`pgagAMybxz2oo^R8z9p}4A25kq_8+mD_iCHafvmhq_ z8f>T^iq#YJ1ZgOy9oyZN`f=9S4$jH<=nb*`y&fJfQ+lwTKExrrL(s9svRJIq>Y2S{KyPb3MeZ z@)p;hoBzUz0xI~kE;6m@FgfcybWeRy6#cD!rm<1AA%nLdH~xet=0QfsZQDocb&`WO z{_yusrefT0bM0zXAD{?_>~rWzKQY%FBG<}dix@gYCJaYzyxf&`He1J~OsXIi3~J{^ zRT@PnV=u!R)K+R5xWz=TCoe1xuf7$UnR>lBkmZ6l7)JJCwdo1z^gi0$w)-s11sJTK2dp4hCM4GhyfrA3-PH*y8Q8J=&l4 zXf5DOMT1phT+E^Q5()=>niW|wBBoztRR4Ruif!|N%c;-L;h%uIe~Qxe@x>mE_LP zXOJ&HxF9|GkNkwdylJ6VdexmeB@IA!#juyU2^ruwZRu^}R5?c|PV9FDy7!I;* z^fl&k+ag>;s@>Zw+=pBD6)tpIe0pcu6rk^8ivVeeea}##Sa&^{_Vh{8EB$=yV_-|2 zbfD00>s6l$2aA5po&)4C=2w|Z3f`-1mtFc{*;<8hDb>+x-Srfoc||`!bLZM%Zf_D( zeF*QaOz*%d)Cj6kQbWet%mXV6vm0=4T;-lE2T0`2Z~VjQR<%@a$ksqY>i?P{dyD0T zF6NJnz{v!G=MKMtK@6HRwYgLnKw3#1{cF7Vkp#m{zopr0BM-3wg3PC literal 0 HcmV?d00001 diff --git a/admin/public/logos/saml-logo.svg b/admin/public/logos/saml-logo.svg new file mode 100644 index 000000000..36526fc21 --- /dev/null +++ b/admin/public/logos/saml-logo.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/packages/types/src/instance/auth.d.ts b/packages/types/src/instance/auth.d.ts index df8179cf1..d71cfa0bb 100644 --- a/packages/types/src/instance/auth.d.ts +++ b/packages/types/src/instance/auth.d.ts @@ -4,6 +4,7 @@ export type TInstanceAuthenticationModes = { description: string; icon: JSX.Element; config: JSX.Element; + unavailable?: boolean; }; export type TInstanceAuthenticationMethodKeys = @@ -35,3 +36,9 @@ type TInstanceAuthenticationConfigurationKeys = export type TInstanceAuthenticationKeys = | TInstanceAuthenticationMethodKeys | TInstanceAuthenticationConfigurationKeys; + +export type TGetBaseAuthenticationModeProps = { + disabled: boolean; + updateConfig: (key: TInstanceAuthenticationMethodKeys, value: string) => void; + resolvedTheme: string | undefined; +};