Fix: Format entire frontend properly

This commit is contained in:
Daniel Hougaard
2024-03-18 16:00:03 +01:00
parent 1ede551c3e
commit 9002e6cb33
230 changed files with 2752 additions and 2941 deletions
@@ -1,7 +1,7 @@
/* eslint-disable */ /* eslint-disable */
import { PostHog } from 'posthog-js'; import { PostHog } from "posthog-js";
import { initPostHog } from '@app/components/analytics/posthog'; import { initPostHog } from "@app/components/analytics/posthog";
import { ENV } from '@app/components/utilities/config'; import { ENV } from "@app/components/utilities/config";
declare let TELEMETRY_CAPTURING_ENABLED: any; declare let TELEMETRY_CAPTURING_ENABLED: any;
@@ -13,23 +13,23 @@ class Capturer {
} }
capture(item: string) { capture(item: string) {
if (ENV === 'production' && TELEMETRY_CAPTURING_ENABLED === "true") { if (ENV === "production" && TELEMETRY_CAPTURING_ENABLED === "true") {
try { try {
this.api.capture(item); this.api.capture(item);
} catch (error) { } catch (error) {
console.error('PostHog', error); console.error("PostHog", error);
} }
} }
} }
identify(id: string, email?: string) { identify(id: string, email?: string) {
if (ENV === 'production' && TELEMETRY_CAPTURING_ENABLED === "true") { if (ENV === "production" && TELEMETRY_CAPTURING_ENABLED === "true") {
try { try {
this.api.identify(id, { this.api.identify(id, {
email: email email: email
}); });
} catch (error) { } catch (error) {
console.error('PostHog', error); console.error("PostHog", error);
} }
} }
} }
@@ -14,7 +14,7 @@ type Story = StoryObj<typeof Accordion>;
export const Basic: Story = { export const Basic: Story = {
render: (args) => ( render: (args) => (
<div className="flex justify-center w-full"> <div className="flex w-full justify-center">
<Accordion {...args}> <Accordion {...args}>
<AccordionItem value="section-1"> <AccordionItem value="section-1">
<AccordionTrigger>Section 1</AccordionTrigger> <AccordionTrigger>Section 1</AccordionTrigger>
@@ -8,7 +8,7 @@ export const AccordionItem = forwardRef<HTMLDivElement, AccordionPrimitive.Accor
({ children, className, ...props }, forwardedRef) => ( ({ children, className, ...props }, forwardedRef) => (
<AccordionPrimitive.Item <AccordionPrimitive.Item
className={twMerge( className={twMerge(
"mt-px overflow-hidden first:mt-0 data-[state=open]:border-l data-[state=open]:border-primary transition-all border-transparent", "mt-px overflow-hidden border-transparent transition-all first:mt-0 data-[state=open]:border-l data-[state=open]:border-primary",
className className
)} )}
{...props} {...props}
@@ -27,7 +27,7 @@ export const AccordionTrigger = forwardRef<
<AccordionPrimitive.Header className="flex"> <AccordionPrimitive.Header className="flex">
<AccordionPrimitive.Trigger <AccordionPrimitive.Trigger
className={twMerge( className={twMerge(
"py-2 px-4 group data-[state=open]:text-primary h-11 hover:text-primary flex flex-1 outline-none items-center justify-between ", "group flex h-11 flex-1 items-center justify-between py-2 px-4 outline-none hover:text-primary data-[state=open]:text-primary ",
className className
)} )}
{...props} {...props}
@@ -36,7 +36,7 @@ export const AccordionTrigger = forwardRef<
{children} {children}
<FontAwesomeIcon <FontAwesomeIcon
icon={faChevronDown} icon={faChevronDown}
className="ease-[cubic-bezier(0.87,_0,_0.13,_1)] transition-transform duration-300 group-data-[state=open]:rotate-180 text-sm" className="text-sm transition-transform duration-300 ease-[cubic-bezier(0.87,_0,_0.13,_1)] group-data-[state=open]:rotate-180"
aria-hidden aria-hidden
/> />
</AccordionPrimitive.Trigger> </AccordionPrimitive.Trigger>
@@ -51,13 +51,13 @@ export const AccordionContent = forwardRef<
>(({ children, className, ...props }, forwardedRef) => ( >(({ children, className, ...props }, forwardedRef) => (
<AccordionPrimitive.Content <AccordionPrimitive.Content
className={twMerge( className={twMerge(
"data-[state=open]:animate-slideDown data-[state=closed]:animate-slideUp overflow-hidden", "overflow-hidden data-[state=open]:animate-slideDown data-[state=closed]:animate-slideUp",
className className
)} )}
{...props} {...props}
ref={forwardedRef} ref={forwardedRef}
> >
<div className="text-sm py-2 px-4">{children}</div> <div className="py-2 px-4 text-sm">{children}</div>
</AccordionPrimitive.Content> </AccordionPrimitive.Content>
)); ));
@@ -1 +1 @@
export { Accordion, AccordionContent, AccordionItem,AccordionTrigger } from "./Accordion"; export { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from "./Accordion";
+1 -1
View File
@@ -10,7 +10,7 @@ export type CardTitleProps = {
export const CardTitle = ({ children, className, subTitle }: CardTitleProps) => ( export const CardTitle = ({ children, className, subTitle }: CardTitleProps) => (
<div <div
className={twMerge( className={twMerge(
"px-6 py-4 mb-5 font-sans text-lg font-normal border-b border-mineshaft-600 break-words", "mb-5 break-words border-b border-mineshaft-600 px-6 py-4 font-sans text-lg font-normal",
className className
)} )}
> >
@@ -30,7 +30,7 @@ export const Checkbox = ({
<div className="flex items-center font-inter text-bunker-300"> <div className="flex items-center font-inter text-bunker-300">
<CheckboxPrimitive.Root <CheckboxPrimitive.Root
className={twMerge( className={twMerge(
"flex items-center flex-shrink-0 justify-center w-4 h-4 transition-all rounded shadow border border-mineshaft-400 hover:bg-mineshaft-500 bg-mineshaft-600", "flex h-4 w-4 flex-shrink-0 items-center justify-center rounded border border-mineshaft-400 bg-mineshaft-600 shadow transition-all hover:bg-mineshaft-500",
isDisabled && "bg-bunker-400 hover:bg-bunker-400", isDisabled && "bg-bunker-400 hover:bg-bunker-400",
isChecked && "bg-primary hover:bg-primary", isChecked && "bg-primary hover:bg-primary",
Boolean(children) && "mr-3", Boolean(children) && "mr-3",
@@ -46,7 +46,7 @@ export const Checkbox = ({
<FontAwesomeIcon icon={faCheck} size="sm" /> <FontAwesomeIcon icon={faCheck} size="sm" />
</CheckboxPrimitive.Indicator> </CheckboxPrimitive.Indicator>
</CheckboxPrimitive.Root> </CheckboxPrimitive.Root>
<label className="text-sm whitespace-nowrap truncate" htmlFor={id}> <label className="truncate whitespace-nowrap text-sm" htmlFor={id}>
{children} {children}
{isRequired && <span className="pl-1 text-red">*</span>} {isRequired && <span className="pl-1 text-red">*</span>}
</label> </label>
@@ -58,7 +58,7 @@ export const DeleteActionModal = ({
title={title} title={title}
subTitle={subTitle} subTitle={subTitle}
footerContent={ footerContent={
<div className="flex items-center mx-2"> <div className="mx-2 flex items-center">
<Button <Button
className="mr-4" className="mr-4"
colorSchema="danger" colorSchema="danger"
@@ -91,7 +91,11 @@ export const DeleteActionModal = ({
} }
className="mb-0" className="mb-0"
> >
<Input value={inputData} onChange={(e) => setInputData(e.target.value)} placeholder="Type to delete..." /> <Input
value={inputData}
onChange={(e) => setInputData(e.target.value)}
placeholder="Type to delete..."
/>
</FormControl> </FormControl>
</form> </form>
</ModalContent> </ModalContent>
+1 -1
View File
@@ -45,7 +45,7 @@ export const DrawerContent = forwardRef<HTMLDivElement, DrawerContentProps>(
ref={forwardedRef} ref={forwardedRef}
className={twMerge(drawerContentVariation({ direction, className }))} className={twMerge(drawerContentVariation({ direction, className }))}
> >
<Card isRounded={false} className="h-full w-full dark"> <Card isRounded={false} className="dark h-full w-full">
{title && ( {title && (
<CardTitle subTitle={subTitle} className="px-4"> <CardTitle subTitle={subTitle} className="px-4">
{title} {title}
+1 -1
View File
@@ -1 +1 @@
export { Drawer, DrawerClose,DrawerContent, DrawerTrigger } from "./Drawer"; export { Drawer, DrawerClose, DrawerContent, DrawerTrigger } from "./Drawer";
@@ -25,7 +25,7 @@ type Story = StoryObj<typeof DropdownMenuContent>;
export const Basic: Story = { export const Basic: Story = {
render: (args) => ( render: (args) => (
<div className="flex justify-center w-full"> <div className="flex w-full justify-center">
<DropdownMenu> <DropdownMenu>
<DropdownMenuTrigger asChild> <DropdownMenuTrigger asChild>
<IconButton ariaLabel="add"> <IconButton ariaLabel="add">
@@ -43,7 +43,7 @@ export const Basic: Story = {
export const Icons: Story = { export const Icons: Story = {
render: (args) => ( render: (args) => (
<div className="flex justify-center w-full"> <div className="flex w-full justify-center">
<DropdownMenu> <DropdownMenu>
<DropdownMenuTrigger asChild> <DropdownMenuTrigger asChild>
<IconButton ariaLabel="add"> <IconButton ariaLabel="add">
@@ -65,7 +65,7 @@ export const Icons: Story = {
export const WithDivider: Story = { export const WithDivider: Story = {
render: (args) => ( render: (args) => (
<div className="flex justify-center w-full"> <div className="flex w-full justify-center">
<DropdownMenu> <DropdownMenu>
<DropdownMenuTrigger asChild> <DropdownMenuTrigger asChild>
<IconButton ariaLabel="add"> <IconButton ariaLabel="add">
@@ -86,7 +86,7 @@ export const WithDivider: Story = {
export const Group: Story = { export const Group: Story = {
render: (args) => ( render: (args) => (
<div className="flex justify-center w-full"> <div className="flex w-full justify-center">
<DropdownMenu> <DropdownMenu>
<DropdownMenuTrigger asChild> <DropdownMenuTrigger asChild>
<IconButton ariaLabel="add"> <IconButton ariaLabel="add">
@@ -24,7 +24,7 @@ export const DropdownMenuContent = forwardRef<HTMLDivElement, DropdownMenuConten
{...props} {...props}
ref={forwardedRef} ref={forwardedRef}
className={twMerge( className={twMerge(
"min-w-[220px] z-30 bg-mineshaft-900 border border-mineshaft-600 will-change-auto text-bunker-300 rounded-md shadow data-[side=top]:animate-slideDownAndFade data-[side=left]:animate-slideRightAndFade data-[side=right]:animate-slideLeftAndFade data-[side=bottom]:animate-slideUpAndFade", "z-30 min-w-[220px] rounded-md border border-mineshaft-600 bg-mineshaft-900 text-bunker-300 shadow will-change-auto data-[side=top]:animate-slideDownAndFade data-[side=left]:animate-slideRightAndFade data-[side=right]:animate-slideLeftAndFade data-[side=bottom]:animate-slideUpAndFade",
className className
)} )}
> >
@@ -48,7 +48,7 @@ export const DropdownSubMenuContent = forwardRef<HTMLDivElement, DropdownSubMenu
{...props} {...props}
ref={forwardedRef} ref={forwardedRef}
className={twMerge( className={twMerge(
"min-w-[220px] z-30 bg-mineshaft-900 border border-mineshaft-600 will-change-auto text-bunker-300 rounded-md shadow data-[side=top]:animate-slideDownAndFade data-[side=left]:animate-slideRightAndFade data-[side=right]:animate-slideLeftAndFade data-[side=bottom]:animate-slideUpAndFade", "z-30 min-w-[220px] rounded-md border border-mineshaft-600 bg-mineshaft-900 text-bunker-300 shadow will-change-auto data-[side=top]:animate-slideDownAndFade data-[side=left]:animate-slideRightAndFade data-[side=right]:animate-slideLeftAndFade data-[side=bottom]:animate-slideUpAndFade",
className className
)} )}
> >
@@ -66,7 +66,7 @@ export type DropdownLabelProps = DropdownMenuPrimitive.MenuLabelProps;
export const DropdownMenuLabel = ({ className, ...props }: DropdownLabelProps) => ( export const DropdownMenuLabel = ({ className, ...props }: DropdownLabelProps) => (
<DropdownMenuPrimitive.Label <DropdownMenuPrimitive.Label
{...props} {...props}
className={twMerge("text-xs text-bunker-400 px-4 pt-2 pb-1", className)} className={twMerge("px-4 pt-2 pb-1 text-xs text-bunker-400", className)}
/> />
); );
@@ -91,14 +91,14 @@ export const DropdownMenuItem = <T extends ElementType = "button">({
<DropdownMenuPrimitive.Item <DropdownMenuPrimitive.Item
{...props} {...props}
className={twMerge( className={twMerge(
"text-xs text-mineshaft-200 block font-inter px-4 py-2 data-[highlighted]:bg-mineshaft-700 rounded-sm outline-none cursor-pointer", "block cursor-pointer rounded-sm px-4 py-2 font-inter text-xs text-mineshaft-200 outline-none data-[highlighted]:bg-mineshaft-700",
className className
)} )}
> >
<Item type="button" role="menuitem" className="flex w-full items-center" ref={inputRef}> <Item type="button" role="menuitem" className="flex w-full items-center" ref={inputRef}>
{icon && iconPos === "left" && <span className="flex items-center mr-2">{icon}</span>} {icon && iconPos === "left" && <span className="mr-2 flex items-center">{icon}</span>}
<span className="flex-grow text-left">{children}</span> <span className="flex-grow text-left">{children}</span>
{icon && iconPos === "right" && <span className="flex items-center ml-2">{icon}</span>} {icon && iconPos === "right" && <span className="ml-2 flex items-center">{icon}</span>}
</Item> </Item>
</DropdownMenuPrimitive.Item> </DropdownMenuPrimitive.Item>
); );
@@ -124,14 +124,14 @@ export const DropdownSubMenuTrigger = <T extends ElementType = "button">({
<DropdownMenuPrimitive.SubTrigger <DropdownMenuPrimitive.SubTrigger
{...props} {...props}
className={twMerge( className={twMerge(
"text-xs text-mineshaft-200 block font-inter px-4 py-2 data-[highlighted]:bg-mineshaft-700 rounded-sm outline-none cursor-pointer", "block cursor-pointer rounded-sm px-4 py-2 font-inter text-xs text-mineshaft-200 outline-none data-[highlighted]:bg-mineshaft-700",
className className
)} )}
> >
<Item type="button" role="menuitem" className="flex w-full items-center" ref={inputRef}> <Item type="button" role="menuitem" className="flex w-full items-center" ref={inputRef}>
{icon && iconPos === "left" && <span className="flex items-center mr-2">{icon}</span>} {icon && iconPos === "left" && <span className="mr-2 flex items-center">{icon}</span>}
<span className="flex-grow text-left">{children}</span> <span className="flex-grow text-left">{children}</span>
{icon && iconPos === "right" && <span className="flex items-center ml-2">{icon}</span>} {icon && iconPos === "right" && <span className="ml-2 flex items-center">{icon}</span>}
</Item> </Item>
</DropdownMenuPrimitive.SubTrigger> </DropdownMenuPrimitive.SubTrigger>
); );
@@ -143,7 +143,7 @@ export const DropdownMenuGroup = forwardRef<HTMLDivElement, DropdownMenuGroupPro
({ ...props }, ref) => ( ({ ...props }, ref) => (
<DropdownMenuPrimitive.Group <DropdownMenuPrimitive.Group
{...props} {...props}
className={twMerge("text-xs py-2 pl-3", props.className)} className={twMerge("py-2 pl-3 text-xs", props.className)}
ref={ref} ref={ref}
/> />
) )
@@ -159,7 +159,7 @@ export const DropdownMenuSeparator = forwardRef<
<DropdownMenuPrimitive.Separator <DropdownMenuPrimitive.Separator
ref={ref} ref={ref}
{...props} {...props}
className={twMerge("h-[1px] bg-gray-700 m-1", className)} className={twMerge("m-1 h-[1px] bg-gray-700", className)}
/> />
)); ));
@@ -10,7 +10,8 @@ export const EmailServiceSetupModal = ({ isOpen, onOpenChange }: Props): JSX.Ele
<Modal isOpen={isOpen} onOpenChange={onOpenChange}> <Modal isOpen={isOpen} onOpenChange={onOpenChange}>
<ModalContent title="Email service not configured"> <ModalContent title="Email service not configured">
<p className="mb-4 text-bunker-300"> <p className="mb-4 text-bunker-300">
The administrators of this Infisical instance have not yet set up an email service provider required to perform this action The administrators of this Infisical instance have not yet set up an email service provider
required to perform this action
</p> </p>
<a href="https://infisical.com/docs/self-hosting/configuration/email"> <a href="https://infisical.com/docs/self-hosting/configuration/email">
@@ -23,7 +23,7 @@ export const FormLabel = ({ id, label, isRequired, icon, className }: FormLabelP
{label} {label}
{isRequired && <span className="ml-1 text-red">*</span>} {isRequired && <span className="ml-1 text-red">*</span>}
{icon && ( {icon && (
<span className="ml-2 text-mineshaft-300 hover:text-mineshaft-200 cursor-default"> <span className="ml-2 cursor-default text-mineshaft-300 hover:text-mineshaft-200">
{icon} {icon}
</span> </span>
)} )}
@@ -10,22 +10,16 @@ type Props = {
export type HoverCardProps = Props; export type HoverCardProps = Props;
export const HoverObject = ({ export const HoverObject = ({ text, icon, color }: Props): JSX.Element => (
text,
icon,
color
}: Props): JSX.Element => (
<HoverCard.Root openDelay={50}> <HoverCard.Root openDelay={50}>
<HoverCard.Trigger asChild> <HoverCard.Trigger asChild>
<a <a className="ImageTrigger z-20">
className="ImageTrigger z-20"
>
<FontAwesomeIcon icon={icon} className={`text-${color}`} /> <FontAwesomeIcon icon={icon} className={`text-${color}`} />
</a> </a>
</HoverCard.Trigger> </HoverCard.Trigger>
<HoverCard.Portal> <HoverCard.Portal>
<HoverCard.Content className="HoverCardContent z-[300]" sideOffset={5}> <HoverCard.Content className="HoverCardContent z-[300]" sideOffset={5}>
<div className='bg-bunker-700 border border-mineshaft-600 p-2 rounded-md drop-shadow-xl text-bunker-300'> <div className="rounded-md border border-mineshaft-600 bg-bunker-700 p-2 text-bunker-300 drop-shadow-xl">
<div style={{ display: "flex", flexDirection: "column", gap: 15 }}> <div style={{ display: "flex", flexDirection: "column", gap: 15 }}>
<div> <div>
<div className="Text bold">{text}</div> <div className="Text bold">{text}</div>
@@ -1 +1 @@
export { HoverCard,HoverCardContent, HoverCardTrigger } from "./HoverCardv2"; export { HoverCard, HoverCardContent, HoverCardTrigger } from "./HoverCardv2";
+1 -1
View File
@@ -29,7 +29,7 @@ export const ModalContent = forwardRef<HTMLDivElement, ModalContentProps>(
<Card <Card
isRounded isRounded
className={twMerge( className={twMerge(
"fixed top-1/2 left-1/2 z-30 dark:[color-scheme:dark] max-h-screen thin-scrollbar max-w-xl -translate-y-2/4 -translate-x-2/4 animate-popIn border border-mineshaft-600 drop-shadow-2xl", "thin-scrollbar fixed top-1/2 left-1/2 z-30 max-h-screen max-w-xl -translate-y-2/4 -translate-x-2/4 animate-popIn border border-mineshaft-600 drop-shadow-2xl dark:[color-scheme:dark]",
className className
)} )}
> >
@@ -44,7 +44,7 @@ export const Pagination = ({
return ( return (
<div <div
className={twMerge( className={twMerge(
"flex items-center justify-end text-white w-full py-3 px-4 bg-mineshaft-800", "flex w-full items-center justify-end bg-mineshaft-800 py-3 px-4 text-white",
className className
)} )}
> >
+11 -8
View File
@@ -11,31 +11,34 @@ type Props = {
export type PopoverProps = Props; export type PopoverProps = Props;
export const PopoverObject = ({children, text, onChangeHandler, id}: Props) => ( export const PopoverObject = ({ children, text, onChangeHandler, id }: Props) => (
<Popover.Root> <Popover.Root>
<Popover.Trigger asChild className='data-[state=open]:outline data-[state=open]:outline-primary data-[state=closed]:hover:outline data-[state=closed]:hover:outline-mineshaft-400'> <Popover.Trigger
asChild
className="data-[state=open]:outline data-[state=open]:outline-primary data-[state=closed]:hover:outline data-[state=closed]:hover:outline-mineshaft-400"
>
{children} {children}
</Popover.Trigger> </Popover.Trigger>
<Popover.Portal> <Popover.Portal>
<Popover.Content <Popover.Content
className="rounded z-[100] p-3 w-[460px] min-h-fit border border-chicago-700 bg-mineshaft-600 shadow-[0_10px_38px_-10px_hsla(206,22%,7%,.35),0_10px_20px_-15px_hsla(206,22%,7%,.2)] focus:shadow-[0_10px_38px_-10px_hsla(206,22%,7%,.35),0_10px_20px_-15px_hsla(206,22%,7%,.2),0_0_0_2px_theme(colors.violet7)] will-change-[transform,opacity] data-[state=open]:data-[side=top]:animate-slideDownAndFade data-[state=open]:data-[side=right]:animate-slideLeftAndFade data-[state=open]:data-[side=bottom]:animate-slideUpAndFade data-[state=open]:data-[side=left]:animate-slideRightAndFade" className="z-[100] min-h-fit w-[460px] rounded border border-chicago-700 bg-mineshaft-600 p-3 shadow-[0_10px_38px_-10px_hsla(206,22%,7%,.35),0_10px_20px_-15px_hsla(206,22%,7%,.2)] will-change-[transform,opacity] focus:shadow-[0_10px_38px_-10px_hsla(206,22%,7%,.35),0_10px_20px_-15px_hsla(206,22%,7%,.2),0_0_0_2px_theme(colors.violet7)] data-[state=open]:data-[side=top]:animate-slideDownAndFade data-[state=open]:data-[side=right]:animate-slideLeftAndFade data-[state=open]:data-[side=bottom]:animate-slideUpAndFade data-[state=open]:data-[side=left]:animate-slideRightAndFade"
sideOffset={5} sideOffset={5}
hideWhenDetached hideWhenDetached
side="left" side="left"
> >
<div className="flex flex-col pt-2 dark"> <div className="dark flex flex-col pt-2">
<p className="text-bunker-200 text-[15px] leading-[0px] font-medium mb-5">Comment</p> <p className="mb-5 text-[15px] font-medium leading-[0px] text-bunker-200">Comment</p>
<textarea <textarea
onChange={(e) => onChangeHandler(e.target.value, id)} onChange={(e) => onChangeHandler(e.target.value, id)}
// type={type} // type={type}
value={text} value={text}
className='z-10 dark:[color-scheme:dark] peer h-[20rem] ph-no-capture bg-bunker-600 border border-mineshaft-500 rounded-md py-2.5 caret-bunker-200 text-sm px-2 w-full outline-none text-bunker-300 focus:text-bunker-100 placeholder:text-bunker-400 placeholder:focus:text-transparent placeholder duration-200' className="ph-no-capture placeholder peer z-10 h-[20rem] w-full rounded-md border border-mineshaft-500 bg-bunker-600 py-2.5 px-2 text-sm text-bunker-300 caret-bunker-200 outline-none duration-200 placeholder:text-bunker-400 focus:text-bunker-100 placeholder:focus:text-transparent dark:[color-scheme:dark]"
spellCheck="false" spellCheck="false"
placeholder='–' placeholder="–"
/> />
</div> </div>
<Popover.Close <Popover.Close
className="rounded-full h-[25px] w-[25px] inline-flex items-center justify-center text-bunker-300 hover:text-white absolute top-[5px] right-[5px] hover:bg-violet4 focus:shadow-[0_0_0_2px] focus:shadow-violet7 outline-none cursor-default" className="hover:bg-violet4 focus:shadow-violet7 absolute top-[5px] right-[5px] inline-flex h-[25px] w-[25px] cursor-default items-center justify-center rounded-full text-bunker-300 outline-none hover:text-white focus:shadow-[0_0_0_2px]"
aria-label="Close" aria-label="Close"
> >
<FontAwesomeIcon icon={faXmark} /> <FontAwesomeIcon icon={faXmark} />
@@ -1 +1 @@
export { Popover,PopoverContent, PopoverTrigger } from "./Popoverv2"; export { Popover, PopoverContent, PopoverTrigger } from "./Popoverv2";
@@ -7,32 +7,32 @@ export type RadioGroupProps = RadioGroupPrimitive.RadioGroupProps;
// Note this component is not customizable (Heroku integration and potentially other pages depend on it) // Note this component is not customizable (Heroku integration and potentially other pages depend on it)
export const RadioGroup = ({ className, children, ...props }: RadioGroupProps) => ( export const RadioGroup = ({ className, children, ...props }: RadioGroupProps) => (
<RadioGroupPrimitive.Root <RadioGroupPrimitive.Root
className={twMerge("flex flex-row gap-5 px-6 mb-6", className)} className={twMerge("mb-6 flex flex-row gap-5 px-6", className)}
defaultValue="App" defaultValue="App"
aria-label="View density" aria-label="View density"
{...props} {...props}
> >
<div className="flex items-center"> <div className="flex items-center">
<RadioGroupPrimitive.Item <RadioGroupPrimitive.Item
className="bg-bunker-400/20 w-[20px] h-[20px] rounded-full hover:bg-bunker-400/40 border border-bunker-400/60 duration-200 outline-none cursor-default" className="h-[20px] w-[20px] cursor-default rounded-full border border-bunker-400/60 bg-bunker-400/20 outline-none duration-200 hover:bg-bunker-400/40"
value="App" value="App"
id="r1" id="r1"
> >
<RadioGroupPrimitive.Indicator className="flex items-center justify-center w-full h-full relative after:content-[''] after:block after:w-[11px] after:h-[11px] after:rounded-[50%] after:bg-primary" /> <RadioGroupPrimitive.Indicator className="relative flex h-full w-full items-center justify-center after:block after:h-[11px] after:w-[11px] after:rounded-[50%] after:bg-primary after:content-['']" />
</RadioGroupPrimitive.Item> </RadioGroupPrimitive.Item>
<label className="text-bunker-200 text-sm leading-none pl-2" htmlFor="r1"> <label className="pl-2 text-sm leading-none text-bunker-200" htmlFor="r1">
App App
</label> </label>
</div> </div>
<div className="flex items-center"> <div className="flex items-center">
<RadioGroupPrimitive.Item <RadioGroupPrimitive.Item
className="bg-bunker-400/20 w-[22px] h-[22px] rounded-full hover:bg-bunker-400/40 border border-bunker-400/60 duration-200 outline-none cursor-default" className="h-[22px] w-[22px] cursor-default rounded-full border border-bunker-400/60 bg-bunker-400/20 outline-none duration-200 hover:bg-bunker-400/40"
value="Pipeline" value="Pipeline"
id="r2" id="r2"
> >
<RadioGroupPrimitive.Indicator className="flex items-center justify-center w-full h-full relative after:content-[''] after:block after:w-[13px] after:h-[13px] after:rounded-[50%] after:bg-primary" /> <RadioGroupPrimitive.Indicator className="relative flex h-full w-full items-center justify-center after:block after:h-[13px] after:w-[13px] after:rounded-[50%] after:bg-primary after:content-['']" />
</RadioGroupPrimitive.Item> </RadioGroupPrimitive.Item>
<label className="text-bunker-200 text-sm leading-none pl-2" htmlFor="r2"> <label className="pl-2 text-sm leading-none text-bunker-200" htmlFor="r2">
Pipeline Pipeline
</label> </label>
</div> </div>
+2 -2
View File
@@ -1,6 +1,6 @@
import { forwardRef, ReactNode } from "react"; import { forwardRef, ReactNode } from "react";
import { IconProp } from "@fortawesome/fontawesome-svg-core"; import { IconProp } from "@fortawesome/fontawesome-svg-core";
import { faCaretDown, faCaretUp,faCheck } from "@fortawesome/free-solid-svg-icons"; import { faCaretDown, faCaretUp, faCheck } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import * as SelectPrimitive from "@radix-ui/react-select"; import * as SelectPrimitive from "@radix-ui/react-select";
import { twMerge } from "tailwind-merge"; import { twMerge } from "tailwind-merge";
@@ -57,7 +57,7 @@ export const Select = forwardRef<HTMLButtonElement, SelectProps>(
<SelectPrimitive.Portal> <SelectPrimitive.Portal>
<SelectPrimitive.Content <SelectPrimitive.Content
className={twMerge( className={twMerge(
"relative top-1 z-[100] overflow-hidden rounded-md bg-mineshaft-900 border border-mineshaft-600 font-inter text-bunker-100 shadow-md", "relative top-1 z-[100] overflow-hidden rounded-md border border-mineshaft-600 bg-mineshaft-900 font-inter text-bunker-100 shadow-md",
dropdownContainerClassName dropdownContainerClassName
)} )}
position={position} position={position}
@@ -20,7 +20,7 @@ export const Spinner = ({ className, size = "md" }: Props): JSX.Element => {
<svg <svg
aria-hidden="true" aria-hidden="true"
className={twMerge( className={twMerge(
"text-gray-200 animate-spin dark:text-gray-600 fill-primary m-1", "m-1 animate-spin fill-primary text-gray-200 dark:text-gray-600",
sizeChart[size], sizeChart[size],
className className
)} )}
@@ -14,7 +14,7 @@ export const Stepper = ({ activeStep, children, direction, className }: StepperP
return ( return (
<div <div
className={twMerge( className={twMerge(
"flex items-center w-full space-x-3 p-2 border border-bunker-300/30 rounded-md", "flex w-full items-center space-x-3 rounded-md border border-bunker-300/30 p-2",
className className
)} )}
> >
@@ -25,15 +25,15 @@ export const Stepper = ({ activeStep, children, direction, className }: StepperP
return ( return (
<div <div
className={twMerge( className={twMerge(
"flex items-center space-x-3 flex-shrink-0", "flex flex-shrink-0 items-center space-x-3",
isNotLast && "flex-grow" isNotLast && "flex-grow"
)} )}
> >
<div className="flex items-center space-x-2 flex-shrink-0"> <div className="flex flex-shrink-0 items-center space-x-2">
<div <div
className={twMerge( className={twMerge(
"w-7 h-7 flex items-center justify-center font-medium text-mineshaft-800 text-sm rounded-full transition-all", "flex h-7 w-7 items-center justify-center rounded-full text-sm font-medium text-mineshaft-800 transition-all",
isCompleted ? "bg-primary" : "border text-bunker-300 border-primary/30", isCompleted ? "bg-primary" : "border border-primary/30 text-bunker-300",
isActive && "bg-primary text-mineshaft-800" isActive && "bg-primary text-mineshaft-800"
)} )}
> >
@@ -71,7 +71,7 @@ export type StepProps = {
export const Step = ({ title, description }: StepProps) => { export const Step = ({ title, description }: StepProps) => {
return ( return (
<div className="flex flex-col text-gray-300"> <div className="flex flex-col text-gray-300">
<div className="font-medium text-sm">{title}</div> <div className="text-sm font-medium">{title}</div>
{description && <div className="text-xs">{description}</div>} {description && <div className="text-xs">{description}</div>}
</div> </div>
); );
+2 -2
View File
@@ -1,2 +1,2 @@
export type { StepperProps,StepProps } from "./Stepper"; export type { StepperProps, StepProps } from "./Stepper";
export { Step,Stepper } from "./Stepper"; export { Step, Stepper } from "./Stepper";
+3 -2
View File
@@ -6,5 +6,6 @@ export type {
TFootProps, TFootProps,
THeadProps, THeadProps,
ThProps, ThProps,
TrProps} from "./Table"; TrProps
export { Table, TableContainer, TableSkeleton, TBody, Td, TFoot,Th, THead, Tr } from "./Table"; } from "./Table";
export { Table, TableContainer, TableSkeleton, TBody, Td, TFoot, Th, THead, Tr } from "./Table";
+3 -3
View File
@@ -13,7 +13,7 @@ export type TabListProps = TabsPrimitive.TabsListProps;
export const TabList = ({ className, children, ...props }: TabListProps) => ( export const TabList = ({ className, children, ...props }: TabListProps) => (
<TabsPrimitive.List <TabsPrimitive.List
className={twMerge("flex-shrink-0 flex border-b-2 border-mineshaft-800", className)} className={twMerge("flex flex-shrink-0 border-b-2 border-mineshaft-800", className)}
{...props} {...props}
> >
{children} {children}
@@ -25,7 +25,7 @@ export type TabProps = TabsPrimitive.TabsTriggerProps;
export const Tab = ({ className, children, ...props }: TabProps) => ( export const Tab = ({ className, children, ...props }: TabProps) => (
<TabsPrimitive.Trigger <TabsPrimitive.Trigger
className={twMerge( className={twMerge(
"px-3 h-10 font-medium text-sm flex items-center justify-center select-none first:rounded-tl-md last:rounded-tr-md hover:text-mineshaft-200 text-mineshaft-400 transition-all data-[state=active]:text-white data-[state=active]:border-b data-[state=active]:border-primary", "flex h-10 select-none items-center justify-center px-3 text-sm font-medium text-mineshaft-400 transition-all first:rounded-tl-md last:rounded-tr-md hover:text-mineshaft-200 data-[state=active]:border-b data-[state=active]:border-primary data-[state=active]:text-white",
className className
)} )}
{...props} {...props}
@@ -38,7 +38,7 @@ export type TabPanelProps = TabsPrimitive.TabsContentProps;
export const TabPanel = ({ className, children, ...props }: TabPanelProps) => ( export const TabPanel = ({ className, children, ...props }: TabPanelProps) => (
<TabsPrimitive.Content <TabsPrimitive.Content
className={twMerge("outline-none flex-grow py-5 rounded-bl-md rounded-br-md", className)} className={twMerge("flex-grow rounded-bl-md rounded-br-md py-5 outline-none", className)}
{...props} {...props}
> >
{children} {children}
+1 -1
View File
@@ -1,2 +1,2 @@
export type { TabListProps,TabPanelProps, TabProps, TabsProps } from "./Tabs"; export type { TabListProps, TabPanelProps, TabProps, TabsProps } from "./Tabs";
export { Tab, TabList, TabPanel, Tabs } from "./Tabs"; export { Tab, TabList, TabPanel, Tabs } from "./Tabs";
@@ -39,7 +39,7 @@ export const AuthProvider = ({ children }: Props): JSX.Element => {
// wait for app to load the auth state // wait for app to load the auth state
if (isLoading || !isReady) { if (isLoading || !isReady) {
return ( return (
<div className="flex items-center justify-center w-screen h-screen bg-bunker-800"> <div className="flex h-screen w-screen items-center justify-center bg-bunker-800">
<img <img
src="/images/loading/loading.gif" src="/images/loading/loading.gif"
height={70} height={70}
@@ -1,3 +1,3 @@
export { ProjectPermissionProvider, useProjectPermission } from "./ProjectPermissionContext"; export { ProjectPermissionProvider, useProjectPermission } from "./ProjectPermissionContext";
export type { ProjectPermissionSet, TProjectPermission } from "./types"; export type { ProjectPermissionSet, TProjectPermission } from "./types";
export { ProjectPermissionActions,ProjectPermissionSub } from "./types"; export { ProjectPermissionActions, ProjectPermissionSub } from "./types";
@@ -38,22 +38,31 @@ export const ServerConfigProvider = ({ children }: Props): JSX.Element => {
<div className="relative mx-auto flex h-screen w-full flex-col items-center justify-center space-y-8 bg-bunker-800 px-8 text-mineshaft-50 dark:[color-scheme:dark]"> <div className="relative mx-auto flex h-screen w-full flex-col items-center justify-center space-y-8 bg-bunker-800 px-8 text-mineshaft-50 dark:[color-scheme:dark]">
<Head> <Head>
<title>Infisical Maintenance Mode</title> <title>Infisical Maintenance Mode</title>
<link rel='icon' href='/infisical.ico' /> <link rel="icon" href="/infisical.ico" />
</Head> </Head>
<img src="/images/maintenance.png" height={175} width={300} alt="maintenance mode" className="w-[40rem]"/> <img
src="/images/maintenance.png"
height={175}
width={300}
alt="maintenance mode"
className="w-[40rem]"
/>
<p className="mx-8 mb-4 flex justify-center bg-gradient-to-tr from-mineshaft-300 to-white bg-clip-text text-4xl font-bold text-transparent md:mx-16"> <p className="mx-8 mb-4 flex justify-center bg-gradient-to-tr from-mineshaft-300 to-white bg-clip-text text-4xl font-bold text-transparent md:mx-16">
Scheduled Maintenance Scheduled Maintenance
</p> </p>
<div className="mt-2 text-center text-lg text-bunker-300"> <div className="mt-2 text-center text-lg text-bunker-300">
Infisical is undergoing planned maintenance. <br /> No action is required on your end — your applications will continue to fetch secrets. Infisical is undergoing planned maintenance. <br /> No action is required on your end —
<br /> If you have questions, please <a your applications will continue to fetch secrets.
className="text-bunker-300 underline underline-offset-4 decoration-primary-800 hover:decoration-primary-600 hover:text-mineshaft-100 duration-200" <br /> If you have questions, please{" "}
<a
className="text-bunker-300 underline decoration-primary-800 underline-offset-4 duration-200 hover:text-mineshaft-100 hover:decoration-primary-600"
href="https://infisical.com/slack" href="https://infisical.com/slack"
target="_blank" target="_blank"
rel="noopener noreferrer" rel="noopener noreferrer"
> >
join our Slack community join our Slack community
</a>. </a>
.
</div> </div>
</div> </div>
); );
@@ -1 +1 @@
export { ServerConfigProvider,useServerConfig } from "./ServerConfigContext"; export { ServerConfigProvider, useServerConfig } from "./ServerConfigContext";
+1 -1
View File
@@ -14,7 +14,7 @@ export {
ProjectPermissionSub, ProjectPermissionSub,
useProjectPermission useProjectPermission
} from "./ProjectPermissionContext"; } from "./ProjectPermissionContext";
export { ServerConfigProvider,useServerConfig } from "./ServerConfigContext"; export { ServerConfigProvider, useServerConfig } from "./ServerConfigContext";
export { SubscriptionProvider, useSubscription } from "./SubscriptionContext"; export { SubscriptionProvider, useSubscription } from "./SubscriptionContext";
export { UserProvider, useUser } from "./UserContext"; export { UserProvider, useUser } from "./UserContext";
export { useWorkspace, WorkspaceProvider } from "./WorkspaceContext"; export { useWorkspace, WorkspaceProvider } from "./WorkspaceContext";
@@ -15,7 +15,7 @@ const updateUserProjectPermission = async ({
denials: { denials: {
ability: string; ability: string;
environmentSlug: string; environmentSlug: string;
}[] }[];
}) => }) =>
SecurityClient.fetchCall(`/api/v1/membership/${membershipId}/deny-permissions`, { SecurityClient.fetchCall(`/api/v1/membership/${membershipId}/deny-permissions`, {
method: "POST", method: "POST",
+7 -9
View File
@@ -4,32 +4,30 @@
* @returns {String} text - how much time has passed since a certain timestamp * @returns {String} text - how much time has passed since a certain timestamp
*/ */
function timeSince(date: Date) { function timeSince(date: Date) {
const seconds = Math.floor( const seconds = Math.floor(((new Date() as any) - (date as any)) / 1000) as number;
((new Date() as any) - (date as any)) / 1000
) as number;
let interval = seconds / 31536000; let interval = seconds / 31536000;
if (interval > 1) { if (interval > 1) {
return `${Math.floor(interval) } years ago`; return `${Math.floor(interval)} years ago`;
} }
interval = seconds / 2592000; interval = seconds / 2592000;
if (interval > 1) { if (interval > 1) {
return `${Math.floor(interval) } months ago`; return `${Math.floor(interval)} months ago`;
} }
interval = seconds / 86400; interval = seconds / 86400;
if (interval > 1) { if (interval > 1) {
return `${Math.floor(interval) } days ago`; return `${Math.floor(interval)} days ago`;
} }
interval = seconds / 3600; interval = seconds / 3600;
if (interval > 1) { if (interval > 1) {
return `${Math.floor(interval) } hours ago`; return `${Math.floor(interval)} hours ago`;
} }
interval = seconds / 60; interval = seconds / 60;
if (interval > 1) { if (interval > 1) {
return `${Math.floor(interval) } minutes ago`; return `${Math.floor(interval)} minutes ago`;
} }
return `${Math.floor(seconds) } seconds ago`; return `${Math.floor(seconds)} seconds ago`;
} }
export default timeSince; export default timeSince;
+60 -62
View File
@@ -14,73 +14,71 @@ import { deriveArgonKey } from "@app/components/utilities/cryptography/crypto";
* @param {String} obj.protectedKeyTag * @param {String} obj.protectedKeyTag
*/ */
const decryptPrivateKeyHelper = async ({ const decryptPrivateKeyHelper = async ({
encryptionVersion, encryptionVersion,
encryptedPrivateKey, encryptedPrivateKey,
iv, iv,
tag, tag,
password, password,
salt, salt,
protectedKey, protectedKey,
protectedKeyIV, protectedKeyIV,
protectedKeyTag, protectedKeyTag
}: { }: {
encryptionVersion: number; encryptionVersion: number;
encryptedPrivateKey: string; encryptedPrivateKey: string;
iv: string; iv: string;
tag: string; tag: string;
password: string; password: string;
salt: string; salt: string;
protectedKey?: string; protectedKey?: string;
protectedKeyIV?: string; protectedKeyIV?: string;
protectedKeyTag?: string; protectedKeyTag?: string;
}) => { }) => {
let privateKey; let privateKey;
try { try {
if (encryptionVersion === 1) { if (encryptionVersion === 1) {
privateKey = Aes256Gcm.decrypt({ privateKey = Aes256Gcm.decrypt({
ciphertext: encryptedPrivateKey, ciphertext: encryptedPrivateKey,
iv, iv,
tag, tag,
secret: password secret: password
.slice(0, 32) .slice(0, 32)
.padStart(32 + (password.slice(0, 32).length - new Blob([password]).size), "0") .padStart(32 + (password.slice(0, 32).length - new Blob([password]).size), "0")
}); });
} else if (encryptionVersion === 2 && protectedKey && protectedKeyIV && protectedKeyTag) { } else if (encryptionVersion === 2 && protectedKey && protectedKeyIV && protectedKeyTag) {
const derivedKey = await deriveArgonKey({ const derivedKey = await deriveArgonKey({
password, password,
salt, salt,
mem: 65536, mem: 65536,
time: 3, time: 3,
parallelism: 1, parallelism: 1,
hashLen: 32 hashLen: 32
}); });
if (!derivedKey) throw new Error("Failed to generate derived key"); if (!derivedKey) throw new Error("Failed to generate derived key");
const key = Aes256Gcm.decrypt({ const key = Aes256Gcm.decrypt({
ciphertext: protectedKey, ciphertext: protectedKey,
iv: protectedKeyIV, iv: protectedKeyIV,
tag: protectedKeyTag, tag: protectedKeyTag,
secret: Buffer.from(derivedKey.hash) secret: Buffer.from(derivedKey.hash)
}); });
// decrypt back the private key // decrypt back the private key
privateKey = Aes256Gcm.decrypt({ privateKey = Aes256Gcm.decrypt({
ciphertext: encryptedPrivateKey, ciphertext: encryptedPrivateKey,
iv, iv,
tag, tag,
secret: Buffer.from(key, "hex") secret: Buffer.from(key, "hex")
}); });
} else { } else {
throw new Error("Insufficient details to decrypt private key"); throw new Error("Insufficient details to decrypt private key");
}
} catch (err) {
throw new Error("Failed to decrypt private key");
} }
} catch (err) {
throw new Error("Failed to decrypt private key");
}
return privateKey; return privateKey;
}
export {
decryptPrivateKeyHelper
}; };
export { decryptPrivateKeyHelper };
@@ -29,13 +29,13 @@ export const withPermission = <T extends {}, J extends TOrgPermission>(
return ( return (
<div <div
className={twMerge( className={twMerge(
"container h-full mx-auto flex justify-center items-center", "container mx-auto flex h-full items-center justify-center",
containerClassName containerClassName
)} )}
> >
<div <div
className={twMerge( className={twMerge(
"rounded-md bg-mineshaft-800 text-bunker-300 p-16 flex space-x-12 items-end", "flex items-end space-x-12 rounded-md bg-mineshaft-800 p-16 text-bunker-300",
className className
)} )}
> >
@@ -43,7 +43,7 @@ export const withPermission = <T extends {}, J extends TOrgPermission>(
<FontAwesomeIcon icon={faLock} size="6x" /> <FontAwesomeIcon icon={faLock} size="6x" />
</div> </div>
<div> <div>
<div className="text-4xl font-medium mb-2">Access Restricted</div> <div className="mb-2 text-4xl font-medium">Access Restricted</div>
<div className="text-sm"> <div className="text-sm">
Your role has limited permissions, please <br /> contact your admin to gain access Your role has limited permissions, please <br /> contact your admin to gain access
</div> </div>
+1 -4
View File
@@ -1,4 +1 @@
export { export { useCreateAPIKeyV2, useDeleteAPIKeyV2, useUpdateAPIKeyV2 } from "./queries";
useCreateAPIKeyV2,
useDeleteAPIKeyV2,
useUpdateAPIKeyV2} from "./queries";
+11 -13
View File
@@ -8,14 +8,13 @@ import {
CreateAPIKeyDataV2DTO, CreateAPIKeyDataV2DTO,
CreateServiceTokenDataV3Res, CreateServiceTokenDataV3Res,
DeleteAPIKeyDataV2DTO, DeleteAPIKeyDataV2DTO,
UpdateAPIKeyDataV2DTO} from "./types"; UpdateAPIKeyDataV2DTO
} from "./types";
export const useCreateAPIKeyV2 = () => { export const useCreateAPIKeyV2 = () => {
const queryClient = useQueryClient(); const queryClient = useQueryClient();
return useMutation<CreateServiceTokenDataV3Res, {}, CreateAPIKeyDataV2DTO>({ return useMutation<CreateServiceTokenDataV3Res, {}, CreateAPIKeyDataV2DTO>({
mutationFn: async ({ mutationFn: async ({ name }) => {
name
}) => {
const { data } = await apiRequest.post("/api/v3/api-key", { const { data } = await apiRequest.post("/api/v3/api-key", {
name name
}); });
@@ -31,11 +30,10 @@ export const useCreateAPIKeyV2 = () => {
export const useUpdateAPIKeyV2 = () => { export const useUpdateAPIKeyV2 = () => {
const queryClient = useQueryClient(); const queryClient = useQueryClient();
return useMutation<APIKeyDataV2, {}, UpdateAPIKeyDataV2DTO>({ return useMutation<APIKeyDataV2, {}, UpdateAPIKeyDataV2DTO>({
mutationFn: async ({ mutationFn: async ({ apiKeyDataId, name }) => {
apiKeyDataId, const {
name data: { apiKeyData }
}) => { } = await apiRequest.patch(`/api/v3/api-key/${apiKeyDataId}`, {
const { data: { apiKeyData } } = await apiRequest.patch(`/api/v3/api-key/${apiKeyDataId}`, {
name name
}); });
return apiKeyData; return apiKeyData;
@@ -49,10 +47,10 @@ export const useUpdateAPIKeyV2 = () => {
export const useDeleteAPIKeyV2 = () => { export const useDeleteAPIKeyV2 = () => {
const queryClient = useQueryClient(); const queryClient = useQueryClient();
return useMutation<APIKeyDataV2, {}, DeleteAPIKeyDataV2DTO>({ return useMutation<APIKeyDataV2, {}, DeleteAPIKeyDataV2DTO>({
mutationFn: async ({ mutationFn: async ({ apiKeyDataId }) => {
apiKeyDataId const {
}) => { data: { apiKeyData }
const { data: { apiKeyData } } = await apiRequest.delete(`/api/v3/api-key/${apiKeyDataId}`); } = await apiRequest.delete(`/api/v3/api-key/${apiKeyDataId}`);
return apiKeyData; return apiKeyData;
}, },
onSuccess: () => { onSuccess: () => {
+50 -50
View File
@@ -1,57 +1,57 @@
import { EventType, UserAgentType } from "./enums"; import { EventType, UserAgentType } from "./enums";
export const eventToNameMap: { [K in EventType]: string } = { export const eventToNameMap: { [K in EventType]: string } = {
[EventType.GET_SECRETS]: "List secrets", [EventType.GET_SECRETS]: "List secrets",
[EventType.GET_SECRET]: "Read secret", [EventType.GET_SECRET]: "Read secret",
[EventType.CREATE_SECRET]: "Create secret", [EventType.CREATE_SECRET]: "Create secret",
[EventType.UPDATE_SECRET]: "Update secret", [EventType.UPDATE_SECRET]: "Update secret",
[EventType.DELETE_SECRET]: "Delete secret", [EventType.DELETE_SECRET]: "Delete secret",
[EventType.GET_WORKSPACE_KEY]: "Read project key", [EventType.GET_WORKSPACE_KEY]: "Read project key",
[EventType.AUTHORIZE_INTEGRATION]: "Authorize integration", [EventType.AUTHORIZE_INTEGRATION]: "Authorize integration",
[EventType.UNAUTHORIZE_INTEGRATION]: "Unauthorize integration", [EventType.UNAUTHORIZE_INTEGRATION]: "Unauthorize integration",
[EventType.CREATE_INTEGRATION]: "Create integration", [EventType.CREATE_INTEGRATION]: "Create integration",
[EventType.DELETE_INTEGRATION]: "Delete integration", [EventType.DELETE_INTEGRATION]: "Delete integration",
[EventType.ADD_TRUSTED_IP]: "Add trusted IP", [EventType.ADD_TRUSTED_IP]: "Add trusted IP",
[EventType.UPDATE_TRUSTED_IP]: "Update trusted IP", [EventType.UPDATE_TRUSTED_IP]: "Update trusted IP",
[EventType.DELETE_TRUSTED_IP]: "Delete trusted IP", [EventType.DELETE_TRUSTED_IP]: "Delete trusted IP",
[EventType.CREATE_SERVICE_TOKEN]: "Create service token", [EventType.CREATE_SERVICE_TOKEN]: "Create service token",
[EventType.DELETE_SERVICE_TOKEN]: "Delete service token", [EventType.DELETE_SERVICE_TOKEN]: "Delete service token",
[EventType.CREATE_IDENTITY]: "Create identity", [EventType.CREATE_IDENTITY]: "Create identity",
[EventType.UPDATE_IDENTITY]: "Update identity", [EventType.UPDATE_IDENTITY]: "Update identity",
[EventType.DELETE_IDENTITY]: "Delete identity", [EventType.DELETE_IDENTITY]: "Delete identity",
[EventType.LOGIN_IDENTITY_UNIVERSAL_AUTH]: "Login via universal auth", [EventType.LOGIN_IDENTITY_UNIVERSAL_AUTH]: "Login via universal auth",
[EventType.ADD_IDENTITY_UNIVERSAL_AUTH]: "Add universal auth", [EventType.ADD_IDENTITY_UNIVERSAL_AUTH]: "Add universal auth",
[EventType.UPDATE_IDENTITY_UNIVERSAL_AUTH]: "Update universal auth", [EventType.UPDATE_IDENTITY_UNIVERSAL_AUTH]: "Update universal auth",
[EventType.GET_IDENTITY_UNIVERSAL_AUTH]: "Get universal auth", [EventType.GET_IDENTITY_UNIVERSAL_AUTH]: "Get universal auth",
[EventType.CREATE_IDENTITY_UNIVERSAL_AUTH_CLIENT_SECRET]: "Create universal auth client secret", [EventType.CREATE_IDENTITY_UNIVERSAL_AUTH_CLIENT_SECRET]: "Create universal auth client secret",
[EventType.REVOKE_IDENTITY_UNIVERSAL_AUTH_CLIENT_SECRET]: "Revoke universal auth client secret", [EventType.REVOKE_IDENTITY_UNIVERSAL_AUTH_CLIENT_SECRET]: "Revoke universal auth client secret",
[EventType.GET_IDENTITY_UNIVERSAL_AUTH_CLIENT_SECRETS]: "Get universal auth client secrets", [EventType.GET_IDENTITY_UNIVERSAL_AUTH_CLIENT_SECRETS]: "Get universal auth client secrets",
[EventType.GET_IDENTITY_UNIVERSAL_AUTH]: "Get universal auth", [EventType.GET_IDENTITY_UNIVERSAL_AUTH]: "Get universal auth",
[EventType.CREATE_ENVIRONMENT]: "Create environment", [EventType.CREATE_ENVIRONMENT]: "Create environment",
[EventType.UPDATE_ENVIRONMENT]: "Update environment", [EventType.UPDATE_ENVIRONMENT]: "Update environment",
[EventType.DELETE_ENVIRONMENT]: "Delete environment", [EventType.DELETE_ENVIRONMENT]: "Delete environment",
[EventType.ADD_WORKSPACE_MEMBER]: "Add member", [EventType.ADD_WORKSPACE_MEMBER]: "Add member",
[EventType.REMOVE_WORKSPACE_MEMBER]: "Remove member", [EventType.REMOVE_WORKSPACE_MEMBER]: "Remove member",
[EventType.CREATE_FOLDER]: "Create folder", [EventType.CREATE_FOLDER]: "Create folder",
[EventType.UPDATE_FOLDER]: "Update folder", [EventType.UPDATE_FOLDER]: "Update folder",
[EventType.DELETE_FOLDER]: "Delete folder", [EventType.DELETE_FOLDER]: "Delete folder",
[EventType.CREATE_WEBHOOK]: "Create webhook", [EventType.CREATE_WEBHOOK]: "Create webhook",
[EventType.UPDATE_WEBHOOK_STATUS]: "Update webhook status", [EventType.UPDATE_WEBHOOK_STATUS]: "Update webhook status",
[EventType.DELETE_WEBHOOK]: "Delete webhook", [EventType.DELETE_WEBHOOK]: "Delete webhook",
[EventType.GET_SECRET_IMPORTS]: "List secret imports", [EventType.GET_SECRET_IMPORTS]: "List secret imports",
[EventType.CREATE_SECRET_IMPORT]: "Create secret import", [EventType.CREATE_SECRET_IMPORT]: "Create secret import",
[EventType.UPDATE_SECRET_IMPORT]: "Update secret import", [EventType.UPDATE_SECRET_IMPORT]: "Update secret import",
[EventType.DELETE_SECRET_IMPORT]: "Delete secret import", [EventType.DELETE_SECRET_IMPORT]: "Delete secret import",
[EventType.UPDATE_USER_WORKSPACE_DENIED_PERMISSIONS]: "Update denied permissions", [EventType.UPDATE_USER_WORKSPACE_DENIED_PERMISSIONS]: "Update denied permissions",
[EventType.UPDATE_USER_WORKSPACE_ROLE]: "Update user role" [EventType.UPDATE_USER_WORKSPACE_ROLE]: "Update user role"
}; };
export const userAgentTTypeoNameMap: { [K in UserAgentType]: string } = { export const userAgentTTypeoNameMap: { [K in UserAgentType]: string } = {
[UserAgentType.WEB]: "Web", [UserAgentType.WEB]: "Web",
[UserAgentType.CLI]: "CLI", [UserAgentType.CLI]: "CLI",
[UserAgentType.K8_OPERATOR]: "K8s operator", [UserAgentType.K8_OPERATOR]: "K8s operator",
[UserAgentType.TERRAFORM]: "Terraform", [UserAgentType.TERRAFORM]: "Terraform",
[UserAgentType.NODE_SDK]: "InfisicalNodeSDK", [UserAgentType.NODE_SDK]: "InfisicalNodeSDK",
[UserAgentType.PYTHON_SDK]: "InfisicalPythonSDK", [UserAgentType.PYTHON_SDK]: "InfisicalPythonSDK",
[UserAgentType.OTHER]: "Other", [UserAgentType.OTHER]: "Other"
}; };
+1 -1
View File
@@ -38,7 +38,7 @@ export enum EventType {
UPDATE_IDENTITY_UNIVERSAL_AUTH = "update-identity-universal-auth", UPDATE_IDENTITY_UNIVERSAL_AUTH = "update-identity-universal-auth",
GET_IDENTITY_UNIVERSAL_AUTH = "get-identity-universal-auth", GET_IDENTITY_UNIVERSAL_AUTH = "get-identity-universal-auth",
CREATE_IDENTITY_UNIVERSAL_AUTH_CLIENT_SECRET = "create-identity-universal-auth-client-secret", CREATE_IDENTITY_UNIVERSAL_AUTH_CLIENT_SECRET = "create-identity-universal-auth-client-secret",
REVOKE_IDENTITY_UNIVERSAL_AUTH_CLIENT_SECRET = "revoke-identity-universal-auth-client-secret", REVOKE_IDENTITY_UNIVERSAL_AUTH_CLIENT_SECRET = "revoke-identity-universal-auth-client-secret",
GET_IDENTITY_UNIVERSAL_AUTH_CLIENT_SECRETS = "get-identity-universal-auth-client-secret", GET_IDENTITY_UNIVERSAL_AUTH_CLIENT_SECRETS = "get-identity-universal-auth-client-secret",
CREATE_ENVIRONMENT = "create-environment", CREATE_ENVIRONMENT = "create-environment",
UPDATE_ENVIRONMENT = "update-environment", UPDATE_ENVIRONMENT = "update-environment",
+18 -18
View File
@@ -4,12 +4,12 @@ export type GetAuthTokenAPI = {
export type SendMfaTokenDTO = { export type SendMfaTokenDTO = {
email: string; email: string;
} };
export type VerifyMfaTokenDTO = { export type VerifyMfaTokenDTO = {
email: string; email: string;
mfaCode: string; mfaCode: string;
} };
export type VerifyMfaTokenRes = { export type VerifyMfaTokenRes = {
encryptionVersion: number; encryptionVersion: number;
@@ -21,24 +21,24 @@ export type VerifyMfaTokenRes = {
encryptedPrivateKey: string; encryptedPrivateKey: string;
iv: string; iv: string;
tag: string; tag: string;
} };
export type Login1DTO = { export type Login1DTO = {
email: string; email: string;
clientPublicKey: string; clientPublicKey: string;
providerAuthToken?: string; providerAuthToken?: string;
} };
export type Login2DTO = { export type Login2DTO = {
email: string; email: string;
clientProof: string; clientProof: string;
providerAuthToken?: string; providerAuthToken?: string;
} };
export type Login1Res = { export type Login1Res = {
serverPublicKey: string; serverPublicKey: string;
salt: string; salt: string;
} };
export type Login2Res = { export type Login2Res = {
mfaEnabled: boolean; mfaEnabled: boolean;
@@ -51,26 +51,26 @@ export type Login2Res = {
encryptedPrivateKey?: string; encryptedPrivateKey?: string;
iv?: string; iv?: string;
tag?: string; tag?: string;
} };
export type LoginLDAPDTO = { export type LoginLDAPDTO = {
organizationSlug: string; organizationSlug: string;
username: string; username: string;
password: string; password: string;
} };
export type LoginLDAPRes = { export type LoginLDAPRes = {
nextUrl: string; nextUrl: string;
} };
export type SRP1DTO = { export type SRP1DTO = {
clientPublicKey: string; clientPublicKey: string;
} };
export type SRPR1Res = { export type SRPR1Res = {
serverPublicKey: string; serverPublicKey: string;
salt: string; salt: string;
} };
export type CompleteAccountDTO = { export type CompleteAccountDTO = {
email: string; email: string;
@@ -85,19 +85,19 @@ export type CompleteAccountDTO = {
encryptedPrivateKeyTag: string; encryptedPrivateKeyTag: string;
salt: string; salt: string;
verifier: string; verifier: string;
} };
export type CompleteAccountSignupDTO = CompleteAccountDTO & { export type CompleteAccountSignupDTO = CompleteAccountDTO & {
providerAuthToken?: string; providerAuthToken?: string;
attributionSource?: string; attributionSource?: string;
organizationName: string; organizationName: string;
} };
export type VerifySignupInviteDTO = { export type VerifySignupInviteDTO = {
email: string; email: string;
code: string; code: string;
organizationId: string; organizationId: string;
} };
export type ChangePasswordDTO = { export type ChangePasswordDTO = {
clientProof: string; clientProof: string;
@@ -109,7 +109,7 @@ export type ChangePasswordDTO = {
encryptedPrivateKeyTag: string; encryptedPrivateKeyTag: string;
salt: string; salt: string;
verifier: string; verifier: string;
} };
export type ResetPasswordDTO = { export type ResetPasswordDTO = {
protectedKey: string; protectedKey: string;
@@ -121,7 +121,7 @@ export type ResetPasswordDTO = {
salt: string; salt: string;
verifier: string; verifier: string;
verificationToken: string; verificationToken: string;
} };
export type IssueBackupPrivateKeyDTO = { export type IssueBackupPrivateKeyDTO = {
encryptedPrivateKey: string; encryptedPrivateKey: string;
@@ -130,8 +130,8 @@ export type IssueBackupPrivateKeyDTO = {
salt: string; salt: string;
verifier: string; verifier: string;
clientProof: string; clientProof: string;
} };
export type GetBackupEncryptedPrivateKeyDTO = { export type GetBackupEncryptedPrivateKeyDTO = {
verificationToken: string; verificationToken: string;
} };
+3 -1
View File
@@ -12,7 +12,9 @@ export const useGetWorkspaceBot = (workspaceId: string) =>
useQuery({ useQuery({
queryKey: queryKeys.getBot(workspaceId), queryKey: queryKeys.getBot(workspaceId),
queryFn: async () => { queryFn: async () => {
const { data: { bot } } = await apiRequest.get<{ bot: TBot }>(`/api/v1/bot/${workspaceId}`); const {
data: { bot }
} = await apiRequest.get<{ bot: TBot }>(`/api/v1/bot/${workspaceId}`);
return bot; return bot;
}, },
enabled: Boolean(workspaceId) enabled: Boolean(workspaceId)
@@ -1,5 +1,5 @@
import { IdentityAuthMethod } from "./enums"; import { IdentityAuthMethod } from "./enums";
export const identityAuthToNameMap: { [I in IdentityAuthMethod]: string } = { export const identityAuthToNameMap: { [I in IdentityAuthMethod]: string } = {
[IdentityAuthMethod.UNIVERSAL_AUTH]: "Universal Auth" [IdentityAuthMethod.UNIVERSAL_AUTH]: "Universal Auth"
}; };
+9 -11
View File
@@ -1,14 +1,12 @@
export { identityAuthToNameMap } from "./constants"; export { identityAuthToNameMap } from "./constants";
export { IdentityAuthMethod } from "./enums"; export { IdentityAuthMethod } from "./enums";
export { export {
useAddIdentityUniversalAuth, useAddIdentityUniversalAuth,
useCreateIdentity, useCreateIdentity,
useCreateIdentityUniversalAuthClientSecret, useCreateIdentityUniversalAuthClientSecret,
useDeleteIdentity, useDeleteIdentity,
useRevokeIdentityUniversalAuthClientSecret, useRevokeIdentityUniversalAuthClientSecret,
useUpdateIdentity, useUpdateIdentity,
useUpdateIdentityUniversalAuth} from "./mutations"; useUpdateIdentityUniversalAuth
export { } from "./mutations";
useGetIdentityUniversalAuth, export { useGetIdentityUniversalAuth, useGetIdentityUniversalAuthClientSecrets } from "./queries";
useGetIdentityUniversalAuthClientSecrets
} from "./queries";
+140 -133
View File
@@ -5,160 +5,167 @@ import { apiRequest } from "@app/config/request";
import { organizationKeys } from "../organization/queries"; import { organizationKeys } from "../organization/queries";
import { identitiesKeys } from "./queries"; import { identitiesKeys } from "./queries";
import { import {
AddIdentityUniversalAuthDTO, AddIdentityUniversalAuthDTO,
ClientSecretData, ClientSecretData,
CreateIdentityDTO, CreateIdentityDTO,
CreateIdentityUniversalAuthClientSecretDTO, CreateIdentityUniversalAuthClientSecretDTO,
CreateIdentityUniversalAuthClientSecretRes, CreateIdentityUniversalAuthClientSecretRes,
DeleteIdentityDTO, DeleteIdentityDTO,
DeleteIdentityUniversalAuthClientSecretDTO, DeleteIdentityUniversalAuthClientSecretDTO,
Identity, Identity,
IdentityUniversalAuth, IdentityUniversalAuth,
UpdateIdentityDTO, UpdateIdentityDTO,
UpdateIdentityUniversalAuthDTO} from "./types"; UpdateIdentityUniversalAuthDTO
} from "./types";
export const useCreateIdentity = () => { export const useCreateIdentity = () => {
const queryClient = useQueryClient(); const queryClient = useQueryClient();
return useMutation<Identity, {}, CreateIdentityDTO>({ return useMutation<Identity, {}, CreateIdentityDTO>({
mutationFn: async (body) => { mutationFn: async (body) => {
const { data: { identity } } = await apiRequest.post("/api/v1/identities/", body); const {
return identity; data: { identity }
}, } = await apiRequest.post("/api/v1/identities/", body);
onSuccess: (_, { organizationId }) => { return identity;
queryClient.invalidateQueries(organizationKeys.getOrgIdentityMemberships(organizationId)); },
} onSuccess: (_, { organizationId }) => {
}); queryClient.invalidateQueries(organizationKeys.getOrgIdentityMemberships(organizationId));
}
});
}; };
export const useUpdateIdentity = () => { export const useUpdateIdentity = () => {
const queryClient = useQueryClient(); const queryClient = useQueryClient();
return useMutation<Identity, {}, UpdateIdentityDTO>({ return useMutation<Identity, {}, UpdateIdentityDTO>({
mutationFn: async ({ mutationFn: async ({ identityId, name, role }) => {
identityId, const {
name, data: { identity }
role } = await apiRequest.patch(`/api/v1/identities/${identityId}`, {
}) => { name,
role
});
const { data: { identity } } = await apiRequest.patch(`/api/v1/identities/${identityId}`, { return identity;
name, },
role onSuccess: (_, { organizationId }) => {
}); queryClient.invalidateQueries(organizationKeys.getOrgIdentityMemberships(organizationId));
}
return identity; });
}, };
onSuccess: (_, { organizationId }) => {
queryClient.invalidateQueries(organizationKeys.getOrgIdentityMemberships(organizationId));
}
});
}
export const useDeleteIdentity = () => { export const useDeleteIdentity = () => {
const queryClient = useQueryClient(); const queryClient = useQueryClient();
return useMutation<Identity, {}, DeleteIdentityDTO>({ return useMutation<Identity, {}, DeleteIdentityDTO>({
mutationFn: async ({ mutationFn: async ({ identityId }) => {
identityId, const {
}) => { data: { identity }
const { data: { identity } } = await apiRequest.delete(`/api/v1/identities/${identityId}`); } = await apiRequest.delete(`/api/v1/identities/${identityId}`);
return identity; return identity;
}, },
onSuccess: (_, { organizationId }) => { onSuccess: (_, { organizationId }) => {
queryClient.invalidateQueries(organizationKeys.getOrgIdentityMemberships(organizationId)); queryClient.invalidateQueries(organizationKeys.getOrgIdentityMemberships(organizationId));
} }
}); });
}; };
// TODO: move these to /auth // TODO: move these to /auth
export const useAddIdentityUniversalAuth = () => { export const useAddIdentityUniversalAuth = () => {
const queryClient = useQueryClient(); const queryClient = useQueryClient();
return useMutation<IdentityUniversalAuth, {}, AddIdentityUniversalAuthDTO>({ return useMutation<IdentityUniversalAuth, {}, AddIdentityUniversalAuthDTO>({
mutationFn: async ({ mutationFn: async ({
identityId, identityId,
clientSecretTrustedIps, clientSecretTrustedIps,
accessTokenTTL, accessTokenTTL,
accessTokenMaxTTL, accessTokenMaxTTL,
accessTokenNumUsesLimit, accessTokenNumUsesLimit,
accessTokenTrustedIps, accessTokenTrustedIps
}) => { }) => {
const { data: { identityUniversalAuth } } = await apiRequest.post(`/api/v1/auth/universal-auth/identities/${identityId}`, const {
{ data: { identityUniversalAuth }
clientSecretTrustedIps, } = await apiRequest.post(`/api/v1/auth/universal-auth/identities/${identityId}`, {
accessTokenTTL, clientSecretTrustedIps,
accessTokenMaxTTL, accessTokenTTL,
accessTokenNumUsesLimit, accessTokenMaxTTL,
accessTokenTrustedIps, accessTokenNumUsesLimit,
} accessTokenTrustedIps
); });
return identityUniversalAuth; return identityUniversalAuth;
}, },
onSuccess: (_, { organizationId }) => { onSuccess: (_, { organizationId }) => {
queryClient.invalidateQueries(organizationKeys.getOrgIdentityMemberships(organizationId)); queryClient.invalidateQueries(organizationKeys.getOrgIdentityMemberships(organizationId));
} }
}); });
}; };
export const useUpdateIdentityUniversalAuth = () => { export const useUpdateIdentityUniversalAuth = () => {
const queryClient = useQueryClient(); const queryClient = useQueryClient();
return useMutation<IdentityUniversalAuth, {}, UpdateIdentityUniversalAuthDTO>({ return useMutation<IdentityUniversalAuth, {}, UpdateIdentityUniversalAuthDTO>({
mutationFn: async ({ mutationFn: async ({
identityId, identityId,
clientSecretTrustedIps, clientSecretTrustedIps,
accessTokenTTL, accessTokenTTL,
accessTokenMaxTTL, accessTokenMaxTTL,
accessTokenNumUsesLimit, accessTokenNumUsesLimit,
accessTokenTrustedIps, accessTokenTrustedIps
}) => { }) => {
const { data: { identityUniversalAuth } } = await apiRequest.patch(`/api/v1/auth/universal-auth/identities/${identityId}`, const {
{ data: { identityUniversalAuth }
clientSecretTrustedIps, } = await apiRequest.patch(`/api/v1/auth/universal-auth/identities/${identityId}`, {
accessTokenTTL, clientSecretTrustedIps,
accessTokenMaxTTL, accessTokenTTL,
accessTokenNumUsesLimit, accessTokenMaxTTL,
accessTokenTrustedIps, accessTokenNumUsesLimit,
} accessTokenTrustedIps
); });
return identityUniversalAuth; return identityUniversalAuth;
}, },
onSuccess: (_, { organizationId }) => { onSuccess: (_, { organizationId }) => {
queryClient.invalidateQueries(organizationKeys.getOrgIdentityMemberships(organizationId)); queryClient.invalidateQueries(organizationKeys.getOrgIdentityMemberships(organizationId));
} }
}); });
}; };
export const useCreateIdentityUniversalAuthClientSecret = () => { export const useCreateIdentityUniversalAuthClientSecret = () => {
const queryClient = useQueryClient(); const queryClient = useQueryClient();
return useMutation<CreateIdentityUniversalAuthClientSecretRes, {}, CreateIdentityUniversalAuthClientSecretDTO>({ return useMutation<
mutationFn: async ({ CreateIdentityUniversalAuthClientSecretRes,
identityId, {},
description, CreateIdentityUniversalAuthClientSecretDTO
ttl, >({
numUsesLimit mutationFn: async ({ identityId, description, ttl, numUsesLimit }) => {
}) => { const { data } = await apiRequest.post(
const { data } = await apiRequest.post(`/api/v1/auth/universal-auth/identities/${identityId}/client-secrets`, { `/api/v1/auth/universal-auth/identities/${identityId}/client-secrets`,
description, {
ttl, description,
numUsesLimit ttl,
}); numUsesLimit
return data;
},
onSuccess: (_, { identityId }) => {
queryClient.invalidateQueries(identitiesKeys.getIdentityUniversalAuthClientSecrets(identityId));
} }
}); );
return data;
},
onSuccess: (_, { identityId }) => {
queryClient.invalidateQueries(
identitiesKeys.getIdentityUniversalAuthClientSecrets(identityId)
);
}
});
}; };
export const useRevokeIdentityUniversalAuthClientSecret = () => { export const useRevokeIdentityUniversalAuthClientSecret = () => {
const queryClient = useQueryClient(); const queryClient = useQueryClient();
return useMutation<ClientSecretData, {}, DeleteIdentityUniversalAuthClientSecretDTO>({ return useMutation<ClientSecretData, {}, DeleteIdentityUniversalAuthClientSecretDTO>({
mutationFn: async ({ mutationFn: async ({ identityId, clientSecretId }) => {
identityId, const {
clientSecretId data: { clientSecretData }
}) => { } = await apiRequest.post<{ clientSecretData: ClientSecretData }>(
const { data: { clientSecretData } } = await apiRequest.post<{ clientSecretData: ClientSecretData }>(`/api/v1/auth/universal-auth/identities/${identityId}/client-secrets/${clientSecretId}/revoke`); `/api/v1/auth/universal-auth/identities/${identityId}/client-secrets/${clientSecretId}/revoke`
return clientSecretData; );
}, return clientSecretData;
onSuccess: (_, { identityId }) => { },
queryClient.invalidateQueries(identitiesKeys.getIdentityUniversalAuthClientSecrets(identityId)); onSuccess: (_, { identityId }) => {
} queryClient.invalidateQueries(
}); identitiesKeys.getIdentityUniversalAuthClientSecrets(identityId)
);
}
});
}; };
+32 -26
View File
@@ -2,39 +2,45 @@ import { useQuery } from "@tanstack/react-query";
import { apiRequest } from "@app/config/request"; import { apiRequest } from "@app/config/request";
import { ClientSecretData , IdentityUniversalAuth } from "./types"; import { ClientSecretData, IdentityUniversalAuth } from "./types";
export const identitiesKeys = { export const identitiesKeys = {
getIdentityUniversalAuth: (identityId: string) => [{ identityId }, "identity-universal-auth"] as const, getIdentityUniversalAuth: (identityId: string) =>
getIdentityUniversalAuthClientSecrets: (identityId: string) => [{ identityId }, "identity-universal-auth-client-secrets"] as const [{ identityId }, "identity-universal-auth"] as const,
} getIdentityUniversalAuthClientSecrets: (identityId: string) =>
[{ identityId }, "identity-universal-auth-client-secrets"] as const
};
export const useGetIdentityUniversalAuth = (identityId: string) => { export const useGetIdentityUniversalAuth = (identityId: string) => {
return useQuery({ return useQuery({
queryKey: identitiesKeys.getIdentityUniversalAuth(identityId), queryKey: identitiesKeys.getIdentityUniversalAuth(identityId),
queryFn: async () => { queryFn: async () => {
if (identityId === "") throw new Error("Identity ID is required"); if (identityId === "") throw new Error("Identity ID is required");
const { data: { identityUniversalAuth } } = await apiRequest.get<{ identityUniversalAuth: IdentityUniversalAuth }>( const {
`/api/v1/auth/universal-auth/identities/${identityId}` data: { identityUniversalAuth }
); } = await apiRequest.get<{ identityUniversalAuth: IdentityUniversalAuth }>(
`/api/v1/auth/universal-auth/identities/${identityId}`
);
return identityUniversalAuth; return identityUniversalAuth;
} }
}); });
} };
export const useGetIdentityUniversalAuthClientSecrets = (identityId: string) => { export const useGetIdentityUniversalAuthClientSecrets = (identityId: string) => {
return useQuery({ return useQuery({
queryKey: identitiesKeys.getIdentityUniversalAuthClientSecrets(identityId), queryKey: identitiesKeys.getIdentityUniversalAuthClientSecrets(identityId),
queryFn: async () => { queryFn: async () => {
if (identityId === "") return []; if (identityId === "") return [];
const { data: { clientSecretData } } = await apiRequest.get<{ clientSecretData: ClientSecretData[] }>( const {
`/api/v1/auth/universal-auth/identities/${identityId}/client-secrets` data: { clientSecretData }
); } = await apiRequest.get<{ clientSecretData: ClientSecretData[] }>(
`/api/v1/auth/universal-auth/identities/${identityId}/client-secrets`
);
return clientSecretData; return clientSecretData;
} }
}); });
} };
+1 -1
View File
@@ -1,4 +1,4 @@
export * from "./admin" export * from "./admin";
export * from "./apiKeys"; export * from "./apiKeys";
export * from "./auditLogs"; export * from "./auditLogs";
export * from "./auth"; export * from "./auth";
@@ -68,8 +68,8 @@ const integrationAuthKeys = {
environmentId: string; environmentId: string;
scope: "job" | "application" | "container"; scope: "job" | "application" | "container";
}) => [{ integrationAuthId, environmentId, scope }, "integrationAuthQoveryScopes"] as const, }) => [{ integrationAuthId, environmentId, scope }, "integrationAuthQoveryScopes"] as const,
getIntegrationAuthHerokuPipelines: ({ integrationAuthId }: { integrationAuthId: string; }) => getIntegrationAuthHerokuPipelines: ({ integrationAuthId }: { integrationAuthId: string }) =>
[{ integrationAuthId}, "integrationAuthHerokuPipelines"] as const, [{ integrationAuthId }, "integrationAuthHerokuPipelines"] as const,
getIntegrationAuthRailwayEnvironments: ({ getIntegrationAuthRailwayEnvironments: ({
integrationAuthId, integrationAuthId,
appId appId
@@ -322,7 +322,9 @@ const fetchIntegrationAuthQoveryScopes = async ({
return undefined; return undefined;
}; };
const fetchIntegrationAuthHerokuPipelines = async ({ integrationAuthId }: { const fetchIntegrationAuthHerokuPipelines = async ({
integrationAuthId
}: {
integrationAuthId: string; integrationAuthId: string;
}) => { }) => {
const { const {
@@ -1,5 +1 @@
export { export { useCreateIntegration, useDeleteIntegration, useGetCloudIntegrations } from "./queries";
useCreateIntegration,
useDeleteIntegration,
useGetCloudIntegrations
} from "./queries";
@@ -63,9 +63,11 @@ export const useCreateIntegration = () => {
secretSuffix?: string; secretSuffix?: string;
initialSyncBehavior?: string; initialSyncBehavior?: string;
shouldAutoRedeploy?: boolean; shouldAutoRedeploy?: boolean;
} };
}) => { }) => {
const { data: { integration } } = await apiRequest.post("/api/v1/integration", { const {
data: { integration }
} = await apiRequest.post("/api/v1/integration", {
integrationAuthId, integrationAuthId,
isActive, isActive,
app, app,
+1 -5
View File
@@ -1,5 +1 @@
export { export { useCreateLDAPConfig, useGetLDAPConfig, useUpdateLDAPConfig } from "./queries";
useCreateLDAPConfig,
useGetLDAPConfig,
useUpdateLDAPConfig
} from "./queries";
+40 -48
View File
@@ -3,27 +3,42 @@ import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { apiRequest } from "@app/config/request"; import { apiRequest } from "@app/config/request";
const ldapConfigKeys = { const ldapConfigKeys = {
getLDAPConfig: (orgId: string) => [{ orgId }, "organization-ldap"] as const, getLDAPConfig: (orgId: string) => [{ orgId }, "organization-ldap"] as const
} };
export const useGetLDAPConfig = (organizationId: string) => { export const useGetLDAPConfig = (organizationId: string) => {
return useQuery({ return useQuery({
queryKey: ldapConfigKeys.getLDAPConfig(organizationId), queryKey: ldapConfigKeys.getLDAPConfig(organizationId),
queryFn: async () => { queryFn: async () => {
const { data } = await apiRequest.get( const { data } = await apiRequest.get(`/api/v1/ldap/config?organizationId=${organizationId}`);
`/api/v1/ldap/config?organizationId=${organizationId}`
);
return data; return data;
}, },
enabled: true enabled: true
}); });
} };
export const useCreateLDAPConfig = () => { export const useCreateLDAPConfig = () => {
const queryClient = useQueryClient(); const queryClient = useQueryClient();
return useMutation({ return useMutation({
mutationFn: async ({ mutationFn: async ({
organizationId,
isActive,
url,
bindDN,
bindPass,
searchBase,
caCert
}: {
organizationId: string;
isActive: boolean;
url: string;
bindDN: string;
bindPass: string;
searchBase: string;
caCert?: string;
}) => {
const { data } = await apiRequest.post("/api/v1/ldap/config", {
organizationId, organizationId,
isActive, isActive,
url, url,
@@ -31,27 +46,7 @@ export const useCreateLDAPConfig = () => {
bindPass, bindPass,
searchBase, searchBase,
caCert caCert
}: { });
organizationId: string;
isActive: boolean;
url: string;
bindDN: string;
bindPass: string;
searchBase: string;
caCert?: string;
}) => {
const { data } = await apiRequest.post(
"/api/v1/ldap/config",
{
organizationId,
isActive,
url,
bindDN,
bindPass,
searchBase,
caCert
}
);
return data; return data;
}, },
@@ -65,6 +60,23 @@ export const useUpdateLDAPConfig = () => {
const queryClient = useQueryClient(); const queryClient = useQueryClient();
return useMutation({ return useMutation({
mutationFn: async ({ mutationFn: async ({
organizationId,
isActive,
url,
bindDN,
bindPass,
searchBase,
caCert
}: {
organizationId: string;
isActive?: boolean;
url?: string;
bindDN?: string;
bindPass?: string;
searchBase?: string;
caCert?: string;
}) => {
const { data } = await apiRequest.patch("/api/v1/ldap/config", {
organizationId, organizationId,
isActive, isActive,
url, url,
@@ -72,27 +84,7 @@ export const useUpdateLDAPConfig = () => {
bindPass, bindPass,
searchBase, searchBase,
caCert caCert
}: { });
organizationId: string;
isActive?: boolean;
url?: string;
bindDN?: string;
bindPass?: string;
searchBase?: string;
caCert?: string;
}) => {
const { data } = await apiRequest.patch(
"/api/v1/ldap/config",
{
organizationId,
isActive,
url,
bindDN,
bindPass,
searchBase,
caCert
}
);
return data; return data;
}, },
+20 -20
View File
@@ -1,22 +1,22 @@
export { export {
useAddOrgPmtMethod, useAddOrgPmtMethod,
useAddOrgTaxId, useAddOrgTaxId,
useCreateCustomerPortalSession, useCreateCustomerPortalSession,
useCreateOrg, useCreateOrg,
useDeleteOrgById, useDeleteOrgById,
useDeleteOrgPmtMethod, useDeleteOrgPmtMethod,
useDeleteOrgTaxId, useDeleteOrgTaxId,
useGetIdentityMembershipOrgs, useGetIdentityMembershipOrgs,
useGetOrganizations, useGetOrganizations,
useGetOrgBillingDetails, useGetOrgBillingDetails,
useGetOrgInvoices, useGetOrgInvoices,
useGetOrgLicenses, useGetOrgLicenses,
useGetOrgPlanBillingInfo, useGetOrgPlanBillingInfo,
useGetOrgPlansTable, useGetOrgPlansTable,
useGetOrgPlanTable, useGetOrgPlanTable,
useGetOrgPmtMethods, useGetOrgPmtMethods,
useGetOrgTaxIds, useGetOrgTaxIds,
useGetOrgTrialUrl, useGetOrgTrialUrl,
useUpdateOrg, useUpdateOrg,
useUpdateOrgBillingDetails useUpdateOrgBillingDetails
} from "./queries"; } from "./queries";
+1 -4
View File
@@ -1,5 +1,2 @@
export { export { useCreateScimToken, useDeleteScimToken } from "./mutations";
useCreateScimToken,
useDeleteScimToken
} from "./mutations";
export { useGetScimTokens } from "./queries"; export { useGetScimTokens } from "./queries";
+25 -33
View File
@@ -3,43 +3,35 @@ import { useMutation, useQueryClient } from "@tanstack/react-query";
import { apiRequest } from "@app/config/request"; import { apiRequest } from "@app/config/request";
import { scimKeys } from "./queries"; import { scimKeys } from "./queries";
import { import { CreateScimTokenDTO, CreateScimTokenRes, DeleteScimTokenDTO } from "./types";
CreateScimTokenDTO,
CreateScimTokenRes,
DeleteScimTokenDTO
} from "./types";
export const useCreateScimToken = () => { export const useCreateScimToken = () => {
const queryClient = useQueryClient(); const queryClient = useQueryClient();
return useMutation<CreateScimTokenRes, {}, CreateScimTokenDTO>({ return useMutation<CreateScimTokenRes, {}, CreateScimTokenDTO>({
mutationFn: async ({ mutationFn: async ({ organizationId, description, ttlDays }) => {
organizationId, const { data } = await apiRequest.post("/api/v1/scim/scim-tokens", {
description, organizationId,
ttlDays description,
}) => { ttlDays
const { data } = await apiRequest.post("/api/v1/scim/scim-tokens", { });
organizationId,
description,
ttlDays
});
return data; return data;
}, },
onSuccess: (_, { organizationId }) => { onSuccess: (_, { organizationId }) => {
queryClient.invalidateQueries(scimKeys.getScimTokens(organizationId)); queryClient.invalidateQueries(scimKeys.getScimTokens(organizationId));
} }
}); });
}; };
export const useDeleteScimToken = () => { export const useDeleteScimToken = () => {
const queryClient = useQueryClient(); const queryClient = useQueryClient();
return useMutation<CreateScimTokenRes, {}, DeleteScimTokenDTO>({ return useMutation<CreateScimTokenRes, {}, DeleteScimTokenDTO>({
mutationFn: async ({ scimTokenId }) => { mutationFn: async ({ scimTokenId }) => {
const { data } = await apiRequest.delete(`/api/v1/scim/scim-tokens/${scimTokenId}`); const { data } = await apiRequest.delete(`/api/v1/scim/scim-tokens/${scimTokenId}`);
return data; return data;
}, },
onSuccess: (_, { organizationId }) => { onSuccess: (_, { organizationId }) => {
queryClient.invalidateQueries(scimKeys.getScimTokens(organizationId)); queryClient.invalidateQueries(scimKeys.getScimTokens(organizationId));
} }
}); });
}; };
+16 -12
View File
@@ -5,21 +5,25 @@ import { apiRequest } from "@app/config/request";
import { ScimTokenData } from "./types"; import { ScimTokenData } from "./types";
export const scimKeys = { export const scimKeys = {
getScimTokens: (orgId: string) => [{ orgId }, "organization-scim-token"] as const, getScimTokens: (orgId: string) => [{ orgId }, "organization-scim-token"] as const
}; };
export const useGetScimTokens = (organizationId: string) => { export const useGetScimTokens = (organizationId: string) => {
return useQuery({ return useQuery({
queryKey: scimKeys.getScimTokens(organizationId), queryKey: scimKeys.getScimTokens(organizationId),
queryFn: async () => { queryFn: async () => {
if (organizationId === "") { if (organizationId === "") {
return undefined; return undefined;
} }
const { data: { scimTokens } } = await apiRequest.get<{ scimTokens: ScimTokenData[] }>(`/api/v1/scim/scim-tokens?organizationId=${organizationId}`); const {
data: { scimTokens }
} = await apiRequest.get<{ scimTokens: ScimTokenData[] }>(
`/api/v1/scim/scim-tokens?organizationId=${organizationId}`
);
return scimTokens; return scimTokens;
}, },
enabled: true enabled: true
}); });
}; };
+16 -16
View File
@@ -1,24 +1,24 @@
export type ScimTokenData = { export type ScimTokenData = {
id: string; id: string;
ttlDays: number; ttlDays: number;
description: string; description: string;
tokenSuffix: string; tokenSuffix: string;
orgId: string; orgId: string;
createdAt: string; createdAt: string;
updatedAt: string; updatedAt: string;
}; };
export type CreateScimTokenDTO = { export type CreateScimTokenDTO = {
organizationId: string; organizationId: string;
description?: string; description?: string;
ttlDays?: number; ttlDays?: number;
} };
export type DeleteScimTokenDTO = { export type DeleteScimTokenDTO = {
organizationId: string; organizationId: string;
scimTokenId: string; scimTokenId: string;
} };
export type CreateScimTokenRes = { export type CreateScimTokenRes = {
scimToken: string; scimToken: string;
} };
@@ -1 +1 @@
export { useFetchServerStatus } from "./queries" export { useFetchServerStatus } from "./queries";
@@ -1,4 +1,4 @@
import {useQuery } from "@tanstack/react-query"; import { useQuery } from "@tanstack/react-query";
import { apiRequest } from "@app/config/request"; import { apiRequest } from "@app/config/request";
@@ -10,10 +10,10 @@ const serverStatusKeys = {
}; };
const fetchServerStatus = async () => { const fetchServerStatus = async () => {
const {data} = await apiRequest.get<ServerStatus>("/api/status"); const { data } = await apiRequest.get<ServerStatus>("/api/status");
return data; return data;
}; };
export const useFetchServerStatus= () => { export const useFetchServerStatus = () => {
return useQuery({ queryKey: serverStatusKeys.serverStatus, queryFn: fetchServerStatus }); return useQuery({ queryKey: serverStatusKeys.serverStatus, queryFn: fetchServerStatus });
} };
@@ -2,6 +2,6 @@ export type ServerStatus = {
date: string; date: string;
message: string; message: string;
emailConfigured: boolean; emailConfigured: boolean;
secretScanningConfigured: boolean secretScanningConfigured: boolean;
redisConfigured: boolean redisConfigured: boolean;
}; };
@@ -1,4 +1,4 @@
export enum Permission { export enum Permission {
READ = "read", READ = "read",
WRITE = "write" WRITE = "write"
} }
@@ -1,5 +1 @@
export { export { useCreateServiceToken, useDeleteServiceToken, useGetUserWsServiceTokens } from "./queries";
useCreateServiceToken,
useDeleteServiceToken,
useGetUserWsServiceTokens,
} from "./queries";
+1 -5
View File
@@ -1,5 +1 @@
export { export { useCreateSSOConfig, useGetSSOConfig, useUpdateSSOConfig } from "./queries";
useCreateSSOConfig,
useGetSSOConfig,
useUpdateSSOConfig
} from "./queries";
+5 -4
View File
@@ -1,5 +1,6 @@
export { export {
useAddTrustedIp, useAddTrustedIp,
useDeleteTrustedIp, useDeleteTrustedIp,
useGetTrustedIps, useGetTrustedIps,
useUpdateTrustedIp} from "./queries"; useUpdateTrustedIp
} from "./queries";
+84 -87
View File
@@ -2,107 +2,104 @@ import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { apiRequest } from "@app/config/request"; import { apiRequest } from "@app/config/request";
import { import { TrustedIp } from "./types";
TrustedIp
} from "./types";
const trustedIps = { const trustedIps = {
getTrustedIps: (workspaceId: string) => [{ workspaceId }, "trusted-ips"] as const getTrustedIps: (workspaceId: string) => [{ workspaceId }, "trusted-ips"] as const
} };
export const useGetTrustedIps = (workspaceId: string) => { export const useGetTrustedIps = (workspaceId: string) => {
return useQuery({ return useQuery({
queryKey: trustedIps.getTrustedIps(workspaceId), queryKey: trustedIps.getTrustedIps(workspaceId),
queryFn: async () => { queryFn: async () => {
const { data } = await apiRequest.get<{ trustedIps: TrustedIp[] }>(`/api/v1/workspace/${workspaceId}/trusted-ips`); const { data } = await apiRequest.get<{ trustedIps: TrustedIp[] }>(
`/api/v1/workspace/${workspaceId}/trusted-ips`
);
return data.trustedIps; return data.trustedIps;
} }
}); });
} };
export const useAddTrustedIp = () => { export const useAddTrustedIp = () => {
const queryClient = useQueryClient(); const queryClient = useQueryClient();
return useMutation({ return useMutation({
mutationFn: async ({ mutationFn: async ({
workspaceId, workspaceId,
ipAddress, ipAddress,
comment, comment,
isActive isActive
}: { }: {
workspaceId: string; workspaceId: string;
ipAddress: string; ipAddress: string;
comment?: string; comment?: string;
isActive: boolean; isActive: boolean;
}) => { }) => {
const { data } = await apiRequest.post( const { data } = await apiRequest.post(`/api/v1/workspace/${workspaceId}/trusted-ips`, {
`/api/v1/workspace/${workspaceId}/trusted-ips`, ipAddress,
{ ...(comment ? { comment } : {}),
ipAddress, isActive
...(comment ? { comment } : {}), });
isActive
}
);
return data; return data;
}, },
onSuccess(_, dto) { onSuccess(_, dto) {
queryClient.invalidateQueries(trustedIps.getTrustedIps(dto.workspaceId)); queryClient.invalidateQueries(trustedIps.getTrustedIps(dto.workspaceId));
} }
}); });
}; };
export const useUpdateTrustedIp = () => { export const useUpdateTrustedIp = () => {
const queryClient = useQueryClient(); const queryClient = useQueryClient();
return useMutation({ return useMutation({
mutationFn: async ({ mutationFn: async ({
workspaceId, workspaceId,
trustedIpId, trustedIpId,
ipAddress, ipAddress,
comment, comment,
isActive isActive
}: { }: {
workspaceId: string; workspaceId: string;
trustedIpId: string; trustedIpId: string;
ipAddress: string; ipAddress: string;
comment?: string; comment?: string;
isActive: boolean; isActive: boolean;
}) => { }) => {
const { data } = await apiRequest.patch( const { data } = await apiRequest.patch(
`/api/v1/workspace/${workspaceId}/trusted-ips/${trustedIpId}`, `/api/v1/workspace/${workspaceId}/trusted-ips/${trustedIpId}`,
{ {
ipAddress, ipAddress,
...(comment ? { comment } : {}), ...(comment ? { comment } : {}),
isActive isActive
}
);
return data;
},
onSuccess(_, dto) {
queryClient.invalidateQueries(trustedIps.getTrustedIps(dto.workspaceId));
} }
}); );
return data;
},
onSuccess(_, dto) {
queryClient.invalidateQueries(trustedIps.getTrustedIps(dto.workspaceId));
}
});
}; };
export const useDeleteTrustedIp = () => { export const useDeleteTrustedIp = () => {
const queryClient = useQueryClient(); const queryClient = useQueryClient();
return useMutation({ return useMutation({
mutationFn: async ({ mutationFn: async ({
workspaceId, workspaceId,
trustedIpId, trustedIpId
}: { }: {
workspaceId: string; workspaceId: string;
trustedIpId: string; trustedIpId: string;
}) => { }) => {
const { data } = await apiRequest.delete( const { data } = await apiRequest.delete(
`/api/v1/workspace/${workspaceId}/trusted-ips/${trustedIpId}` `/api/v1/workspace/${workspaceId}/trusted-ips/${trustedIpId}`
); );
return data; return data;
}, },
onSuccess(_, dto) { onSuccess(_, dto) {
queryClient.invalidateQueries(trustedIps.getTrustedIps(dto.workspaceId)); queryClient.invalidateQueries(trustedIps.getTrustedIps(dto.workspaceId));
} }
}); });
}; };
+8 -6
View File
@@ -325,7 +325,13 @@ export const useDeleteUserFromWorkspace = () => {
const queryClient = useQueryClient(); const queryClient = useQueryClient();
return useMutation({ return useMutation({
mutationFn: async ({ usernames, workspaceId }: { workspaceId: string; usernames: string[] }) => { mutationFn: async ({
usernames,
workspaceId
}: {
workspaceId: string;
usernames: string[];
}) => {
const { const {
data: { deletedMembership } data: { deletedMembership }
} = await apiRequest.delete(`/api/v2/workspace/${workspaceId}/memberships`, { } = await apiRequest.delete(`/api/v2/workspace/${workspaceId}/memberships`, {
@@ -391,11 +397,7 @@ export const useAddIdentityToWorkspace = () => {
export const useUpdateIdentityWorkspaceRole = () => { export const useUpdateIdentityWorkspaceRole = () => {
const queryClient = useQueryClient(); const queryClient = useQueryClient();
return useMutation({ return useMutation({
mutationFn: async ({ mutationFn: async ({ identityId, workspaceId, roles }: TUpdateWorkspaceIdentityRoleDTO) => {
identityId,
workspaceId,
roles
}:TUpdateWorkspaceIdentityRoleDTO)=> {
const { const {
data: { identityMembership } data: { identityMembership }
} = await apiRequest.patch( } = await apiRequest.patch(
+18 -18
View File
@@ -82,16 +82,16 @@ export type TUpdateWorkspaceUserRoleDTO = {
workspaceId: string; workspaceId: string;
roles: ( roles: (
| { | {
role: string; role: string;
isTemporary?: false; isTemporary?: false;
} }
| { | {
role: string; role: string;
isTemporary: true; isTemporary: true;
temporaryMode: ProjectUserMembershipTemporaryMode; temporaryMode: ProjectUserMembershipTemporaryMode;
temporaryRange: string; temporaryRange: string;
temporaryAccessStartTime: string; temporaryAccessStartTime: string;
} }
)[]; )[];
}; };
@@ -100,15 +100,15 @@ export type TUpdateWorkspaceIdentityRoleDTO = {
workspaceId: string; workspaceId: string;
roles: ( roles: (
| { | {
role: string; role: string;
isTemporary?: false; isTemporary?: false;
} }
| { | {
role: string; role: string;
isTemporary: true; isTemporary: true;
temporaryMode: ProjectUserMembershipTemporaryMode; temporaryMode: ProjectUserMembershipTemporaryMode;
temporaryRange: string; temporaryRange: string;
temporaryAccessStartTime: string; temporaryAccessStartTime: string;
} }
)[]; )[];
}; };
+1 -1
View File
@@ -19,7 +19,7 @@ i18n
// init i18next // init i18next
// for all options read: https://www.i18next.com/overview/configuration-options // for all options read: https://www.i18next.com/overview/configuration-options
.init({ .init({
lng:"en", lng: "en",
fallbackLng: "en", fallbackLng: "en",
// supportedLngs: ["en", "ko", "fr", "pt-BR", "pt-PT", "es"], // supportedLngs: ["en", "ko", "fr", "pt-BR", "pt-PT", "es"],
debug: process.env.NODE_ENV === "development", debug: process.env.NODE_ENV === "development",
+8 -8
View File
@@ -4,12 +4,12 @@
* each item in that group. * each item in that group.
*/ */
export const groupBy = <T, Key extends string | number | symbol>( export const groupBy = <T, Key extends string | number | symbol>(
array: readonly T[], array: readonly T[],
getGroupId: (item: T) => Key getGroupId: (item: T) => Key
): Record<Key, T[]> => ): Record<Key, T[]> =>
array.reduce((acc, item) => { array.reduce((acc, item) => {
const groupId = getGroupId(item); const groupId = getGroupId(item);
if (!acc[groupId]) acc[groupId] = []; if (!acc[groupId]) acc[groupId] = [];
acc[groupId].push(item); acc[groupId].push(item);
return acc; return acc;
}, {} as Record<Key, T[]>); }, {} as Record<Key, T[]>);
+11 -14
View File
@@ -4,34 +4,31 @@ import Link from "next/link";
export default function Custom404() { export default function Custom404() {
return ( return (
<div className='bg-bunker-800 md:h-screen flex flex-col justify-between'> <div className="flex flex-col justify-between bg-bunker-800 md:h-screen">
<Head> <Head>
<title>Infisical | Page Not Found</title> <title>Infisical | Page Not Found</title>
<link rel='icon' href='/infisical.ico' /> <link rel="icon" href="/infisical.ico" />
</Head> </Head>
<div className='flex flex-col items-center justify-center text-gray-200 h-screen w-screen'> <div className="flex h-screen w-screen flex-col items-center justify-center text-gray-200">
<p className='text-4xl mt-32'>Oops, something went wrong</p> <p className="mt-32 text-4xl">Oops, something went wrong</p>
<p className='mt-2 mb-1 text-lg'> <p className="mt-2 mb-1 text-lg">
Think this is a mistake? Email{" "} Think this is a mistake? Email{" "}
<a <a className="text-primary underline underline-offset-4" href="mailto:[email protected]">
className='text-primary underline underline-offset-4'
href='mailto:[email protected]'
>
team@infisical.com team@infisical.com
</a>{" "} </a>{" "}
and we`ll fix it!{" "} and we`ll fix it!{" "}
</p> </p>
<Link href='/dashboard'> <Link href="/dashboard">
<div className="mt-8 bg-mineshaft-500 py-2 px-4 rounded-md hover:bg-primary diration-200 hover:text-black font-semibold cursor-default"> <div className="diration-200 mt-8 cursor-default rounded-md bg-mineshaft-500 py-2 px-4 font-semibold hover:bg-primary hover:text-black">
Go to Dashboard Go to Dashboard
</div> </div>
</Link> </Link>
<Image <Image
src='/images/dragon-404.svg' src="/images/dragon-404.svg"
height={554} height={554}
width={942} width={942}
alt='infisical dragon - page not found' alt="infisical dragon - page not found"
/> />
</div> </div>
</div> </div>
); );
+1 -1
View File
@@ -7,7 +7,7 @@ export default function LoginPage() {
const { t } = useTranslation(); const { t } = useTranslation();
return ( return (
<div className="flex min-h-screen max-h-screen overflow-y-auto flex-col justify-center bg-gradient-to-tr from-mineshaft-600 via-mineshaft-800 to-bunker-700 px-6"> <div className="flex max-h-screen min-h-screen flex-col justify-center overflow-y-auto bg-gradient-to-tr from-mineshaft-600 via-mineshaft-800 to-bunker-700 px-6">
<Head> <Head>
<title>{t("common.head-title", { title: t("signup.title") })}</title> <title>{t("common.head-title", { title: t("signup.title") })}</title>
<link rel="icon" href="/infisical.ico" /> <link rel="icon" href="/infisical.ico" />
+1 -1
View File
@@ -11,6 +11,6 @@ const checkAuth = async () => {
"Content-Type": "application/json" "Content-Type": "application/json"
} }
}).then((res) => res); }).then((res) => res);
} };
export default checkAuth; export default checkAuth;
@@ -16,7 +16,7 @@ const linkGitAppInstallationWithOrganization = (installationId: string, sessionI
}) })
}).then(async (res) => { }).then(async (res) => {
if (res && res.status === 200) { if (res && res.status === 200) {
return true return true;
} }
console.log("Failed to link installation to organization"); console.log("Failed to link installation to organization");
return undefined; return undefined;
@@ -4,25 +4,26 @@ export enum RiskStatus {
RESOLVED_FALSE_POSITIVE = "RESOLVED_FALSE_POSITIVE", RESOLVED_FALSE_POSITIVE = "RESOLVED_FALSE_POSITIVE",
RESOLVED_REVOKED = "RESOLVED_REVOKED", RESOLVED_REVOKED = "RESOLVED_REVOKED",
RESOLVED_NOT_REVOKED = "RESOLVED_NOT_REVOKED", RESOLVED_NOT_REVOKED = "RESOLVED_NOT_REVOKED",
UNRESOLVED = "UNRESOLVED", UNRESOLVED = "UNRESOLVED"
} }
/** /**
* Will create a new integration session and return it for the given org * Will create a new integration session and return it for the given org
* @returns * @returns
*/ */
const updateRiskStatus = (organizationId: string, riskId: string, status: RiskStatus) => const updateRiskStatus = (organizationId: string, riskId: string, status: RiskStatus) =>
SecurityClient.fetchCall(`/api/v1/secret-scanning/organization/${organizationId}/risks/${riskId}/status`, { SecurityClient.fetchCall(
method: "POST", `/api/v1/secret-scanning/organization/${organizationId}/risks/${riskId}/status`,
headers: { {
"Content-Type": "application/json" method: "POST",
}, headers: {
body: JSON.stringify({ "Content-Type": "application/json"
status },
}) body: JSON.stringify({
}).then(async (res) => { status
})
}
).then(async (res) => {
if (res && res.status === 200) { if (res && res.status === 200) {
return res.json(); return res.json();
} }
+7 -5
View File
@@ -3,17 +3,19 @@ import Image from "next/image";
export default function CliRedirect() { export default function CliRedirect() {
return ( return (
<div className='bg-bunker-800 md:h-screen flex flex-col justify-between'> <div className="flex flex-col justify-between bg-bunker-800 md:h-screen">
<Head> <Head>
<title>Infisical CLI | Login Successful!</title> <title>Infisical CLI | Login Successful!</title>
<link rel='icon' href='/infisical.ico' /> <link rel="icon" href="/infisical.ico" />
</Head> </Head>
<div className='flex flex-col items-center justify-center text-gray-200 h-screen w-screen'> <div className="flex h-screen w-screen flex-col items-center justify-center text-gray-200">
<div className="mb-8 flex justify-center"> <div className="mb-8 flex justify-center">
<Image src="/images/gradientLogo.svg" height={90} width={120} alt="Infisical Logo" /> <Image src="/images/gradientLogo.svg" height={90} width={120} alt="Infisical Logo" />
</div> </div>
<p className='text-3xl font-medium text-transparent bg-clip-text bg-gradient-to-b from-white to-bunker-200 text-center'>Head back to your terminal</p> <p className="bg-gradient-to-b from-white to-bunker-200 bg-clip-text text-center text-3xl font-medium text-transparent">
<p className='mb-1 text-lg text-light text-mineshaft-400'> Head back to your terminal
</p>
<p className="text-light mb-1 text-lg text-mineshaft-400">
You&apos;ve successfully logged in to the Infisical CLI You&apos;ve successfully logged in to the Infisical CLI
</p> </p>
</div> </div>
+3 -3
View File
@@ -3,16 +3,16 @@ import Head from "next/head";
export default function EmailNotFeriviedPage() { export default function EmailNotFeriviedPage() {
return ( return (
<div className="bg-bunker-800 md:h-screen flex flex-col justify-between"> <div className="flex flex-col justify-between bg-bunker-800 md:h-screen">
<Head> <Head>
<title>Request a New Invite</title> <title>Request a New Invite</title>
<link rel="icon" href="/infisical.ico" /> <link rel="icon" href="/infisical.ico" />
</Head> </Head>
<div className="flex flex-col items-center justify-center text-gray-200 h-screen w-screen"> <div className="flex h-screen w-screen flex-col items-center justify-center text-gray-200">
<p className="text-6xl">Oops.</p> <p className="text-6xl">Oops.</p>
<p className="mt-2 mb-1 text-xl">Your email was not verified. </p> <p className="mt-2 mb-1 text-xl">Your email was not verified. </p>
<p className="text-xl">Please try again.</p> <p className="text-xl">Please try again.</p>
<p className="text-md mt-8 text-gray-600 max-w-sm text-center"> <p className="text-md mt-8 max-w-sm text-center text-gray-600">
Note: If it still doesn&apos;t work, please reach out to us at support@infisical.com Note: If it still doesn&apos;t work, please reach out to us at support@infisical.com
</p> </p>
</div> </div>
+1 -1
View File
@@ -9,5 +9,5 @@ export default function Home() {
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps
}, []); }, []);
return <div className="bg-bunker-800 w-screen" />; return <div className="w-screen bg-bunker-800" />;
} }
@@ -1,92 +1,87 @@
import { useState } from "react"; import { useState } from "react";
import { useRouter } from "next/router"; import { useRouter } from "next/router";
import { import { useSaveIntegrationAccessToken } from "@app/hooks/api";
useSaveIntegrationAccessToken
} from "@app/hooks/api";
import { Button,Card, CardTitle, FormControl, Input } from "../../../components/v2"; import { Button, Card, CardTitle, FormControl, Input } from "../../../components/v2";
export default function CloudflarePagesIntegrationPage() { export default function CloudflarePagesIntegrationPage() {
const router = useRouter(); const router = useRouter();
const { mutateAsync } = useSaveIntegrationAccessToken(); const { mutateAsync } = useSaveIntegrationAccessToken();
const [accessKey, setAccessKey] = useState(""); const [accessKey, setAccessKey] = useState("");
const [accessKeyErrorText, setAccessKeyErrorText] = useState(""); const [accessKeyErrorText, setAccessKeyErrorText] = useState("");
const [accountId, setAccountId] = useState(""); const [accountId, setAccountId] = useState("");
const [accountIdErrorText, setAccountIdErrorText] = useState(""); const [accountIdErrorText, setAccountIdErrorText] = useState("");
const [isLoading, setIsLoading] = useState(false); const [isLoading, setIsLoading] = useState(false);
const handleButtonClick = async () => { const handleButtonClick = async () => {
try { try {
setAccessKeyErrorText(""); setAccessKeyErrorText("");
setAccountIdErrorText(""); setAccountIdErrorText("");
if (accessKey.length === 0 || accountId.length === 0) { if (accessKey.length === 0 || accountId.length === 0) {
if (accessKey.length === 0) setAccessKeyErrorText("API token cannot be blank!"); if (accessKey.length === 0) setAccessKeyErrorText("API token cannot be blank!");
if (accountId.length === 0) setAccountIdErrorText("Account ID cannot be blank!"); if (accountId.length === 0) setAccountIdErrorText("Account ID cannot be blank!");
return; return;
} }
setIsLoading(true); setIsLoading(true);
const integrationAuth = await mutateAsync({ const integrationAuth = await mutateAsync({
workspaceId: localStorage.getItem("projectData.id"), workspaceId: localStorage.getItem("projectData.id"),
integration: "cloudflare-pages", integration: "cloudflare-pages",
accessId: accountId, accessId: accountId,
accessToken: accessKey accessToken: accessKey
}); });
setAccessKey(""); setAccessKey("");
setAccountId(""); setAccountId("");
setIsLoading(false); setIsLoading(false);
router.push(`/integrations/cloudflare-pages/create?integrationAuthId=${integrationAuth.id}`); router.push(`/integrations/cloudflare-pages/create?integrationAuthId=${integrationAuth.id}`);
} catch (err) { } catch (err) {
console.error(err); console.error(err);
}
} }
};
return ( return (
<div className="flex h-full w-full items-center justify-center"> <div className="flex h-full w-full items-center justify-center">
<Card className="max-w-lg rounded-md border border-mineshaft-600 mb-12"> <Card className="mb-12 max-w-lg rounded-md border border-mineshaft-600">
<CardTitle className="text-left px-6" subTitle="After adding your API-key, you will be prompted to set up an integration for a particular Infisical project and environment.">Cloudflare Pages Integration</CardTitle> <CardTitle
<FormControl className="px-6 text-left"
label="Cloudflare Pages API token" subTitle="After adding your API-key, you will be prompted to set up an integration for a particular Infisical project and environment."
errorText={accessKeyErrorText} >
isError={accessKeyErrorText !== "" ?? false} Cloudflare Pages Integration
className="mx-6" </CardTitle>
> <FormControl
<Input label="Cloudflare Pages API token"
placeholder="" errorText={accessKeyErrorText}
value={accessKey} isError={accessKeyErrorText !== "" ?? false}
onChange={(e) => setAccessKey(e.target.value)} className="mx-6"
/> >
</FormControl> <Input placeholder="" value={accessKey} onChange={(e) => setAccessKey(e.target.value)} />
<FormControl </FormControl>
label="Cloudflare Pages Account ID" <FormControl
errorText={accountIdErrorText} label="Cloudflare Pages Account ID"
isError={accountIdErrorText !== "" ?? false} errorText={accountIdErrorText}
className="mx-6" isError={accountIdErrorText !== "" ?? false}
> className="mx-6"
<Input >
placeholder="" <Input placeholder="" value={accountId} onChange={(e) => setAccountId(e.target.value)} />
value={accountId} </FormControl>
onChange={(e) => setAccountId(e.target.value)} <Button
/> onClick={handleButtonClick}
</FormControl> color="mineshaft"
<Button variant="outline_bg"
onClick={handleButtonClick} className="mb-6 mt-2 ml-auto mr-6 w-min"
color="mineshaft" isFullWidth={false}
variant="outline_bg" isLoading={isLoading}
className="mb-6 mt-2 ml-auto mr-6 w-min" >
isFullWidth={false} Connect to Cloudflare Pages
isLoading={isLoading} </Button>
> </Card>
Connect to Cloudflare Pages </div>
</Button> );
</Card>
</div>
);
} }
CloudflarePagesIntegrationPage.requireAuth = true; CloudflarePagesIntegrationPage.requireAuth = true;
@@ -6,7 +6,15 @@ import queryString from "query-string";
import { useNotificationContext } from "@app/components/context/Notifications/NotificationProvider"; import { useNotificationContext } from "@app/components/context/Notifications/NotificationProvider";
import { useCreateIntegration, useGetWorkspaceById } from "@app/hooks/api"; import { useCreateIntegration, useGetWorkspaceById } from "@app/hooks/api";
import { Button, Card, CardTitle, FormControl, Input, Select, SelectItem } from "../../../components/v2"; import {
Button,
Card,
CardTitle,
FormControl,
Input,
Select,
SelectItem
} from "../../../components/v2";
import { import {
useGetIntegrationAuthApps, useGetIntegrationAuthApps,
useGetIntegrationAuthById useGetIntegrationAuthById
@@ -7,7 +7,7 @@ import { useRouter } from "next/router";
import { import {
faArrowUpRightFromSquare, faArrowUpRightFromSquare,
faBookOpen, faBookOpen,
faBugs, faBugs
// faCircleInfo // faCircleInfo
} from "@fortawesome/free-solid-svg-icons"; } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
@@ -40,7 +40,10 @@ import {
} from "../../../hooks/api/workspace"; } from "../../../hooks/api/workspace";
const initialSyncBehaviors = [ const initialSyncBehaviors = [
{ label: "No Import - Overwrite all values in Heroku", value: IntegrationSyncBehavior.OVERWRITE_TARGET }, {
label: "No Import - Overwrite all values in Heroku",
value: IntegrationSyncBehavior.OVERWRITE_TARGET
},
{ label: "Import - Prefer values from Heroku", value: IntegrationSyncBehavior.PREFER_TARGET }, { label: "Import - Prefer values from Heroku", value: IntegrationSyncBehavior.PREFER_TARGET },
{ label: "Import - Prefer values from Infisical", value: IntegrationSyncBehavior.PREFER_SOURCE } { label: "Import - Prefer values from Infisical", value: IntegrationSyncBehavior.PREFER_SOURCE }
]; ];
@@ -51,7 +54,10 @@ const schema = yup.object({
targetApp: yup.string().required("Heroku app is required"), targetApp: yup.string().required("Heroku app is required"),
initialSyncBehavior: yup initialSyncBehavior: yup
.string() .string()
.oneOf(initialSyncBehaviors.map((b) => b.value), "Invalid initial sync behavior") .oneOf(
initialSyncBehaviors.map((b) => b.value),
"Invalid initial sync behavior"
)
.required("Initial sync behavior is required") .required("Initial sync behavior is required")
}); });
@@ -70,7 +76,6 @@ export default function HerokuCreateIntegrationPage() {
const selectedSourceEnvironment = watch("selectedSourceEnvironment"); const selectedSourceEnvironment = watch("selectedSourceEnvironment");
const { mutateAsync } = useCreateIntegration(); const { mutateAsync } = useCreateIntegration();
// const { mutateAsync: mutateAsyncEnv } = useCreateWsEnvironment(); // const { mutateAsync: mutateAsyncEnv } = useCreateWsEnvironment();
@@ -78,9 +83,10 @@ export default function HerokuCreateIntegrationPage() {
const { data: workspace } = useGetWorkspaceById(localStorage.getItem("projectData.id") ?? ""); const { data: workspace } = useGetWorkspaceById(localStorage.getItem("projectData.id") ?? "");
const { data: integrationAuth } = useGetIntegrationAuthById((integrationAuthId as string) ?? ""); const { data: integrationAuth } = useGetIntegrationAuthById((integrationAuthId as string) ?? "");
const { data: integrationAuthApps, isLoading: isIntegrationAuthAppsLoading } = useGetIntegrationAuthApps({ const { data: integrationAuthApps, isLoading: isIntegrationAuthAppsLoading } =
integrationAuthId: (integrationAuthId as string) ?? "" useGetIntegrationAuthApps({
}); integrationAuthId: (integrationAuthId as string) ?? ""
});
// const { data: integrationAuthPipelineCouplings } = useGetIntegrationAuthHerokuPipelines({ // const { data: integrationAuthPipelineCouplings } = useGetIntegrationAuthHerokuPipelines({
// integrationAuthId: (integrationAuthId as string) ?? "" // integrationAuthId: (integrationAuthId as string) ?? ""
@@ -181,11 +187,7 @@ export default function HerokuCreateIntegrationPage() {
// } // }
// }; // };
const onFormSubmit = async ({ const onFormSubmit = async ({ secretPath, targetApp, initialSyncBehavior }: FormData) => {
secretPath,
targetApp,
initialSyncBehavior,
}: FormData) => {
try { try {
if (!integrationAuth?.id) return; if (!integrationAuth?.id) return;
@@ -207,13 +209,10 @@ export default function HerokuCreateIntegrationPage() {
} catch (err) { } catch (err) {
console.error(err); console.error(err);
} }
} };
return integrationAuth && return integrationAuth && workspace && selectedSourceEnvironment && integrationAuthApps ? (
workspace && <div className="flex h-full w-full flex-col items-center justify-center">
selectedSourceEnvironment &&
integrationAuthApps ? (
<div className="flex flex-col h-full w-full items-center justify-center">
<Head> <Head>
<title>Set Up Heroku Integration</title> <title>Set Up Heroku Integration</title>
<link rel="icon" href="/infisical.ico" /> <link rel="icon" href="/infisical.ico" />
@@ -280,11 +279,7 @@ export default function HerokuCreateIntegrationPage() {
defaultValue="" defaultValue=""
name="secretPath" name="secretPath"
render={({ field, fieldState: { error } }) => ( render={({ field, fieldState: { error } }) => (
<FormControl <FormControl label="Secrets Path" isError={Boolean(error)} errorText={error?.message}>
label="Secrets Path"
isError={Boolean(error)}
errorText={error?.message}
>
<Input {...field} placeholder="/" /> <Input {...field} placeholder="/" />
</FormControl> </FormControl>
)} )}
@@ -294,11 +289,7 @@ export default function HerokuCreateIntegrationPage() {
name="targetApp" name="targetApp"
render={({ field: { onChange, ...field }, fieldState: { error } }) => { render={({ field: { onChange, ...field }, fieldState: { error } }) => {
return ( return (
<FormControl <FormControl label="Heroku App" errorText={error?.message} isError={Boolean(error)}>
label="Heroku App"
errorText={error?.message}
isError={Boolean(error)}
>
<Select <Select
{...field} {...field}
onValueChange={(e) => { onValueChange={(e) => {
@@ -114,7 +114,9 @@ export default function RailwayCreateIntegrationPage() {
} }
}; };
const filteredTargetServices = targetServices ? [ { name: "", serviceId: "none" }, ...targetServices ] : [ { name: "", serviceId: "none" } ]; const filteredTargetServices = targetServices
? [{ name: "", serviceId: "none" }, ...targetServices]
: [{ name: "", serviceId: "none" }];
return workspace && return workspace &&
selectedSourceEnvironment && selectedSourceEnvironment &&
@@ -201,14 +203,14 @@ export default function RailwayCreateIntegrationPage() {
className="w-full border border-mineshaft-500" className="w-full border border-mineshaft-500"
isDisabled={targetServices.length === 0} isDisabled={targetServices.length === 0}
> >
{filteredTargetServices.map((targetService) => ( {filteredTargetServices.map((targetService) => (
<SelectItem <SelectItem
value={targetService.serviceId as string} value={targetService.serviceId as string}
key={`target-service-${targetService.serviceId as string}`} key={`target-service-${targetService.serviceId as string}`}
> >
{targetService.name} {targetService.name}
</SelectItem> </SelectItem>
))} ))}
</Select> </Select>
</FormControl> </FormControl>
<Button <Button
@@ -85,11 +85,7 @@ export default function RenderCreateIntegrationPage() {
} }
}, [integrationAuthApps]); }, [integrationAuthApps]);
const onFormSubmit = async ({ const onFormSubmit = async ({ secretPath, targetAppId, shouldAutoRedeploy }: FormData) => {
secretPath,
targetAppId,
shouldAutoRedeploy
}: FormData) => {
try { try {
if (!integrationAuth?.id) return; if (!integrationAuth?.id) return;
@@ -115,12 +111,9 @@ export default function RenderCreateIntegrationPage() {
} catch (err) { } catch (err) {
console.error(err); console.error(err);
} }
} };
return integrationAuth && return integrationAuth && workspace && selectedSourceEnvironment && integrationAuthApps ? (
workspace &&
selectedSourceEnvironment &&
integrationAuthApps ? (
<form <form
onSubmit={handleSubmit(onFormSubmit)} onSubmit={handleSubmit(onFormSubmit)}
className="flex h-full w-full flex-col items-center justify-center" className="flex h-full w-full flex-col items-center justify-center"
@@ -191,11 +184,7 @@ export default function RenderCreateIntegrationPage() {
defaultValue="" defaultValue=""
name="secretPath" name="secretPath"
render={({ field, fieldState: { error } }) => ( render={({ field, fieldState: { error } }) => (
<FormControl <FormControl label="Secrets Path" isError={Boolean(error)} errorText={error?.message}>
label="Secrets Path"
isError={Boolean(error)}
errorText={error?.message}
>
<Input {...field} placeholder="/" /> <Input {...field} placeholder="/" />
</FormControl> </FormControl>
)} )}
@@ -256,7 +245,7 @@ export default function RenderCreateIntegrationPage() {
<Button <Button
colorSchema="primary" colorSchema="primary"
variant="outline_bg" variant="outline_bg"
className="mb-8 ml-auto mr-6 w-min mt-4" className="mb-8 ml-auto mr-6 mt-4 w-min"
size="sm" size="sm"
type="submit" type="submit"
isLoading={isLoading} isLoading={isLoading}
+2 -2
View File
@@ -9,7 +9,7 @@ export default function LoginPage() {
const { t } = useTranslation(); const { t } = useTranslation();
return ( return (
<div className="flex min-h-screen max-h-screen overflow-y-auto flex-col justify-center bg-gradient-to-tr from-mineshaft-600 via-mineshaft-800 to-bunker-700 px-6"> <div className="flex max-h-screen min-h-screen flex-col justify-center overflow-y-auto bg-gradient-to-tr from-mineshaft-600 via-mineshaft-800 to-bunker-700 px-6">
<Head> <Head>
<title>{t("common.head-title", { title: t("login.title") })}</title> <title>{t("common.head-title", { title: t("login.title") })}</title>
<link rel="icon" href="/infisical.ico" /> <link rel="icon" href="/infisical.ico" />
@@ -23,7 +23,7 @@ export default function LoginPage() {
</div> </div>
</Link> </Link>
<Login /> <Login />
<div className="pb-28"/> <div className="pb-28" />
</div> </div>
); );
} }
+5 -5
View File
@@ -1,10 +1,10 @@
import { useEffect } from "react"; import { useEffect } from "react";
export default function LoginProviderError() { export default function LoginProviderError() {
useEffect(() => { useEffect(() => {
window.localStorage.setItem("PROVIDER_AUTH_ERROR", "err"); window.localStorage.setItem("PROVIDER_AUTH_ERROR", "err");
window.close(); window.close();
}, []) }, []);
return <div /> return <div />;
} }
@@ -1,16 +1,16 @@
import { useEffect } from "react"; import { useEffect } from "react";
import { useRouter } from "next/router" import { useRouter } from "next/router";
import SecurityClient from "@app/components/utilities/SecurityClient"; import SecurityClient from "@app/components/utilities/SecurityClient";
export default function LoginProviderSuccess() { export default function LoginProviderSuccess() {
const router = useRouter(); const router = useRouter();
useEffect(() => { useEffect(() => {
const { token } = router.query; const { token } = router.query;
SecurityClient.setProviderAuthToken(token as string); SecurityClient.setProviderAuthToken(token as string);
window.close(); window.close();
}, []) }, []);
return <div /> return <div />;
} }
+20 -20
View File
@@ -2,30 +2,30 @@ import { useTranslation } from "react-i18next";
import Head from "next/head"; import Head from "next/head";
import Image from "next/image"; import Image from "next/image";
import Link from "next/link"; import Link from "next/link";
import { useRouter } from "next/router" import { useRouter } from "next/router";
import { LoginSSO } from "@app/views/Login"; import { LoginSSO } from "@app/views/Login";
export default function LoginSSOPage() { export default function LoginSSOPage() {
const { t } = useTranslation(); const { t } = useTranslation();
const router = useRouter(); const router = useRouter();
const token = router.query.token as string; const token = router.query.token as string;
return ( return (
<div className="flex h-screen flex-col justify-center bg-gradient-to-tr from-mineshaft-600 via-mineshaft-800 to-bunker-700 px-6 pb-28 "> <div className="flex h-screen flex-col justify-center bg-gradient-to-tr from-mineshaft-600 via-mineshaft-800 to-bunker-700 px-6 pb-28 ">
<Head> <Head>
<title>{t("common.head-title", { title: t("login.title") })}</title> <title>{t("common.head-title", { title: t("login.title") })}</title>
<link rel="icon" href="/infisical.ico" /> <link rel="icon" href="/infisical.ico" />
<meta property="og:image" content="/images/message.png" /> <meta property="og:image" content="/images/message.png" />
<meta property="og:title" content={t("login.og-title") ?? ""} /> <meta property="og:title" content={t("login.og-title") ?? ""} />
<meta name="og:description" content={t("login.og-description") ?? ""} /> <meta name="og:description" content={t("login.og-description") ?? ""} />
</Head> </Head>
<Link href="/"> <Link href="/">
<div className="mb-4 mt-20 flex justify-center"> <div className="mb-4 mt-20 flex justify-center">
<Image src="/images/gradientLogo.svg" height={90} width={120} alt="Infisical logo" /> <Image src="/images/gradientLogo.svg" height={90} width={120} alt="Infisical logo" />
</div> </div>
</Link> </Link>
<LoginSSO providerAuthToken={token} /> <LoginSSO providerAuthToken={token} />
</div> </div>
); );
} }
@@ -454,7 +454,12 @@ const LearningItemSquare = ({
}; };
const formSchema = yup.object({ const formSchema = yup.object({
name: yup.string().required().label("Project Name").trim().max(64, "Too long, maximum length is 64 characters"), name: yup
.string()
.required()
.label("Project Name")
.trim()
.max(64, "Too long, maximum length is 64 characters"),
addMembers: yup.bool().required().label("Add Members") addMembers: yup.bool().required().label("Add Members")
}); });
+10 -10
View File
@@ -5,16 +5,16 @@ import Head from "next/head";
import { NonePage } from "@app/views/Org/NonePage"; import { NonePage } from "@app/views/Org/NonePage";
export default function NoneOrganization() { export default function NoneOrganization() {
const { t } = useTranslation(); const { t } = useTranslation();
return ( return (
<> <>
<Head> <Head>
<title>{t("common.head-title", { title: t("settings.org.title") })}</title> <title>{t("common.head-title", { title: t("settings.org.title") })}</title>
<link rel="icon" href="/infisical.ico" /> <link rel="icon" href="/infisical.ico" />
</Head> </Head>
<NonePage /> <NonePage />
</> </>
); );
} }
NoneOrganization.requireAuth = true; NoneOrganization.requireAuth = true;
+41 -47
View File
@@ -308,64 +308,58 @@ export default function PasswordReset() {
<FontAwesomeIcon icon={faCheck} className="text-md mr-2 text-primary" /> <FontAwesomeIcon icon={faCheck} className="text-md mr-2 text-primary" />
)} )}
<div <div
className={`${passwordErrorNoNumOrSpecialChar ? "text-gray-400" : "text-gray-600"} text-sm`} className={`${
passwordErrorNoNumOrSpecialChar ? "text-gray-400" : "text-gray-600"
} text-sm`}
> >
at least 1 number or special character at least 1 number or special character
</div> </div>
</div> </div>
<div className="ml-1 flex flex-row items-center justify-start"> <div className="ml-1 flex flex-row items-center justify-start">
{passwordErrorRepeatedChar ? ( {passwordErrorRepeatedChar ? (
<FontAwesomeIcon icon={faX} className="text-md mr-2.5 text-red" /> <FontAwesomeIcon icon={faX} className="text-md mr-2.5 text-red" />
) : ( ) : (
<FontAwesomeIcon icon={faCheck} className="text-md mr-2 text-primary" /> <FontAwesomeIcon icon={faCheck} className="text-md mr-2 text-primary" />
)} )}
<div <div
className={`${ className={`${passwordErrorRepeatedChar ? "text-gray-400" : "text-gray-600"} text-sm`}
passwordErrorRepeatedChar ? "text-gray-400" : "text-gray-600" >
} text-sm`} at most 3 repeated, consecutive characters
> </div>
at most 3 repeated, consecutive characters
</div>
</div> </div>
<div className="ml-1 flex flex-row items-center justify-start"> <div className="ml-1 flex flex-row items-center justify-start">
{passwordErrorEscapeChar ? ( {passwordErrorEscapeChar ? (
<FontAwesomeIcon icon={faX} className="text-md mr-2.5 text-red" /> <FontAwesomeIcon icon={faX} className="text-md mr-2.5 text-red" />
) : ( ) : (
<FontAwesomeIcon icon={faCheck} className="text-md mr-2 text-primary" /> <FontAwesomeIcon icon={faCheck} className="text-md mr-2 text-primary" />
)} )}
<div <div
className={`${ className={`${passwordErrorEscapeChar ? "text-gray-400" : "text-gray-600"} text-sm`}
passwordErrorEscapeChar ? "text-gray-400" : "text-gray-600" >
} text-sm`} No escape characters allowed.
> </div>
No escape characters allowed.
</div>
</div> </div>
<div className="ml-1 flex flex-row items-center justify-start"> <div className="ml-1 flex flex-row items-center justify-start">
{passwordErrorLowEntropy ? ( {passwordErrorLowEntropy ? (
<FontAwesomeIcon icon={faX} className="text-md mr-2.5 text-red" /> <FontAwesomeIcon icon={faX} className="text-md mr-2.5 text-red" />
) : ( ) : (
<FontAwesomeIcon icon={faCheck} className="text-md mr-2 text-primary" /> <FontAwesomeIcon icon={faCheck} className="text-md mr-2 text-primary" />
)} )}
<div <div
className={`${passwordErrorLowEntropy ? "text-gray-400" : "text-gray-600"} text-sm`} className={`${passwordErrorLowEntropy ? "text-gray-400" : "text-gray-600"} text-sm`}
> >
Password contains personal info. Password contains personal info.
</div> </div>
</div> </div>
<div className="ml-1 flex flex-row items-center justify-start"> <div className="ml-1 flex flex-row items-center justify-start">
{passwordErrorBreached ? ( {passwordErrorBreached ? (
<FontAwesomeIcon icon={faX} className="text-md mr-2.5 text-red" /> <FontAwesomeIcon icon={faX} className="text-md mr-2.5 text-red" />
) : ( ) : (
<FontAwesomeIcon icon={faCheck} className="text-md mr-2 text-primary" /> <FontAwesomeIcon icon={faCheck} className="text-md mr-2 text-primary" />
)} )}
<div <div className={`${passwordErrorBreached ? "text-gray-400" : "text-gray-600"} text-sm`}>
className={`${ Password was found in a data breach.
passwordErrorBreached ? "text-gray-400" : "text-gray-600" </div>
} text-sm`}
>
Password was found in a data breach.
</div>
</div> </div>
</div> </div>
) : ( ) : (
+1 -1
View File
@@ -7,7 +7,7 @@ export default function PersonalSettings() {
const { t } = useTranslation(); const { t } = useTranslation();
return ( return (
<div className="bg-bunker-800 text-white h-full"> <div className="h-full bg-bunker-800 text-white">
<Head> <Head>
<title>{t("common.head-title", { title: t("settings.personal.title") })}</title> <title>{t("common.head-title", { title: t("settings.personal.title") })}</title>
<link rel="icon" href="/infisical.ico" /> <link rel="icon" href="/infisical.ico" />
@@ -4,17 +4,17 @@ import Head from "next/head";
import { IPAllowlistPage } from "@app/views/Project/IPAllowListPage"; import { IPAllowlistPage } from "@app/views/Project/IPAllowListPage";
const ProjectAllowlist = () => { const ProjectAllowlist = () => {
const { t } = useTranslation(); const { t } = useTranslation();
return ( return (
<> <>
<Head> <Head>
<title>{t("common.head-title", { title: t("settings.project.title") })}</title> <title>{t("common.head-title", { title: t("settings.project.title") })}</title>
<link rel="icon" href="/infisical.ico" /> <link rel="icon" href="/infisical.ico" />
</Head> </Head>
<IPAllowlistPage /> <IPAllowlistPage />
</> </>
); );
} };
export default ProjectAllowlist; export default ProjectAllowlist;
@@ -4,19 +4,19 @@ import Head from "next/head";
import { AuditLogsPage } from "@app/views/Project/AuditLogsPage"; import { AuditLogsPage } from "@app/views/Project/AuditLogsPage";
const Logs = () => { const Logs = () => {
const { t } = useTranslation(); const { t } = useTranslation();
return ( return (
<div className="h-full bg-bunker-800"> <div className="h-full bg-bunker-800">
<Head> <Head>
<title>{t("common.head-title", { title: t("settings.project.title") })}</title> <title>{t("common.head-title", { title: t("settings.project.title") })}</title>
<link rel="icon" href="/infisical.ico" /> <link rel="icon" href="/infisical.ico" />
<meta property="og:image" content="/images/message.png" /> <meta property="og:image" content="/images/message.png" />
</Head> </Head>
<AuditLogsPage /> <AuditLogsPage />
</div> </div>
); );
} };
export default Logs; export default Logs;
+11 -6
View File
@@ -7,20 +7,25 @@ import Image from "next/image";
*/ */
export default function RequestNewInvite() { export default function RequestNewInvite() {
return ( return (
<div className="bg-bunker-700 md:h-screen flex flex-col justify-between"> <div className="flex flex-col justify-between bg-bunker-700 md:h-screen">
<Head> <Head>
<title>Request a New Invite</title> <title>Request a New Invite</title>
<link rel="icon" href="/infisical.ico" /> <link rel="icon" href="/infisical.ico" />
</Head> </Head>
<div className="flex flex-col items-center justify-center text-bunker-200 h-screen w-screen mt-8"> <div className="mt-8 flex h-screen w-screen flex-col items-center justify-center text-bunker-200">
<p className="text-4xl text-primary-100">Oops, your invite has expired.</p> <p className="text-4xl text-primary-100">Oops, your invite has expired.</p>
<p className="text-lg my-4">Ask your admin for a new one.</p> <p className="my-4 text-lg">Ask your admin for a new one.</p>
<p className="text-sm text-bunker-400 max-w-xs px-7 text-center leading-tight"> <p className="max-w-xs px-7 text-center text-sm leading-tight text-bunker-400">
<span className="bg-primary-500/40 text-black px-1 rounded-md">Note:</span> If it still <span className="rounded-md bg-primary-500/40 px-1 text-black">Note:</span> If it still
doesn&apos;t work, please reach out to us at support@infisical.com doesn&apos;t work, please reach out to us at support@infisical.com
</p> </p>
<div className=""> <div className="">
<Image src="/images/invitation-expired.svg" height={500} width={800} alt="invitation expired illustration" /> <Image
src="/images/invitation-expired.svg"
height={500}
width={800}
alt="invitation expired illustration"
/>
</div> </div>
</div> </div>
</div> </div>
+9 -6
View File
@@ -1,15 +1,18 @@
import { useEffect } from "react"; import { useEffect } from "react";
import { useRouter } from "next/router" import { useRouter } from "next/router";
export default function SecretScanning() { export default function SecretScanning() {
const router = useRouter(); const router = useRouter();
useEffect(()=>{ useEffect(() => {
router.push(`${router.asPath.split("secret-scanning")[0]}/org/${localStorage.getItem("orgData.id")}/secret-scanning${router.asPath.split("secret-scanning")[1]}`) router.push(
}, []) `${router.asPath.split("secret-scanning")[0]}/org/${localStorage.getItem(
"orgData.id"
)}/secret-scanning${router.asPath.split("secret-scanning")[1]}`
);
}, []);
return <div />;
return <div/>;
} }
SecretScanning.requireAuth = true; SecretScanning.requireAuth = true;
+19 -19
View File
@@ -1,28 +1,28 @@
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import Head from "next/head"; import Head from "next/head";
import Image from "next/image"; import Image from "next/image";
import { useRouter } from "next/router" import { useRouter } from "next/router";
import { SignupSSO } from "@app/views/Signup"; import { SignupSSO } from "@app/views/Signup";
export default function SignupSSOPage() { export default function SignupSSOPage() {
const { t } = useTranslation(); const { t } = useTranslation();
const router = useRouter(); const router = useRouter();
const token = router.query.token as string; const token = router.query.token as string;
return ( return (
<div className="flex min-h-screen flex-col justify-center bg-gradient-to-tr from-mineshaft-600 via-mineshaft-800 to-bunker-700 px-6 pb-28 "> <div className="flex min-h-screen flex-col justify-center bg-gradient-to-tr from-mineshaft-600 via-mineshaft-800 to-bunker-700 px-6 pb-28 ">
<Head> <Head>
<title>{t("common.head-title", { title: t("signup.title") })}</title> <title>{t("common.head-title", { title: t("signup.title") })}</title>
<link rel="icon" href="/infisical.ico" /> <link rel="icon" href="/infisical.ico" />
<meta property="og:image" content="/images/message.png" /> <meta property="og:image" content="/images/message.png" />
<meta property="og:title" content={t("signup.og-title") as string} /> <meta property="og:title" content={t("signup.og-title") as string} />
<meta name="og:description" content={t("signup.og-description") as string} /> <meta name="og:description" content={t("signup.og-description") as string} />
</Head> </Head>
<div className="mb-4 mt-20 flex justify-center"> <div className="mb-4 mt-20 flex justify-center">
<Image src="/images/gradientLogo.svg" height={90} width={120} alt="Infisical Logo" /> <Image src="/images/gradientLogo.svg" height={90} width={120} alt="Infisical Logo" />
</div> </div>
<SignupSSO providerAuthToken={token} /> <SignupSSO providerAuthToken={token} />
</div> </div>
); );
} }
+11 -2
View File
@@ -59,7 +59,10 @@ export default function VerifyEmail() {
</div> </div>
</Link> </Link>
{step === 1 && ( {step === 1 && (
<form onSubmit={onSubmit} className="h-7/12 mx-auto w-full max-w-md rounded-xl bg-bunker px-6 py-4 pt-8 drop-shadow-xl"> <form
onSubmit={onSubmit}
className="h-7/12 mx-auto w-full max-w-md rounded-xl bg-bunker px-6 py-4 pt-8 drop-shadow-xl"
>
<p className="mx-auto mb-6 flex w-max justify-center text-2xl font-semibold text-bunker-100 md:text-3xl"> <p className="mx-auto mb-6 flex w-max justify-center text-2xl font-semibold text-bunker-100 md:text-3xl">
Forgot your password? Forgot your password?
</p> </p>
@@ -81,7 +84,13 @@ export default function VerifyEmail() {
</div> </div>
<div className="mx-auto mt-4 flex max-h-20 w-full max-w-md flex-col items-center justify-center text-sm md:p-2"> <div className="mx-auto mt-4 flex max-h-20 w-full max-w-md flex-col items-center justify-center text-sm md:p-2">
<div className="text-l m-8 mt-6 px-8 py-3 text-lg"> <div className="text-l m-8 mt-6 px-8 py-3 text-lg">
<Button type="submit" text="Continue" size="lg" onButtonPressed={() => {}} loading={loading} /> <Button
type="submit"
text="Continue"
size="lg"
onButtonPressed={() => {}}
loading={loading}
/>
</div> </div>
</div> </div>
</form> </form>
+89 -96
View File
@@ -1,9 +1,8 @@
import { import {
decryptAssymmetric, decryptAssymmetric,
encryptAssymmetric} from "@app/components/utilities/cryptography/crypto"; encryptAssymmetric
import { } from "@app/components/utilities/cryptography/crypto";
decryptPrivateKeyHelper import { decryptPrivateKeyHelper } from "@app/helpers/key";
} from "@app/helpers/key";
/** /**
* Class to handle key actions * Class to handle key actions
@@ -11,101 +10,95 @@ import {
* must pass through this class * must pass through this class
*/ */
class KeyService { class KeyService {
private static privateKey: string = ""; private static privateKey: string = "";
static setPrivateKey(privateKey: string) { static setPrivateKey(privateKey: string) {
KeyService.privateKey = privateKey; KeyService.privateKey = privateKey;
} }
/** Return the user's decrypted private key /** Return the user's decrypted private key
* @param {Object} obj * @param {Object} obj
* @param {Number} obj.encryptionVersion * @param {Number} obj.encryptionVersion
* @param {String} obj.encryptedPrivateKey * @param {String} obj.encryptedPrivateKey
* @param {String} obj.iv * @param {String} obj.iv
* @param {String} obj.tag * @param {String} obj.tag
* @param {String} obj.password * @param {String} obj.password
* @param {String} obj.salt * @param {String} obj.salt
* @param {String} obj.protectedKey * @param {String} obj.protectedKey
* @param {String} obj.protectedKeyIV * @param {String} obj.protectedKeyIV
* @param {String} obj.protectedKeyTag * @param {String} obj.protectedKeyTag
* @returns {String} privateKey - decrypted private key * @returns {String} privateKey - decrypted private key
*/ */
static async decryptPrivateKey({ static async decryptPrivateKey({
encryptionVersion, encryptionVersion,
encryptedPrivateKey, encryptedPrivateKey,
iv, iv,
tag, tag,
password, password,
salt, salt,
protectedKey, protectedKey,
protectedKeyIV, protectedKeyIV,
protectedKeyTag, protectedKeyTag
}: { }: {
encryptionVersion: number; encryptionVersion: number;
encryptedPrivateKey: string; encryptedPrivateKey: string;
iv: string; iv: string;
tag: string; tag: string;
password: string; password: string;
salt: string; salt: string;
protectedKey?: string; protectedKey?: string;
protectedKeyIV?: string; protectedKeyIV?: string;
protectedKeyTag?: string; protectedKeyTag?: string;
}) { }) {
return decryptPrivateKeyHelper({ return decryptPrivateKeyHelper({
encryptionVersion, encryptionVersion,
encryptedPrivateKey, encryptedPrivateKey,
iv, iv,
tag, tag,
password, password,
salt, salt,
protectedKey, protectedKey,
protectedKeyIV, protectedKeyIV,
protectedKeyTag protectedKeyTag
}); });
} }
/** /**
* Return [plaintext] encrypted by the user's private key * Return [plaintext] encrypted by the user's private key
* @param {Object} obj * @param {Object} obj
* @param {String} obj.plaintext - plaintext to encrypt * @param {String} obj.plaintext - plaintext to encrypt
*/ */
static encryptWithPrivateKey({ static encryptWithPrivateKey({ plaintext, publicKey }: { plaintext: string; publicKey: string }) {
plaintext, return encryptAssymmetric({
publicKey, plaintext,
}: { publicKey,
plaintext: string; privateKey: KeyService.privateKey
publicKey: string; });
}) { }
return encryptAssymmetric({
plaintext,
publicKey,
privateKey: KeyService.privateKey
});
}
/** /**
* Return [ciphertext] decrypted by the user's private key * Return [ciphertext] decrypted by the user's private key
* @param {Object} obj * @param {Object} obj
* @param {String} obj.ciphertext - ciphertext to decrypt * @param {String} obj.ciphertext - ciphertext to decrypt
* @param {String} obj.ciphertext - iv of ciphertext * @param {String} obj.ciphertext - iv of ciphertext
* @param {String} obj.ciphertext - tag of ciphertext * @param {String} obj.ciphertext - tag of ciphertext
*/ */
static decryptWithPrivateKey({ static decryptWithPrivateKey({
ciphertext, ciphertext,
nonce, nonce,
publicKey publicKey
}: { }: {
ciphertext: string; ciphertext: string;
nonce: string; nonce: string;
publicKey: string; publicKey: string;
}) { }) {
return decryptAssymmetric({ return decryptAssymmetric({
ciphertext, ciphertext,
nonce, nonce,
publicKey, publicKey,
privateKey: KeyService.privateKey privateKey: KeyService.privateKey
}); });
} }
} }
export default KeyService; export default KeyService;
+1 -4
View File
@@ -1,7 +1,4 @@
import KeyService from "./KeyService"; import KeyService from "./KeyService";
import ProjectService from "./ProjectService"; import ProjectService from "./ProjectService";
export { export { KeyService, ProjectService };
KeyService,
ProjectService
}
@@ -207,7 +207,11 @@ export const IntegrationsSection = ({
(popUp?.deleteConfirmation.data as TIntegration)?.integration || " " (popUp?.deleteConfirmation.data as TIntegration)?.integration || " "
} integration for ${(popUp?.deleteConfirmation.data as TIntegration)?.app || " "}?`} } integration for ${(popUp?.deleteConfirmation.data as TIntegration)?.app || " "}?`}
onChange={(isOpen) => handlePopUpToggle("deleteConfirmation", isOpen)} onChange={(isOpen) => handlePopUpToggle("deleteConfirmation", isOpen)}
deleteKey={(popUp?.deleteConfirmation?.data as TIntegration)?.app || (popUp?.deleteConfirmation?.data as TIntegration)?.owner || ""} deleteKey={
(popUp?.deleteConfirmation?.data as TIntegration)?.app ||
(popUp?.deleteConfirmation?.data as TIntegration)?.owner ||
""
}
onDeleteApproved={async () => onDeleteApproved={async () =>
onIntegrationDelete(popUp?.deleteConfirmation.data as TIntegration, () => onIntegrationDelete(popUp?.deleteConfirmation.data as TIntegration, () =>
handlePopUpClose("deleteConfirmation") handlePopUpClose("deleteConfirmation")
+35 -51
View File
@@ -1,62 +1,46 @@
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import jwt_decode from "jwt-decode"; import jwt_decode from "jwt-decode";
import { import { MFAStep, PasswordStep } from "./components";
MFAStep,
PasswordStep
} from "./components";
type Props = { type Props = {
providerAuthToken: string; providerAuthToken: string;
} };
export const LoginSSO = ({ providerAuthToken }: Props) => { export const LoginSSO = ({ providerAuthToken }: Props) => {
const [step, setStep] = useState(0); const [step, setStep] = useState(0);
const [password, setPassword] = useState(""); const [password, setPassword] = useState("");
const { const { username, isUserCompleted } = jwt_decode(providerAuthToken) as any;
username,
isUserCompleted
} = jwt_decode(providerAuthToken) as any;
useEffect(() => { useEffect(() => {
if (isUserCompleted) { if (isUserCompleted) {
setStep(1); setStep(1);
}
}, []);
const renderView = () => {
switch (step) {
case 0:
return (
<div />
);
case 1:
return (
<PasswordStep
providerAuthToken={providerAuthToken}
email={username}
password={password}
setPassword={setPassword}
setStep={setStep}
/>
);
case 2:
return (
<MFAStep
providerAuthToken={providerAuthToken}
email={username}
password={password}
/>
);
default:
return <div />;
}
} }
}, []);
return ( const renderView = () => {
<div> switch (step) {
{renderView()} case 0:
</div> return <div />;
); case 1:
} return (
<PasswordStep
providerAuthToken={providerAuthToken}
email={username}
password={password}
setPassword={setPassword}
setStep={setStep}
/>
);
case 2:
return (
<MFAStep providerAuthToken={providerAuthToken} email={username} password={password} />
);
default:
return <div />;
}
};
return <div>{renderView()}</div>;
};

Some files were not shown because too many files have changed in this diff Show More