| 
									
										
										
										
											2022-01-13 20:05:23 +00:00
										 |  |  | import React, { useEffect, useState, useRef } from "react"; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import { useLocale } from "@lib/hooks/useLocale"; | 
					
						
							|  |  |  | import showToast from "@lib/notification"; | 
					
						
							| 
									
										
										
										
											2022-02-02 18:33:27 +00:00
										 |  |  | import { collectPageParameters, telemetryEventTypes, useTelemetry } from "@lib/telemetry"; | 
					
						
							| 
									
										
										
										
											2022-01-13 20:05:23 +00:00
										 |  |  | import { trpc } from "@lib/trpc"; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import { Dialog, DialogTrigger } from "@components/Dialog"; | 
					
						
							|  |  |  | import ConfirmationDialogContent from "@components/dialog/ConfirmationDialogContent"; | 
					
						
							| 
									
										
										
										
											2022-02-07 23:35:26 +00:00
										 |  |  | import { TextArea } from "@components/form/fields"; | 
					
						
							| 
									
										
										
										
											2022-01-13 20:05:23 +00:00
										 |  |  | import { Alert } from "@components/ui/Alert"; | 
					
						
							|  |  |  | import Badge from "@components/ui/Badge"; | 
					
						
							|  |  |  | import Button from "@components/ui/Button"; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | export default function SAMLConfiguration({ | 
					
						
							|  |  |  |   teamsView, | 
					
						
							|  |  |  |   teamId, | 
					
						
							|  |  |  | }: { | 
					
						
							|  |  |  |   teamsView: boolean; | 
					
						
							|  |  |  |   teamId: null | undefined | number; | 
					
						
							|  |  |  | }) { | 
					
						
							|  |  |  |   const [isSAMLLoginEnabled, setIsSAMLLoginEnabled] = useState(false); | 
					
						
							|  |  |  |   const [samlConfig, setSAMLConfig] = useState<string | null>(null); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const query = trpc.useQuery(["viewer.showSAMLView", { teamsView, teamId }]); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-02 18:33:27 +00:00
										 |  |  |   const telemetry = useTelemetry(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-13 20:05:23 +00:00
										 |  |  |   useEffect(() => { | 
					
						
							|  |  |  |     const data = query.data; | 
					
						
							|  |  |  |     setIsSAMLLoginEnabled(data?.isSAMLLoginEnabled ?? false); | 
					
						
							|  |  |  |     setSAMLConfig(data?.provider ?? null); | 
					
						
							|  |  |  |   }, [query.data]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const mutation = trpc.useMutation("viewer.updateSAMLConfig", { | 
					
						
							|  |  |  |     onSuccess: (data: { provider: string | undefined }) => { | 
					
						
							|  |  |  |       showToast(t("saml_config_updated_successfully"), "success"); | 
					
						
							|  |  |  |       setHasErrors(false); // dismiss any open errors
 | 
					
						
							|  |  |  |       setSAMLConfig(data?.provider ?? null); | 
					
						
							|  |  |  |       samlConfigRef.current.value = ""; | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  |     onError: () => { | 
					
						
							|  |  |  |       setHasErrors(true); | 
					
						
							|  |  |  |       setErrorMessage(t("saml_configuration_update_failed")); | 
					
						
							|  |  |  |       document?.getElementsByTagName("main")[0]?.scrollTo({ top: 0, behavior: "smooth" }); | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const deleteMutation = trpc.useMutation("viewer.deleteSAMLConfig", { | 
					
						
							|  |  |  |     onSuccess: () => { | 
					
						
							|  |  |  |       showToast(t("saml_config_deleted_successfully"), "success"); | 
					
						
							|  |  |  |       setHasErrors(false); // dismiss any open errors
 | 
					
						
							|  |  |  |       setSAMLConfig(null); | 
					
						
							|  |  |  |       samlConfigRef.current.value = ""; | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  |     onError: () => { | 
					
						
							|  |  |  |       setHasErrors(true); | 
					
						
							|  |  |  |       setErrorMessage(t("saml_configuration_delete_failed")); | 
					
						
							|  |  |  |       document?.getElementsByTagName("main")[0]?.scrollTo({ top: 0, behavior: "smooth" }); | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const samlConfigRef = useRef<HTMLTextAreaElement>() as React.MutableRefObject<HTMLTextAreaElement>; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const [hasErrors, setHasErrors] = useState(false); | 
					
						
							|  |  |  |   const [errorMessage, setErrorMessage] = useState(""); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   async function updateSAMLConfigHandler(event: React.FormEvent<HTMLElement>) { | 
					
						
							|  |  |  |     event.preventDefault(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const rawMetadata = samlConfigRef.current.value; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-02 18:33:27 +00:00
										 |  |  |     // track Google logins. Without personal data/payload
 | 
					
						
							|  |  |  |     telemetry.withJitsu((jitsu) => jitsu.track(telemetryEventTypes.samlConfig, collectPageParameters())); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-13 20:05:23 +00:00
										 |  |  |     mutation.mutate({ | 
					
						
							| 
									
										
										
										
											2022-02-02 18:33:27 +00:00
										 |  |  |       encodedRawMetadata: Buffer.from(rawMetadata).toString("base64"), | 
					
						
							| 
									
										
										
										
											2022-01-13 20:05:23 +00:00
										 |  |  |       teamId, | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   async function deleteSAMLConfigHandler(event: React.MouseEvent<HTMLElement, MouseEvent>) { | 
					
						
							|  |  |  |     event.preventDefault(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     deleteMutation.mutate({ | 
					
						
							|  |  |  |       teamId, | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const { t } = useLocale(); | 
					
						
							|  |  |  |   return ( | 
					
						
							|  |  |  |     <> | 
					
						
							|  |  |  |       {isSAMLLoginEnabled ? ( | 
					
						
							|  |  |  |         <> | 
					
						
							| 
									
										
										
										
											2022-02-07 23:35:26 +00:00
										 |  |  |           <hr className="mt-8" /> | 
					
						
							| 
									
										
										
										
											2022-01-13 20:05:23 +00:00
										 |  |  |           <div className="mt-6"> | 
					
						
							| 
									
										
										
										
											2022-02-09 00:05:13 +00:00
										 |  |  |             <h2 className="font-cal text-lg font-medium leading-6 text-gray-900"> | 
					
						
							| 
									
										
										
										
											2022-01-13 20:05:23 +00:00
										 |  |  |               {t("saml_configuration")} | 
					
						
							| 
									
										
										
										
											2022-02-02 18:33:27 +00:00
										 |  |  |               <Badge className="ml-2 text-xs" variant={samlConfig ? "success" : "gray"}> | 
					
						
							| 
									
										
										
										
											2022-01-13 20:05:23 +00:00
										 |  |  |                 {samlConfig ? t("enabled") : t("disabled")} | 
					
						
							|  |  |  |               </Badge> | 
					
						
							|  |  |  |               {samlConfig ? ( | 
					
						
							|  |  |  |                 <> | 
					
						
							| 
									
										
										
										
											2022-02-02 18:33:27 +00:00
										 |  |  |                   <Badge className="ml-2 text-xs" variant={"success"}> | 
					
						
							| 
									
										
										
										
											2022-01-13 20:05:23 +00:00
										 |  |  |                     {samlConfig ? samlConfig : ""} | 
					
						
							|  |  |  |                   </Badge> | 
					
						
							|  |  |  |                 </> | 
					
						
							|  |  |  |               ) : null} | 
					
						
							|  |  |  |             </h2> | 
					
						
							|  |  |  |           </div> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           {samlConfig ? ( | 
					
						
							| 
									
										
										
										
											2022-02-09 00:05:13 +00:00
										 |  |  |             <div className="mt-2 flex"> | 
					
						
							| 
									
										
										
										
											2022-01-13 20:05:23 +00:00
										 |  |  |               <Dialog> | 
					
						
							|  |  |  |                 <DialogTrigger asChild> | 
					
						
							|  |  |  |                   <Button | 
					
						
							|  |  |  |                     color="warn" | 
					
						
							|  |  |  |                     type="button" | 
					
						
							|  |  |  |                     onClick={(e) => { | 
					
						
							|  |  |  |                       e.stopPropagation(); | 
					
						
							|  |  |  |                     }}> | 
					
						
							|  |  |  |                     {t("delete_saml_configuration")} | 
					
						
							|  |  |  |                   </Button> | 
					
						
							|  |  |  |                 </DialogTrigger> | 
					
						
							|  |  |  |                 <ConfirmationDialogContent | 
					
						
							|  |  |  |                   variety="danger" | 
					
						
							|  |  |  |                   title={t("delete_saml_configuration")} | 
					
						
							|  |  |  |                   confirmBtnText={t("confirm_delete_saml_configuration")} | 
					
						
							|  |  |  |                   cancelBtnText={t("cancel")} | 
					
						
							|  |  |  |                   onConfirm={deleteSAMLConfigHandler}> | 
					
						
							|  |  |  |                   {t("delete_saml_configuration_confirmation_message")} | 
					
						
							|  |  |  |                 </ConfirmationDialogContent> | 
					
						
							|  |  |  |               </Dialog> | 
					
						
							|  |  |  |             </div> | 
					
						
							|  |  |  |           ) : ( | 
					
						
							|  |  |  |             <p className="mt-1 text-sm text-gray-500">{!samlConfig ? t("saml_not_configured_yet") : ""}</p> | 
					
						
							|  |  |  |           )} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           <p className="mt-1 text-sm text-gray-500">{t("saml_configuration_description")}</p> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           <form className="mt-3 divide-y divide-gray-200 lg:col-span-9" onSubmit={updateSAMLConfigHandler}> | 
					
						
							|  |  |  |             {hasErrors && <Alert severity="error" title={errorMessage} />} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-07 23:35:26 +00:00
										 |  |  |             <TextArea | 
					
						
							| 
									
										
										
										
											2022-01-13 20:05:23 +00:00
										 |  |  |               data-testid="saml_config" | 
					
						
							|  |  |  |               ref={samlConfigRef} | 
					
						
							|  |  |  |               name="saml_config" | 
					
						
							|  |  |  |               id="saml_config" | 
					
						
							|  |  |  |               required={true} | 
					
						
							|  |  |  |               rows={10} | 
					
						
							|  |  |  |               placeholder={t("saml_configuration_placeholder")} | 
					
						
							|  |  |  |             /> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             <div className="flex justify-end py-8"> | 
					
						
							| 
									
										
										
										
											2022-02-02 18:33:27 +00:00
										 |  |  |               <Button type="submit">{t("save")}</Button> | 
					
						
							| 
									
										
										
										
											2022-01-13 20:05:23 +00:00
										 |  |  |             </div> | 
					
						
							|  |  |  |             <hr className="mt-4" /> | 
					
						
							|  |  |  |           </form> | 
					
						
							|  |  |  |         </> | 
					
						
							|  |  |  |       ) : null} | 
					
						
							|  |  |  |     </> | 
					
						
							|  |  |  |   ); | 
					
						
							|  |  |  | } |