feat(infisical-pg): changed frontend api types _id to normal id

This commit is contained in:
Akhil Mohan
2023-12-08 11:21:40 +05:30
parent f3b37de3f3
commit aaba4a0895
161 changed files with 5359 additions and 4511 deletions

View File

@@ -8,7 +8,7 @@
"start:docker": "next build && next start",
"lint": "eslint --ext js,ts,tsx ./src",
"lint:fix": "eslint --fix --ext js,ts,tsx ./src",
"type-check": "tsc --project tsconfig.json",
"type:check": "tsc --project tsconfig.json --noEmit",
"storybook": "storybook dev -p 6006 -s ./public",
"build-storybook": "storybook build"
},

View File

@@ -1,5 +1,5 @@
export interface Tag {
_id: string;
id: string;
name: string;
slug: string;
user: string;
@@ -16,4 +16,4 @@ export interface SecretDataProps {
idOverride?: string;
comment: string;
tags: Tag[];
}
}

View File

@@ -31,18 +31,18 @@ const AddTagPopoverContent = ({
return (
<PopoverContent
side="left"
className="relative max-h-96 w-auto min-w-[200px] p-2 overflow-y-auto overflow-x-hidden border border-mineshaft-600 bg-mineshaft-800 text-bunker-200"
className="relative max-h-96 w-auto min-w-[200px] overflow-y-auto overflow-x-hidden border border-mineshaft-600 bg-mineshaft-800 p-2 text-bunker-200"
hideCloseBtn
>
<div className=" text-center text-sm font-medium text-bunker-200">
Add tags to {secKey || "this secret"}
</div>
<div className="absolute left-0 w-full border-mineshaft-600 border-t mt-2" />
<div className="absolute left-0 mt-2 w-full border-t border-mineshaft-600" />
<div className="flex flex-col space-y-1.5">
{wsTags?.map((wsTag: WsTag) => (
<div
key={`tag-${wsTag.id}`}
className="mt-4 h-[32px] relative flex items-center justify-start hover:border-mineshaft-600 hover:border hover:bg-mineshaft-700 p-2 rounded-md hover:text-bunker-200 bg-none"
className="relative mt-4 flex h-[32px] items-center justify-start rounded-md bg-none p-2 hover:border hover:border-mineshaft-600 hover:bg-mineshaft-700 hover:text-bunker-200"
onClick={() => handleSelectTag(wsTag)}
onMouseEnter={() => handleTagOnMouseEnter(wsTag)}
onMouseLeave={() => handleTagOnMouseLeave()}
@@ -54,7 +54,7 @@ const AddTagPopoverContent = ({
<Checkbox
id="autoCapitalization"
isChecked={selectedTagIds?.[wsTag.slug]}
className="absolute top-[50%] translate-y-[-50%] left-[10px] "
className="absolute top-[50%] left-[10px] translate-y-[-50%] "
checkIndicatorBg={`${
!selectedTagIds?.[wsTag.slug] ? "text-transparent" : "text-mineshaft-800"
}`}
@@ -62,7 +62,7 @@ const AddTagPopoverContent = ({
)}
<div className="ml-7 flex items-center gap-3">
<div
className="w-[10px] h-[10px] rounded-full"
className="h-[10px] w-[10px] rounded-full"
style={{ background: wsTag?.tagColor ? wsTag.tagColor : "#bec2c8" }}
>
{" "}

View File

@@ -4,73 +4,64 @@ import { Dialog, Transition } from "@headlessui/react";
import { useOrganization } from "@app/context";
// REFACTOR: Move all these modals into one reusable one
// REFACTOR: Move all these modals into one reusable one
type Props = {
isOpen?: boolean;
onClose: ()=>void;
onClose: () => void;
text: string;
}
};
const UpgradePlanModal = ({
isOpen,
onClose,
text,
}:Props) => {
const UpgradePlanModal = ({ isOpen, onClose, text }: Props) => {
const router = useRouter();
const { currentOrg } = useOrganization();
return (
<div>
<Transition appear show={isOpen} as={Fragment}>
<Dialog as='div' className='relative z-10' onClose={onClose}>
<Dialog as="div" className="relative z-10" onClose={onClose}>
<Transition.Child
as={Fragment}
enter='ease-out duration-300'
enterFrom='opacity-0'
enterTo='opacity-100'
leave='ease-in duration-150'
leaveFrom='opacity-100'
leaveTo='opacity-0'
enter="ease-out duration-300"
enterFrom="opacity-0"
enterTo="opacity-100"
leave="ease-in duration-150"
leaveFrom="opacity-100"
leaveTo="opacity-0"
>
<div className='fixed inset-0 bg-black bg-opacity-50 drop-shadow-xl' />
<div className="fixed inset-0 bg-black bg-opacity-50 drop-shadow-xl" />
</Transition.Child>
<div className='fixed inset-0 overflow-y-auto'>
<div className='flex min-h-full items-center justify-center p-4 text-center'>
<div className="fixed inset-0 overflow-y-auto">
<div className="flex min-h-full items-center justify-center p-4 text-center">
<Transition.Child
as={Fragment}
enter='ease-out duration-300'
enterFrom='opacity-0 scale-95'
enterTo='opacity-100 scale-100'
leave='ease-in duration-200'
leaveFrom='opacity-100 scale-100'
leaveTo='opacity-0 scale-95'
enter="ease-out duration-300"
enterFrom="opacity-0 scale-95"
enterTo="opacity-100 scale-100"
leave="ease-in duration-200"
leaveFrom="opacity-100 scale-100"
leaveTo="opacity-0 scale-95"
>
<Dialog.Panel className='w-full max-w-md transform overflow-hidden rounded-md bg-bunker border border-mineshaft-500 p-6 pt-5 text-left align-middle shadow-xl transition-all'>
<Dialog.Title
as='h3'
className='text-xl font-medium leading-6 text-primary'
>
<Dialog.Panel className="w-full max-w-md transform overflow-hidden rounded-md border border-mineshaft-500 bg-bunker p-6 pt-5 text-left align-middle shadow-xl transition-all">
<Dialog.Title as="h3" className="text-xl font-medium leading-6 text-primary">
Unleash Infisical&apos;s Full Power
</Dialog.Title>
<div className='mt-2'>
<p className='text-sm text-bunker-300 mb-1'>
{text}
</p>
<p className='text-sm text-bunker-300'>
<div className="mt-2">
<p className="mb-1 text-sm text-bunker-300">{text}</p>
<p className="text-sm text-bunker-300">
Upgrade and get access to this, as well as to other powerful enhancements.
</p>
</div>
<div className='mt-4'>
<div className="mt-4">
<button
type='button'
className='inline-flex justify-center rounded-md border border-transparent bg-primary opacity-80 hover:opacity-100 px-4 py-2 text-sm font-medium text-black hover:text-semibold duration-200 focus:outline-none focus-visible:ring-2 focus-visible:ring-blue-500 focus-visible:ring-offset-2'
type="button"
className="hover:text-semibold inline-flex justify-center rounded-md border border-transparent bg-primary px-4 py-2 text-sm font-medium text-black opacity-80 duration-200 hover:opacity-100 focus:outline-none focus-visible:ring-2 focus-visible:ring-blue-500 focus-visible:ring-offset-2"
onClick={() => router.push(`/org/${currentOrg?.id}/billing`)}
>
Upgrade Now
</button>
<button
type='button'
className='ml-2 inline-flex justify-center rounded-md border border-transparent bg-gray-800 px-4 py-2 text-sm font-medium text-gray-400 hover:border-red hover:text-red hover:text-semibold duration-200 focus:outline-none focus-visible:ring-2 focus-visible:ring-blue-500 focus-visible:ring-offset-2'
type="button"
className="hover:text-semibold ml-2 inline-flex justify-center rounded-md border border-transparent bg-gray-800 px-4 py-2 text-sm font-medium text-gray-400 duration-200 hover:border-red hover:text-red focus:outline-none focus-visible:ring-2 focus-visible:ring-blue-500 focus-visible:ring-offset-2"
onClick={onClose}
>
Maybe Later

View File

@@ -10,7 +10,8 @@ import {
useDeleteUserFromWorkspace,
useGetUserWsKey,
useUpdateUserWorkspaceRole,
useUploadWsKey} from "@app/hooks/api";
useUploadWsKey
} from "@app/hooks/api";
import { decryptAssymmetric, encryptAssymmetric } from "../../utilities/cryptography/crypto";
import guidGenerator from "../../utilities/randomId";
@@ -64,7 +65,7 @@ const ProjectUsersTable = ({ userData, changeData, myUser, filter, isUserListLoa
const handleRoleUpdate = async (index: number, e: string) => {
await updateUserWorkspaceRoleMutateAsync({
membershipId: userData[index].membershipId,
membershipId: userData[index].membershipId,
role: e.toLowerCase()
});
createNotification({
@@ -191,11 +192,15 @@ const ProjectUsersTable = ({ userData, changeData, myUser, filter, isUserListLoa
<UpgradePlanModal
isOpen={isUpgradeModalOpen}
onClose={closeUpgradeModal}
text={subscription.slug === null ? "You can use RBAC under an Enterprise license" : "You can use RBAC if you switch to Infisical's Team Plan."}
text={
subscription.slug === null
? "You can use RBAC under an Enterprise license"
: "You can use RBAC if you switch to Infisical's Team Plan."
}
/>
)}
<table className="my-0.5 w-full">
<thead className="text-xs font-light text-gray-400 bg-mineshaft-800">
<thead className="bg-mineshaft-800 text-xs font-light text-gray-400">
<tr>
<th className="py-3.5 pl-4 text-left">NAME</th>
<th className="py-3.5 pl-4 text-left">EMAIL</th>
@@ -213,12 +218,13 @@ const ProjectUsersTable = ({ userData, changeData, myUser, filter, isUserListLoa
</tr>
</thead>
<tbody>
{!isUserListLoading && userData?.filter(
(user) =>
user.firstName?.toLowerCase().includes(filter) ||
user.lastName?.toLowerCase().includes(filter) ||
user.email?.toLowerCase().includes(filter)
).length > 0 &&
{!isUserListLoading &&
userData?.filter(
(user) =>
user.firstName?.toLowerCase().includes(filter) ||
user.lastName?.toLowerCase().includes(filter) ||
user.email?.toLowerCase().includes(filter)
).length > 0 &&
userData
?.filter(
(user) =>
@@ -373,10 +379,18 @@ const ProjectUsersTable = ({ userData, changeData, myUser, filter, isUserListLoa
</td>
</tr>
))}
{isUserListLoading && <>
<tr key={guidGenerator()} className="bg-mineshaft-800 text-sm animate-pulse h-14 w-full"/>
<tr key={guidGenerator()} className="bg-mineshaft-800 text-sm animate-pulse h-14 w-full"/>
</>}
{isUserListLoading && (
<>
<tr
key={guidGenerator()}
className="h-14 w-full animate-pulse bg-mineshaft-800 text-sm"
/>
<tr
key={guidGenerator()}
className="h-14 w-full animate-pulse bg-mineshaft-800 text-sm"
/>
</>
)}
</tbody>
</table>
</div>

View File

@@ -13,17 +13,27 @@ import { Tag } from "public/data/frequentInterfaces";
* @param {function} obj.modifyTags - modify tags for a certain secret
* @param {Tag[]} obj.position - currently selected tags for a certain secret
*/
const AddTagsMenu = ({ allTags, currentTags, modifyTags, id }: { allTags: Tag[]; currentTags: Tag[]; modifyTags: (value: Tag[], id: string) => void; id: string; }) => {
const AddTagsMenu = ({
allTags,
currentTags,
modifyTags,
id
}: {
allTags: Tag[];
currentTags: Tag[];
modifyTags: (value: Tag[], id: string) => void;
id: string;
}) => {
const router = useRouter();
return (
<Menu as="div" className="ml-2 relative inline-block text-left">
<Menu as="div" className="relative ml-2 inline-block text-left">
<Menu.Button
as="div"
className="flex justify-center items-center font-medium focus:outline-none focus-visible:ring-2 focus-visible:ring-white focus-visible:ring-opacity-75"
className="flex items-center justify-center font-medium focus:outline-none focus-visible:ring-2 focus-visible:ring-white focus-visible:ring-opacity-75"
>
<div className='bg-mineshaft/30 cursor-pointer rounded-sm text-sm text-mineshaft-200/50 hover:bg-mineshaft/70 duration-200 flex items-center'>
<FontAwesomeIcon icon={faPlus} className="p-[0.28rem]"/>
{currentTags?.length > 2 && <span className='pr-2'>{currentTags.length - 2}</span>}
<div className="flex cursor-pointer items-center rounded-sm bg-mineshaft/30 text-sm text-mineshaft-200/50 duration-200 hover:bg-mineshaft/70">
<FontAwesomeIcon icon={faPlus} className="p-[0.28rem]" />
{currentTags?.length > 2 && <span className="pr-2">{currentTags.length - 2}</span>}
</div>
</Menu.Button>
<Transition
@@ -35,24 +45,40 @@ const AddTagsMenu = ({ allTags, currentTags, modifyTags, id }: { allTags: Tag[];
leaveFrom="transform opacity-100 scale-100"
leaveTo="transform opacity-0 scale-95"
>
<Menu.Items className="absolute z-[90] text-sm drop-shadow-xl right-0 mt-0.5 w-[12rem] origin-top-right rounded-md bg-mineshaft-600 border border-mineshaft-500 shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none p-1 space-y-1">
{allTags?.map((tag) => { return (
<Menu.Item key={tag.id}>
<button
type="button"
className={`${currentTags?.map(currentTag => currentTag.name).includes(tag.name) ? "opacity-30 cursor-default" : "hover:bg-mineshaft-700"} w-full text-left bg-mineshaft-800 px-2 py-0.5 text-bunker-200 rounded-sm flex items-center`}
onClick={() => {if (!currentTags?.map(currentTag => currentTag.name).includes(tag.name)) {modifyTags(currentTags.concat([tag]), id)}}}
>
{currentTags?.map(currentTag => currentTag.name).includes(tag.name) ? <FontAwesomeIcon icon={faCheckSquare} className="text-xs mr-2 text-primary"/> : <FontAwesomeIcon icon={faSquare} className="text-xs mr-2"/>} {tag.name}
</button>
</Menu.Item>
)})}
<Menu.Items className="absolute right-0 z-[90] mt-0.5 w-[12rem] origin-top-right space-y-1 rounded-md border border-mineshaft-500 bg-mineshaft-600 p-1 text-sm shadow-lg ring-1 ring-black ring-opacity-5 drop-shadow-xl focus:outline-none">
{allTags?.map((tag) => {
return (
<Menu.Item key={tag.id}>
<button
type="button"
className={`${
currentTags?.map((currentTag) => currentTag.name).includes(tag.name)
? "cursor-default opacity-30"
: "hover:bg-mineshaft-700"
} flex w-full items-center rounded-sm bg-mineshaft-800 px-2 py-0.5 text-left text-bunker-200`}
onClick={() => {
if (!currentTags?.map((currentTag) => currentTag.name).includes(tag.name)) {
modifyTags(currentTags.concat([tag]), id);
}
}}
>
{currentTags?.map((currentTag) => currentTag.name).includes(tag.name) ? (
<FontAwesomeIcon icon={faCheckSquare} className="mr-2 text-xs text-primary" />
) : (
<FontAwesomeIcon icon={faSquare} className="mr-2 text-xs" />
)}{" "}
{tag.name}
</button>
</Menu.Item>
);
})}
<button
type="button"
className='w-full text-left bg-mineshaft-800 hover:bg-primary hover:text-black duration-200 px-2 py-0.5 text-bunker-200 rounded-sm'
className="w-full rounded-sm bg-mineshaft-800 px-2 py-0.5 text-left text-bunker-200 duration-200 hover:bg-primary hover:text-black"
onClick={() => router.push(`/project/${String(router.query.id)}/settings`)}
>
<FontAwesomeIcon icon={faPlus} className="mr-2 text-xs" />Add more tags
<FontAwesomeIcon icon={faPlus} className="mr-2 text-xs" />
Add more tags
</button>
</Menu.Items>
</Transition>

View File

@@ -38,8 +38,7 @@ const colors = [
"bg-[#6F1AB6]/40",
"bg-[#C40B13]/40",
"bg-[#332FD0]/40"
]
];
const colorsText = [
"text-[#fcf0c3]/70",
@@ -50,7 +49,7 @@ const colorsText = [
"text-[#FFE5F1]/70",
"text-[#FFDEDE]/70",
"text-[#DFF6FF]/70"
]
];
/**
* This component represent a single row for an environemnt variable on the dashboard
@@ -83,117 +82,160 @@ const KeyPair = ({
toggleSidebar,
sidebarSecretId,
isCapitalized,
isSnapshot,
isSnapshot,
deleteRow,
togglePITSidebar,
tags
}: KeyPairProps) => {
const tagData = (tags.map((tag, index) => {return {
...tag,
color: colors[index%colors.length],
colorText: colorsText[index%colorsText.length]
}}));
const tagData = tags.map((tag, index) => {
return {
...tag,
color: colors[index % colors.length],
colorText: colorsText[index % colorsText.length]
};
});
return (
<div
className={`group flex flex-col items-center border-b border-mineshaft-500 hover:bg-white/[0.03] duration-100 ${isSnapshot && "pointer-events-none"} ${
keyPair.id === sidebarSecretId && "bg-mineshaft-700 duration-200"
}`}
>
<div className="relative flex flex-row justify-between w-full mr-auto max-h-14 items-center">
<div className="w-[23%] border-r border-mineshaft-600 flex flex-row items-center">
<div className='text-bunker-400 text-xs flex items-center justify-center w-14 h-10 cursor-default'>{keyPair.pos + 1}</div>
<div className="flex items-center max-h-16 w-full">
<DashboardInputField
isCapitalized = {isCapitalized}
onChangeHandler={modifyKey}
type="varName"
id={keyPair.id ? keyPair.id : (keyPair.idOverride || "")}
value={keyPair.key}
isDuplicate={isDuplicate}
overrideEnabled={keyPair.valueOverride !== undefined}
modifyValueOverride={modifyValueOverride}
isSideBarOpen={keyPair.id === sidebarSecretId}
<div
className={`group flex flex-col items-center border-b border-mineshaft-500 duration-100 hover:bg-white/[0.03] ${
isSnapshot && "pointer-events-none"
} ${keyPair.id === sidebarSecretId && "bg-mineshaft-700 duration-200"}`}
>
<div className="relative mr-auto flex max-h-14 w-full flex-row items-center justify-between">
<div className="flex w-[23%] flex-row items-center border-r border-mineshaft-600">
<div className="flex h-10 w-14 cursor-default items-center justify-center text-xs text-bunker-400">
{keyPair.pos + 1}
</div>
<div className="flex max-h-16 w-full items-center">
<DashboardInputField
isCapitalized={isCapitalized}
onChangeHandler={modifyKey}
type="varName"
id={keyPair.id ? keyPair.id : keyPair.idOverride || ""}
value={keyPair.key}
isDuplicate={isDuplicate}
overrideEnabled={keyPair.valueOverride !== undefined}
modifyValueOverride={modifyValueOverride}
isSideBarOpen={keyPair.id === sidebarSecretId}
/>
</div>
</div>
<div className="w-5/12 border-r border-mineshaft-600">
<div className="mt-4 flex max-h-10 items-center rounded-lg md:mt-0">
<DashboardInputField
onChangeHandler={
keyPair.valueOverride !== undefined ? modifyValueOverride : modifyValue
}
type="value"
id={keyPair.id ? keyPair.id : keyPair.idOverride || ""}
value={keyPair.valueOverride !== undefined ? keyPair.valueOverride : keyPair.value}
blurred={isBlurred}
overrideEnabled={keyPair.valueOverride !== undefined}
isSideBarOpen={keyPair.id === sidebarSecretId}
/>
</div>
</div>
<div className="w-[calc(10%)] border-r border-mineshaft-600">
<div className="flex max-h-16 items-center">
<DashboardInputField
onChangeHandler={modifyComment}
type="comment"
id={keyPair.id ? keyPair.id : keyPair.idOverride || ""}
value={keyPair.comment}
isDuplicate={isDuplicate}
isSideBarOpen={keyPair.id === sidebarSecretId}
/>
</div>
</div>
</div>
<div className="overflow-r-scroll no-scrollbar::-webkit-scrollbar flex h-10 w-2/12 items-center overflow-visible no-scrollbar">
<div className="flex max-h-16 items-center">
{keyPair.tags?.map(
(tag, index) =>
index < 2 && (
<div
key={keyPair.pos}
className={`ml-2 px-1.5 ${
tagData.filter((tagDp) => tagDp.id === tag.id)[0]?.color
} rounded-sm text-sm ${
tagData.filter((tagDp) => tagDp.id === tag.id)[0]?.colorText
} flex items-center`}
>
<span className="mb-0.5 cursor-default">{tag.name}</span>
<FontAwesomeIcon
icon={faXmark}
className="ml-1 cursor-pointer p-1"
onClick={() =>
modifyTags(
keyPair.tags.filter((ttag) => ttag.id !== tag.id),
keyPair.id
)
}
/>
</div>
)
)}
<AddTagsMenu
allTags={tags}
currentTags={keyPair.tags}
modifyTags={modifyTags}
id={keyPair.id ? keyPair.id : keyPair.idOverride || ""}
/>
</div>
</div>
<div className="w-5/12 border-r border-mineshaft-600">
<div
className='flex items-center rounded-lg mt-4 md:mt-0 max-h-10'
>
<DashboardInputField
onChangeHandler={keyPair.valueOverride !== undefined ? modifyValueOverride : modifyValue}
type="value"
id={keyPair.id ? keyPair.id : (keyPair.idOverride || "")}
value={keyPair.valueOverride !== undefined ? keyPair.valueOverride : keyPair.value}
blurred={isBlurred}
overrideEnabled={keyPair.valueOverride !== undefined}
isSideBarOpen={keyPair.id === sidebarSecretId}
/>
</div>
</div>
<div className="w-[calc(10%)] border-r border-mineshaft-600">
<div className="flex items-center max-h-16">
<DashboardInputField
onChangeHandler={modifyComment}
type="comment"
id={keyPair.id ? keyPair.id : (keyPair.idOverride || "")}
value={keyPair.comment}
isDuplicate={isDuplicate}
isSideBarOpen={keyPair.id === sidebarSecretId}
/>
</div>
</div>
<div className="w-2/12 h-10 flex items-center overflow-visible overflow-r-scroll no-scrollbar no-scrollbar::-webkit-scrollbar">
<div className="flex items-center max-h-16">
{keyPair.tags?.map((tag, index) => (
index < 2 && <div key={keyPair.pos} className={`ml-2 px-1.5 ${tagData.filter(tagDp => tagDp.id === tag.id)[0]?.color} rounded-sm text-sm ${tagData.filter(tagDp => tagDp.id === tag.id)[0]?.colorText} flex items-center`}>
<span className='mb-0.5 cursor-default'>{tag.name}</span>
<FontAwesomeIcon icon={faXmark} className="ml-1 cursor-pointer p-1" onClick={() => modifyTags(keyPair.tags.filter(ttag => ttag.id !== tag.id), keyPair.id)}/>
</div>
))}
<AddTagsMenu allTags={tags} currentTags={keyPair.tags} modifyTags={modifyTags} id={keyPair.id ? keyPair.id : (keyPair.idOverride || "")} />
</div>
</div>
<div
onKeyDown={() => null}
role="button"
tabIndex={0}
onClick={() => {
if (togglePITSidebar) {
togglePITSidebar(false);
}
toggleSidebar(keyPair.id)
}}
className={`cursor-pointer w-[1.5rem] h-[2.35rem] ml-auto group-hover:bg-mineshaft-700 z-50 rounded-md invisible group-hover:visible flex flex-row justify-center items-center ${isSnapshot ?? "invisible"}`}
>
<FontAwesomeIcon className="text-bunker-300 hover:text-primary text-lg" icon={faEllipsis} />
</div>
<div className={`group-hover:bg-mineshaft-700 z-50 ${isSnapshot ?? "invisible"}`}>
{keyPair.key || keyPair.value
? <DeleteActionButton
onSubmit={() => { if (deleteRow) {
deleteRow({ ids: [keyPair.id], secretName: keyPair?.key })
}}}
isPlain
/>
: <div className='cursor-pointer w-[1.5rem] h-[2.35rem] mr-2 flex items-center justfy-center'>
<div
onKeyDown={() => null}
role="button"
tabIndex={0}
onClick={() => { if (deleteRow) {
deleteRow({ ids: [keyPair.id], secretName: keyPair?.key })
}}}
className="invisible group-hover:visible"
onClick={() => {
if (togglePITSidebar) {
togglePITSidebar(false);
}
toggleSidebar(keyPair.id);
}}
className={`invisible z-50 ml-auto flex h-[2.35rem] w-[1.5rem] cursor-pointer flex-row items-center justify-center rounded-md group-hover:visible group-hover:bg-mineshaft-700 ${
isSnapshot ?? "invisible"
}`}
>
<FontAwesomeIcon className="text-bunker-300 hover:text-red pl-2 pr-6 text-lg mt-0.5" icon={faXmark} />
<FontAwesomeIcon
className="text-lg text-bunker-300 hover:text-primary"
icon={faEllipsis}
/>
</div>
<div className={`z-50 group-hover:bg-mineshaft-700 ${isSnapshot ?? "invisible"}`}>
{keyPair.key || keyPair.value ? (
<DeleteActionButton
onSubmit={() => {
if (deleteRow) {
deleteRow({ ids: [keyPair.id], secretName: keyPair?.key });
}
}}
isPlain
/>
) : (
<div className="justfy-center mr-2 flex h-[2.35rem] w-[1.5rem] cursor-pointer items-center">
<div
onKeyDown={() => null}
role="button"
tabIndex={0}
onClick={() => {
if (deleteRow) {
deleteRow({ ids: [keyPair.id], secretName: keyPair?.key });
}
}}
className="invisible group-hover:visible"
>
<FontAwesomeIcon
className="mt-0.5 pl-2 pr-6 text-lg text-bunker-300 hover:text-red"
icon={faXmark}
/>
</div>
</div>
)}
</div>
</div>}
</div>
</div>
</div>
)};
);
};
export default KeyPair;

View File

@@ -157,7 +157,7 @@ export default function NavHeader({
})}
{isProtectedBranch && (
<Tooltip content={`Protected by policy ${protectionPolicyName}`}>
<FontAwesomeIcon icon={faLock} className="text-primary ml-2" />
<FontAwesomeIcon icon={faLock} className="ml-2 text-primary" />
</Tooltip>
)}
</div>

View File

@@ -119,9 +119,9 @@ export const CreateTagModal = ({ isOpen, onToggle }: Props): JSX.Element => {
const [showHexInput, setShowHexInput] = useState<boolean>(false);
const selectedTagColor = watch("color", secretTagsColors[0].hex);
useEffect(()=>{
if(!isOpen) reset();
},[isOpen])
useEffect(() => {
if (!isOpen) reset();
}, [isOpen]);
const onFormSubmit = async ({ name, color }: FormData) => {
try {
@@ -168,21 +168,21 @@ export const CreateTagModal = ({ isOpen, onToggle }: Props): JSX.Element => {
Tag Color
</div>
<div className="flex space-x-2">
<div className="p-2 rounded flex items-center justify-center border border-mineshaft-500 bg-mineshaft-900 ">
<div className="flex items-center justify-center rounded border border-mineshaft-500 bg-mineshaft-900 p-2 ">
<div
className="w-6 h-6 rounded-full"
className="h-6 w-6 rounded-full"
style={{ background: `${selectedTagColor}` }}
/>
</div>
<div className="flex-grow flex items-center rounded border-mineshaft-500 bg-mineshaft-900 px-1 pr-2">
<div className="flex flex-grow items-center rounded border-mineshaft-500 bg-mineshaft-900 px-1 pr-2">
{!showHexInput ? (
<div className="inline-flex gap-3 items-center pl-3">
<div className="inline-flex items-center gap-3 pl-3">
{secretTagsColors.map(($tagColor: TagColor) => {
return (
<div key={`tag-color-${$tagColor.id}`}>
<Tooltip content={`${$tagColor.name}`}>
<div
className=" flex items-center justify-center w-[26px] h-[26px] hover:ring-offset-2 hover:ring-2 bg-[#bec2c8] border-2 p-2 hover:shadow-lg border-transparent hover:border-black rounded-full"
className=" flex h-[26px] w-[26px] items-center justify-center rounded-full border-2 border-transparent bg-[#bec2c8] p-2 hover:border-black hover:shadow-lg hover:ring-2 hover:ring-offset-2"
key={`tag-${$tagColor.id}`}
style={{ backgroundColor: `${$tagColor.hex}` }}
onClick={() => setValue("color", $tagColor.hex)}
@@ -200,18 +200,18 @@ export const CreateTagModal = ({ isOpen, onToggle }: Props): JSX.Element => {
})}
</div>
) : (
<div className="flex flex-grow items-center px-2 tags-hex-wrapper">
<div className="flex items-center relative rounded-md ">
<div className="tags-hex-wrapper flex flex-grow items-center px-2">
<div className="relative flex items-center rounded-md ">
{isValidHexColor(selectedTagColor) && (
<div
className="w-7 h-7 rounded-full flex items-center justify-center"
className="flex h-7 w-7 items-center justify-center rounded-full"
style={{ background: `${selectedTagColor}` }}
>
<FontAwesomeIcon icon={faCheck} style={{ color: "#00000070" }} />
</div>
)}
{!isValidHexColor(selectedTagColor) && (
<div className="border-dashed border bg-blue rounded-full w-7 h-7 border-mineshaft-500" />
<div className="bg-blue h-7 w-7 rounded-full border border-dashed border-mineshaft-500" />
)}
</div>
<div className="flex-grow">
@@ -225,10 +225,10 @@ export const CreateTagModal = ({ isOpen, onToggle }: Props): JSX.Element => {
</div>
</div>
)}
<div className="border-mineshaft-500 border h-8 mx-4" />
<div className="w-7 h-7 flex items-center justify-center">
<div className="mx-4 h-8 border border-mineshaft-500" />
<div className="flex h-7 w-7 items-center justify-center">
<div
className={`flex items-center justify-center w-7 h-7 bg-transparent cursor-pointer hover:ring-offset-1 hover:ring-2 border-mineshaft-500 border bg-mineshaft-900 rounded-sm p-2 ${
className={`flex h-7 w-7 cursor-pointer items-center justify-center rounded-sm border border-mineshaft-500 bg-transparent bg-mineshaft-900 p-2 hover:ring-2 hover:ring-offset-1 ${
showHexInput ? "tags-conic-bg rounded-full" : ""
}`}
onClick={() => setShowHexInput((prev) => !prev)}

View File

@@ -1,12 +1,6 @@
const ENV = process.env.NEXT_PUBLIC_ENV! || "development"; // investigate
const POSTHOG_API_KEY = process.env.NEXT_PUBLIC_POSTHOG_API_KEY!;
const POSTHOG_HOST =
process.env.NEXT_PUBLIC_POSTHOG_HOST! || "https://app.posthog.com";
const POSTHOG_HOST = process.env.NEXT_PUBLIC_POSTHOG_HOST! || "https://app.posthog.com";
const INTERCOMid = process.env.NEXT_PUBLIC_INTERCOMid!;
export {
ENV,
INTERCOMid,
POSTHOG_API_KEY,
POSTHOG_HOST
};
export { ENV, INTERCOMid, POSTHOG_API_KEY, POSTHOG_HOST };

View File

@@ -54,11 +54,9 @@ export const load = () => {
// Initializes Intercom
export const boot = (options = {}) => {
window &&
window.Intercom &&
window.Intercom("boot", { appid: APPid, ...options });
window && window.Intercom && window.Intercom("boot", { appid: APPid, ...options });
};
export const update = () => {
window && window.Intercom && window.Intercom("update");
};
};

View File

@@ -22,7 +22,7 @@ export const OrgPermissionProvider = ({ children }: Props): JSX.Element => {
if (isLoading) {
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
src="/images/loading/loading.gif"
height={70}
@@ -35,7 +35,7 @@ export const OrgPermissionProvider = ({ children }: Props): JSX.Element => {
if (!permission) {
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">
Failed to load user permissions
</div>
);

View File

@@ -3,7 +3,6 @@ import { createContext, ReactNode, useContext, useMemo } from "react";
import { useGetOrganizations } from "@app/hooks/api";
import { Organization } from "@app/hooks/api/types";
type TOrgContext = {
orgs?: Organization[];
currentOrg?: Organization;
@@ -18,7 +17,7 @@ type Props = {
export const OrgProvider = ({ children }: Props): JSX.Element => {
const { data: userOrgs, isLoading } = useGetOrganizations();
// const currentWsOrgID = currentWorkspace?.organization;
const currentWsOrgID = localStorage.getItem("orgData.id");

View File

@@ -18,7 +18,7 @@ export const ProjectPermissionProvider = ({ children }: Props): JSX.Element => {
if ((isLoading && currentWorkspace) || isWsLoading) {
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
src="/images/loading/loading.gif"
height={70}
@@ -31,7 +31,7 @@ export const ProjectPermissionProvider = ({ children }: Props): JSX.Element => {
if (!permission && currentWorkspace) {
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">
Failed to load user permissions
</div>
);

View File

@@ -72,9 +72,9 @@ export const ServerConfigProvider = ({ children }: Props): JSX.Element => {
export const useServerConfig = () => {
const ctx = useContext(ServerConfigContext);
// if (!ctx) {
// throw new Error("useServerConfig has to be used within <UserContext.Provider>");
// }
if (!ctx) {
throw new Error("useServerConfig has to be used within <UserContext.Provider>");
}
return ctx || { config: { allowSignUp: true } };
return ctx;
};

View File

@@ -1,10 +1,10 @@
import { createContext, ReactNode, useContext, useMemo } from "react";
import { useGetUser } from "@app/hooks/api";
import { User } from "@app/hooks/api/types";
import { User, UserEnc } from "@app/hooks/api/types";
type TUserContext = {
user: User;
user: User & UserEnc;
isLoading: boolean;
};

View File

@@ -26,7 +26,7 @@ export const WorkspaceProvider = ({ children }: Props): JSX.Element => {
const wsId = workspaceId || localStorage.getItem("projectData.id");
return {
workspaces: ws || [],
currentWorkspace: (ws || []).find(({ id: id }) => id === wsId),
currentWorkspace: (ws || []).find(({ id }) => id === wsId),
isLoading
};
}, [ws, workspaceId, isLoading]);

View File

@@ -112,8 +112,8 @@ const initProjectHelper = async ({
});
await uploadWsKey({
workspaceId: workspace._id,
userId: user._id,
workspaceId: workspace.id,
userId: user.id,
encryptedKey: ciphertext,
nonce
});
@@ -121,13 +121,13 @@ const initProjectHelper = async ({
// encrypt and upload secrets to new project
const secrets = await encryptSecrets({
secretsToEncrypt: secretsToBeAdded,
workspaceId: workspace._id,
workspaceId: workspace.id,
env: "dev"
});
secrets?.forEach((secret) => {
createSecret({
workspaceId: workspace._id,
workspaceId: workspace.id,
environment: secret.environment,
type: secret.type,
secretKey: secret.secretName,

View File

@@ -1,27 +1,27 @@
export type APIKeyDataV2 = {
id: string;
name: string;
user: string;
lastUsed?: string;
usageCount: number;
createdAt: string;
updatedAt: string;
};
id: string;
name: string;
user: string;
lastUsed?: string;
usageCount: number;
createdAt: string;
updatedAt: string;
};
export type CreateAPIKeyDataV2DTO = {
name: string;
}
name: string;
};
export type CreateServiceTokenDataV3Res = {
apiKeyData: APIKeyDataV2;
apiKey: string;
}
apiKeyData: APIKeyDataV2;
apiKey: string;
};
export type UpdateAPIKeyDataV2DTO = {
apiKeyDataId: string;
name: string;
}
apiKeyDataId: string;
name: string;
};
export type DeleteAPIKeyDataV2DTO = {
apiKeyDataId: string;
}
apiKeyDataId: string;
};

View File

@@ -194,7 +194,8 @@ interface DeleteServiceTokenEvent {
};
}
interface CreateIdentityEvent { // note: currently not logging org-role
interface CreateIdentityEvent {
// note: currently not logging org-role
type: EventType.CREATE_IDENTITY;
metadata: {
identityId: string;
@@ -218,7 +219,7 @@ interface DeleteIdentityEvent {
}
interface LoginIdentityUniversalAuthEvent {
type: EventType.LOGIN_IDENTITY_UNIVERSAL_AUTH ;
type: EventType.LOGIN_IDENTITY_UNIVERSAL_AUTH;
metadata: {
identityId: string;
identityUniversalAuthId: string;
@@ -259,7 +260,7 @@ interface GetIdentityUniversalAuthEvent {
}
interface CreateIdentityUniversalAuthClientSecretEvent {
type: EventType.CREATE_IDENTITY_UNIVERSAL_AUTH_CLIENT_SECRET ;
type: EventType.CREATE_IDENTITY_UNIVERSAL_AUTH_CLIENT_SECRET;
metadata: {
identityId: string;
clientSecretId: string;
@@ -273,9 +274,8 @@ interface GetIdentityUniversalAuthClientSecretsEvent {
};
}
interface RevokeIdentityUniversalAuthClientSecretEvent {
type: EventType.REVOKE_IDENTITY_UNIVERSAL_AUTH_CLIENT_SECRET ;
type: EventType.REVOKE_IDENTITY_UNIVERSAL_AUTH_CLIENT_SECRET;
metadata: {
identityId: string;
clientSecretId: string;
@@ -507,7 +507,7 @@ export type Event =
| UpdateUserDeniedPermissions;
export type AuditLog = {
_id: string;
id: string;
actor: Actor;
organization: string;
workspace: string;

View File

@@ -55,14 +55,14 @@ export type BitBucketWorkspace = {
uuid: string;
name: string;
slug: string;
}
};
export type NorthflankSecretGroup = {
name: string;
groupId: string;
}
};
export type TeamCityBuildConfig = {
name: string;
buildConfigId: string;
}
};

View File

@@ -32,9 +32,9 @@ export type TIntegration = {
__v: number;
metadata?: {
secretSuffix?: string;
scope: string;
scope: string;
org: string;
project: string;
environment: string;
}
};
};

View File

@@ -13,7 +13,7 @@ export type RenameOrgDTO = {
export type BillingDetails = {
name: string;
email: string;
}
};
export type PlanBillingInfo = {
amount: number;
@@ -22,7 +22,7 @@ export type PlanBillingInfo = {
interval: "month" | "year";
intervalCount: number;
quantity: number;
}
};
export type Invoice = {
id: string;
@@ -31,23 +31,23 @@ export type Invoice = {
number: string;
paid: boolean;
total: number;
}
};
export type PmtMethod = {
id: string;
brand: string;
exp_month: number;
exp_month: number;
exp_year: number;
funding: string;
last4: string;
}
};
export type TaxID = {
id: string;
country: string;
type: string;
value: string;
}
};
export type License = {
id: string;
@@ -58,22 +58,22 @@ export type License = {
expiresAt: string;
createdAt: string;
updatedAt: string;
}
};
export type OrgPlanTableHead = {
name: string;
}
};
export type OrgPlanTableRow = {
name: string;
allowed: number | boolean | null;
used: string;
}
};
export type OrgPlanTable = {
head: OrgPlanTableHead[];
rows: OrgPlanTableRow[];
}
};
export type ProductsTableHead = {
name: string;
@@ -82,7 +82,7 @@ export type ProductsTableHead = {
productId: string;
slug: string;
tier: number;
}
};
export type ProductsTableRow = {
name: string;
@@ -90,9 +90,9 @@ export type ProductsTableRow = {
team: number | boolean | null;
pro: number | boolean | null;
enterprise: number | boolean | null;
}
};
export type ProductsTable = {
head: ProductsTableHead[];
rows: ProductsTableRow[];
}
};

View File

@@ -4,7 +4,7 @@ export type ServiceTokenScope = {
};
export type ServiceToken = {
_id: string;
id: string;
name: string;
workspace: string;
scopes: ServiceTokenScope[];
@@ -32,4 +32,4 @@ export type CreateServiceTokenRes = {
serviceTokenData: ServiceToken;
};
export type DeleteServiceTokenRes = { serviceTokenData: ServiceToken };
export type DeleteServiceTokenRes = { serviceTokenData: ServiceToken };

View File

@@ -9,7 +9,7 @@ export type WsTag = {
createdAt: string;
updatedAt: string;
__v: number;
}
};
export type WorkspaceTag = { id: string; name: string; slug: string };
@@ -30,7 +30,7 @@ export type CreateTagRes = {
id: string;
};
export type DeleteTagDTO = { tagID: string; };
export type DeleteTagDTO = { tagID: string };
export type DeleteWsTagRes = {
name: string;
@@ -41,17 +41,16 @@ export type DeleteWsTagRes = {
id: string;
};
export type SecretTags = {
id: string;
export type SecretTags = {
id: string;
slug: string;
slug: string;
tagColor: string;
}
};
export type TagColor = {
export type TagColor = {
id: number;
hex: string
rgba: string
name: string
selected: boolean
}
hex: string;
rgba: string;
name: string;
selected: boolean;
};

View File

@@ -1,9 +1,9 @@
export type TrustedIp = {
id: string;
workspace: string;
ipAddress: string;
type: "ipv4" | "ipv6";
isActive: boolean;
comment: string;
prefix?: number;
};
id: string;
workspace: string;
ipAddress: string;
type: "ipv4" | "ipv6";
isActive: boolean;
comment: string;
prefix?: number;
};

View File

@@ -23,7 +23,7 @@ export * from "./secrets/types";
export type { CreateServiceTokenDTO, ServiceToken } from "./serviceTokens/types";
export type { SubscriptionPlan } from "./subscriptions/types";
export type { WsTag } from "./tags/types";
export type { AddUserToWsDTO, OrgUser, TWorkspaceUser, User } from "./users/types";
export type { AddUserToWsDTO, OrgUser, TWorkspaceUser, User, UserEnc } from "./users/types";
export type { TWebhook } from "./webhooks/types";
export type {
CreateEnvironmentDTO,

View File

@@ -14,7 +14,8 @@ import {
RenameUserDTO,
TokenVersion,
UpdateOrgUserRoleDTO,
User
User,
UserEnc
} from "./types";
export const userKeys = {
@@ -29,7 +30,7 @@ export const userKeys = {
};
export const fetchUserDetails = async () => {
const { data } = await apiRequest.get<{ user: User }>("/api/v1/user");
const { data } = await apiRequest.get<{ user: User & UserEnc }>("/api/v1/user");
return data.user;
};

View File

@@ -19,6 +19,12 @@ export type User = {
lastName?: string;
authProvider?: AuthMethod;
authMethods: AuthMethod[];
isMfaEnabled: boolean;
seenIps: string[];
id: string;
};
export type UserEnc = {
encryptionVersion?: number;
protectedKey?: string;
protectedKeyIV?: string;
@@ -27,19 +33,15 @@ export type User = {
encryptedPrivateKey?: string;
iv?: string;
tag?: string;
isMfaEnabled: boolean;
seenIps: string[];
_id: string;
__v: number;
};
export type OrgUser = {
_id: string;
id: string;
user: {
email: string;
firstName: string;
lastName: string;
_id: string;
id: string;
publicKey: string;
};
inviteEmail: string;
@@ -88,7 +90,7 @@ export type RenameUserDTO = {
};
export type APIKeyData = {
_id: string;
id: string;
name: string;
user: string;
lastUsed: string;
@@ -97,7 +99,7 @@ export type APIKeyData = {
};
export type TokenVersion = {
_id: string;
id: string;
user: string;
userAgent: string;
ip: string;

View File

@@ -22,7 +22,7 @@ export type NameWorkspaceSecretsDTO = {
secretName: string;
id: string;
}[];
}
};
// mutation dto
export type CreateWorkspaceDTO = {
@@ -47,7 +47,6 @@ export type ReorderEnvironmentsDTO = {
environmentName: string;
otherEnvironmentSlug: string;
otherEnvironmentName: string;
};
export type UpdateEnvironmentDTO = {
@@ -57,4 +56,4 @@ export type UpdateEnvironmentDTO = {
environmentName: string;
};
export type DeleteEnvironmentDTO = { workspaceID: string; environmentSlug: string };
export type DeleteEnvironmentDTO = { workspaceID: string; environmentSlug: string };

View File

@@ -100,7 +100,7 @@ export const AdminLayout = ({ children }: LayoutProps) => {
<nav className="items-between flex h-full flex-col justify-between overflow-y-auto dark:[color-scheme:dark]">
<div>
{!router.asPath.includes("personal") && (
<div className="flex h-12 cursor-default justify-between items-center px-3 pt-6">
<div className="flex h-12 cursor-default items-center justify-between px-3 pt-6">
<Link href={`/org/${currentOrg?.id}/overview`}>
<div className="my-6 flex cursor-default items-center justify-center pr-2 text-sm text-mineshaft-300 hover:text-mineshaft-100">
<FontAwesomeIcon icon={faArrowLeft} className="pr-3" />
@@ -179,7 +179,7 @@ export const AdminLayout = ({ children }: LayoutProps) => {
<div
className={`${
!updateClosed ? "block" : "hidden"
} relative z-10 mb-6 flex pb-2 w-52 flex-col items-center justify-start rounded-md border border-mineshaft-600 bg-mineshaft-900 px-3`}
} relative z-10 mb-6 flex w-52 flex-col items-center justify-start rounded-md border border-mineshaft-600 bg-mineshaft-900 px-3 pb-2`}
>
<div className="text-md mt-2 w-full font-semibold text-mineshaft-100">
Infisical December update

View File

@@ -120,7 +120,7 @@ export const AppLayout = ({ children }: LayoutProps) => {
const { user } = useUser();
const { subscription } = useSubscription();
const workspaceId = currentWorkspace?._id || "";
const workspaceId = currentWorkspace?.id || "";
const { data: updateClosed } = useGetUserAction("december_update_closed");
const { data: secretApprovalReqCount } = useGetSecretApprovalRequestCount({ workspaceId });
@@ -179,19 +179,19 @@ export const AppLayout = ({ children }: LayoutProps) => {
// Put a user in an org if they're not in one yet
const putUserInOrg = async () => {
if (tempLocalStorage("orgData.id") === "") {
localStorage.setItem("orgData.id", orgs[0]?._id);
localStorage.setItem("orgData.id", orgs[0]?.id);
}
if (
currentOrg &&
((workspaces?.length === 0 && router.asPath.includes("project")) ||
router.asPath.includes("/project/undefined") ||
(!orgs?.map((org) => org._id)?.includes(router.query.id) &&
(!orgs?.map((org) => org.id)?.includes(router.query.id) &&
!router.asPath.includes("project") &&
!router.asPath.includes("personal") &&
!router.asPath.includes("integration")))
) {
router.push(`/org/${currentOrg?._id}/overview`);
router.push(`/org/${currentOrg?.id}/overview`);
}
// else if (!router.asPath.includes("org") && !router.asPath.includes("project") && !router.asPath.includes("integrations") && !router.asPath.includes("personal-settings")) {
@@ -221,14 +221,14 @@ export const AppLayout = ({ children }: LayoutProps) => {
const onCreateProject = async ({ name, addMembers }: TAddProjectFormData) => {
// type check
if (!currentOrg?._id) return;
if (!currentOrg?.id) return;
try {
const {
data: {
workspace: { _id: newWorkspaceId }
workspace: { id: newWorkspaceId }
}
} = await createWs.mutateAsync({
organizationId: currentOrg?._id,
organizationId: currentOrg?.id,
workspaceName: name
});
@@ -243,13 +243,13 @@ export const AppLayout = ({ children }: LayoutProps) => {
await uploadWsKey.mutateAsync({
encryptedKey: ciphertext,
nonce,
userId: user?._id,
userId: user?.id,
workspaceId: newWorkspaceId
});
if (addMembers) {
// not using hooks because need at this point only
const orgUsers = await fetchOrgUsers(currentOrg._id);
const orgUsers = await fetchOrgUsers(currentOrg.id);
const decryptKey = await fetchUserWsKey(newWorkspaceId);
await addWsUser.mutateAsync({
workspaceId: newWorkspaceId,
@@ -259,7 +259,7 @@ export const AppLayout = ({ children }: LayoutProps) => {
.filter(
({ status, user: orgUser }) => status === "accepted" && user.email !== orgUser.email
)
.map(({ user: orgUser, _id: orgMembershipId }) => ({
.map(({ user: orgUser, id: orgMembershipId }) => ({
userPublicKey: orgUser.publicKey,
orgMembershipId
}))
@@ -285,7 +285,7 @@ export const AppLayout = ({ children }: LayoutProps) => {
<div className="flex h-12 cursor-default items-center px-3 pt-6">
{(router.asPath.includes("project") ||
router.asPath.includes("integrations")) && (
<Link href={`/org/${currentOrg?._id}/overview`}>
<Link href={`/org/${currentOrg?.id}/overview`}>
<div className="pl-1 pr-2 text-mineshaft-400 duration-200 hover:text-mineshaft-100">
<FontAwesomeIcon icon={faArrowLeft} />
</div>
@@ -298,7 +298,7 @@ export const AppLayout = ({ children }: LayoutProps) => {
{currentOrg?.name.charAt(0)}
</div>
<div
className="pl-2 text-sm text-mineshaft-100 text-ellipsis overflow-hidden"
className="overflow-hidden text-ellipsis pl-2 text-sm text-mineshaft-100"
style={{ maxWidth: "140px" }}
>
{currentOrg?.name}
@@ -312,15 +312,15 @@ export const AppLayout = ({ children }: LayoutProps) => {
<DropdownMenuContent align="start" className="p-1">
<div className="px-2 py-1 text-xs text-mineshaft-400">{user?.email}</div>
{orgs?.map((org) => (
<DropdownMenuItem key={org._id}>
<DropdownMenuItem key={org.id}>
<Button
onClick={() => changeOrg(org?._id)}
onClick={() => changeOrg(org?.id)}
variant="plain"
colorSchema="secondary"
size="xs"
className="flex w-full items-center justify-start p-0 font-normal"
leftIcon={
currentOrg._id === org._id && (
currentOrg.id === org.id && (
<FontAwesomeIcon icon={faCheck} className="mr-3 text-primary" />
)
}
@@ -421,8 +421,8 @@ export const AppLayout = ({ children }: LayoutProps) => {
Project
</p>
<Select
defaultValue={currentWorkspace?._id}
value={currentWorkspace?._id}
defaultValue={currentWorkspace?.id}
value={currentWorkspace?.id}
className="w-full truncate bg-mineshaft-600 py-2.5 font-medium"
onValueChange={(value) => {
router.push(`/project/${value}/secrets/overview`);
@@ -433,12 +433,12 @@ export const AppLayout = ({ children }: LayoutProps) => {
>
<div className="no-scrollbar::-webkit-scrollbar h-full no-scrollbar">
{workspaces
.filter((ws) => ws.organization === currentOrg?._id)
.map(({ _id, name }) => (
.filter((ws) => ws.organization === currentOrg?.id)
.map(({ id, name }) => (
<SelectItem
key={`ws-layout-list-${_id}`}
value={_id}
className={`${currentWorkspace?._id === _id && "bg-mineshaft-600"}`}
key={`ws-layout-list-${id}`}
value={id}
className={`${currentWorkspace?.id === id && "bg-mineshaft-600"}`}
>
{name}
</SelectItem>
@@ -474,7 +474,7 @@ export const AppLayout = ({ children }: LayoutProps) => {
</Select>
</div>
) : (
<Link href={`/org/${currentOrg?._id}/overview`}>
<Link href={`/org/${currentOrg?.id}/overview`}>
<div className="my-6 flex cursor-default items-center justify-center pr-2 text-sm text-mineshaft-300 hover:text-mineshaft-100">
<FontAwesomeIcon icon={faArrowLeft} className="pr-3" />
Back to organization
@@ -485,11 +485,11 @@ export const AppLayout = ({ children }: LayoutProps) => {
{(router.asPath.includes("project") || router.asPath.includes("integrations")) &&
currentWorkspace ? (
<Menu>
<Link href={`/project/${currentWorkspace?._id}/secrets/overview`} passHref>
<Link href={`/project/${currentWorkspace?.id}/secrets/overview`} passHref>
<a>
<MenuItem
isSelected={router.asPath.includes(
`/project/${currentWorkspace?._id}/secrets`
`/project/${currentWorkspace?.id}/secrets`
)}
icon="system-outline-90-lock-closed"
>
@@ -497,11 +497,11 @@ export const AppLayout = ({ children }: LayoutProps) => {
</MenuItem>
</a>
</Link>
<Link href={`/project/${currentWorkspace?._id}/members`} passHref>
<Link href={`/project/${currentWorkspace?.id}/members`} passHref>
<a>
<MenuItem
isSelected={
router.asPath === `/project/${currentWorkspace?._id}/members`
router.asPath === `/project/${currentWorkspace?.id}/members`
}
icon="system-outline-96-groups"
>
@@ -509,7 +509,7 @@ export const AppLayout = ({ children }: LayoutProps) => {
</MenuItem>
</a>
</Link>
<Link href={`/integrations/${currentWorkspace?._id}`} passHref>
<Link href={`/integrations/${currentWorkspace?.id}`} passHref>
<a>
<MenuItem
isSelected={router.asPath.includes("/integrations")}
@@ -519,11 +519,11 @@ export const AppLayout = ({ children }: LayoutProps) => {
</MenuItem>
</a>
</Link>
<Link href={`/project/${currentWorkspace?._id}/secret-rotation`} passHref>
<Link href={`/project/${currentWorkspace?.id}/secret-rotation`} passHref>
<a className="relative">
<MenuItem
isSelected={
router.asPath === `/project/${currentWorkspace?._id}/secret-rotation`
router.asPath === `/project/${currentWorkspace?.id}/secret-rotation`
}
icon="rotation"
>
@@ -531,11 +531,11 @@ export const AppLayout = ({ children }: LayoutProps) => {
</MenuItem>
</a>
</Link>
<Link href={`/project/${currentWorkspace?._id}/approval`} passHref>
<Link href={`/project/${currentWorkspace?.id}/approval`} passHref>
<a className="relative">
<MenuItem
isSelected={
router.asPath === `/project/${currentWorkspace?._id}/approval`
router.asPath === `/project/${currentWorkspace?.id}/approval`
}
icon="system-outline-189-domain-verification"
>
@@ -548,11 +548,11 @@ export const AppLayout = ({ children }: LayoutProps) => {
</MenuItem>
</a>
</Link>
<Link href={`/project/${currentWorkspace?._id}/audit-logs`} passHref>
<Link href={`/project/${currentWorkspace?.id}/audit-logs`} passHref>
<a>
<MenuItem
isSelected={
router.asPath === `/project/${currentWorkspace?._id}/audit-logs`
router.asPath === `/project/${currentWorkspace?.id}/audit-logs`
}
icon="system-outline-168-view-headline"
>
@@ -560,11 +560,11 @@ export const AppLayout = ({ children }: LayoutProps) => {
</MenuItem>
</a>
</Link>
<Link href={`/project/${currentWorkspace?._id}/settings`} passHref>
<Link href={`/project/${currentWorkspace?.id}/settings`} passHref>
<a>
<MenuItem
isSelected={
router.asPath === `/project/${currentWorkspace?._id}/settings`
router.asPath === `/project/${currentWorkspace?.id}/settings`
}
icon="system-outline-109-slider-toggle-settings"
>
@@ -575,7 +575,7 @@ export const AppLayout = ({ children }: LayoutProps) => {
</Menu>
) : (
<Menu className="mt-4">
<Link href={`/org/${currentOrg?._id}/overview`} passHref>
<Link href={`/org/${currentOrg?.id}/overview`} passHref>
<a>
<MenuItem
isSelected={router.asPath.includes("/overview")}
@@ -585,40 +585,40 @@ export const AppLayout = ({ children }: LayoutProps) => {
</MenuItem>
</a>
</Link>
<Link href={`/org/${currentOrg?._id}/members`} passHref>
<Link href={`/org/${currentOrg?.id}/members`} passHref>
<a>
<MenuItem
isSelected={router.asPath === `/org/${currentOrg?._id}/members`}
isSelected={router.asPath === `/org/${currentOrg?.id}/members`}
icon="system-outline-96-groups"
>
Access Control
</MenuItem>
</a>
</Link>
<Link href={`/org/${currentOrg?._id}/secret-scanning`} passHref>
<Link href={`/org/${currentOrg?.id}/secret-scanning`} passHref>
<a>
<MenuItem
isSelected={router.asPath === `/org/${currentOrg?._id}/secret-scanning`}
isSelected={router.asPath === `/org/${currentOrg?.id}/secret-scanning`}
icon="system-outline-69-document-scan"
>
Secret Scanning
</MenuItem>
</a>
</Link>
<Link href={`/org/${currentOrg?._id}/billing`} passHref>
<Link href={`/org/${currentOrg?.id}/billing`} passHref>
<a>
<MenuItem
isSelected={router.asPath === `/org/${currentOrg?._id}/billing`}
isSelected={router.asPath === `/org/${currentOrg?.id}/billing`}
icon="system-outline-103-coin-cash-monetization"
>
Usage & Billing
</MenuItem>
</a>
</Link>
<Link href={`/org/${currentOrg?._id}/settings`} passHref>
<Link href={`/org/${currentOrg?.id}/settings`} passHref>
<a>
<MenuItem
isSelected={router.asPath === `/org/${currentOrg?._id}/settings`}
isSelected={router.asPath === `/org/${currentOrg?.id}/settings`}
icon="system-outline-109-slider-toggle-settings"
>
Organization Settings
@@ -717,7 +717,7 @@ export const AppLayout = ({ children }: LayoutProps) => {
</DropdownMenuItem>
))}
{infisicalPlatformVersion && (
<div className="cursor-default mb-2 mt-2 w-full pl-5 duration-200 hover:text-mineshaft-200 text-sm">
<div className="mb-2 mt-2 w-full cursor-default pl-5 text-sm duration-200 hover:text-mineshaft-200">
<FontAwesomeIcon icon={faInfo} className="mr-4 px-[0.1rem]" />
Version: {infisicalPlatformVersion}
</div>
@@ -734,7 +734,7 @@ export const AppLayout = ({ children }: LayoutProps) => {
// direct user to start pro trial
const url = await mutateAsync({
orgId: currentOrg._id,
orgId: currentOrg.id,
success_url: window.location.href
});

View File

@@ -17,13 +17,11 @@ import {
} from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { Menu, Transition } from "@headlessui/react";
import {TFunction} from "i18next";
import { TFunction } from "i18next";
import guidGenerator from "@app/components/utilities/randomId";
import { useOrganization, useSubscription,useUser } from "@app/context";
import {
useGetOrgTrialUrl,
useLogoutUser} from "@app/hooks/api";
import { useOrganization, useSubscription, useUser } from "@app/context";
import { useGetOrgTrialUrl, useLogoutUser } from "@app/hooks/api";
const supportOptions = (t: TFunction) => [
[
@@ -80,7 +78,7 @@ export const Navbar = () => {
const closeApp = async () => {
try {
console.log("Logging out...")
console.log("Logging out...");
await logout.mutateAsync();
localStorage.removeItem("protectedKey");
localStorage.removeItem("protectedKeyIV");
@@ -101,243 +99,245 @@ export const Navbar = () => {
return (
<div className="z-[70] border-b border-mineshaft-500 bg-mineshaft-900 text-white">
<div className="flex w-full justify-between px-4">
<div className="flex flex-row items-center">
<div className="flex justify-center py-4">
<Image src="/images/logotransparent.png" height={23} width={57} alt="logo" />
<div className="flex flex-row items-center">
<div className="flex justify-center py-4">
<Image src="/images/logotransparent.png" height={23} width={57} alt="logo" />
</div>
<a href="#" className="mx-2 text-2xl font-semibold text-white">
Infisical
</a>
</div>
<a href="#" className="mx-2 text-2xl font-semibold text-white">
Infisical
</a>
</div>
<div className="relative z-40 mx-2 flex items-center justify-start">
<a
href="https://infisical.com/docs/documentation/getting-started/introduction"
target="_blank"
rel="noopener noreferrer"
className="mr-4 flex items-center rounded-md px-3 py-2 text-sm text-gray-200 duration-200 hover:bg-white/10"
>
<FontAwesomeIcon icon={faBook} className="mr-2 text-xl" />
Docs
</a>
<Menu as="div" className="relative inline-block text-left">
<div className="mr-4">
<Menu.Button className="inline-flex w-full justify-center rounded-md px-2 py-2 text-sm font-medium text-gray-200 duration-200 hover:bg-white/10 focus:outline-none focus-visible:ring-2 focus-visible:ring-white focus-visible:ring-opacity-75">
<FontAwesomeIcon className="text-xl" icon={faCircleQuestion} />
</Menu.Button>
</div>
<Transition
as={Fragment}
enter="transition ease-out duration-100"
enterFrom="transform opacity-0 scale-95"
enterTo="transform opacity-100 scale-100"
leave="transition ease-in duration-75"
leaveFrom="transform opacity-100 scale-100"
leaveTo="transform opacity-0 scale-95"
<div className="relative z-40 mx-2 flex items-center justify-start">
<a
href="https://infisical.com/docs/documentation/getting-started/introduction"
target="_blank"
rel="noopener noreferrer"
className="mr-4 flex items-center rounded-md px-3 py-2 text-sm text-gray-200 duration-200 hover:bg-white/10"
>
<Menu.Items className="absolute right-0 z-20 mt-0.5 w-64 origin-top-right rounded-md border border-mineshaft-700 bg-bunker px-2 py-1.5 shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none">
{supportOptionsList.map(([icon, text, url]) => (
<a
key={guidGenerator()}
target="_blank"
rel="noopener noreferrer"
href={String(url)}
className="flex w-full items-center rounded-md py-0.5 font-normal text-gray-300 duration-200"
>
<div className="relative flex w-full cursor-pointer select-none items-center justify-start rounded-md py-2 px-2 text-gray-400 duration-200 hover:bg-white/10 hover:text-gray-200">
{icon}
<div className="text-sm">{text}</div>
</div>
</a>
))}
</Menu.Items>
</Transition>
</Menu>
<Menu as="div" className="relative mr-4 inline-block text-left">
<div>
<Menu.Button className="inline-flex w-full justify-center rounded-md py-2 pr-2 pl-2 text-sm font-medium text-gray-200 duration-200 hover:bg-white/10 focus:outline-none focus-visible:ring-2 focus-visible:ring-white focus-visible:ring-opacity-75">
{user?.firstName} {user?.lastName}
<FontAwesomeIcon
icon={faAngleDown}
className="ml-2 mt-1 text-sm text-gray-300 hover:text-lime-100"
/>
</Menu.Button>
</div>
<Transition
as={Fragment}
enter="transition ease-out duration-100"
enterFrom="transform opacity-0 scale-95"
enterTo="transform opacity-100 scale-100"
leave="transition ease-in duration-75"
leaveFrom="transform opacity-100 scale-100"
leaveTo="transform opacity-0 scale-95"
>
<Menu.Items className="absolute right-0 z-[125] mt-0.5 w-68 origin-top-right divide-y divide-mineshaft-700 drop-shadow-2xl rounded-md border border-mineshaft-700 bg-mineshaft-900 shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none">
<div className="px-1 py-1">
<div className="ml-2 mt-2 self-start text-xs font-semibold tracking-wide text-gray-400">
{t("nav.user.signed-in-as")}
</div>
<div
onKeyDown={() => null}
role="button"
tabIndex={0}
onClick={() => router.push("/personal-settings")}
className="mx-1 my-1 flex cursor-pointer flex-row items-center rounded-md px-1 hover:bg-white/5"
>
<div className="flex h-8 w-9 items-center justify-center rounded-full bg-white/10 text-gray-300">
{user?.firstName?.charAt(0)}
</div>
<div className="flex w-full items-center justify-between">
<div>
<p className="px-2 pt-1 text-sm text-gray-300">
{" "}
{user?.firstName} {user?.lastName}
</p>
<p className="px-2 pb-1 text-xs text-gray-400">{user?.email}</p>
<FontAwesomeIcon icon={faBook} className="mr-2 text-xl" />
Docs
</a>
<Menu as="div" className="relative inline-block text-left">
<div className="mr-4">
<Menu.Button className="inline-flex w-full justify-center rounded-md px-2 py-2 text-sm font-medium text-gray-200 duration-200 hover:bg-white/10 focus:outline-none focus-visible:ring-2 focus-visible:ring-white focus-visible:ring-opacity-75">
<FontAwesomeIcon className="text-xl" icon={faCircleQuestion} />
</Menu.Button>
</div>
<Transition
as={Fragment}
enter="transition ease-out duration-100"
enterFrom="transform opacity-0 scale-95"
enterTo="transform opacity-100 scale-100"
leave="transition ease-in duration-75"
leaveFrom="transform opacity-100 scale-100"
leaveTo="transform opacity-0 scale-95"
>
<Menu.Items className="absolute right-0 z-20 mt-0.5 w-64 origin-top-right rounded-md border border-mineshaft-700 bg-bunker px-2 py-1.5 shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none">
{supportOptionsList.map(([icon, text, url]) => (
<a
key={guidGenerator()}
target="_blank"
rel="noopener noreferrer"
href={String(url)}
className="flex w-full items-center rounded-md py-0.5 font-normal text-gray-300 duration-200"
>
<div className="relative flex w-full cursor-pointer select-none items-center justify-start rounded-md py-2 px-2 text-gray-400 duration-200 hover:bg-white/10 hover:text-gray-200">
{icon}
<div className="text-sm">{text}</div>
</div>
</a>
))}
</Menu.Items>
</Transition>
</Menu>
<Menu as="div" className="relative mr-4 inline-block text-left">
<div>
<Menu.Button className="inline-flex w-full justify-center rounded-md py-2 pr-2 pl-2 text-sm font-medium text-gray-200 duration-200 hover:bg-white/10 focus:outline-none focus-visible:ring-2 focus-visible:ring-white focus-visible:ring-opacity-75">
{user?.firstName} {user?.lastName}
<FontAwesomeIcon
icon={faAngleDown}
className="ml-2 mt-1 text-sm text-gray-300 hover:text-lime-100"
/>
</Menu.Button>
</div>
<Transition
as={Fragment}
enter="transition ease-out duration-100"
enterFrom="transform opacity-0 scale-95"
enterTo="transform opacity-100 scale-100"
leave="transition ease-in duration-75"
leaveFrom="transform opacity-100 scale-100"
leaveTo="transform opacity-0 scale-95"
>
<Menu.Items className="w-68 absolute right-0 z-[125] mt-0.5 origin-top-right divide-y divide-mineshaft-700 rounded-md border border-mineshaft-700 bg-mineshaft-900 shadow-lg ring-1 ring-black ring-opacity-5 drop-shadow-2xl focus:outline-none">
<div className="px-1 py-1">
<div className="ml-2 mt-2 self-start text-xs font-semibold tracking-wide text-gray-400">
{t("nav.user.signed-in-as")}
</div>
<div
onKeyDown={() => null}
role="button"
tabIndex={0}
onClick={() => router.push("/personal-settings")}
className="mx-1 my-1 flex cursor-pointer flex-row items-center rounded-md px-1 hover:bg-white/5"
>
<div className="flex h-8 w-9 items-center justify-center rounded-full bg-white/10 text-gray-300">
{user?.firstName?.charAt(0)}
</div>
<div className="flex w-full items-center justify-between">
<div>
<p className="px-2 pt-1 text-sm text-gray-300">
{" "}
{user?.firstName} {user?.lastName}
</p>
<p className="px-2 pb-1 text-xs text-gray-400">{user?.email}</p>
</div>
<FontAwesomeIcon
icon={faGear}
className="mr-1 cursor-pointer rounded-md p-2 text-lg text-gray-400 hover:bg-white/10"
/>
</div>
<FontAwesomeIcon
icon={faGear}
className="mr-1 cursor-pointer rounded-md p-2 text-lg text-gray-400 hover:bg-white/10"
/>
</div>
</div>
</div>
<div className="px-2 pt-2">
<div className="ml-2 mt-2 self-start text-xs font-semibold tracking-wide text-gray-400">
{t("nav.user.current-organization")}
</div>
<div
onKeyDown={() => null}
role="button"
tabIndex={0}
onClick={() => router.push(`/settings/org/${router.query.id}`)}
className="mt-2 flex cursor-pointer flex-row items-center rounded-md px-2 py-1 hover:bg-white/5"
>
<div className="flex h-7 w-8 items-center justify-center rounded-md bg-white/10 text-gray-300">
{currentOrg?.name?.charAt(0)}
<div className="px-2 pt-2">
<div className="ml-2 mt-2 self-start text-xs font-semibold tracking-wide text-gray-400">
{t("nav.user.current-organization")}
</div>
<div className="flex w-full items-center justify-between">
<p className="px-2 text-sm text-gray-300">{currentOrg?.name}</p>
<FontAwesomeIcon
icon={faGear}
className="cursor-pointer rounded-md p-2 text-lg text-gray-400 hover:bg-white/10"
/>
<div
onKeyDown={() => null}
role="button"
tabIndex={0}
onClick={() => router.push(`/settings/org/${router.query.id}`)}
className="mt-2 flex cursor-pointer flex-row items-center rounded-md px-2 py-1 hover:bg-white/5"
>
<div className="flex h-7 w-8 items-center justify-center rounded-md bg-white/10 text-gray-300">
{currentOrg?.name?.charAt(0)}
</div>
<div className="flex w-full items-center justify-between">
<p className="px-2 text-sm text-gray-300">{currentOrg?.name}</p>
<FontAwesomeIcon
icon={faGear}
className="cursor-pointer rounded-md p-2 text-lg text-gray-400 hover:bg-white/10"
/>
</div>
</div>
</div>
{subscription && subscription.slug !== null && (
{subscription && subscription.slug !== null && (
<button
// onClick={buttonAction}
type="button"
className="w-full cursor-pointer"
>
<div
onKeyDown={() => null}
role="button"
tabIndex={0}
onClick={() => router.push(`/settings/billing/${router.query.id}`)}
className="relative mt-1 flex cursor-pointer select-none justify-start rounded-md py-2 px-2 text-gray-400 duration-200 hover:bg-white/5 hover:text-gray-200"
>
<FontAwesomeIcon className="pl-1.5 pr-3 text-lg" icon={faCoins} />
<div className="text-sm">{t("nav.user.usage-billing")}</div>
</div>
</button>
)}
<button
// onClick={buttonAction}
type="button"
className="w-full cursor-pointer"
// onClick={buttonAction}
className="mb-2 w-full cursor-pointer"
>
<div
onKeyDown={() => null}
role="button"
tabIndex={0}
onClick={() => router.push(`/settings/billing/${router.query.id}`)}
className="relative mt-1 flex cursor-pointer select-none justify-start rounded-md py-2 px-2 text-gray-400 duration-200 hover:bg-white/5 hover:text-gray-200"
onClick={() => router.push(`/settings/org/${router.query.id}?invite`)}
className="relative mt-1 flex cursor-pointer select-none justify-start rounded-md py-2 pl-10 pr-4 text-gray-400 duration-200 hover:bg-primary/100 hover:font-semibold hover:text-black"
>
<FontAwesomeIcon className="pl-1.5 pr-3 text-lg" icon={faCoins} />
<div className="text-sm">{t("nav.user.usage-billing")}</div>
<span className="absolute inset-y-0 left-0 flex items-center rounded-lg pl-3 pr-4">
<FontAwesomeIcon icon={faPlus} className="ml-1" />
</span>
<div className="ml-1 text-sm">{t("nav.user.invite")}</div>
</div>
</button>
)}
<button
type="button"
// onClick={buttonAction}
className="mb-2 w-full cursor-pointer"
>
<div
onKeyDown={() => null}
role="button"
tabIndex={0}
onClick={() => router.push(`/settings/org/${router.query.id}?invite`)}
className="relative mt-1 flex cursor-pointer select-none justify-start rounded-md py-2 pl-10 pr-4 text-gray-400 duration-200 hover:bg-primary/100 hover:font-semibold hover:text-black"
>
<span className="absolute inset-y-0 left-0 flex items-center rounded-lg pl-3 pr-4">
<FontAwesomeIcon icon={faPlus} className="ml-1" />
</span>
<div className="ml-1 text-sm">{t("nav.user.invite")}</div>
</div>
</button>
</div>
{orgs && orgs?.length > 1 && (
<div className="px-1 pt-1">
<div className="ml-2 mt-2 self-start text-xs font-semibold tracking-wide text-gray-400">
{t("nav.user.other-organizations")}
</div>
<div className="mt-3 mb-2 flex flex-col items-start px-1">
{orgs
?.filter((org: { id: string }) => org.id !== currentOrg?.id)
.map((org: { id: string; name: string }) => (
<div
onKeyDown={() => null}
role="button"
tabIndex={0}
key={guidGenerator()}
onClick={() => {
localStorage.setItem("orgData.id", org.id);
router.reload();
}}
className="flex w-full cursor-pointer flex-row items-center justify-start rounded-md p-1.5 hover:bg-white/5"
>
<div className="flex h-7 w-8 items-center justify-center rounded-md bg-white/10 text-gray-300">
{org.name.charAt(0)}
</div>
<div className="flex w-full items-center justify-between">
<p className="px-2 text-sm text-gray-300">{org.name}</p>
</div>
</div>
))}
</div>
</div>
)}
<div className="px-1 py-1">
<Menu.Item>
{({ active }) => (
<button
type="button"
onClick={closeApp}
className={`${
active ? "bg-red font-semibold text-white" : "text-gray-400"
} group flex w-full items-center rounded-md px-2 py-2 text-sm`}
>
<div className="relative flex cursor-pointer select-none items-center justify-start">
<FontAwesomeIcon
className="ml-1.5 mr-3 text-lg"
icon={faRightFromBracket}
/>
{t("common.logout")}
</div>
</button>
)}
</Menu.Item>
</div>
</Menu.Items>
</Transition>
</Menu>
</div>
{orgs && orgs?.length > 1 && (
<div className="px-1 pt-1">
<div className="ml-2 mt-2 self-start text-xs font-semibold tracking-wide text-gray-400">
{t("nav.user.other-organizations")}
</div>
<div className="mt-3 mb-2 flex flex-col items-start px-1">
{orgs
?.filter((org: { id: string }) => org.id !== currentOrg?.id)
.map((org: { id: string; name: string }) => (
<div
onKeyDown={() => null}
role="button"
tabIndex={0}
key={guidGenerator()}
onClick={() => {
localStorage.setItem("orgData.id", org.id);
router.reload();
}}
className="flex w-full cursor-pointer flex-row items-center justify-start rounded-md p-1.5 hover:bg-white/5"
>
<div className="flex h-7 w-8 items-center justify-center rounded-md bg-white/10 text-gray-300">
{org.name.charAt(0)}
</div>
<div className="flex w-full items-center justify-between">
<p className="px-2 text-sm text-gray-300">{org.name}</p>
</div>
</div>
))}
</div>
</div>
)}
<div className="px-1 py-1">
<Menu.Item>
{({ active }) => (
<button
type="button"
onClick={closeApp}
className={`${
active ? "bg-red font-semibold text-white" : "text-gray-400"
} group flex w-full items-center rounded-md px-2 py-2 text-sm`}
>
<div className="relative flex cursor-pointer select-none items-center justify-start">
<FontAwesomeIcon
className="ml-1.5 mr-3 text-lg"
icon={faRightFromBracket}
/>
{t("common.logout")}
</div>
</button>
)}
</Menu.Item>
</div>
</Menu.Items>
</Transition>
</Menu>
</div>
</div>
{subscription && subscription.slug === "starter" && !subscription.has_used_trial && (
<div className="w-full mx-auto border-t border-mineshaft-500 text-center">
<button
<div className="mx-auto w-full border-t border-mineshaft-500 text-center">
<button
type="button"
onClick={async () => {
if (!subscription || !currentOrg) return;
// direct user to start pro trial
const url = await mutateAsync({
orgId: currentOrg.id,
orgId: currentOrg._id,
success_url: window.location.href
});
window.location.href = url;
}}
className="text-center py-4 text-sm mx-auto"
className="mx-auto py-4 text-center text-sm"
>
You are currently on the <span className="font-semibold">Starter</span> plan. Unlock the full power of Infisical on the <span className="font-semibold">Pro Free Trial &rarr;</span>
You are currently on the <span className="font-semibold">Starter</span> plan. Unlock the
full power of Infisical on the{" "}
<span className="font-semibold">Pro Free Trial &rarr;</span>
</button>
</div>
)}
</div>
);
};
};

View File

@@ -25,28 +25,28 @@ export type IGitRisks = {
isFalsePositive: boolean; // New field for marking risks as false positives
isResolved: boolean; // New field for marking risks as resolved
riskOwner: string | null; // New field for setting a risk owner (nullable string)
installationId: string,
repositoryId: string,
repositoryLink: string
repositoryFullName: string
installationId: string;
repositoryId: string;
repositoryLink: string;
repositoryFullName: string;
pusher: {
name: string,
email: string
},
createdAt: string,
organization: string,
}
name: string;
email: string;
};
createdAt: string;
organization: string;
};
/**
* Will create a new integration session and return it for the given org
* @returns
* @returns
*/
const getRisksByOrganization = (oranizationId: string): Promise<IGitRisks[]> =>
SecurityClient.fetchCall(`/api/v1/secret-scanning/organization/${oranizationId}/risks`, {
method: "GET",
headers: {
"Content-Type": "application/json"
},
}
}).then(async (res) => {
if (res && res.status === 200) {
return (await res.json()).risks;

View File

@@ -18,9 +18,9 @@ export default function DashboardRedirect() {
if (localStorage.getItem("orgData.id")) {
router.push(`/org/${localStorage.getItem("orgData.id")}/overview`);
} else if (userOrgs) {
userOrg = userOrgs[0].id;
router.push(`/org/${userOrg}/overview`);
}
userOrg = userOrgs[0].id;
router.push(`/org/${userOrg}/overview`);
}
} catch (error) {
console.log("Error - Not logged in yet");
}

View File

@@ -6,16 +6,14 @@ import { useRouter } from "next/router";
import { faArrowUpRightFromSquare, faBookOpen } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import {
useSaveIntegrationAccessToken
} from "@app/hooks/api";
import { useSaveIntegrationAccessToken } from "@app/hooks/api";
import { Button, Card, CardTitle, FormControl, Input } from "../../../components/v2";
export default function AWSParameterStoreAuthorizeIntegrationPage() {
const router = useRouter();
const { mutateAsync } = useSaveIntegrationAccessToken();
const [isLoading, setIsLoading] = useState(false);
const [accessKey, setAccessKey] = useState("");
@@ -63,11 +61,11 @@ export default function AWSParameterStoreAuthorizeIntegrationPage() {
<div className="flex h-full w-full items-center justify-center">
<Head>
<title>Authorize AWS Parameter Integration</title>
<link rel='icon' href='/infisical.ico' />
<link rel="icon" href="/infisical.ico" />
</Head>
<Card className="max-w-lg rounded-md border border-mineshaft-600">
<CardTitle
className="text-left px-6 text-xl"
<CardTitle
className="px-6 text-left text-xl"
subTitle="After adding the details below, you will be prompted to set up an integration for a particular Infisical project and environment."
>
<div className="flex flex-row items-center">
@@ -82,10 +80,13 @@ export default function AWSParameterStoreAuthorizeIntegrationPage() {
<span className="ml-1.5">AWS Parameter Store Integration </span>
<Link href="https://infisical.com/docs/integrations/cloud/aws-parameter-store" passHref>
<a target="_blank" rel="noopener noreferrer">
<div className="ml-2 mb-1 rounded-md text-yellow text-sm inline-block bg-yellow/20 px-1.5 pb-[0.03rem] pt-[0.04rem] opacity-80 hover:opacity-100 cursor-default">
<FontAwesomeIcon icon={faBookOpen} className="mr-1.5"/>
<div className="ml-2 mb-1 inline-block cursor-default rounded-md bg-yellow/20 px-1.5 pb-[0.03rem] pt-[0.04rem] text-sm text-yellow opacity-80 hover:opacity-100">
<FontAwesomeIcon icon={faBookOpen} className="mr-1.5" />
Docs
<FontAwesomeIcon icon={faArrowUpRightFromSquare} className="ml-1.5 text-xxs mb-[0.07rem]"/>
<FontAwesomeIcon
icon={faArrowUpRightFromSquare}
className="ml-1.5 mb-[0.07rem] text-xxs"
/>
</div>
</a>
</Link>
@@ -97,11 +98,7 @@ export default function AWSParameterStoreAuthorizeIntegrationPage() {
isError={accessKeyErrorText !== "" ?? false}
className="px-6"
>
<Input
placeholder=""
value={accessKey}
onChange={(e) => setAccessKey(e.target.value)}
/>
<Input placeholder="" value={accessKey} onChange={(e) => setAccessKey(e.target.value)} />
</FormControl>
<FormControl
label="Secret Access Key"

View File

@@ -3,13 +3,16 @@ import Head from "next/head";
import Image from "next/image";
import Link from "next/link";
import { useRouter } from "next/router";
import { faArrowUpRightFromSquare, faBookOpen, faBugs, faCircleInfo } from "@fortawesome/free-solid-svg-icons";
import {
faArrowUpRightFromSquare,
faBookOpen,
faBugs,
faCircleInfo
} from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import queryString from "query-string";
import {
useCreateIntegration
} from "@app/hooks/api";
import { useCreateIntegration } from "@app/hooks/api";
import {
Button,
@@ -62,7 +65,9 @@ export default function AWSParameterStoreCreateIntegrationPage() {
const { integrationAuthId } = queryString.parse(router.asPath.split("?")[1]);
const { data: workspace } = useGetWorkspaceById(localStorage.getItem("projectData.id") ?? "");
const { data: integrationAuth, isLoading: isintegrationAuthLoading } = useGetIntegrationAuthById((integrationAuthId as string) ?? "");
const { data: integrationAuth, isLoading: isintegrationAuthLoading } = useGetIntegrationAuthById(
(integrationAuthId as string) ?? ""
);
const [selectedSourceEnvironment, setSelectedSourceEnvironment] = useState("");
const [secretPath, setSecretPath] = useState("/");
@@ -118,14 +123,14 @@ export default function AWSParameterStoreCreateIntegrationPage() {
};
return integrationAuth && workspace && selectedSourceEnvironment ? (
<div className="flex flex-col h-full w-full items-center justify-center">
<div className="flex h-full w-full flex-col items-center justify-center">
<Head>
<title>Set Up AWS Parameter Integration</title>
<link rel='icon' href='/infisical.ico' />
<link rel="icon" href="/infisical.ico" />
</Head>
<Card className="max-w-lg rounded-md border border-mineshaft-600">
<CardTitle
className="text-left px-6 text-xl"
<CardTitle
className="px-6 text-left text-xl"
subTitle="Choose which environment in Infisical you want to sync to secerts in AWS Parameter Store."
>
<div className="flex flex-row items-center">
@@ -140,10 +145,13 @@ export default function AWSParameterStoreCreateIntegrationPage() {
<span className="ml-1.5">AWS Parameter Store Integration </span>
<Link href="https://infisical.com/docs/integrations/cloud/aws-parameter-store" passHref>
<a target="_blank" rel="noopener noreferrer">
<div className="ml-2 mb-1 rounded-md text-yellow text-sm inline-block bg-yellow/20 px-1.5 pb-[0.03rem] pt-[0.04rem] opacity-80 hover:opacity-100 cursor-default">
<FontAwesomeIcon icon={faBookOpen} className="mr-1.5"/>
<div className="ml-2 mb-1 inline-block cursor-default rounded-md bg-yellow/20 px-1.5 pb-[0.03rem] pt-[0.04rem] text-sm text-yellow opacity-80 hover:opacity-100">
<FontAwesomeIcon icon={faBookOpen} className="mr-1.5" />
Docs
<FontAwesomeIcon icon={faArrowUpRightFromSquare} className="ml-1.5 text-xxs mb-[0.07rem]"/>
<FontAwesomeIcon
icon={faArrowUpRightFromSquare}
className="ml-1.5 mb-[0.07rem] text-xxs"
/>
</div>
</a>
</Link>
@@ -185,7 +193,12 @@ export default function AWSParameterStoreCreateIntegrationPage() {
))}
</Select>
</FormControl>
<FormControl label="Path" errorText={pathErrorText} isError={pathErrorText !== "" ?? false} className="px-6">
<FormControl
label="Path"
errorText={pathErrorText}
isError={pathErrorText !== "" ?? false}
className="px-6"
>
<Input
placeholder={`/${workspace.name
.toLowerCase()
@@ -204,31 +217,49 @@ export default function AWSParameterStoreCreateIntegrationPage() {
Create Integration
</Button>
</Card>
<div className="border-t border-mineshaft-800 w-full max-w-md mt-6"/>
<div className="flex flex-col bg-mineshaft-800 border border-mineshaft-600 w-full p-4 max-w-lg mt-6 rounded-md">
<div className="flex flex-row items-center"><FontAwesomeIcon icon={faCircleInfo} className="text-mineshaft-200 text-xl"/> <span className="ml-3 text-md text-mineshaft-100">Pro Tips</span></div>
<span className="text-mineshaft-300 text-sm mt-4">After creating an integration, your secrets will start syncing immediately. This might cause an unexpected override of current secrets in AWS Parameter Store with secrets from Infisical.</span>
<div className="mt-6 w-full max-w-md border-t border-mineshaft-800" />
<div className="mt-6 flex w-full max-w-lg flex-col rounded-md border border-mineshaft-600 bg-mineshaft-800 p-4">
<div className="flex flex-row items-center">
<FontAwesomeIcon icon={faCircleInfo} className="text-xl text-mineshaft-200" />{" "}
<span className="text-md ml-3 text-mineshaft-100">Pro Tips</span>
</div>
<span className="mt-4 text-sm text-mineshaft-300">
After creating an integration, your secrets will start syncing immediately. This might
cause an unexpected override of current secrets in AWS Parameter Store with secrets from
Infisical.
</span>
</div>
</div>
) : (
<div className="flex justify-center items-center w-full h-full">
<div className="flex h-full w-full items-center justify-center">
<Head>
<title>Set Up AWS Parameter Store Integration</title>
<link rel='icon' href='/infisical.ico' />
<link rel="icon" href="/infisical.ico" />
</Head>
{isintegrationAuthLoading ? <img src="/images/loading/loading.gif" height={70} width={120} alt="infisical loading indicator" /> : <div className="max-w-md h-max p-6 border border-mineshaft-600 rounded-md bg-mineshaft-800 text-mineshaft-200 flex flex-col text-center">
<FontAwesomeIcon icon={faBugs} className="text-6xl my-2 inlineli"/>
<p>
Something went wrong. Please contact <a
className="inline underline underline-offset-4 decoration-primary-500 opacity-80 hover:opacity-100 text-mineshaft-100 duration-200 cursor-pointer"
target="_blank"
rel="noopener noreferrer"
href="mailto:support@infisical.com"
>
support@infisical.com
</a> if the issue persists.
</p>
</div>}
{isintegrationAuthLoading ? (
<img
src="/images/loading/loading.gif"
height={70}
width={120}
alt="infisical loading indicator"
/>
) : (
<div className="flex h-max max-w-md flex-col rounded-md border border-mineshaft-600 bg-mineshaft-800 p-6 text-center text-mineshaft-200">
<FontAwesomeIcon icon={faBugs} className="inlineli my-2 text-6xl" />
<p>
Something went wrong. Please contact{" "}
<a
className="inline cursor-pointer text-mineshaft-100 underline decoration-primary-500 underline-offset-4 opacity-80 duration-200 hover:opacity-100"
target="_blank"
rel="noopener noreferrer"
href="mailto:support@infisical.com"
>
support@infisical.com
</a>{" "}
if the issue persists.
</p>
</div>
)}
</div>
);
}

View File

@@ -61,11 +61,11 @@ export default function AWSSecretManagerCreateIntegrationPage() {
<div className="flex h-full w-full items-center justify-center">
<Head>
<title>Authorize AWS Secrets Manager Integration</title>
<link rel='icon' href='/infisical.ico' />
<link rel="icon" href="/infisical.ico" />
</Head>
<Card className="max-w-lg rounded-md border border-mineshaft-600">
<CardTitle
className="text-left px-6 text-xl"
<CardTitle
className="px-6 text-left text-xl"
subTitle="After adding the details below, you will be prompted to set up an integration for a particular Infisical project and environment."
>
<div className="flex flex-row items-center">
@@ -80,10 +80,13 @@ export default function AWSSecretManagerCreateIntegrationPage() {
<span className="ml-1.5">AWS Secrets Manager Integration </span>
<Link href="https://infisical.com/docs/integrations/cloud/aws-secret-manager" passHref>
<a target="_blank" rel="noopener noreferrer">
<div className="ml-2 mb-1 rounded-md text-yellow text-sm inline-block bg-yellow/20 px-1.5 pb-[0.03rem] pt-[0.04rem] opacity-80 hover:opacity-100 cursor-default">
<FontAwesomeIcon icon={faBookOpen} className="mr-1.5"/>
<div className="ml-2 mb-1 inline-block cursor-default rounded-md bg-yellow/20 px-1.5 pb-[0.03rem] pt-[0.04rem] text-sm text-yellow opacity-80 hover:opacity-100">
<FontAwesomeIcon icon={faBookOpen} className="mr-1.5" />
Docs
<FontAwesomeIcon icon={faArrowUpRightFromSquare} className="ml-1.5 text-xxs mb-[0.07rem]"/>
<FontAwesomeIcon
icon={faArrowUpRightFromSquare}
className="ml-1.5 mb-[0.07rem] text-xxs"
/>
</div>
</a>
</Link>

View File

@@ -3,13 +3,16 @@ import Head from "next/head";
import Image from "next/image";
import Link from "next/link";
import { useRouter } from "next/router";
import { faArrowUpRightFromSquare, faBookOpen, faBugs, faCircleInfo } from "@fortawesome/free-solid-svg-icons";
import {
faArrowUpRightFromSquare,
faBookOpen,
faBugs,
faCircleInfo
} from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import queryString from "query-string";
import {
useCreateIntegration
} from "@app/hooks/api";
import { useCreateIntegration } from "@app/hooks/api";
import {
Button,
@@ -62,7 +65,9 @@ export default function AWSSecretManagerCreateIntegrationPage() {
const { integrationAuthId } = queryString.parse(router.asPath.split("?")[1]);
const { data: workspace } = useGetWorkspaceById(localStorage.getItem("projectData.id") ?? "");
const { data: integrationAuth, isLoading: isintegrationAuthLoading } = useGetIntegrationAuthById((integrationAuthId as string) ?? "");
const { data: integrationAuth, isLoading: isintegrationAuthLoading } = useGetIntegrationAuthById(
(integrationAuthId as string) ?? ""
);
const [selectedSourceEnvironment, setSelectedSourceEnvironment] = useState("");
const [secretPath, setSecretPath] = useState("/");
@@ -117,14 +122,14 @@ export default function AWSSecretManagerCreateIntegrationPage() {
};
return integrationAuth && workspace && selectedSourceEnvironment ? (
<div className="flex flex-col h-full w-full items-center justify-center">
<div className="flex h-full w-full flex-col items-center justify-center">
<Head>
<title>Set Up AWS Secrets Manager Integration</title>
<link rel='icon' href='/infisical.ico' />
<link rel="icon" href="/infisical.ico" />
</Head>
<Card className="max-w-lg rounded-md border border-mineshaft-600">
<CardTitle
className="text-left px-6 text-xl"
<CardTitle
className="px-6 text-left text-xl"
subTitle="Choose which environment in Infisical you want to sync to secerts in AWS Secrets Manager."
>
<div className="flex flex-row items-center">
@@ -139,10 +144,13 @@ export default function AWSSecretManagerCreateIntegrationPage() {
<span className="ml-1.5">AWS Secrets Manager Integration </span>
<Link href="https://infisical.com/docs/integrations/cloud/aws-secret-manager" passHref>
<a target="_blank" rel="noopener noreferrer">
<div className="ml-2 mb-1 rounded-md text-yellow text-sm inline-block bg-yellow/20 px-1.5 pb-[0.03rem] pt-[0.04rem] opacity-80 hover:opacity-100 cursor-default">
<FontAwesomeIcon icon={faBookOpen} className="mr-1.5"/>
<div className="ml-2 mb-1 inline-block cursor-default rounded-md bg-yellow/20 px-1.5 pb-[0.03rem] pt-[0.04rem] text-sm text-yellow opacity-80 hover:opacity-100">
<FontAwesomeIcon icon={faBookOpen} className="mr-1.5" />
Docs
<FontAwesomeIcon icon={faArrowUpRightFromSquare} className="ml-1.5 text-xxs mb-[0.07rem]"/>
<FontAwesomeIcon
icon={faArrowUpRightFromSquare}
className="ml-1.5 mb-[0.07rem] text-xxs"
/>
</div>
</a>
</Link>
@@ -208,31 +216,49 @@ export default function AWSSecretManagerCreateIntegrationPage() {
Create Integration
</Button>
</Card>
<div className="border-t border-mineshaft-800 w-full max-w-md mt-6"/>
<div className="flex flex-col bg-mineshaft-800 border border-mineshaft-600 w-full p-4 max-w-lg mt-6 rounded-md">
<div className="flex flex-row items-center"><FontAwesomeIcon icon={faCircleInfo} className="text-mineshaft-200 text-xl"/> <span className="ml-3 text-md text-mineshaft-100">Pro Tips</span></div>
<span className="text-mineshaft-300 text-sm mt-4">After creating an integration, your secrets will start syncing immediately. This might cause an unexpected override of current secrets in AWS Secrets Manager with secrets from Infisical.</span>
<div className="mt-6 w-full max-w-md border-t border-mineshaft-800" />
<div className="mt-6 flex w-full max-w-lg flex-col rounded-md border border-mineshaft-600 bg-mineshaft-800 p-4">
<div className="flex flex-row items-center">
<FontAwesomeIcon icon={faCircleInfo} className="text-xl text-mineshaft-200" />{" "}
<span className="text-md ml-3 text-mineshaft-100">Pro Tips</span>
</div>
<span className="mt-4 text-sm text-mineshaft-300">
After creating an integration, your secrets will start syncing immediately. This might
cause an unexpected override of current secrets in AWS Secrets Manager with secrets from
Infisical.
</span>
</div>
</div>
) : (
<div className="flex justify-center items-center w-full h-full">
<div className="flex h-full w-full items-center justify-center">
<Head>
<title>Set Up AWS Secrets Manager Integration</title>
<link rel='icon' href='/infisical.ico' />
<link rel="icon" href="/infisical.ico" />
</Head>
{isintegrationAuthLoading ? <img src="/images/loading/loading.gif" height={70} width={120} alt="infisical loading indicator" /> : <div className="max-w-md h-max p-6 border border-mineshaft-600 rounded-md bg-mineshaft-800 text-mineshaft-200 flex flex-col text-center">
<FontAwesomeIcon icon={faBugs} className="text-6xl my-2 inlineli"/>
<p>
Something went wrong. Please contact <a
className="inline underline underline-offset-4 decoration-primary-500 opacity-80 hover:opacity-100 text-mineshaft-100 duration-200 cursor-pointer"
target="_blank"
rel="noopener noreferrer"
href="mailto:support@infisical.com"
>
support@infisical.com
</a> if the issue persists.
</p>
</div>}
{isintegrationAuthLoading ? (
<img
src="/images/loading/loading.gif"
height={70}
width={120}
alt="infisical loading indicator"
/>
) : (
<div className="flex h-max max-w-md flex-col rounded-md border border-mineshaft-600 bg-mineshaft-800 p-6 text-center text-mineshaft-200">
<FontAwesomeIcon icon={faBugs} className="inlineli my-2 text-6xl" />
<p>
Something went wrong. Please contact{" "}
<a
className="inline cursor-pointer text-mineshaft-100 underline decoration-primary-500 underline-offset-4 opacity-80 duration-200 hover:opacity-100"
target="_blank"
rel="noopener noreferrer"
href="mailto:support@infisical.com"
>
support@infisical.com
</a>{" "}
if the issue persists.
</p>
</div>
)}
</div>
);
}

View File

@@ -2,9 +2,7 @@ import { useEffect, useState } from "react";
import { useRouter } from "next/router";
import queryString from "query-string";
import {
useCreateIntegration
} from "@app/hooks/api";
import { useCreateIntegration } from "@app/hooks/api";
import {
Button,

View File

@@ -2,9 +2,7 @@ import { useEffect } from "react";
import { useRouter } from "next/router";
import queryString from "query-string";
import {
useAuthorizeIntegration
} from "@app/hooks/api";
import { useAuthorizeIntegration } from "@app/hooks/api";
export default function AzureKeyVaultOAuth2CallbackPage() {
const router = useRouter();
@@ -25,9 +23,7 @@ export default function AzureKeyVaultOAuth2CallbackPage() {
integration: "azure-key-vault"
});
router.push(
`/integrations/azure-key-vault/create?integrationAuthId=${integrationAuth.id}`
);
router.push(`/integrations/azure-key-vault/create?integrationAuthId=${integrationAuth.id}`);
} catch (err) {
console.error(err);
}

View File

@@ -2,9 +2,7 @@ import { useEffect, useState } from "react";
import { useRouter } from "next/router";
import queryString from "query-string";
import {
useCreateIntegration
} from "@app/hooks/api";
import { useCreateIntegration } from "@app/hooks/api";
import {
Button,
@@ -18,7 +16,7 @@ import {
import {
useGetIntegrationAuthApps,
useGetIntegrationAuthBitBucketWorkspaces,
useGetIntegrationAuthById,
useGetIntegrationAuthById
} from "../../../hooks/api/integrationAuth";
import { useGetWorkspaceById } from "../../../hooks/api/workspace";
@@ -36,7 +34,9 @@ export default function BitBucketCreateIntegrationPage() {
const { integrationAuthId } = queryString.parse(router.asPath.split("?")[1]);
const { data: integrationAuth } = useGetIntegrationAuthById((integrationAuthId as string) ?? "");
const { data: workspace } = useGetWorkspaceById(localStorage.getItem("projectData.id") ?? "");
const { data: targetEnvironments } = useGetIntegrationAuthBitBucketWorkspaces((integrationAuthId as string) ?? "");
const { data: targetEnvironments } = useGetIntegrationAuthBitBucketWorkspaces(
(integrationAuthId as string) ?? ""
);
const { data: integrationAuthApps } = useGetIntegrationAuthApps({
integrationAuthId: (integrationAuthId as string) ?? "",
workspaceSlug: targetEnvironmentId

View File

@@ -2,9 +2,7 @@ import { useEffect } from "react";
import { useRouter } from "next/router";
import queryString from "query-string";
import {
useAuthorizeIntegration
} from "@app/hooks/api";
import { useAuthorizeIntegration } from "@app/hooks/api";
export default function BitBucketOAuth2CallbackPage() {
const router = useRouter();

View File

@@ -6,9 +6,7 @@ import { useRouter } from "next/router";
import { faArrowUpRightFromSquare, faBookOpen } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import {
useSaveIntegrationAccessToken
} from "@app/hooks/api";
import { useSaveIntegrationAccessToken } from "@app/hooks/api";
import { Button, Card, CardTitle, FormControl, Input } from "../../../components/v2";
@@ -48,11 +46,11 @@ export default function ChecklyCreateIntegrationPage() {
<div className="flex h-full w-full items-center justify-center">
<Head>
<title>Authorize Checkly Integration</title>
<link rel='icon' href='/infisical.ico' />
<link rel="icon" href="/infisical.ico" />
</Head>
<Card className="max-w-lg rounded-md border border-mineshaft-600 mb-12">
<CardTitle
className="text-left px-6 text-xl"
<Card className="mb-12 max-w-lg rounded-md border border-mineshaft-600">
<CardTitle
className="px-6 text-left text-xl"
subTitle="After adding your API key, you will be prompted to set up an integration for a particular Infisical project and environment."
>
<div className="flex flex-row items-center">
@@ -67,10 +65,13 @@ export default function ChecklyCreateIntegrationPage() {
<span className="ml-2.5">Checkly Integration </span>
<Link href="https://infisical.com/docs/integrations/cloud/checkly" passHref>
<a target="_blank" rel="noopener noreferrer">
<div className="ml-2 mb-1 rounded-md text-yellow text-sm inline-block bg-yellow/20 px-1.5 pb-[0.03rem] pt-[0.04rem] opacity-80 hover:opacity-100 cursor-default">
<FontAwesomeIcon icon={faBookOpen} className="mr-1.5"/>
<div className="ml-2 mb-1 inline-block cursor-default rounded-md bg-yellow/20 px-1.5 pb-[0.03rem] pt-[0.04rem] text-sm text-yellow opacity-80 hover:opacity-100">
<FontAwesomeIcon icon={faBookOpen} className="mr-1.5" />
Docs
<FontAwesomeIcon icon={faArrowUpRightFromSquare} className="ml-1.5 text-xxs mb-[0.07rem]"/>
<FontAwesomeIcon
icon={faArrowUpRightFromSquare}
className="ml-1.5 mb-[0.07rem] text-xxs"
/>
</div>
</a>
</Link>

View File

@@ -21,9 +21,7 @@ import {
TabPanel,
Tabs
} from "@app/components/v2";
import {
useCreateIntegration
} from "@app/hooks/api";
import { useCreateIntegration } from "@app/hooks/api";
import {
useGetIntegrationAuthApps,
@@ -54,13 +52,15 @@ export default function ChecklyCreateIntegrationPage() {
const { data: workspace } = useGetWorkspaceById(localStorage.getItem("projectData.id") ?? "");
const { data: integrationAuth } = useGetIntegrationAuthById((integrationAuthId as string) ?? "");
const { data: integrationAuthApps, isLoading: isIntegrationAuthAppsLoading } = useGetIntegrationAuthApps({
integrationAuthId: (integrationAuthId as string) ?? ""
});
const { data: integrationAuthGroups, isLoading: isintegrationAuthGroupsLoading } = useGetIntegrationAuthChecklyGroups({
integrationAuthId: (integrationAuthId as string) ?? "",
accountId: targetAppId
});
const { data: integrationAuthApps, isLoading: isIntegrationAuthAppsLoading } =
useGetIntegrationAuthApps({
integrationAuthId: (integrationAuthId as string) ?? ""
});
const { data: integrationAuthGroups, isLoading: isintegrationAuthGroupsLoading } =
useGetIntegrationAuthChecklyGroups({
integrationAuthId: (integrationAuthId as string) ?? "",
accountId: targetAppId
});
useEffect(() => {
if (workspace) {
@@ -90,9 +90,9 @@ export default function ChecklyCreateIntegrationPage() {
const targetGroup = integrationAuthGroups?.find(
(group) => group.groupId === Number(targetGroupId)
);
if (!targetApp) return;
await mutateAsync({
integrationAuthId: integrationAuth?.id,
isActive: true,
@@ -118,17 +118,17 @@ export default function ChecklyCreateIntegrationPage() {
return integrationAuth &&
workspace &&
selectedSourceEnvironment &&
integrationAuthApps &&
integrationAuthApps &&
integrationAuthGroups &&
targetAppId ? (
<div className="flex h-full flex-col w-full py-6 items-center justify-center bg-gradient-to-tr from-mineshaft-900 to-bunker-900">
<div className="flex h-full w-full flex-col items-center justify-center bg-gradient-to-tr from-mineshaft-900 to-bunker-900 py-6">
<Head>
<title>Set Up Checkly Integration</title>
<link rel='icon' href='/infisical.ico' />
<link rel="icon" href="/infisical.ico" />
</Head>
<Card className="max-w-lg rounded-md border border-mineshaft-600 p-0">
<CardTitle
className="text-left px-6 text-xl"
<CardTitle
className="px-6 text-left text-xl"
subTitle="Choose which environment in Infisical you want to sync to Checkly environment variables."
>
<div className="flex flex-row items-center">
@@ -143,10 +143,13 @@ export default function ChecklyCreateIntegrationPage() {
<span className="ml-2.5">Checkly Integration </span>
<Link href="https://infisical.com/docs/integrations/cloud/checkly" passHref>
<a target="_blank" rel="noopener noreferrer">
<div className="ml-2 mb-1 rounded-md text-yellow text-sm inline-block bg-yellow/20 px-1.5 pb-[0.03rem] pt-[0.04rem] opacity-80 hover:opacity-100 cursor-default">
<FontAwesomeIcon icon={faBookOpen} className="mr-1.5"/>
<div className="ml-2 mb-1 inline-block cursor-default rounded-md bg-yellow/20 px-1.5 pb-[0.03rem] pt-[0.04rem] text-sm text-yellow opacity-80 hover:opacity-100">
<FontAwesomeIcon icon={faBookOpen} className="mr-1.5" />
Docs
<FontAwesomeIcon icon={faArrowUpRightFromSquare} className="ml-1.5 text-xxs mb-[0.07rem]"/>
<FontAwesomeIcon
icon={faArrowUpRightFromSquare}
className="ml-1.5 mb-[0.07rem] text-xxs"
/>
</div>
</a>
</Link>
@@ -154,7 +157,7 @@ export default function ChecklyCreateIntegrationPage() {
</CardTitle>
<Tabs defaultValue={TabSections.Connection} className="px-6">
<TabList>
<div className="flex flex-row border-b border-mineshaft-600 w-full">
<div className="flex w-full flex-row border-b border-mineshaft-600">
<Tab value={TabSections.Connection}>Connection</Tab>
<Tab value={TabSections.Options}>Options</Tab>
</div>
@@ -268,24 +271,35 @@ export default function ChecklyCreateIntegrationPage() {
</Card>
</div>
) : (
<div className="flex justify-center items-center w-full h-full">
<div className="flex h-full w-full items-center justify-center">
<Head>
<title>Set Up Checkly Integration</title>
<link rel='icon' href='/infisical.ico' />
<link rel="icon" href="/infisical.ico" />
</Head>
{isIntegrationAuthAppsLoading || isintegrationAuthGroupsLoading ? <img src="/images/loading/loading.gif" height={70} width={120} alt="infisical loading indicator" /> : <div className="max-w-md h-max p-6 border border-mineshaft-600 rounded-md bg-mineshaft-800 text-mineshaft-200 flex flex-col text-center">
<FontAwesomeIcon icon={faBugs} className="text-6xl my-2 inlineli"/>
<p>
Something went wrong. Please contact <a
className="inline underline underline-offset-4 decoration-primary-500 opacity-80 hover:opacity-100 text-mineshaft-100 duration-200 cursor-pointer"
target="_blank"
rel="noopener noreferrer"
href="mailto:support@infisical.com"
>
support@infisical.com
</a> if the issue persists.
</p>
</div>}
{isIntegrationAuthAppsLoading || isintegrationAuthGroupsLoading ? (
<img
src="/images/loading/loading.gif"
height={70}
width={120}
alt="infisical loading indicator"
/>
) : (
<div className="flex h-max max-w-md flex-col rounded-md border border-mineshaft-600 bg-mineshaft-800 p-6 text-center text-mineshaft-200">
<FontAwesomeIcon icon={faBugs} className="inlineli my-2 text-6xl" />
<p>
Something went wrong. Please contact{" "}
<a
className="inline cursor-pointer text-mineshaft-100 underline decoration-primary-500 underline-offset-4 opacity-80 duration-200 hover:opacity-100"
target="_blank"
rel="noopener noreferrer"
href="mailto:support@infisical.com"
>
support@infisical.com
</a>{" "}
if the issue persists.
</p>
</div>
)}
</div>
);
}

View File

@@ -6,9 +6,7 @@ import { useRouter } from "next/router";
import { faArrowUpRightFromSquare, faBookOpen } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import {
useSaveIntegrationAccessToken
} from "@app/hooks/api";
import { useSaveIntegrationAccessToken } from "@app/hooks/api";
import { Button, Card, CardTitle, FormControl, Input } from "../../../components/v2";
@@ -48,11 +46,11 @@ export default function CircleCICreateIntegrationPage() {
<div className="flex h-full w-full items-center justify-center">
<Head>
<title>Authorize CircleCI Integration</title>
<link rel='icon' href='/infisical.ico' />
<link rel="icon" href="/infisical.ico" />
</Head>
<Card className="max-w-lg rounded-md border border-mineshaft-600 mb-12">
<CardTitle
className="text-left px-6 text-xl"
<Card className="mb-12 max-w-lg rounded-md border border-mineshaft-600">
<CardTitle
className="px-6 text-left text-xl"
subTitle="After adding your API Token, you will be prompted to set up an integration for a particular Infisical project and environment."
>
<div className="flex flex-row items-center">
@@ -67,10 +65,13 @@ export default function CircleCICreateIntegrationPage() {
<span className="ml-1.5">CircleCI Integration </span>
<Link href="https://infisical.com/docs/integrations/cicd/circleci" passHref>
<a target="_blank" rel="noopener noreferrer">
<div className="ml-2 mb-1 rounded-md text-yellow text-sm inline-block bg-yellow/20 px-1.5 pb-[0.03rem] pt-[0.04rem] opacity-80 hover:opacity-100 cursor-default">
<FontAwesomeIcon icon={faBookOpen} className="mr-1.5"/>
<div className="ml-2 mb-1 inline-block cursor-default rounded-md bg-yellow/20 px-1.5 pb-[0.03rem] pt-[0.04rem] text-sm text-yellow opacity-80 hover:opacity-100">
<FontAwesomeIcon icon={faBookOpen} className="mr-1.5" />
Docs
<FontAwesomeIcon icon={faArrowUpRightFromSquare} className="ml-1.5 text-xxs mb-[0.07rem]"/>
<FontAwesomeIcon
icon={faArrowUpRightFromSquare}
className="ml-1.5 mb-[0.07rem] text-xxs"
/>
</div>
</a>
</Link>

View File

@@ -3,13 +3,16 @@ import Head from "next/head";
import Image from "next/image";
import Link from "next/link";
import { useRouter } from "next/router";
import { faArrowUpRightFromSquare, faBookOpen, faBugs, faCircleInfo } from "@fortawesome/free-solid-svg-icons";
import {
faArrowUpRightFromSquare,
faBookOpen,
faBugs,
faCircleInfo
} from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import queryString from "query-string";
import {
useCreateIntegration
} from "@app/hooks/api";
import { useCreateIntegration } from "@app/hooks/api";
import {
Button,
@@ -33,10 +36,13 @@ export default function CircleCICreateIntegrationPage() {
const { integrationAuthId } = queryString.parse(router.asPath.split("?")[1]);
const { data: workspace } = useGetWorkspaceById(localStorage.getItem("projectData.id") ?? "");
const { data: integrationAuth, isLoading: isintegrationAuthLoading } = useGetIntegrationAuthById((integrationAuthId as string) ?? "");
const { data: integrationAuthApps, isLoading: isIntegrationAuthAppsLoading } = useGetIntegrationAuthApps({
integrationAuthId: (integrationAuthId as string) ?? ""
});
const { data: integrationAuth, isLoading: isintegrationAuthLoading } = useGetIntegrationAuthById(
(integrationAuthId as string) ?? ""
);
const { data: integrationAuthApps, isLoading: isIntegrationAuthAppsLoading } =
useGetIntegrationAuthApps({
integrationAuthId: (integrationAuthId as string) ?? ""
});
const [selectedSourceEnvironment, setSelectedSourceEnvironment] = useState("");
const [secretPath, setSecretPath] = useState("/");
@@ -71,7 +77,9 @@ export default function CircleCICreateIntegrationPage() {
integrationAuthId: integrationAuth?.id,
isActive: true,
app: targetApp,
appId: integrationAuthApps?.find((integrationAuthApp) => integrationAuthApp.name === targetApp)?.appId,
appId: integrationAuthApps?.find(
(integrationAuthApp) => integrationAuthApp.name === targetApp
)?.appId,
sourceEnvironment: selectedSourceEnvironment,
secretPath
});
@@ -89,14 +97,14 @@ export default function CircleCICreateIntegrationPage() {
selectedSourceEnvironment &&
integrationAuthApps &&
targetApp ? (
<div className="flex flex-col h-full w-full items-center justify-center">
<div className="flex h-full w-full flex-col items-center justify-center">
<Head>
<title>Set Up CircleCI Integration</title>
<link rel='icon' href='/infisical.ico' />
<link rel="icon" href="/infisical.ico" />
</Head>
<Card className="max-w-lg rounded-md border border-mineshaft-600">
<CardTitle
className="text-left px-6 text-xl"
<CardTitle
className="px-6 text-left text-xl"
subTitle="Choose which environment or folder in Infisical you want to sync to CircleCI environment variables."
>
<div className="flex flex-row items-center">
@@ -111,10 +119,13 @@ export default function CircleCICreateIntegrationPage() {
<span className="ml-1.5">CircleCI Integration </span>
<Link href="https://infisical.com/docs/integrations/cicd/circleci" passHref>
<a target="_blank" rel="noopener noreferrer">
<div className="ml-2 mb-1 rounded-md text-yellow text-sm inline-block bg-yellow/20 px-1.5 pb-[0.03rem] pt-[0.04rem] opacity-80 hover:opacity-100 cursor-default">
<FontAwesomeIcon icon={faBookOpen} className="mr-1.5"/>
<div className="ml-2 mb-1 inline-block cursor-default rounded-md bg-yellow/20 px-1.5 pb-[0.03rem] pt-[0.04rem] text-sm text-yellow opacity-80 hover:opacity-100">
<FontAwesomeIcon icon={faBookOpen} className="mr-1.5" />
Docs
<FontAwesomeIcon icon={faArrowUpRightFromSquare} className="ml-1.5 text-xxs mb-[0.07rem]"/>
<FontAwesomeIcon
icon={faArrowUpRightFromSquare}
className="ml-1.5 mb-[0.07rem] text-xxs"
/>
</div>
</a>
</Link>
@@ -177,31 +188,48 @@ export default function CircleCICreateIntegrationPage() {
Create Integration
</Button>
</Card>
<div className="border-t border-mineshaft-800 w-full max-w-md mt-6"/>
<div className="flex flex-col bg-mineshaft-800 border border-mineshaft-600 w-full p-4 max-w-lg mt-6 rounded-md">
<div className="flex flex-row items-center"><FontAwesomeIcon icon={faCircleInfo} className="text-mineshaft-200 text-xl"/> <span className="ml-3 text-md text-mineshaft-100">Pro Tips</span></div>
<span className="text-mineshaft-300 text-sm mt-4">After creating an integration, your secrets will start syncing immediately. This might cause an unexpected override of current secrets in CircleCI with secrets from Infisical.</span>
<div className="mt-6 w-full max-w-md border-t border-mineshaft-800" />
<div className="mt-6 flex w-full max-w-lg flex-col rounded-md border border-mineshaft-600 bg-mineshaft-800 p-4">
<div className="flex flex-row items-center">
<FontAwesomeIcon icon={faCircleInfo} className="text-xl text-mineshaft-200" />{" "}
<span className="text-md ml-3 text-mineshaft-100">Pro Tips</span>
</div>
<span className="mt-4 text-sm text-mineshaft-300">
After creating an integration, your secrets will start syncing immediately. This might
cause an unexpected override of current secrets in CircleCI with secrets from Infisical.
</span>
</div>
</div>
) : (
<div className="flex justify-center items-center w-full h-full">
<div className="flex h-full w-full items-center justify-center">
<Head>
<title>Set Up CircleCI Integration</title>
<link rel='icon' href='/infisical.ico' />
<link rel="icon" href="/infisical.ico" />
</Head>
{isIntegrationAuthAppsLoading || isintegrationAuthLoading ? <img src="/images/loading/loading.gif" height={70} width={120} alt="infisical loading indicator" /> : <div className="max-w-md h-max p-6 border border-mineshaft-600 rounded-md bg-mineshaft-800 text-mineshaft-200 flex flex-col text-center">
<FontAwesomeIcon icon={faBugs} className="text-6xl my-2 inlineli"/>
<p>
Something went wrong. Please contact <a
className="inline underline underline-offset-4 decoration-primary-500 opacity-80 hover:opacity-100 text-mineshaft-100 duration-200 cursor-pointer"
target="_blank"
rel="noopener noreferrer"
href="mailto:support@infisical.com"
>
support@infisical.com
</a> if the issue persists.
</p>
</div>}
{isIntegrationAuthAppsLoading || isintegrationAuthLoading ? (
<img
src="/images/loading/loading.gif"
height={70}
width={120}
alt="infisical loading indicator"
/>
) : (
<div className="flex h-max max-w-md flex-col rounded-md border border-mineshaft-600 bg-mineshaft-800 p-6 text-center text-mineshaft-200">
<FontAwesomeIcon icon={faBugs} className="inlineli my-2 text-6xl" />
<p>
Something went wrong. Please contact{" "}
<a
className="inline cursor-pointer text-mineshaft-100 underline decoration-primary-500 underline-offset-4 opacity-80 duration-200 hover:opacity-100"
target="_blank"
rel="noopener noreferrer"
href="mailto:support@infisical.com"
>
support@infisical.com
</a>{" "}
if the issue persists.
</p>
</div>
)}
</div>
);
}

View File

@@ -1,9 +1,7 @@
import { useState } from "react";
import { useRouter } from "next/router";
import {
useSaveIntegrationAccessToken
} from "@app/hooks/api";
import { useSaveIntegrationAccessToken } from "@app/hooks/api";
import { Button, Card, CardTitle, FormControl, Input } from "../../../components/v2";

View File

@@ -2,9 +2,7 @@ import { useEffect, useState } from "react";
import { useRouter } from "next/router";
import queryString from "query-string";
import {
useCreateIntegration
} from "@app/hooks/api";
import { useCreateIntegration } from "@app/hooks/api";
import {
Button,
@@ -16,8 +14,8 @@ import {
SelectItem
} from "../../../components/v2";
import {
useGetIntegrationAuthApps,
useGetIntegrationAuthById,
useGetIntegrationAuthApps,
useGetIntegrationAuthById
} from "../../../hooks/api/integrationAuth";
import { useGetWorkspaceById } from "../../../hooks/api/workspace";
@@ -64,7 +62,9 @@ export default function Cloud66CreateIntegrationPage() {
integrationAuthId: integrationAuth?.id,
isActive: true,
app: targetApp,
appId: integrationAuthApps?.find((integrationAuthApp) => integrationAuthApp.name === targetApp)?.appId,
appId: integrationAuthApps?.find(
(integrationAuthApp) => integrationAuthApp.name === targetApp
)?.appId,
sourceEnvironment: selectedSourceEnvironment,
secretPath
});

View File

@@ -1,92 +1,102 @@
import { useState } from "react";
import Head from "next/head";
import Image from "next/image";
import Link from "next/link";
import { useRouter } from "next/router";
import { faArrowUpRightFromSquare, faBookOpen } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import {
useSaveIntegrationAccessToken
} from "@app/hooks/api";
import { 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() {
const router = useRouter();
const { mutateAsync } = useSaveIntegrationAccessToken();
export default function RenderCreateIntegrationPage() {
const router = useRouter();
const { mutateAsync } = useSaveIntegrationAccessToken();
const [accessKey, setAccessKey] = useState("");
const [accessKeyErrorText, setAccessKeyErrorText] = useState("");
const [accountId, setAccountId] = useState("");
const [accountIdErrorText, setAccountIdErrorText] = useState("");
const [isLoading, setIsLoading] = useState(false);
const [apiKey, setApiKey] = useState("");
const [apiKeyErrorText, setApiKeyErrorText] = useState("");
const [isLoading, setIsLoading] = useState(false);
const handleButtonClick = async () => {
try {
setAccessKeyErrorText("");
setAccountIdErrorText("");
if (accessKey.length === 0 || accountId.length === 0) {
if (accessKey.length === 0) setAccessKeyErrorText("API token cannot be blank!");
if (accountId.length === 0) setAccountIdErrorText("Account ID cannot be blank!");
return;
}
const handleButtonClick = async () => {
try {
setApiKeyErrorText("");
if (apiKey.length === 0) {
setApiKeyErrorText("API Key cannot be blank");
return;
}
setIsLoading(true);
setIsLoading(true);
const integrationAuth = await mutateAsync({
workspaceId: localStorage.getItem("projectData.id"),
integration: "cloudflare-pages",
accessId: accountId,
accessToken: accessKey
});
const integrationAuth = await mutateAsync({
workspaceId: localStorage.getItem("projectData.id"),
integration: "render",
accessToken: apiKey
});
setAccessKey("");
setAccountId("");
setIsLoading(false);
setIsLoading(false);
router.push(`/integrations/cloudflare-pages/create?integrationAuthId=${integrationAuth.id}`);
} catch (err) {
console.error(err);
}
router.push(`/integrations/render/create?integrationAuthId=${integrationAuth._id}`);
} catch (err) {
console.error(err);
}
};
return (
<div className="flex h-full w-full items-center justify-center">
<Card className="max-w-lg rounded-md border border-mineshaft-600 mb-12">
<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>
<FormControl
label="Cloudflare Pages API token"
errorText={accessKeyErrorText}
isError={accessKeyErrorText !== "" ?? false}
className="mx-6"
>
<Input
placeholder=""
value={accessKey}
onChange={(e) => setAccessKey(e.target.value)}
/>
</FormControl>
<FormControl
label="Cloudflare Pages Account ID"
errorText={accountIdErrorText}
isError={accountIdErrorText !== "" ?? false}
className="mx-6"
>
<Input
placeholder=""
value={accountId}
onChange={(e) => setAccountId(e.target.value)}
/>
</FormControl>
<Button
onClick={handleButtonClick}
color="mineshaft"
variant="outline_bg"
className="mb-6 mt-2 ml-auto mr-6 w-min"
isFullWidth={false}
isLoading={isLoading}
>
Connect to Cloudflare Pages
</Button>
</Card>
</div>
);
return (
<div className="flex h-full w-full items-center justify-center">
<Head>
<title>Authorize Render Integration</title>
<link rel="icon" href="/infisical.ico" />
</Head>
<Card className="mb-12 max-w-lg rounded-md border border-mineshaft-600">
<CardTitle
className="px-6 text-left text-xl"
subTitle="After adding your API key, you will be prompted to set up an integration for a particular Infisical project and environment."
>
<div className="flex flex-row items-center">
<div className="inline flex items-center pb-0.5">
<Image
src="/images/integrations/Render.png"
height={30}
width={30}
alt="Render logo"
/>
</div>
<span className="ml-2.5">Render Integration </span>
<Link href="https://infisical.com/docs/integrations/cloud/render" passHref>
<a target="_blank" rel="noopener noreferrer">
<div className="ml-2 mb-1 inline-block cursor-default rounded-md bg-yellow/20 px-1.5 pb-[0.03rem] pt-[0.04rem] text-sm text-yellow opacity-80 hover:opacity-100">
<FontAwesomeIcon icon={faBookOpen} className="mr-1.5" />
Docs
<FontAwesomeIcon
icon={faArrowUpRightFromSquare}
className="ml-1.5 mb-[0.07rem] text-xxs"
/>
</div>
</a>
</Link>
</div>
</CardTitle>
<FormControl
label="Render API Key"
errorText={apiKeyErrorText}
isError={apiKeyErrorText !== "" ?? false}
className="px-6"
>
<Input placeholder="rnd_xxx" value={apiKey} onChange={(e) => setApiKey(e.target.value)} />
</FormControl>
<Button
onClick={handleButtonClick}
colorSchema="primary"
variant="outline_bg"
className="mb-6 mt-2 ml-auto mr-6 w-min"
isLoading={isLoading}
>
Connect to Render
</Button>
</Card>
</div>
);
}
CloudflarePagesIntegrationPage.requireAuth = true;
RenderCreateIntegrationPage.requireAuth = true;

View File

@@ -1,159 +1,165 @@
import { useEffect,useState } from "react";
import { useEffect, useState } from "react";
import { useRouter } from "next/router";
import queryString from "query-string";
import {
useCreateIntegration
, useGetWorkspaceById } from "@app/hooks/api";
import { useCreateIntegration, useGetWorkspaceById } from "@app/hooks/api";
import { Button, Card, CardTitle, FormControl, Select, SelectItem } from "../../../components/v2";
import { useGetIntegrationAuthApps, useGetIntegrationAuthById } from "../../../hooks/api/integrationAuth";
import {
useGetIntegrationAuthApps,
useGetIntegrationAuthById
} from "../../../hooks/api/integrationAuth";
const cloudflareEnvironments = [
{ name: "Production", slug: "production" },
{ name: "Preview", slug: "preview" }
{ name: "Production", slug: "production" },
{ name: "Preview", slug: "preview" }
];
export default function CloudflarePagesIntegrationPage() {
const router = useRouter();
const { mutateAsync } = useCreateIntegration();
const router = useRouter();
const { mutateAsync } = useCreateIntegration();
const { integrationAuthId } = queryString.parse(router.asPath.split("?")[1]);
const { data: workspace } = useGetWorkspaceById(localStorage.getItem("projectData.id") ?? "");
const { data: integrationAuth } = useGetIntegrationAuthById((integrationAuthId as string) ?? "");
const { data: integrationAuthApps } = useGetIntegrationAuthApps({
integrationAuthId: (integrationAuthId as string) ?? ""
});
const { integrationAuthId } = queryString.parse(router.asPath.split("?")[1]);
const { data: workspace } = useGetWorkspaceById(localStorage.getItem("projectData.id") ?? "");
const { data: integrationAuth } = useGetIntegrationAuthById((integrationAuthId as string) ?? "");
const { data: integrationAuthApps } = useGetIntegrationAuthApps({
integrationAuthId: (integrationAuthId as string) ?? ""
});
const [selectedSourceEnvironment, setSelectedSourceEnvironment] = useState("");
const [targetApp, setTargetApp] = useState("");
const [targetAppId, setTargetAppId] = useState("");
const [targetEnvironment, setTargetEnvironment] = useState("");
const [selectedSourceEnvironment, setSelectedSourceEnvironment] = useState("");
const [targetApp, setTargetApp] = useState("");
const [targetAppId, setTargetAppId] = useState("");
const [targetEnvironment, setTargetEnvironment] = useState("");
const [isLoading, setIsLoading] = useState(false);
const [isLoading, setIsLoading] = useState(false);
useEffect(() => {
if (workspace) {
setSelectedSourceEnvironment(workspace.environments[0].slug);
}
}, [workspace]);
useEffect(() => {
if (integrationAuthApps) {
if (integrationAuthApps.length > 0) {
setTargetApp(integrationAuthApps[0].name);
setTargetAppId(String(integrationAuthApps[0].appId));
setTargetEnvironment(cloudflareEnvironments[0].slug);
} else {
setTargetApp("none");
setTargetEnvironment(cloudflareEnvironments[0].slug);
}
}
}, [integrationAuthApps]);
const handleButtonClick = async () => {
try {
if (!integrationAuth?.id) return;
setIsLoading(true);
await mutateAsync({
integrationAuthId: integrationAuth?.id,
isActive: true,
app: targetApp,
appId: targetAppId,
sourceEnvironment: selectedSourceEnvironment,
targetEnvironment,
secretPath: "/",
});
setIsLoading(false);
router.push(`/integrations/${localStorage.getItem("projectData.id")}`);
} catch(err) {
console.error(err);
}
useEffect(() => {
if (workspace) {
setSelectedSourceEnvironment(workspace.environments[0].slug);
}
}, [workspace]);
return integrationAuth &&
workspace &&
selectedSourceEnvironment &&
integrationAuthApps &&
targetEnvironment &&
targetApp ? (
<div className="flex h-full w-full items-center justify-center bg-gradient-to-tr from-mineshaft-900 to-bunker-900">
<Card className="max-w-lg rounded-md p-0 border border-mineshaft-600">
<CardTitle className="text-left px-6" subTitle="Choose which environment in Infisical you want to sync with your Cloudflare Pages project.">Cloudflare Pages Integration</CardTitle>
<FormControl label="Infisical Project Environment" className="mt-2 px-6">
<Select
value={selectedSourceEnvironment}
onValueChange={(val) => setSelectedSourceEnvironment(val)}
className="w-full border border-mineshaft-500"
>
{workspace?.environments.map((sourceEnvironment) => (
<SelectItem
value={sourceEnvironment.slug}
key={`source-environment-${sourceEnvironment.slug}`}
>
{sourceEnvironment.name}
</SelectItem>
))}
</Select>
</FormControl>
<FormControl label="Cloudflare Pages Project" className="mt-4 px-6">
<Select
value={targetApp}
onValueChange={(val) => setTargetApp(val)}
className="w-full border border-mineshaft-500"
isDisabled={integrationAuthApps.length === 0}
>
{integrationAuthApps.length > 0 ? (
integrationAuthApps.map((integrationAuthApp) => (
<SelectItem
value={integrationAuthApp.name}
key={`target-app-${integrationAuthApp.name}`}
>
{integrationAuthApp.name}
</SelectItem>
))
) : (
<SelectItem value="none" key="target-app-none">
No apps found
</SelectItem>
)}
</Select>
</FormControl>
<FormControl label="Cloudflare Pages Environment" className="mt-4 px-6">
<Select
value={targetEnvironment}
onValueChange={(val) => setTargetEnvironment(val)}
className="w-full border border-mineshaft-500"
>
{cloudflareEnvironments.map((cloudflareEnvironment) => (
<SelectItem
value={cloudflareEnvironment.slug}
key={`target-environment-${cloudflareEnvironment.slug}`}
>
{cloudflareEnvironment.name}
</SelectItem>
))}
</Select>
</FormControl>
<Button
onClick={handleButtonClick}
color="mineshaft"
variant="outline_bg"
className="mt-2 mb-6 ml-auto mr-6"
isFullWidth={false}
isLoading={isLoading}
useEffect(() => {
if (integrationAuthApps) {
if (integrationAuthApps.length > 0) {
setTargetApp(integrationAuthApps[0].name);
setTargetAppId(String(integrationAuthApps[0].appId));
setTargetEnvironment(cloudflareEnvironments[0].slug);
} else {
setTargetApp("none");
setTargetEnvironment(cloudflareEnvironments[0].slug);
}
}
}, [integrationAuthApps]);
const handleButtonClick = async () => {
try {
if (!integrationAuth?.id) return;
setIsLoading(true);
await mutateAsync({
integrationAuthId: integrationAuth?.id,
isActive: true,
app: targetApp,
appId: targetAppId,
sourceEnvironment: selectedSourceEnvironment,
targetEnvironment,
secretPath: "/"
});
setIsLoading(false);
router.push(`/integrations/${localStorage.getItem("projectData.id")}`);
} catch (err) {
console.error(err);
}
};
return integrationAuth &&
workspace &&
selectedSourceEnvironment &&
integrationAuthApps &&
targetEnvironment &&
targetApp ? (
<div className="flex h-full w-full items-center justify-center bg-gradient-to-tr from-mineshaft-900 to-bunker-900">
<Card className="max-w-lg rounded-md border border-mineshaft-600 p-0">
<CardTitle
className="px-6 text-left"
subTitle="Choose which environment in Infisical you want to sync with your Cloudflare Pages project."
>
Cloudflare Pages Integration
</CardTitle>
<FormControl label="Infisical Project Environment" className="mt-2 px-6">
<Select
value={selectedSourceEnvironment}
onValueChange={(val) => setSelectedSourceEnvironment(val)}
className="w-full border border-mineshaft-500"
>
{workspace?.environments.map((sourceEnvironment) => (
<SelectItem
value={sourceEnvironment.slug}
key={`source-environment-${sourceEnvironment.slug}`}
>
{sourceEnvironment.name}
</SelectItem>
))}
</Select>
</FormControl>
<FormControl label="Cloudflare Pages Project" className="mt-4 px-6">
<Select
value={targetApp}
onValueChange={(val) => setTargetApp(val)}
className="w-full border border-mineshaft-500"
isDisabled={integrationAuthApps.length === 0}
>
{integrationAuthApps.length > 0 ? (
integrationAuthApps.map((integrationAuthApp) => (
<SelectItem
value={integrationAuthApp.name}
key={`target-app-${integrationAuthApp.name}`}
>
Create Integration
</Button>
</Card>
</div>
) : (
<div />
);
{integrationAuthApp.name}
</SelectItem>
))
) : (
<SelectItem value="none" key="target-app-none">
No apps found
</SelectItem>
)}
</Select>
</FormControl>
<FormControl label="Cloudflare Pages Environment" className="mt-4 px-6">
<Select
value={targetEnvironment}
onValueChange={(val) => setTargetEnvironment(val)}
className="w-full border border-mineshaft-500"
>
{cloudflareEnvironments.map((cloudflareEnvironment) => (
<SelectItem
value={cloudflareEnvironment.slug}
key={`target-environment-${cloudflareEnvironment.slug}`}
>
{cloudflareEnvironment.name}
</SelectItem>
))}
</Select>
</FormControl>
<Button
onClick={handleButtonClick}
color="mineshaft"
variant="outline_bg"
className="mt-2 mb-6 ml-auto mr-6"
isFullWidth={false}
isLoading={isLoading}
>
Create Integration
</Button>
</Card>
</div>
) : (
<div />
);
}
CloudflarePagesIntegrationPage.requireAuth = true;
CloudflarePagesIntegrationPage.requireAuth = true;

View File

@@ -1,92 +1,89 @@
import { useState } from "react";
import { useRouter } from "next/router";
import {
useSaveIntegrationAccessToken
} from "@app/hooks/api";
import { 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 CloudflareWorkersIntegrationPage() {
const router = useRouter();
const { mutateAsync } = useSaveIntegrationAccessToken();
const router = useRouter();
const { mutateAsync } = useSaveIntegrationAccessToken();
const [accessKey, setAccessKey] = useState("");
const [accessKeyErrorText, setAccessKeyErrorText] = useState("");
const [accountId, setAccountId] = useState("");
const [accountIdErrorText, setAccountIdErrorText] = useState("");
const [isLoading, setIsLoading] = useState(false);
const [accessKey, setAccessKey] = useState("");
const [accessKeyErrorText, setAccessKeyErrorText] = useState("");
const [accountId, setAccountId] = useState("");
const [accountIdErrorText, setAccountIdErrorText] = useState("");
const [isLoading, setIsLoading] = useState(false);
const handleButtonClick = async () => {
try {
setAccessKeyErrorText("");
setAccountIdErrorText("");
if (accessKey.length === 0 || accountId.length === 0) {
if (accessKey.length === 0) setAccessKeyErrorText("API token cannot be blank!");
if (accountId.length === 0) setAccountIdErrorText("Account ID cannot be blank!");
return;
}
const handleButtonClick = async () => {
try {
setAccessKeyErrorText("");
setAccountIdErrorText("");
if (accessKey.length === 0 || accountId.length === 0) {
if (accessKey.length === 0) setAccessKeyErrorText("API token cannot be blank!");
if (accountId.length === 0) setAccountIdErrorText("Account ID cannot be blank!");
return;
}
setIsLoading(true);
setIsLoading(true);
const integrationAuth = await mutateAsync({
workspaceId: localStorage.getItem("projectData.id"),
integration: "cloudflare-workers",
accessId: accountId,
accessToken: accessKey
});
const integrationAuth = await mutateAsync({
workspaceId: localStorage.getItem("projectData.id"),
integration: "cloudflare-workers",
accessId: accountId,
accessToken: accessKey
});
setAccessKey("");
setAccountId("");
setIsLoading(false);
setAccessKey("");
setAccountId("");
setIsLoading(false);
router.push(`/integrations/cloudflare-workers/create?integrationAuthId=${integrationAuth.id}`);
} catch (err) {
console.error(err);
}
router.push(
`/integrations/cloudflare-workers/create?integrationAuthId=${integrationAuth.id}`
);
} catch (err) {
console.error(err);
}
};
return (
<div className="flex h-full w-full items-center justify-center">
<Card className="max-w-lg rounded-md border border-mineshaft-600 mb-12">
<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 Workers Integration</CardTitle>
<FormControl
label="Cloudflare Workers API token"
errorText={accessKeyErrorText}
isError={accessKeyErrorText !== "" ?? false}
className="mx-6"
>
<Input
placeholder=""
value={accessKey}
onChange={(e) => setAccessKey(e.target.value)}
/>
</FormControl>
<FormControl
label="Cloudflare Workers Account ID"
errorText={accountIdErrorText}
isError={accountIdErrorText !== "" ?? false}
className="mx-6"
>
<Input
placeholder=""
value={accountId}
onChange={(e) => setAccountId(e.target.value)}
/>
</FormControl>
<Button
onClick={handleButtonClick}
color="mineshaft"
variant="outline_bg"
className="mb-6 mt-2 ml-auto mr-6 w-min"
isFullWidth={false}
isLoading={isLoading}
>
Connect to Cloudflare Workers
</Button>
</Card>
</div>
);
return (
<div className="flex h-full w-full items-center justify-center">
<Card className="mb-12 max-w-lg rounded-md border border-mineshaft-600">
<CardTitle
className="px-6 text-left"
subTitle="After adding your API-key, you will be prompted to set up an integration for a particular Infisical project and environment."
>
Cloudflare Workers Integration
</CardTitle>
<FormControl
label="Cloudflare Workers API token"
errorText={accessKeyErrorText}
isError={accessKeyErrorText !== "" ?? false}
className="mx-6"
>
<Input placeholder="" value={accessKey} onChange={(e) => setAccessKey(e.target.value)} />
</FormControl>
<FormControl
label="Cloudflare Workers Account ID"
errorText={accountIdErrorText}
isError={accountIdErrorText !== "" ?? false}
className="mx-6"
>
<Input placeholder="" value={accountId} onChange={(e) => setAccountId(e.target.value)} />
</FormControl>
<Button
onClick={handleButtonClick}
color="mineshaft"
variant="outline_bg"
className="mb-6 mt-2 ml-auto mr-6 w-min"
isFullWidth={false}
isLoading={isLoading}
>
Connect to Cloudflare Workers
</Button>
</Card>
</div>
);
}
CloudflareWorkersIntegrationPage.requireAuth = true;
CloudflareWorkersIntegrationPage.requireAuth = true;

View File

@@ -1,133 +1,139 @@
import { useEffect,useState } from "react";
import { useEffect, useState } from "react";
import { useRouter } from "next/router";
import queryString from "query-string";
import {
useCreateIntegration
, useGetWorkspaceById } from "@app/hooks/api";
import { useCreateIntegration, useGetWorkspaceById } from "@app/hooks/api";
import { Button, Card, CardTitle, FormControl, Select, SelectItem } from "../../../components/v2";
import { useGetIntegrationAuthApps, useGetIntegrationAuthById } from "../../../hooks/api/integrationAuth";
import {
useGetIntegrationAuthApps,
useGetIntegrationAuthById
} from "../../../hooks/api/integrationAuth";
export default function CloudflareWorkersIntegrationPage() {
const router = useRouter();
const { mutateAsync } = useCreateIntegration();
const router = useRouter();
const { mutateAsync } = useCreateIntegration();
const { integrationAuthId } = queryString.parse(router.asPath.split("?")[1]);
const { data: workspace } = useGetWorkspaceById(localStorage.getItem("projectData.id") ?? "");
const { data: integrationAuth } = useGetIntegrationAuthById((integrationAuthId as string) ?? "");
const { data: integrationAuthApps } = useGetIntegrationAuthApps({
integrationAuthId: (integrationAuthId as string) ?? ""
});
const { integrationAuthId } = queryString.parse(router.asPath.split("?")[1]);
const { data: workspace } = useGetWorkspaceById(localStorage.getItem("projectData.id") ?? "");
const { data: integrationAuth } = useGetIntegrationAuthById((integrationAuthId as string) ?? "");
const { data: integrationAuthApps } = useGetIntegrationAuthApps({
integrationAuthId: (integrationAuthId as string) ?? ""
});
const [selectedSourceEnvironment, setSelectedSourceEnvironment] = useState("");
const [targetApp, setTargetApp] = useState("");
const [targetAppId, setTargetAppId] = useState("");
const [selectedSourceEnvironment, setSelectedSourceEnvironment] = useState("");
const [targetApp, setTargetApp] = useState("");
const [targetAppId, setTargetAppId] = useState("");
const [isLoading, setIsLoading] = useState(false);
const [isLoading, setIsLoading] = useState(false);
useEffect(() => {
if (workspace) {
setSelectedSourceEnvironment(workspace.environments[0].slug);
}
}, [workspace]);
useEffect(() => {
if (integrationAuthApps) {
if (integrationAuthApps.length > 0) {
setTargetApp(integrationAuthApps[0].name);
setTargetAppId(String(integrationAuthApps[0].appId));
} else {
setTargetApp("none");
}
}
}, [integrationAuthApps]);
const handleButtonClick = async () => {
try {
if (!integrationAuth?.id) return;
setIsLoading(true);
await mutateAsync({
integrationAuthId: integrationAuth?.id,
isActive: true,
app: targetApp,
appId: targetAppId,
sourceEnvironment: selectedSourceEnvironment,
secretPath: "/",
});
setIsLoading(false);
router.push(`/integrations/${localStorage.getItem("projectData.id")}`);
} catch(err) {
console.error(err);
}
useEffect(() => {
if (workspace) {
setSelectedSourceEnvironment(workspace.environments[0].slug);
}
}, [workspace]);
return integrationAuth &&
workspace &&
selectedSourceEnvironment &&
integrationAuthApps &&
targetApp ? (
<div className="flex h-full w-full items-center justify-center bg-gradient-to-tr from-mineshaft-900 to-bunker-900">
<Card className="max-w-lg rounded-md p-0 border border-mineshaft-600">
<CardTitle className="text-left px-6" subTitle="Choose which environment in Infisical you want to sync with your Cloudflare Workers project.">Cloudflare Workers Integration</CardTitle>
<FormControl label="Infisical Project Environment" className="mt-2 px-6">
<Select
value={selectedSourceEnvironment}
onValueChange={(val) => setSelectedSourceEnvironment(val)}
className="w-full border border-mineshaft-500"
>
{workspace?.environments.map((sourceEnvironment) => (
<SelectItem
value={sourceEnvironment.slug}
key={`source-environment-${sourceEnvironment.slug}`}
>
{sourceEnvironment.name}
</SelectItem>
))}
</Select>
</FormControl>
<FormControl label="Cloudflare Workers Project" className="mt-4 px-6">
<Select
value={targetApp}
onValueChange={(val) => setTargetApp(val)}
className="w-full border border-mineshaft-500"
isDisabled={integrationAuthApps.length === 0}
>
{integrationAuthApps.length > 0 ? (
integrationAuthApps.map((integrationAuthApp) => (
<SelectItem
value={integrationAuthApp.name}
key={`target-app-${integrationAuthApp.name}`}
>
{integrationAuthApp.name}
</SelectItem>
))
) : (
<SelectItem value="none" key="target-app-none">
No apps found
</SelectItem>
)}
</Select>
</FormControl>
<Button
onClick={handleButtonClick}
color="mineshaft"
variant="outline_bg"
className="mt-2 mb-6 ml-auto mr-6"
isFullWidth={false}
isLoading={isLoading}
useEffect(() => {
if (integrationAuthApps) {
if (integrationAuthApps.length > 0) {
setTargetApp(integrationAuthApps[0].name);
setTargetAppId(String(integrationAuthApps[0].appId));
} else {
setTargetApp("none");
}
}
}, [integrationAuthApps]);
const handleButtonClick = async () => {
try {
if (!integrationAuth?._id) return;
setIsLoading(true);
await mutateAsync({
integrationAuthId: integrationAuth?._id,
isActive: true,
app: targetApp,
appId: targetAppId,
sourceEnvironment: selectedSourceEnvironment,
secretPath: "/"
});
setIsLoading(false);
router.push(`/integrations/${localStorage.getItem("projectData.id")}`);
} catch (err) {
console.error(err);
}
};
return integrationAuth &&
workspace &&
selectedSourceEnvironment &&
integrationAuthApps &&
targetApp ? (
<div className="flex h-full w-full items-center justify-center bg-gradient-to-tr from-mineshaft-900 to-bunker-900">
<Card className="max-w-lg rounded-md border border-mineshaft-600 p-0">
<CardTitle
className="px-6 text-left"
subTitle="Choose which environment in Infisical you want to sync with your Cloudflare Workers project."
>
Cloudflare Workers Integration
</CardTitle>
<FormControl label="Infisical Project Environment" className="mt-2 px-6">
<Select
value={selectedSourceEnvironment}
onValueChange={(val) => setSelectedSourceEnvironment(val)}
className="w-full border border-mineshaft-500"
>
{workspace?.environments.map((sourceEnvironment) => (
<SelectItem
value={sourceEnvironment.slug}
key={`source-environment-${sourceEnvironment.slug}`}
>
{sourceEnvironment.name}
</SelectItem>
))}
</Select>
</FormControl>
<FormControl label="Cloudflare Workers Project" className="mt-4 px-6">
<Select
value={targetApp}
onValueChange={(val) => setTargetApp(val)}
className="w-full border border-mineshaft-500"
isDisabled={integrationAuthApps.length === 0}
>
{integrationAuthApps.length > 0 ? (
integrationAuthApps.map((integrationAuthApp) => (
<SelectItem
value={integrationAuthApp.name}
key={`target-app-${integrationAuthApp.name}`}
>
Create Integration
</Button>
</Card>
</div>
) : (
<div />
);
{integrationAuthApp.name}
</SelectItem>
))
) : (
<SelectItem value="none" key="target-app-none">
No apps found
</SelectItem>
)}
</Select>
</FormControl>
<Button
onClick={handleButtonClick}
color="mineshaft"
variant="outline_bg"
className="mt-2 mb-6 ml-auto mr-6"
isFullWidth={false}
isLoading={isLoading}
>
Create Integration
</Button>
</Card>
</div>
) : (
<div />
);
}
CloudflareWorkersIntegrationPage.requireAuth = true;
CloudflareWorkersIntegrationPage.requireAuth = true;

View File

@@ -1,9 +1,7 @@
import { useState } from "react";
import { useRouter } from "next/router";
import {
useSaveIntegrationAccessToken
} from "@app/hooks/api";
import { useSaveIntegrationAccessToken } from "@app/hooks/api";
import { Button, Card, CardTitle, FormControl, Input } from "../../../components/v2";

View File

@@ -2,9 +2,7 @@ import { useEffect, useState } from "react";
import { useRouter } from "next/router";
import queryString from "query-string";
import {
useCreateIntegration
} from "@app/hooks/api";
import { useCreateIntegration } from "@app/hooks/api";
import {
Button,
@@ -64,7 +62,9 @@ export default function CodefreshCreateIntegrationPage() {
integrationAuthId: integrationAuth?.id,
isActive: true,
app: targetApp,
appId: integrationAuthApps?.find((integrationAuthApp) => integrationAuthApp.name === targetApp)?.appId,
appId: integrationAuthApps?.find(
(integrationAuthApp) => integrationAuthApp.name === targetApp
)?.appId,
sourceEnvironment: selectedSourceEnvironment,
secretPath
});

View File

@@ -1,16 +1,14 @@
import { useState } from "react";
import { useRouter } from "next/router";
import {
useSaveIntegrationAccessToken
} from "@app/hooks/api";
import { useSaveIntegrationAccessToken } from "@app/hooks/api";
import { Button, Card, CardTitle, FormControl, Input } from "../../../components/v2";
export default function DigitalOceanAppPlatformCreateIntegrationPage() {
const router = useRouter();
const { mutateAsync } = useSaveIntegrationAccessToken();
const [apiKey, setApiKey] = useState("");
const [apiKeyErrorText, setApiKeyErrorText] = useState("");
const [isLoading, setIsLoading] = useState(false);
@@ -33,7 +31,9 @@ export default function DigitalOceanAppPlatformCreateIntegrationPage() {
setIsLoading(false);
router.push(`/integrations/digital-ocean-app-platform/create?integrationAuthId=${integrationAuth.id}`);
router.push(
`/integrations/digital-ocean-app-platform/create?integrationAuthId=${integrationAuth.id}`
);
} catch (err) {
console.error(err);
}

View File

@@ -2,9 +2,7 @@ import { useEffect, useState } from "react";
import { useRouter } from "next/router";
import queryString from "query-string";
import {
useCreateIntegration
} from "@app/hooks/api";
import { useCreateIntegration } from "@app/hooks/api";
import {
Button,
@@ -64,7 +62,9 @@ export default function DigitalOceanAppPlatformCreateIntegrationPage() {
integrationAuthId: integrationAuth?.id,
isActive: true,
app: targetApp,
appId: integrationAuthApps?.find((integrationAuthApp) => integrationAuthApp.name === targetApp)?.appId,
appId: integrationAuthApps?.find(
(integrationAuthApp) => integrationAuthApp.name === targetApp
)?.appId,
sourceEnvironment: selectedSourceEnvironment,
secretPath
});

View File

@@ -9,9 +9,7 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { yupResolver } from "@hookform/resolvers/yup";
import * as yup from "yup";
import {
useSaveIntegrationAccessToken
} from "@app/hooks/api";
import { useSaveIntegrationAccessToken } from "@app/hooks/api";
import { Button, Card, CardTitle, FormControl, Input } from "../../../components/v2";
@@ -24,10 +22,7 @@ type FormData = yup.InferType<typeof schema>;
export default function FlyioAuthorizeIntegrationPage() {
const router = useRouter();
const {
control,
handleSubmit
} = useForm<FormData>({
const { control, handleSubmit } = useForm<FormData>({
resolver: yupResolver(schema),
defaultValues: {
accessToken: ""
@@ -35,38 +30,36 @@ export default function FlyioAuthorizeIntegrationPage() {
});
const { mutateAsync } = useSaveIntegrationAccessToken();
const [isLoading, setIsLoading] = useState(false);
const onFormSubmit = async ({
accessToken
}: FormData) => {
const onFormSubmit = async ({ accessToken }: FormData) => {
try {
setIsLoading(true);
const integrationAuth = await mutateAsync({
workspaceId: localStorage.getItem("projectData.id"),
integration: "flyio",
accessToken
});
setIsLoading(false);
router.push(`/integrations/flyio/create?integrationAuthId=${integrationAuth.id}`);
} catch (err) {
setIsLoading(false);
console.error(err);
}
}
};
return (
<div className="flex h-full w-full items-center justify-center">
<Head>
<title>Authorize Fly.io Integration</title>
<link rel='icon' href='/infisical.ico' />
<link rel="icon" href="/infisical.ico" />
</Head>
<Card className="max-w-lg rounded-md border border-mineshaft-600 mb-12">
<CardTitle
className="text-left px-6 text-xl"
<Card className="mb-12 max-w-lg rounded-md border border-mineshaft-600">
<CardTitle
className="px-6 text-left text-xl"
subTitle="After adding your access token, you will be prompted to set up an integration for a particular Infisical project and environment."
>
<div className="flex flex-row items-center">
@@ -81,19 +74,19 @@ export default function FlyioAuthorizeIntegrationPage() {
<span className="ml-2.5">Fly.io Integration </span>
<Link href="https://infisical.com/docs/integrations/cloud/flyio" passHref>
<a target="_blank" rel="noopener noreferrer">
<div className="ml-2 mb-1 rounded-md text-yellow text-sm inline-block bg-yellow/20 px-1.5 pb-[0.03rem] pt-[0.04rem] opacity-80 hover:opacity-100 cursor-default">
<FontAwesomeIcon icon={faBookOpen} className="mr-1.5"/>
Docs
<FontAwesomeIcon icon={faArrowUpRightFromSquare} className="ml-1.5 text-xxs mb-[0.07rem]"/>
<div className="ml-2 mb-1 inline-block cursor-default rounded-md bg-yellow/20 px-1.5 pb-[0.03rem] pt-[0.04rem] text-sm text-yellow opacity-80 hover:opacity-100">
<FontAwesomeIcon icon={faBookOpen} className="mr-1.5" />
Docs
<FontAwesomeIcon
icon={faArrowUpRightFromSquare}
className="ml-1.5 mb-[0.07rem] text-xxs"
/>
</div>
</a>
</Link>
</div>
</CardTitle>
<form
onSubmit={handleSubmit(onFormSubmit)}
className="px-6 text-right pb-8"
>
<form onSubmit={handleSubmit(onFormSubmit)} className="px-6 pb-8 text-right">
<Controller
control={control}
name="accessToken"
@@ -103,10 +96,7 @@ export default function FlyioAuthorizeIntegrationPage() {
errorText={error?.message}
isError={Boolean(error)}
>
<Input
{...field}
placeholder=""
/>
<Input {...field} placeholder="" />
</FormControl>
)}
/>

View File

@@ -3,13 +3,16 @@ import Head from "next/head";
import Image from "next/image";
import Link from "next/link";
import { useRouter } from "next/router";
import { faArrowUpRightFromSquare, faBookOpen, faBugs, faCircleInfo } from "@fortawesome/free-solid-svg-icons";
import {
faArrowUpRightFromSquare,
faBookOpen,
faBugs,
faCircleInfo
} from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import queryString from "query-string";
import {
useCreateIntegration
} from "@app/hooks/api";
import { useCreateIntegration } from "@app/hooks/api";
import {
Button,
@@ -28,16 +31,19 @@ import { useGetWorkspaceById } from "../../../hooks/api/workspace";
export default function FlyioCreateIntegrationPage() {
const router = useRouter();
const { mutateAsync } = useCreateIntegration();
const { integrationAuthId } = queryString.parse(router.asPath.split("?")[1]);
const { data: workspace } = useGetWorkspaceById(localStorage.getItem("projectData.id") ?? "");
const { data: integrationAuth, isLoading: isIntegrationAuthLoading } = useGetIntegrationAuthById((integrationAuthId as string) ?? "");
const { data: integrationAuthApps, isLoading: isIntegrationAuthAppsLoading } = useGetIntegrationAuthApps({
integrationAuthId: (integrationAuthId as string) ?? ""
});
const { data: integrationAuth, isLoading: isIntegrationAuthLoading } = useGetIntegrationAuthById(
(integrationAuthId as string) ?? ""
);
const { data: integrationAuthApps, isLoading: isIntegrationAuthAppsLoading } =
useGetIntegrationAuthApps({
integrationAuthId: (integrationAuthId as string) ?? ""
});
const [selectedSourceEnvironment, setSelectedSourceEnvironment] = useState("");
const [secretPath, setSecretPath] = useState("/");
@@ -90,14 +96,14 @@ export default function FlyioCreateIntegrationPage() {
selectedSourceEnvironment &&
integrationAuthApps &&
targetApp ? (
<div className="flex flex-col h-full w-full items-center justify-center">
<div className="flex h-full w-full flex-col items-center justify-center">
<Head>
<title>Set Up Fly.io Integration</title>
<link rel='icon' href='/infisical.ico' />
<link rel="icon" href="/infisical.ico" />
</Head>
<Card className="max-w-lg rounded-md border border-mineshaft-600">
<CardTitle
className="text-left px-6 text-xl"
<CardTitle
className="px-6 text-left text-xl"
subTitle="Choose which environment or folder in Infisical you want to sync to Fly.io environment variables."
>
<div className="flex flex-row items-center">
@@ -112,10 +118,13 @@ export default function FlyioCreateIntegrationPage() {
<span className="ml-2.5">Fly.io Integration </span>
<Link href="https://infisical.com/docs/integrations/cloud/flyio" passHref>
<a target="_blank" rel="noopener noreferrer">
<div className="ml-2 mb-1 rounded-md text-yellow text-sm inline-block bg-yellow/20 px-1.5 pb-[0.03rem] pt-[0.04rem] opacity-80 hover:opacity-100 cursor-default">
<FontAwesomeIcon icon={faBookOpen} className="mr-1.5"/>
<div className="ml-2 mb-1 inline-block cursor-default rounded-md bg-yellow/20 px-1.5 pb-[0.03rem] pt-[0.04rem] text-sm text-yellow opacity-80 hover:opacity-100">
<FontAwesomeIcon icon={faBookOpen} className="mr-1.5" />
Docs
<FontAwesomeIcon icon={faArrowUpRightFromSquare} className="ml-1.5 text-xxs mb-[0.07rem]"/>
<FontAwesomeIcon
icon={faArrowUpRightFromSquare}
className="ml-1.5 mb-[0.07rem] text-xxs"
/>
</div>
</a>
</Link>
@@ -178,31 +187,48 @@ export default function FlyioCreateIntegrationPage() {
Create Integration
</Button>
</Card>
<div className="border-t border-mineshaft-800 w-full max-w-md mt-6"/>
<div className="flex flex-col bg-mineshaft-800 border border-mineshaft-600 w-full p-4 max-w-lg mt-6 rounded-md">
<div className="flex flex-row items-center"><FontAwesomeIcon icon={faCircleInfo} className="text-mineshaft-200 text-xl"/> <span className="ml-3 text-md text-mineshaft-100">Pro Tips</span></div>
<span className="text-mineshaft-300 text-sm mt-4">After creating an integration, your secrets will start syncing immediately. This might cause an unexpected override of current secrets in Fly.io with secrets from Infisical.</span>
<div className="mt-6 w-full max-w-md border-t border-mineshaft-800" />
<div className="mt-6 flex w-full max-w-lg flex-col rounded-md border border-mineshaft-600 bg-mineshaft-800 p-4">
<div className="flex flex-row items-center">
<FontAwesomeIcon icon={faCircleInfo} className="text-xl text-mineshaft-200" />{" "}
<span className="text-md ml-3 text-mineshaft-100">Pro Tips</span>
</div>
<span className="mt-4 text-sm text-mineshaft-300">
After creating an integration, your secrets will start syncing immediately. This might
cause an unexpected override of current secrets in Fly.io with secrets from Infisical.
</span>
</div>
</div>
) : (
<div className="flex justify-center items-center w-full h-full">
<div className="flex h-full w-full items-center justify-center">
<Head>
<title>Set Up Fly.io Integration</title>
<link rel='icon' href='/infisical.ico' />
<link rel="icon" href="/infisical.ico" />
</Head>
{isIntegrationAuthLoading || isIntegrationAuthAppsLoading ? <img src="/images/loading/loading.gif" height={70} width={120} alt="infisical loading indicator" /> : <div className="max-w-md h-max p-6 border border-mineshaft-600 rounded-md bg-mineshaft-800 text-mineshaft-200 flex flex-col text-center">
<FontAwesomeIcon icon={faBugs} className="text-6xl my-2 inlineli"/>
<p>
Something went wrong. Please contact <a
className="inline underline underline-offset-4 decoration-primary-500 opacity-80 hover:opacity-100 text-mineshaft-100 duration-200 cursor-pointer"
target="_blank"
rel="noopener noreferrer"
href="mailto:support@infisical.com"
>
support@infisical.com
</a> if the issue persists.
</p>
</div>}
{isIntegrationAuthLoading || isIntegrationAuthAppsLoading ? (
<img
src="/images/loading/loading.gif"
height={70}
width={120}
alt="infisical loading indicator"
/>
) : (
<div className="flex h-max max-w-md flex-col rounded-md border border-mineshaft-600 bg-mineshaft-800 p-6 text-center text-mineshaft-200">
<FontAwesomeIcon icon={faBugs} className="inlineli my-2 text-6xl" />
<p>
Something went wrong. Please contact{" "}
<a
className="inline cursor-pointer text-mineshaft-100 underline decoration-primary-500 underline-offset-4 opacity-80 duration-200 hover:opacity-100"
target="_blank"
rel="noopener noreferrer"
href="mailto:support@infisical.com"
>
support@infisical.com
</a>{" "}
if the issue persists.
</p>
</div>
)}
</div>
);
}

View File

@@ -12,9 +12,7 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { yupResolver } from "@hookform/resolvers/yup";
import * as yup from "yup";
import {
useGetCloudIntegrations,
useSaveIntegrationAccessToken} from "@app/hooks/api";
import { useGetCloudIntegrations, useSaveIntegrationAccessToken } from "@app/hooks/api";
import { Button, Card, CardTitle, FormControl, TextArea } from "../../../components/v2";
@@ -27,61 +25,60 @@ type FormData = yup.InferType<typeof schema>;
export default function GCPSecretManagerAuthorizeIntegrationPage() {
const router = useRouter();
const {
control,
handleSubmit
} = useForm<FormData>({
const { control, handleSubmit } = useForm<FormData>({
resolver: yupResolver(schema)
});
const { data: cloudIntegrations } = useGetCloudIntegrations();
const { mutateAsync } = useSaveIntegrationAccessToken();
const [isLoading, setIsLoading] = useState(false);
const handleIntegrateWithOAuth = () => {
if (!cloudIntegrations) return;
const integrationOption = cloudIntegrations.find((integration) => integration.slug === "gcp-secret-manager");
const integrationOption = cloudIntegrations.find(
(integration) => integration.slug === "gcp-secret-manager"
);
if (!integrationOption) return;
const state = crypto.randomBytes(16).toString("hex");
localStorage.setItem("latestCSRFToken", state);
const link = `https://accounts.google.com/o/oauth2/auth?scope=https://www.googleapis.com/auth/cloud-platform&response_type=code&access_type=offline&state=${state}&redirect_uri=${window.location.origin}/integrations/gcp-secret-manager/oauth2/callback&clientid=${integrationOption.clientId}`;
window.location.assign(link);
}
const onFormSubmit = async ({
accessToken
}: FormData) => {
};
const onFormSubmit = async ({ accessToken }: FormData) => {
try {
setIsLoading(true);
const integrationAuth = await mutateAsync({
workspaceId: localStorage.getItem("projectData.id"),
integration: "gcp-secret-manager",
refreshToken: accessToken
});
setIsLoading(false);
router.push(`/integrations/gcp-secret-manager/create?integrationAuthId=${integrationAuth.id}`);
router.push(
`/integrations/gcp-secret-manager/create?integrationAuthId=${integrationAuth.id}`
);
} catch (err) {
console.error(err);
setIsLoading(false);
}
}
};
return (
<div className="flex h-full w-full items-center justify-center">
<Head>
<title>Authorize GCP Secret Manager Integration</title>
<link rel='icon' href='/infisical.ico' />
<link rel="icon" href="/infisical.ico" />
</Head>
<Card className="max-w-lg rounded-md border border-mineshaft-600 mb-12">
<CardTitle
className="text-left px-6 text-xl"
<Card className="mb-12 max-w-lg rounded-md border border-mineshaft-600">
<CardTitle
className="px-6 text-left text-xl"
subTitle="Connect Infisical to GCP Secret Manager to sync secrets."
>
<div className="flex flex-row items-center">
@@ -96,10 +93,13 @@ export default function GCPSecretManagerAuthorizeIntegrationPage() {
<span className="ml-1.5">GCP Secret Manager Integration </span>
<Link href="https://infisical.com/docs/integrations/cloud/gcp-secret-manager" passHref>
<a target="_blank" rel="noopener noreferrer">
<div className="ml-2 mb-1 rounded-md text-yellow text-sm inline-block bg-yellow/20 px-1.5 pb-[0.03rem] pt-[0.04rem] opacity-80 hover:opacity-100 cursor-default">
<FontAwesomeIcon icon={faBookOpen} className="mr-1.5"/>
<div className="ml-2 mb-1 inline-block cursor-default rounded-md bg-yellow/20 px-1.5 pb-[0.03rem] pt-[0.04rem] text-sm text-yellow opacity-80 hover:opacity-100">
<FontAwesomeIcon icon={faBookOpen} className="mr-1.5" />
Docs
<FontAwesomeIcon icon={faArrowUpRightFromSquare} className="ml-1.5 text-xxs mb-[0.07rem]"/>
<FontAwesomeIcon
icon={faArrowUpRightFromSquare}
className="ml-1.5 mb-[0.07rem] text-xxs"
/>
</div>
</a>
</Link>
@@ -107,24 +107,21 @@ export default function GCPSecretManagerAuthorizeIntegrationPage() {
</CardTitle>
<div className="px-6">
<Button
colorSchema="primary"
variant="outline_bg"
onClick={handleIntegrateWithOAuth}
leftIcon={<FontAwesomeIcon icon={faGoogle} className="mr-2" />}
className="h-11 w-full mx-0 mt-4"
>
Continue with OAuth
colorSchema="primary"
variant="outline_bg"
onClick={handleIntegrateWithOAuth}
leftIcon={<FontAwesomeIcon icon={faGoogle} className="mr-2" />}
className="mx-0 mt-4 h-11 w-full"
>
Continue with OAuth
</Button>
<div className='w-full flex flex-row items-center my-4 py-2'>
<div className='w-full border-t border-mineshaft-400/40' />
<span className="mx-2 text-mineshaft-400 text-xs">or</span>
<div className='w-full border-t border-mineshaft-400/40' />
<div className="my-4 flex w-full flex-row items-center py-2">
<div className="w-full border-t border-mineshaft-400/40" />
<span className="mx-2 text-xs text-mineshaft-400">or</span>
<div className="w-full border-t border-mineshaft-400/40" />
</div>
</div>
<form
onSubmit={handleSubmit(onFormSubmit)}
className="px-6 text-right pb-8"
>
<form onSubmit={handleSubmit(onFormSubmit)} className="px-6 pb-8 text-right">
<Controller
control={control}
name="accessToken"
@@ -134,7 +131,7 @@ export default function GCPSecretManagerAuthorizeIntegrationPage() {
errorText={error?.message}
isError={Boolean(error)}
>
<TextArea
<TextArea
{...field}
className="h-48 border border-mineshaft-600 bg-bunker-900/80"
/>

View File

@@ -12,9 +12,7 @@ import queryString from "query-string";
import * as yup from "yup";
import { usePopUp } from "@app/hooks";
import {
useCreateIntegration
} from "@app/hooks/api";
import { useCreateIntegration } from "@app/hooks/api";
import {
Button,
@@ -30,7 +28,8 @@ import {
Tab,
TabList,
TabPanel,
Tabs} from "../../../components/v2";
Tabs
} from "../../../components/v2";
import {
useGetIntegrationAuthApps,
useGetIntegrationAuthById
@@ -60,13 +59,8 @@ export default function GCPSecretManagerCreateIntegrationPage() {
const { popUp, handlePopUpOpen, handlePopUpToggle, handlePopUpClose } = usePopUp([
"confirmIntegration"
] as const);
const {
control,
handleSubmit,
setValue,
watch
} = useForm<FormData>({
const { control, handleSubmit, setValue, watch } = useForm<FormData>({
resolver: yupResolver(schema),
defaultValues: {
secretPath: "/",
@@ -77,7 +71,7 @@ export default function GCPSecretManagerCreateIntegrationPage() {
labelValue: "infisical"
}
});
const shouldLabel = watch("shouldLabel");
const selectedSourceEnvironment = watch("selectedSourceEnvironment");
@@ -87,19 +81,20 @@ export default function GCPSecretManagerCreateIntegrationPage() {
const { data: workspace } = useGetWorkspaceById(localStorage.getItem("projectData.id") ?? "");
const { data: integrationAuth } = useGetIntegrationAuthById((integrationAuthId as string) ?? "");
const { data: integrationAuthApps, isLoading: isIntegrationAuthAppsLoading } = useGetIntegrationAuthApps({
integrationAuthId: (integrationAuthId as string) ?? ""
});
const { data: integrationAuthApps, isLoading: isIntegrationAuthAppsLoading } =
useGetIntegrationAuthApps({
integrationAuthId: (integrationAuthId as string) ?? ""
});
const [isLoading, setIsLoading] = useState(false);
useEffect(() => {
if (shouldLabel) {
setValue("labelName", "managed-by");
setValue("labelValue", "infisical");
return;
}
setValue("labelName", "");
setValue("labelValue", "");
}, [shouldLabel]);
@@ -119,7 +114,7 @@ export default function GCPSecretManagerCreateIntegrationPage() {
}
}
}, [integrationAuthApps]);
const onFormSubmit = async ({
selectedSourceEnvironment: sce,
secretPath,
@@ -134,56 +129,57 @@ export default function GCPSecretManagerCreateIntegrationPage() {
setIsLoading(true);
if (!integrationAuth?.id) return;
await mutateAsync({
integrationAuthId: integrationAuth?.id,
isActive: true,
app: integrationAuthApps?.find((integrationAuthApp) => integrationAuthApp.appId === targetAppId)?.name,
app: integrationAuthApps?.find(
(integrationAuthApp) => integrationAuthApp.appId === targetAppId
)?.name,
appId: targetAppId,
sourceEnvironment: sce,
secretPath,
metadata: {
...(secretPrefix ? { secretPrefix } : {}),
...(secretSuffix ? { secretSuffix } : {}),
...(sl ? {
secretGCPLabel: {
labelName,
labelValue
}
} : {})
...(sl
? {
secretGCPLabel: {
labelName,
labelValue
}
}
: {})
}
});
setIsLoading(false);
router.push(`/integrations/${localStorage.getItem("projectData.id")}`);
} catch (err) {
console.error(err);
setIsLoading(false);
}
}
return integrationAuth &&
workspace &&
selectedSourceEnvironment &&
integrationAuthApps ? (
<form
};
return integrationAuth && workspace && selectedSourceEnvironment && integrationAuthApps ? (
<form
onSubmit={handleSubmit((data: FormData) => {
if (!data.secretPrefix && !data.secretSuffix && !data.shouldLabel) {
handlePopUpOpen("confirmIntegration", data);
handlePopUpOpen("confirmIntegration", data);
return;
}
onFormSubmit(data);
})}
className="flex flex-col h-full w-full items-center justify-center"
className="flex h-full w-full flex-col items-center justify-center"
>
<Card className="max-w-lg rounded-md border border-mineshaft-600">
<Head>
<title>Set Up GCP Secret Manager Integration</title>
<link rel='icon' href='/infisical.ico' />
<link rel="icon" href="/infisical.ico" />
</Head>
<CardTitle
className="text-left px-6 text-xl mb-2"
<CardTitle
className="mb-2 px-6 text-left text-xl"
subTitle="Select which environment or folder in Infisical you want to sync to GCP Secret Manager."
>
<div className="flex flex-row items-center">
@@ -198,10 +194,13 @@ export default function GCPSecretManagerCreateIntegrationPage() {
<span className="ml-1.5">GCP Secret Manager Integration </span>
<Link href="https://infisical.com/docs/integrations/cloud/gcp-secret-manager" passHref>
<a target="_blank" rel="noopener noreferrer">
<div className="ml-2 mb-1 rounded-md text-yellow text-sm inline-block bg-yellow/20 px-1.5 pb-[0.03rem] pt-[0.04rem] opacity-80 hover:opacity-100 cursor-default">
<FontAwesomeIcon icon={faBookOpen} className="mr-1.5"/>
<div className="ml-2 mb-1 inline-block cursor-default rounded-md bg-yellow/20 px-1.5 pb-[0.03rem] pt-[0.04rem] text-sm text-yellow opacity-80 hover:opacity-100">
<FontAwesomeIcon icon={faBookOpen} className="mr-1.5" />
Docs
<FontAwesomeIcon icon={faArrowUpRightFromSquare} className="ml-1.5 text-xxs mb-[0.07rem]"/>
<FontAwesomeIcon
icon={faArrowUpRightFromSquare}
className="ml-1.5 mb-[0.07rem] text-xxs"
/>
</div>
</a>
</Link>
@@ -209,7 +208,7 @@ export default function GCPSecretManagerCreateIntegrationPage() {
</CardTitle>
<Tabs defaultValue={TabSections.Connection} className="px-6">
<TabList>
<div className="flex flex-row border-b border-mineshaft-600 w-full">
<div className="flex w-full flex-row border-b border-mineshaft-600">
<Tab value={TabSections.Connection}>Connection</Tab>
<Tab value={TabSections.Options}>Options</Tab>
</div>
@@ -250,26 +249,23 @@ export default function GCPSecretManagerCreateIntegrationPage() {
)}
/>
<Controller
control={control}
defaultValue=""
name="secretPath"
render={({ field, fieldState: { error } }) => (
<FormControl
label="Secrets Path"
isError={Boolean(error)}
errorText={error?.message}
>
<Input
{...field}
placeholder="/"
/>
</FormControl>
)}
control={control}
defaultValue=""
name="secretPath"
render={({ field, fieldState: { error } }) => (
<FormControl
label="Secrets Path"
isError={Boolean(error)}
errorText={error?.message}
>
<Input {...field} placeholder="/" />
</FormControl>
)}
/>
<Controller
control={control}
name="targetAppId"
render={({ field: { onChange, ...field }, fieldState: { error } }) => {
control={control}
name="targetAppId"
render={({ field: { onChange, ...field }, fieldState: { error } }) => {
return (
<FormControl
label="GCP Project"
@@ -280,7 +276,7 @@ export default function GCPSecretManagerCreateIntegrationPage() {
{...field}
onValueChange={(e) => {
if (e === "") return;
onChange(e)
onChange(e);
}}
className="w-full"
>
@@ -300,7 +296,7 @@ export default function GCPSecretManagerCreateIntegrationPage() {
)}
</Select>
</FormControl>
)
);
}}
/>
</motion.div>
@@ -317,32 +313,26 @@ export default function GCPSecretManagerCreateIntegrationPage() {
control={control}
name="secretPrefix"
render={({ field, fieldState: { error } }) => (
<FormControl
label="Secret Prefix"
isError={Boolean(error)}
errorText={error?.message}
>
<Input
{...field}
placeholder="INFISICAL_"
/>
</FormControl>
<FormControl
label="Secret Prefix"
isError={Boolean(error)}
errorText={error?.message}
>
<Input {...field} placeholder="INFISICAL_" />
</FormControl>
)}
/>
<Controller
control={control}
name="secretSuffix"
render={({ field, fieldState: { error } }) => (
<FormControl
label="Secret Suffix"
isError={Boolean(error)}
errorText={error?.message}
>
<Input
{...field}
placeholder="_INFISICAL"
/>
</FormControl>
<FormControl
label="Secret Suffix"
isError={Boolean(error)}
errorText={error?.message}
>
<Input {...field} placeholder="_INFISICAL" />
</FormControl>
)}
/>
<div className="mt-8 mb-[2.36rem]">
@@ -366,32 +356,26 @@ export default function GCPSecretManagerCreateIntegrationPage() {
control={control}
name="labelName"
render={({ field, fieldState: { error } }) => (
<FormControl
label="Label Name"
isError={Boolean(error)}
errorText={error?.message}
>
<Input
{...field}
placeholder="managed-by"
/>
</FormControl>
<FormControl
label="Label Name"
isError={Boolean(error)}
errorText={error?.message}
>
<Input {...field} placeholder="managed-by" />
</FormControl>
)}
/>
<Controller
control={control}
name="labelValue"
render={({ field, fieldState: { error } }) => (
<FormControl
label="Label Name"
isError={Boolean(error)}
errorText={error?.message}
>
<Input
{...field}
placeholder="infisical"
/>
</FormControl>
<FormControl
label="Label Name"
isError={Boolean(error)}
errorText={error?.message}
>
<Input {...field} placeholder="infisical" />
</FormControl>
)}
/>
</div>
@@ -424,56 +408,66 @@ export default function GCPSecretManagerCreateIntegrationPage() {
</span>
</div> */}
<Modal
isOpen={popUp.confirmIntegration?.isOpen}
onOpenChange={(isOpen) => handlePopUpToggle("confirmIntegration", isOpen)}
isOpen={popUp.confirmIntegration?.isOpen}
onOpenChange={(isOpen) => handlePopUpToggle("confirmIntegration", isOpen)}
>
<ModalContent
title="Heads Up"
footerContent={
<div className="flex items-center space-x-2">
<Button onClick={() => onFormSubmit(popUp.confirmIntegration?.data as FormData)}>
Continue Anyway
</Button>
<Button
onClick={() => handlePopUpClose("confirmIntegration")}
variant="outline_bg"
colorSchema="secondary"
>
Cancel
</Button>
</div>
}
>
<ModalContent
title="Heads Up"
footerContent={
<div className="flex items-center space-x-2">
<Button onClick={() => onFormSubmit(popUp.confirmIntegration?.data as FormData)}>
Continue Anyway
</Button>
<Button
onClick={() => handlePopUpClose("confirmIntegration")}
variant="outline_bg"
colorSchema="secondary"
>
Cancel
</Button>
</div>
}
>
<p>
You&apos;re about to overwrite any existing secrets in GCP Secret Manager.
</p>
<p className="mt-4">
To avoid this behavior, you may consider adding a secret prefix/suffix or enabling labeling in the options tab.
</p>
</ModalContent>
</Modal>
<p>You&apos;re about to overwrite any existing secrets in GCP Secret Manager.</p>
<p className="mt-4">
To avoid this behavior, you may consider adding a secret prefix/suffix or enabling
labeling in the options tab.
</p>
</ModalContent>
</Modal>
</form>
) : (
<div className="flex justify-center items-center w-full h-full">
<div className="flex h-full w-full items-center justify-center">
<Head>
<title>Set Up GCP Secret Manager Integration</title>
<link rel='icon' href='/infisical.ico' />
<link rel="icon" href="/infisical.ico" />
</Head>
{isIntegrationAuthAppsLoading ? <img src="/images/loading/loading.gif" height={70} width={120} alt="infisical loading indicator" /> : <div className="max-w-md h-max p-6 border border-mineshaft-600 rounded-md bg-mineshaft-800 text-mineshaft-200 flex flex-col text-center">
<FontAwesomeIcon icon={faBugs} className="text-6xl my-2 inlineli"/>
<p>
Something went wrong. Please contact <a
className="inline underline underline-offset-4 decoration-primary-500 opacity-80 hover:opacity-100 text-mineshaft-100 duration-200 cursor-pointer"
target="_blank"
rel="noopener noreferrer"
href="mailto:support@infisical.com"
>
support@infisical.com
</a> if the issue persists.
</p>
</div>}
{isIntegrationAuthAppsLoading ? (
<img
src="/images/loading/loading.gif"
height={70}
width={120}
alt="infisical loading indicator"
/>
) : (
<div className="flex h-max max-w-md flex-col rounded-md border border-mineshaft-600 bg-mineshaft-800 p-6 text-center text-mineshaft-200">
<FontAwesomeIcon icon={faBugs} className="inlineli my-2 text-6xl" />
<p>
Something went wrong. Please contact{" "}
<a
className="inline cursor-pointer text-mineshaft-100 underline decoration-primary-500 underline-offset-4 opacity-80 duration-200 hover:opacity-100"
target="_blank"
rel="noopener noreferrer"
href="mailto:support@infisical.com"
>
support@infisical.com
</a>{" "}
if the issue persists.
</p>
</div>
)}
</div>
);
}
GCPSecretManagerCreateIntegrationPage.requireAuth = true;
GCPSecretManagerCreateIntegrationPage.requireAuth = true;

View File

@@ -2,15 +2,13 @@ import { useEffect } from "react";
import { useRouter } from "next/router";
import queryString from "query-string";
import {
useAuthorizeIntegration
} from "@app/hooks/api";
import { useAuthorizeIntegration } from "@app/hooks/api";
export default function GCPSecretManagerOAuth2CallbackPage() {
const router = useRouter();
const { mutateAsync } = useAuthorizeIntegration();
const router = useRouter();
const { mutateAsync } = useAuthorizeIntegration();
const { code, state } = queryString.parse(router.asPath.split("?")[1]);
const { code, state } = queryString.parse(router.asPath.split("?")[1]);
useEffect(() => {
(async () => {
@@ -24,8 +22,10 @@ export default function GCPSecretManagerOAuth2CallbackPage() {
code: code as string,
integration: "gcp-secret-manager"
});
router.push(`/integrations/gcp-secret-manager/create?integrationAuthId=${integrationAuth.id}`);
router.push(
`/integrations/gcp-secret-manager/create?integrationAuthId=${integrationAuth.id}`
);
} catch (err) {
console.error(err);
}

View File

@@ -3,14 +3,19 @@ import Head from "next/head";
import Image from "next/image";
import Link from "next/link";
import { useRouter } from "next/router";
import { faAngleDown, faArrowUpRightFromSquare, faBookOpen, faBugs, faCheckCircle, faCircleInfo } from "@fortawesome/free-solid-svg-icons";
import {
faAngleDown,
faArrowUpRightFromSquare,
faBookOpen,
faBugs,
faCheckCircle,
faCircleInfo
} from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { motion } from "framer-motion";
import queryString from "query-string";
import {
useCreateIntegration
} from "@app/hooks/api";
import { useCreateIntegration } from "@app/hooks/api";
import {
Button,
@@ -48,9 +53,10 @@ export default function GitHubCreateIntegrationPage() {
const { data: workspace } = useGetWorkspaceById(localStorage.getItem("projectData.id") ?? "");
const { data: integrationAuth } = useGetIntegrationAuthById((integrationAuthId as string) ?? "");
const { data: integrationAuthApps, isLoading: isIntegrationAuthAppsLoading } = useGetIntegrationAuthApps({
integrationAuthId: (integrationAuthId as string) ?? ""
});
const { data: integrationAuthApps, isLoading: isIntegrationAuthAppsLoading } =
useGetIntegrationAuthApps({
integrationAuthId: (integrationAuthId as string) ?? ""
});
const [selectedSourceEnvironment, setSelectedSourceEnvironment] = useState("");
const [secretPath, setSecretPath] = useState("/");
@@ -81,8 +87,8 @@ export default function GitHubCreateIntegrationPage() {
if (!integrationAuth?.id) return;
const targetApps = integrationAuthApps?.filter(
(integrationAuthApp) => targetAppIds.includes(String(integrationAuthApp.appId))
const targetApps = integrationAuthApps?.filter((integrationAuthApp) =>
targetAppIds.includes(String(integrationAuthApp.appId))
);
if (!targetApps) return;
@@ -99,7 +105,7 @@ export default function GitHubCreateIntegrationPage() {
metadata: {
secretSuffix
}
})
});
})
);
@@ -115,18 +121,18 @@ export default function GitHubCreateIntegrationPage() {
selectedSourceEnvironment &&
integrationAuthApps &&
targetAppIds ? (
<div className="flex flex-col h-full w-full items-center justify-center">
<div className="flex h-full w-full flex-col items-center justify-center">
<Head>
<title>Set Up GitHub Integration</title>
<link rel='icon' href='/infisical.ico' />
<link rel="icon" href="/infisical.ico" />
</Head>
<Card className="max-w-lg rounded-md border border-mineshaft-600 p-0">
<CardTitle
className="text-left px-6 text-xl"
<CardTitle
className="px-6 text-left text-xl"
subTitle="Choose which environment in Infisical you want to sync to environment variables in GitHub."
>
<div className="flex flex-row items-center">
<div className="inline flex items-center bg-mineshaft-200 rounded-full">
<div className="inline flex items-center rounded-full bg-mineshaft-200">
<Image
src="/images/integrations/GitHub.png"
height={30}
@@ -137,10 +143,13 @@ export default function GitHubCreateIntegrationPage() {
<span className="ml-2.5">GitHub Integration </span>
<Link href="https://infisical.com/docs/integrations/cicd/githubactions" passHref>
<a target="_blank" rel="noopener noreferrer">
<div className="ml-2 mb-1 rounded-md text-yellow text-sm inline-block bg-yellow/20 px-1.5 pb-[0.03rem] pt-[0.04rem] opacity-80 hover:opacity-100 cursor-default">
<FontAwesomeIcon icon={faBookOpen} className="mr-1.5"/>
<div className="ml-2 mb-1 inline-block cursor-default rounded-md bg-yellow/20 px-1.5 pb-[0.03rem] pt-[0.04rem] text-sm text-yellow opacity-80 hover:opacity-100">
<FontAwesomeIcon icon={faBookOpen} className="mr-1.5" />
Docs
<FontAwesomeIcon icon={faArrowUpRightFromSquare} className="ml-1.5 text-xxs mb-[0.07rem]"/>
<FontAwesomeIcon
icon={faArrowUpRightFromSquare}
className="ml-1.5 mb-[0.07rem] text-xxs"
/>
</div>
</a>
</Link>
@@ -148,7 +157,7 @@ export default function GitHubCreateIntegrationPage() {
</CardTitle>
<Tabs defaultValue={TabSections.Connection} className="px-6">
<TabList>
<div className="flex flex-row border-b border-mineshaft-600 w-full">
<div className="flex w-full flex-row border-b border-mineshaft-600">
<Tab value={TabSections.Connection}>Connection</Tab>
<Tab value={TabSections.Options}>Options</Tab>
</div>
@@ -187,17 +196,27 @@ export default function GitHubCreateIntegrationPage() {
<FormControl label="GitHub Repo">
<DropdownMenu>
<DropdownMenuTrigger asChild>
{(integrationAuthApps.length > 0) ? <div className="w-full cursor-pointer border border-mineshaft-600 inline-flex items-center justify-between rounded-md bg-mineshaft-900 px-3 py-2 font-inter text-sm font-normal text-bunker-200 outline-none data-[placeholder]:text-mineshaft-200">
{targetAppIds.length === 1 ? integrationAuthApps?.find(
(integrationAuthApp) => targetAppIds[0] === String(integrationAuthApp.appId)
)?.name : `${targetAppIds.length} repositories selected`}
{integrationAuthApps.length > 0 ? (
<div className="inline-flex w-full cursor-pointer items-center justify-between rounded-md border border-mineshaft-600 bg-mineshaft-900 px-3 py-2 font-inter text-sm font-normal text-bunker-200 outline-none data-[placeholder]:text-mineshaft-200">
{targetAppIds.length === 1
? integrationAuthApps?.find(
(integrationAuthApp) =>
targetAppIds[0] === String(integrationAuthApp.appId)
)?.name
: `${targetAppIds.length} repositories selected`}
<FontAwesomeIcon icon={faAngleDown} className="text-xs" />
</div> : <div className="w-full cursor-default border border-mineshaft-600 inline-flex items-center justify-between rounded-md bg-mineshaft-900 px-3 py-2 font-inter text-sm font-normal text-bunker-200 outline-none data-[placeholder]:text-mineshaft-200">
</div>
) : (
<div className="inline-flex w-full cursor-default items-center justify-between rounded-md border border-mineshaft-600 bg-mineshaft-900 px-3 py-2 font-inter text-sm font-normal text-bunker-200 outline-none data-[placeholder]:text-mineshaft-200">
No repositories found
</div>}
</div>
)}
</DropdownMenuTrigger>
<DropdownMenuContent align="start" className="z-[100] max-h-80 overflow-y-scroll thin-scrollbar">
{(integrationAuthApps.length > 0) ? (
<DropdownMenuContent
align="start"
className="thin-scrollbar z-[100] max-h-80 overflow-y-scroll"
>
{integrationAuthApps.length > 0 ? (
integrationAuthApps.map((integrationAuthApp) => {
const isSelected = targetAppIds.includes(String(integrationAuthApp.appId));
@@ -205,20 +224,39 @@ export default function GitHubCreateIntegrationPage() {
<DropdownMenuItem
onClick={() => {
if (targetAppIds.includes(String(integrationAuthApp.appId))) {
setTargetAppIds(targetAppIds.filter((appId) => appId !== String(integrationAuthApp.appId)));
setTargetAppIds(
targetAppIds.filter(
(appId) => appId !== String(integrationAuthApp.appId)
)
);
} else {
setTargetAppIds([...targetAppIds, String(integrationAuthApp.appId)]);
setTargetAppIds([
...targetAppIds,
String(integrationAuthApp.appId)
]);
}
}}
key={integrationAuthApp.appId}
icon={isSelected ? <FontAwesomeIcon icon={faCheckCircle} className="text-primary pr-0.5" /> : <div className="pl-[1.01rem]"/>}
icon={
isSelected ? (
<FontAwesomeIcon
icon={faCheckCircle}
className="pr-0.5 text-primary"
/>
) : (
<div className="pl-[1.01rem]" />
)
}
iconPos="left"
className="w-[28.4rem] text-sm"
>
{integrationAuthApp.name}
</DropdownMenuItem>
)})
) : <div/>}
</DropdownMenuItem>
);
})
) : (
<div />
)}
</DropdownMenuContent>
</DropdownMenu>
</FormControl>
@@ -253,31 +291,48 @@ export default function GitHubCreateIntegrationPage() {
Create Integration
</Button>
</Card>
<div className="border-t border-mineshaft-800 w-full max-w-md mt-6"/>
<div className="flex flex-col bg-mineshaft-800 border border-mineshaft-600 w-full p-4 max-w-lg mt-6 rounded-md">
<div className="flex flex-row items-center"><FontAwesomeIcon icon={faCircleInfo} className="text-mineshaft-200 text-xl"/> <span className="ml-3 text-md text-mineshaft-100">Pro Tips</span></div>
<span className="text-mineshaft-300 text-sm mt-4">After creating an integration, your secrets will start syncing immediately. This might cause an unexpected override of current secrets in GitHub with secrets from Infisical.</span>
<div className="mt-6 w-full max-w-md border-t border-mineshaft-800" />
<div className="mt-6 flex w-full max-w-lg flex-col rounded-md border border-mineshaft-600 bg-mineshaft-800 p-4">
<div className="flex flex-row items-center">
<FontAwesomeIcon icon={faCircleInfo} className="text-xl text-mineshaft-200" />{" "}
<span className="text-md ml-3 text-mineshaft-100">Pro Tips</span>
</div>
<span className="mt-4 text-sm text-mineshaft-300">
After creating an integration, your secrets will start syncing immediately. This might
cause an unexpected override of current secrets in GitHub with secrets from Infisical.
</span>
</div>
</div>
) : (
<div className="flex justify-center items-center w-full h-full">
<div className="flex h-full w-full items-center justify-center">
<Head>
<title>Set Up GitHub Integration</title>
<link rel='icon' href='/infisical.ico' />
<link rel="icon" href="/infisical.ico" />
</Head>
{isIntegrationAuthAppsLoading ? <img src="/images/loading/loading.gif" height={70} width={120} alt="infisical loading indicator" /> : <div className="max-w-md h-max p-6 border border-mineshaft-600 rounded-md bg-mineshaft-800 text-mineshaft-200 flex flex-col text-center">
<FontAwesomeIcon icon={faBugs} className="text-6xl my-2 inlineli"/>
<p>
Something went wrong. Please contact <a
className="inline underline underline-offset-4 decoration-primary-500 opacity-80 hover:opacity-100 text-mineshaft-100 duration-200 cursor-pointer"
target="_blank"
rel="noopener noreferrer"
href="mailto:support@infisical.com"
>
support@infisical.com
</a> if the issue persists.
</p>
</div>}
{isIntegrationAuthAppsLoading ? (
<img
src="/images/loading/loading.gif"
height={70}
width={120}
alt="infisical loading indicator"
/>
) : (
<div className="flex h-max max-w-md flex-col rounded-md border border-mineshaft-600 bg-mineshaft-800 p-6 text-center text-mineshaft-200">
<FontAwesomeIcon icon={faBugs} className="inlineli my-2 text-6xl" />
<p>
Something went wrong. Please contact{" "}
<a
className="inline cursor-pointer text-mineshaft-100 underline decoration-primary-500 underline-offset-4 opacity-80 duration-200 hover:opacity-100"
target="_blank"
rel="noopener noreferrer"
href="mailto:support@infisical.com"
>
support@infisical.com
</a>{" "}
if the issue persists.
</p>
</div>
)}
</div>
);
}

View File

@@ -2,9 +2,7 @@ import { useEffect } from "react";
import { useRouter } from "next/router";
import queryString from "query-string";
import {
useAuthorizeIntegration
} from "@app/hooks/api";
import { useAuthorizeIntegration } from "@app/hooks/api";
export default function GitHubOAuth2CallbackPage() {
const router = useRouter();

View File

@@ -20,10 +20,7 @@ const schema = yup.object({
type FormData = yup.InferType<typeof schema>;
export default function GitLabAuthorizeIntegrationPage() {
const {
control,
handleSubmit
} = useForm<FormData>({
const { control, handleSubmit } = useForm<FormData>({
resolver: yupResolver(schema),
defaultValues: {
gitLabURL: ""
@@ -31,35 +28,38 @@ export default function GitLabAuthorizeIntegrationPage() {
});
const { data: cloudIntegrations } = useGetCloudIntegrations();
const onFormSubmit = ({
gitLabURL
}: FormData) => {
const onFormSubmit = ({ gitLabURL }: FormData) => {
if (!cloudIntegrations) return;
const integrationOption = cloudIntegrations.find((integration) => integration.slug === "gitlab");
const integrationOption = cloudIntegrations.find(
(integration) => integration.slug === "gitlab"
);
if (!integrationOption) return;
const baseURL = (gitLabURL as string).trim() === "" ? "https://gitlab.com" : (gitLabURL as string).trim();
const baseURL =
(gitLabURL as string).trim() === "" ? "https://gitlab.com" : (gitLabURL as string).trim();
const csrfToken = crypto.randomBytes(16).toString("hex");
localStorage.setItem("latestCSRFToken", csrfToken);
const state = `${csrfToken}|${(gitLabURL as string).trim() === "" ? "" : (gitLabURL as string).trim()}`;
const state = `${csrfToken}|${
(gitLabURL as string).trim() === "" ? "" : (gitLabURL as string).trim()
}`;
const link = `${baseURL}/oauth/authorize?clientid=${integrationOption.clientId}&redirect_uri=${window.location.origin}/integrations/gitlab/oauth2/callback&response_type=code&state=${state}`;
window.location.assign(link);
}
};
return (
<div className="flex h-full w-full items-center justify-center">
<Head>
<title>Authorize GitLab Integration</title>
<link rel='icon' href='/infisical.ico' />
<link rel="icon" href="/infisical.ico" />
</Head>
<Card className="max-w-lg rounded-md border border-mineshaft-600 mb-12">
<CardTitle
className="text-left px-6 text-xl"
<Card className="mb-12 max-w-lg rounded-md border border-mineshaft-600">
<CardTitle
className="px-6 text-left text-xl"
subTitle="Authorize this integration to sync secrets from Infisical to GitLab. If no self-hosted GitLab URL is specified, then Infisical will connect you to GitLab Cloud."
>
<div className="flex flex-row items-center">
@@ -74,19 +74,19 @@ export default function GitLabAuthorizeIntegrationPage() {
<span className="ml-2.5">GitLab Integration </span>
<Link href="https://infisical.com/docs/integrations/cicd/gitlab" passHref>
<a target="_blank" rel="noopener noreferrer">
<div className="ml-2 mb-1 rounded-md text-yellow text-sm inline-block bg-yellow/20 px-1.5 pb-[0.03rem] pt-[0.04rem] opacity-80 hover:opacity-100 cursor-default">
<FontAwesomeIcon icon={faBookOpen} className="mr-1.5"/>
<div className="ml-2 mb-1 inline-block cursor-default rounded-md bg-yellow/20 px-1.5 pb-[0.03rem] pt-[0.04rem] text-sm text-yellow opacity-80 hover:opacity-100">
<FontAwesomeIcon icon={faBookOpen} className="mr-1.5" />
Docs
<FontAwesomeIcon icon={faArrowUpRightFromSquare} className="ml-1.5 text-xxs mb-[0.07rem]"/>
<FontAwesomeIcon
icon={faArrowUpRightFromSquare}
className="ml-1.5 mb-[0.07rem] text-xxs"
/>
</div>
</a>
</Link>
</div>
</CardTitle>
<form
onSubmit={handleSubmit(onFormSubmit)}
className="px-6 text-right pb-8"
>
<form onSubmit={handleSubmit(onFormSubmit)} className="px-6 pb-8 text-right">
<Controller
control={control}
name="gitLabURL"
@@ -96,10 +96,7 @@ export default function GitLabAuthorizeIntegrationPage() {
errorText={error?.message}
isError={Boolean(error)}
>
<Input
{...field}
placeholder="https://self-hosted-gitlab.com"
/>
<Input {...field} placeholder="https://self-hosted-gitlab.com" />
</FormControl>
)}
/>

View File

@@ -12,9 +12,7 @@ import queryString from "query-string";
import * as yup from "yup";
import { usePopUp } from "@app/hooks";
import {
useCreateIntegration
} from "@app/hooks/api";
import { useCreateIntegration } from "@app/hooks/api";
import {
Button,
@@ -49,7 +47,10 @@ enum TabSections {
}
const schema = yup.object({
targetEntity: yup.string().oneOf(gitLabEntities.map(entity => entity.value), "Invalid entity type"),
targetEntity: yup.string().oneOf(
gitLabEntities.map((entity) => entity.value),
"Invalid entity type"
),
targetTeamId: yup.string(),
selectedSourceEnvironment: yup.string().required("Source environment is required"),
secretPath: yup.string().required("Secret path is required"),
@@ -66,20 +67,15 @@ export default function GitLabCreateIntegrationPage() {
const { popUp, handlePopUpOpen, handlePopUpToggle, handlePopUpClose } = usePopUp([
"confirmIntegration"
] as const);
const {
control,
handleSubmit,
setValue,
watch
} = useForm<FormData>({
resolver: yupResolver(schema),
defaultValues: {
targetEntity: "individual",
secretPath: "/",
secretPrefix: "",
secretSuffix: ""
}
const { control, handleSubmit, setValue, watch } = useForm<FormData>({
resolver: yupResolver(schema),
defaultValues: {
targetEntity: "individual",
secretPath: "/",
secretPrefix: "",
secretSuffix: ""
}
});
const selectedSourceEnvironment = watch("selectedSourceEnvironment");
const targetEntity = watch("targetEntity");
@@ -93,17 +89,16 @@ export default function GitLabCreateIntegrationPage() {
const { data: workspace } = useGetWorkspaceById(localStorage.getItem("projectData.id") ?? "");
const { data: integrationAuth } = useGetIntegrationAuthById((integrationAuthId as string) ?? "");
const { data: integrationAuthApps, isLoading: isIntegrationAuthAppsLoading } = useGetIntegrationAuthApps({
integrationAuthId: (integrationAuthId as string) ?? "",
...(targetTeamId ? { teamId: targetTeamId } : {})
});
const { data: integrationAuthTeams, isLoading: isintegrationAuthTeamsLoading } = useGetIntegrationAuthTeams(
(integrationAuthId as string) ?? ""
);
const { data: integrationAuthApps, isLoading: isIntegrationAuthAppsLoading } =
useGetIntegrationAuthApps({
integrationAuthId: (integrationAuthId as string) ?? "",
...(targetTeamId ? { teamId: targetTeamId } : {})
});
const { data: integrationAuthTeams, isLoading: isintegrationAuthTeamsLoading } =
useGetIntegrationAuthTeams((integrationAuthId as string) ?? "");
const [isLoading, setIsLoading] = useState(false);
useEffect(() => {
if (workspace) {
setValue("selectedSourceEnvironment", workspace.environments[0].slug);
@@ -147,11 +142,13 @@ export default function GitLabCreateIntegrationPage() {
try {
setIsLoading(true);
if (!integrationAuth?.id) return;
await mutateAsync({
integrationAuthId: integrationAuth?.id,
isActive: true,
app: integrationAuthApps?.find((integrationAuthApp) => String(integrationAuthApp.appId) === targetAppId)?.name,
app: integrationAuthApps?.find(
(integrationAuthApp) => String(integrationAuthApp.appId) === targetAppId
)?.name,
appId: String(targetAppId),
sourceEnvironment: sse,
targetEnvironment: targetEnvironment === "" ? "*" : targetEnvironment,
@@ -168,31 +165,31 @@ export default function GitLabCreateIntegrationPage() {
console.error(err);
setIsLoading(false);
}
}
};
return integrationAuth &&
workspace &&
selectedSourceEnvironment &&
integrationAuthApps &&
integrationAuthTeams ? (
<form
<form
onSubmit={handleSubmit((data: FormData) => {
if (!data.secretPrefix && !data.secretSuffix) {
handlePopUpOpen("confirmIntegration", data);
handlePopUpOpen("confirmIntegration", data);
return;
}
onFormSubmit(data);
})}
className="flex flex-col h-full w-full items-center justify-center"
className="flex h-full w-full flex-col items-center justify-center"
>
<Head>
<title>Set Up GitLab Integration</title>
<link rel='icon' href='/infisical.ico' />
<link rel="icon" href="/infisical.ico" />
</Head>
<Card className="max-w-lg rounded-md border border-mineshaft-600">
<CardTitle
className="text-left px-6 text-xl"
<CardTitle
className="px-6 text-left text-xl"
subTitle="Select which environment or folder in Infisical you want to sync to GitLab's environment variables."
>
<div className="flex flex-row items-center">
@@ -207,10 +204,13 @@ export default function GitLabCreateIntegrationPage() {
<span className="ml-2.5">GitLab Integration </span>
<Link href="https://infisical.com/docs/integrations/cicd/gitlab" passHref>
<a target="_blank" rel="noopener noreferrer">
<div className="ml-2 mb-1 rounded-md text-yellow text-sm inline-block bg-yellow/20 px-1.5 pb-[0.03rem] pt-[0.04rem] opacity-80 hover:opacity-100 cursor-default">
<FontAwesomeIcon icon={faBookOpen} className="mr-1.5"/>
<div className="ml-2 mb-1 inline-block cursor-default rounded-md bg-yellow/20 px-1.5 pb-[0.03rem] pt-[0.04rem] text-sm text-yellow opacity-80 hover:opacity-100">
<FontAwesomeIcon icon={faBookOpen} className="mr-1.5" />
Docs
<FontAwesomeIcon icon={faArrowUpRightFromSquare} className="ml-1.5 text-xxs mb-[0.07rem]"/>
<FontAwesomeIcon
icon={faArrowUpRightFromSquare}
className="ml-1.5 mb-[0.07rem] text-xxs"
/>
</div>
</a>
</Link>
@@ -218,7 +218,7 @@ export default function GitLabCreateIntegrationPage() {
</CardTitle>
<Tabs defaultValue={TabSections.Connection} className="px-6">
<TabList>
<div className="flex flex-row border-b border-mineshaft-600 w-full">
<div className="flex w-full flex-row border-b border-mineshaft-600">
<Tab value={TabSections.Connection}>Connection</Tab>
<Tab value={TabSections.Options}>Options</Tab>
</div>
@@ -259,21 +259,18 @@ export default function GitLabCreateIntegrationPage() {
)}
/>
<Controller
control={control}
defaultValue=""
name="secretPath"
render={({ field, fieldState: { error } }) => (
<FormControl
label="Secrets Path"
isError={Boolean(error)}
errorText={error?.message}
>
<Input
{...field}
placeholder="/"
/>
</FormControl>
)}
control={control}
defaultValue=""
name="secretPath"
render={({ field, fieldState: { error } }) => (
<FormControl
label="Secrets Path"
isError={Boolean(error)}
errorText={error?.message}
>
<Input {...field} placeholder="/" />
</FormControl>
)}
/>
<Controller
control={control}
@@ -284,11 +281,7 @@ export default function GitLabCreateIntegrationPage() {
errorText={error?.message}
isError={Boolean(error)}
>
<Select
{...field}
onValueChange={(e) => onChange(e)}
className="w-full"
>
<Select {...field} onValueChange={(e) => onChange(e)} className="w-full">
{gitLabEntities.map((entity) => {
return (
<SelectItem value={entity.value} key={`target-entity-${entity.value}`}>
@@ -310,14 +303,9 @@ export default function GitLabCreateIntegrationPage() {
errorText={error?.message}
isError={Boolean(error)}
>
<Select
{...field}
onValueChange={(e) => onChange(e)}
className="w-full"
>
<Select {...field} onValueChange={(e) => onChange(e)} className="w-full">
{integrationAuthTeams.length > 0 ? (
integrationAuthTeams.map((integrationAuthTeam) =>
(
integrationAuthTeams.map((integrationAuthTeam) => (
<SelectItem
value={String(integrationAuthTeam.teamId as string)}
key={`target-team-${String(integrationAuthTeam.teamId)}`}
@@ -349,7 +337,7 @@ export default function GitLabCreateIntegrationPage() {
{...field}
onValueChange={(e) => {
if (e === "") return;
onChange(e)
onChange(e);
}}
className="w-full"
>
@@ -369,24 +357,22 @@ export default function GitLabCreateIntegrationPage() {
)}
</Select>
</FormControl>
)}}
/>
<Controller
control={control}
defaultValue=""
name="targetEnvironment"
render={({ field, fieldState: { error } }) => (
<FormControl
label="GitLab Environment Scope (Optional)"
isError={Boolean(error)}
errorText={error?.message}
>
<Input
{...field}
placeholder="*"
/>
</FormControl>
)}
);
}}
/>
<Controller
control={control}
defaultValue=""
name="targetEnvironment"
render={({ field, fieldState: { error } }) => (
<FormControl
label="GitLab Environment Scope (Optional)"
isError={Boolean(error)}
errorText={error?.message}
>
<Input {...field} placeholder="*" />
</FormControl>
)}
/>
</motion.div>
</TabPanel>
@@ -403,32 +389,26 @@ export default function GitLabCreateIntegrationPage() {
control={control}
name="secretPrefix"
render={({ field, fieldState: { error } }) => (
<FormControl
label="Secret Prefix"
isError={Boolean(error)}
errorText={error?.message}
>
<Input
{...field}
placeholder="INFISICAL_"
/>
</FormControl>
<FormControl
label="Secret Prefix"
isError={Boolean(error)}
errorText={error?.message}
>
<Input {...field} placeholder="INFISICAL_" />
</FormControl>
)}
/>
<Controller
control={control}
name="secretSuffix"
render={({ field, fieldState: { error } }) => (
<FormControl
label="Secret Suffix"
isError={Boolean(error)}
errorText={error?.message}
>
<Input
{...field}
placeholder="_INFISICAL"
/>
</FormControl>
<FormControl
label="Secret Suffix"
isError={Boolean(error)}
errorText={error?.message}
>
<Input {...field} placeholder="_INFISICAL" />
</FormControl>
)}
/>
</motion.div>
@@ -445,61 +425,71 @@ export default function GitLabCreateIntegrationPage() {
>
Create Integration
</Button>
</Card>
</Card>
{/* <div className="border-t border-mineshaft-800 w-full max-w-md mt-6"/>
<div className="flex flex-col bg-mineshaft-800 border border-mineshaft-600 w-full p-4 max-w-lg mt-6 rounded-md">
<div className="flex flex-row items-center"><FontAwesomeIcon icon={faCircleInfo} className="text-mineshaft-200 text-xl"/> <span className="ml-3 text-md text-mineshaft-100">Pro Tips</span></div>
<span className="text-mineshaft-300 text-sm mt-4">After creating an integration, your secrets will start syncing immediately. This might cause an unexpected override of current secrets in GitLab with secrets from Infisical.</span>
</div> */}
<Modal
isOpen={popUp.confirmIntegration?.isOpen}
onOpenChange={(isOpen) => handlePopUpToggle("confirmIntegration", isOpen)}
isOpen={popUp.confirmIntegration?.isOpen}
onOpenChange={(isOpen) => handlePopUpToggle("confirmIntegration", isOpen)}
>
<ModalContent
title="Heads Up"
footerContent={
<div className="flex items-center space-x-2">
<Button onClick={() => onFormSubmit(popUp.confirmIntegration?.data as FormData)}>
Continue Anyway
</Button>
<Button
onClick={() => handlePopUpClose("confirmIntegration")}
variant="outline_bg"
colorSchema="secondary"
>
Cancel
</Button>
</div>
}
>
<ModalContent
title="Heads Up"
footerContent={
<div className="flex items-center space-x-2">
<Button onClick={() => onFormSubmit(popUp.confirmIntegration?.data as FormData)}>
Continue Anyway
</Button>
<Button
onClick={() => handlePopUpClose("confirmIntegration")}
variant="outline_bg"
colorSchema="secondary"
>
Cancel
</Button>
</div>
}
>
<p>
You&apos;re about to overwrite any existing secrets in GitLab.
</p>
<p className="mt-4">
To avoid this behavior, you may consider adding a secret prefix/suffix in the options tab.
</p>
</ModalContent>
</Modal>
<p>You&apos;re about to overwrite any existing secrets in GitLab.</p>
<p className="mt-4">
To avoid this behavior, you may consider adding a secret prefix/suffix in the options
tab.
</p>
</ModalContent>
</Modal>
</form>
) : (
<div className="flex justify-center items-center w-full h-full">
<div className="flex h-full w-full items-center justify-center">
<Head>
<title>Set Up GitLab Integration</title>
<link rel='icon' href='/infisical.ico' />
<link rel="icon" href="/infisical.ico" />
</Head>
{isIntegrationAuthAppsLoading || isintegrationAuthTeamsLoading ? <img src="/images/loading/loading.gif" height={70} width={120} alt="infisical loading indicator" /> : <div className="max-w-md h-max p-6 border border-mineshaft-600 rounded-md bg-mineshaft-800 text-mineshaft-200 flex flex-col text-center">
<FontAwesomeIcon icon={faBugs} className="text-6xl my-2 inlineli"/>
<p>
Something went wrong. Please contact <a
className="inline underline underline-offset-4 decoration-primary-500 opacity-80 hover:opacity-100 text-mineshaft-100 duration-200 cursor-pointer"
target="_blank"
rel="noopener noreferrer"
href="mailto:support@infisical.com"
>
support@infisical.com
</a> if the issue persists.
</p>
</div>}
{isIntegrationAuthAppsLoading || isintegrationAuthTeamsLoading ? (
<img
src="/images/loading/loading.gif"
height={70}
width={120}
alt="infisical loading indicator"
/>
) : (
<div className="flex h-max max-w-md flex-col rounded-md border border-mineshaft-600 bg-mineshaft-800 p-6 text-center text-mineshaft-200">
<FontAwesomeIcon icon={faBugs} className="inlineli my-2 text-6xl" />
<p>
Something went wrong. Please contact{" "}
<a
className="inline cursor-pointer text-mineshaft-100 underline decoration-primary-500 underline-offset-4 opacity-80 duration-200 hover:opacity-100"
target="_blank"
rel="noopener noreferrer"
href="mailto:support@infisical.com"
>
support@infisical.com
</a>{" "}
if the issue persists.
</p>
</div>
)}
</div>
);
}

View File

@@ -2,9 +2,7 @@ import { useEffect } from "react";
import { useRouter } from "next/router";
import queryString from "query-string";
import {
useAuthorizeIntegration
} from "@app/hooks/api";
import { useAuthorizeIntegration } from "@app/hooks/api";
export default function GitLabOAuth2CallbackPage() {
const router = useRouter();
@@ -16,7 +14,7 @@ export default function GitLabOAuth2CallbackPage() {
try {
// validate state
const [csrfToken, url] = (state as string).split("|", 2);
if (csrfToken !== localStorage.getItem("latestCSRFToken")) return;
localStorage.removeItem("latestCSRFToken");
@@ -24,9 +22,11 @@ export default function GitLabOAuth2CallbackPage() {
workspaceId: localStorage.getItem("projectData.id") as string,
code: code as string,
integration: "gitlab",
...(url === "" ? {} : {
url
})
...(url === ""
? {}
: {
url
})
});
router.push(`/integrations/gitlab/create?integrationAuthId=${integrationAuth.id}`);

View File

@@ -6,9 +6,7 @@ import { useRouter } from "next/router";
import { faArrowUpRightFromSquare, faBookOpen } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import {
useSaveIntegrationAccessToken
} from "@app/hooks/api";
import { useSaveIntegrationAccessToken } from "@app/hooks/api";
import { Button, Card, CardTitle, FormControl, Input } from "../../../components/v2";
@@ -18,7 +16,7 @@ export default function HashiCorpVaultAuthorizeIntegrationPage() {
const [vaultURL, setVaultURL] = useState("");
const [vaultURLErrorText, setVaultURLErrorText] = useState("");
const [vaultNamespace, setVaultNamespace] = useState("");
const [vaultNamespaceErrorText, setVaultNamespaceErrorText] = useState("");
@@ -35,44 +33,44 @@ export default function HashiCorpVaultAuthorizeIntegrationPage() {
if (vaultURL.length === 0) {
setVaultURLErrorText("Vault Cluster URL cannot be blank");
} else {
setVaultURLErrorText("");
setVaultURLErrorText("");
}
if (vaultNamespace.length === 0) {
setVaultNamespaceErrorText("Vault Namespace cannot be blank");
} else {
setVaultNamespaceErrorText("");
}
if (vaultRoleID.length === 0) {
setVaultRoleIDErrorText("Vault Role ID cannot be blank");
} else {
setVaultRoleIDErrorText("");
}
if (vaultSecretID.length === 0) {
setVaultSecretIDErrorText("Vault Secret ID cannot be blank");
} else {
setVaultSecretIDErrorText("");
}
if (
vaultURL.length === 0 ||
vaultNamespace.length === 0 ||
vaultRoleID.length === 0 ||
vaultSecretID.length === 0
vaultURL.length === 0 ||
vaultNamespace.length === 0 ||
vaultRoleID.length === 0 ||
vaultSecretID.length === 0
) {
return;
return;
}
setIsLoading(true);
const integrationAuth = await mutateAsync({
workspaceId: localStorage.getItem("projectData.id"),
integration: "hashicorp-vault",
accessId: vaultRoleID,
accessToken: vaultSecretID,
url: vaultURL,
namespace: vaultNamespace
workspaceId: localStorage.getItem("projectData.id"),
integration: "hashicorp-vault",
accessId: vaultRoleID,
accessToken: vaultSecretID,
url: vaultURL,
namespace: vaultNamespace
});
setIsLoading(false);
@@ -87,11 +85,11 @@ export default function HashiCorpVaultAuthorizeIntegrationPage() {
<div className="flex h-full w-full items-center justify-center">
<Head>
<title>Authorize Vault Integration</title>
<link rel='icon' href='/infisical.ico' />
<link rel="icon" href="/infisical.ico" />
</Head>
<Card className="max-w-lg rounded-md border border-mineshaft-600 mb-12">
<CardTitle
className="text-left px-6 text-xl"
<Card className="mb-12 max-w-lg rounded-md border border-mineshaft-600">
<CardTitle
className="px-6 text-left text-xl"
subTitle="After connecting to Vault, you will be prompted to set up an integration for a particular Infisical project and environment."
>
<div className="flex flex-row items-center">
@@ -106,10 +104,13 @@ export default function HashiCorpVaultAuthorizeIntegrationPage() {
<span className="ml-2.5">HashiCorp Vault Integration</span>
<Link href="https://infisical.com/docs/integrations/cloud/hashicorp-vault" passHref>
<a target="_blank" rel="noopener noreferrer">
<div className="ml-2 mb-1 rounded-md text-yellow text-sm inline-block bg-yellow/20 px-1.5 pb-[0.03rem] pt-[0.04rem] opacity-80 hover:opacity-100 cursor-default">
<FontAwesomeIcon icon={faBookOpen} className="mr-1.5"/>
<div className="ml-2 mb-1 inline-block cursor-default rounded-md bg-yellow/20 px-1.5 pb-[0.03rem] pt-[0.04rem] text-sm text-yellow opacity-80 hover:opacity-100">
<FontAwesomeIcon icon={faBookOpen} className="mr-1.5" />
Docs
<FontAwesomeIcon icon={faArrowUpRightFromSquare} className="ml-1.5 text-xxs mb-[0.07rem]"/>
<FontAwesomeIcon
icon={faArrowUpRightFromSquare}
className="ml-1.5 mb-[0.07rem] text-xxs"
/>
</div>
</a>
</Link>
@@ -129,11 +130,11 @@ export default function HashiCorpVaultAuthorizeIntegrationPage() {
isError={vaultNamespaceErrorText !== "" ?? false}
className="px-6"
>
<Input
placeholder="admin/education"
value={vaultNamespace}
onChange={(e) => setVaultNamespace(e.target.value)}
/>
<Input
placeholder="admin/education"
value={vaultNamespace}
onChange={(e) => setVaultNamespace(e.target.value)}
/>
</FormControl>
<FormControl
label="Vault RoleID"
@@ -141,7 +142,11 @@ export default function HashiCorpVaultAuthorizeIntegrationPage() {
isError={vaultRoleIDErrorText !== "" ?? false}
className="px-6"
>
<Input placeholder="" value={vaultRoleID} onChange={(e) => setVaultRoleID(e.target.value)} />
<Input
placeholder=""
value={vaultRoleID}
onChange={(e) => setVaultRoleID(e.target.value)}
/>
</FormControl>
<FormControl
label="Vault SecretID"
@@ -149,11 +154,11 @@ export default function HashiCorpVaultAuthorizeIntegrationPage() {
isError={vaultSecretIDErrorText !== "" ?? false}
className="px-6"
>
<Input
placeholder=""
value={vaultSecretID}
onChange={(e) => setVaultSecretID(e.target.value)}
/>
<Input
placeholder=""
value={vaultSecretID}
onChange={(e) => setVaultSecretID(e.target.value)}
/>
</FormControl>
<Button
onClick={handleButtonClick}
@@ -169,4 +174,4 @@ export default function HashiCorpVaultAuthorizeIntegrationPage() {
);
}
HashiCorpVaultAuthorizeIntegrationPage.requireAuth = true;
HashiCorpVaultAuthorizeIntegrationPage.requireAuth = true;

View File

@@ -3,13 +3,16 @@ import Head from "next/head";
import Image from "next/image";
import Link from "next/link";
import { useRouter } from "next/router";
import { faArrowUpRightFromSquare, faBookOpen, faBugs, faCircleInfo } from "@fortawesome/free-solid-svg-icons";
import {
faArrowUpRightFromSquare,
faBookOpen,
faBugs,
faCircleInfo
} from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import queryString from "query-string";
import {
useCreateIntegration
} from "@app/hooks/api";
import { useCreateIntegration } from "@app/hooks/api";
import {
Button,
@@ -30,7 +33,9 @@ export default function HashiCorpVaultCreateIntegrationPage() {
const { integrationAuthId } = queryString.parse(router.asPath.split("?")[1]);
const { data: workspace } = useGetWorkspaceById(localStorage.getItem("projectData.id") ?? "");
const { data: integrationAuth, isLoading: isintegrationAuthLoading } = useGetIntegrationAuthById((integrationAuthId as string) ?? "");
const { data: integrationAuth, isLoading: isintegrationAuthLoading } = useGetIntegrationAuthById(
(integrationAuthId as string) ?? ""
);
const [vaultEnginePath, setVaultEnginePath] = useState("");
const [vaultEnginePathErrorText, setVaultEnginePathErrorText] = useState("");
@@ -84,14 +89,14 @@ export default function HashiCorpVaultCreateIntegrationPage() {
};
return integrationAuth && workspace ? (
<div className="flex flex-col h-full w-full items-center justify-center">
<div className="flex h-full w-full flex-col items-center justify-center">
<Head>
<title>Set Up Vault Integration</title>
<link rel='icon' href='/infisical.ico' />
<link rel="icon" href="/infisical.ico" />
</Head>
<Card className="max-w-lg rounded-md border border-mineshaft-600">
<CardTitle
className="text-left px-6 text-xl"
<CardTitle
className="px-6 text-left text-xl"
subTitle="Select which environment or folder in Infisical you want to sync to which path in HashiCorp Vault."
>
<div className="flex flex-row items-center">
@@ -106,10 +111,13 @@ export default function HashiCorpVaultCreateIntegrationPage() {
<span className="ml-2.5">HashiCorp Vault Integration</span>
<Link href="https://infisical.com/docs/integrations/cloud/hashicorp-vault" passHref>
<a target="_blank" rel="noopener noreferrer">
<div className="ml-2 mb-1 rounded-md text-yellow text-sm inline-block bg-yellow/20 px-1.5 pb-[0.03rem] pt-[0.04rem] opacity-80 hover:opacity-100 cursor-default">
<FontAwesomeIcon icon={faBookOpen} className="mr-1.5"/>
<div className="ml-2 mb-1 inline-block cursor-default rounded-md bg-yellow/20 px-1.5 pb-[0.03rem] pt-[0.04rem] text-sm text-yellow opacity-80 hover:opacity-100">
<FontAwesomeIcon icon={faBookOpen} className="mr-1.5" />
Docs
<FontAwesomeIcon icon={faArrowUpRightFromSquare} className="ml-1.5 text-xxs mb-[0.07rem]"/>
<FontAwesomeIcon
icon={faArrowUpRightFromSquare}
className="ml-1.5 mb-[0.07rem] text-xxs"
/>
</div>
</a>
</Link>
@@ -173,31 +181,48 @@ export default function HashiCorpVaultCreateIntegrationPage() {
Create Integration
</Button>
</Card>
<div className="border-t border-mineshaft-800 w-full max-w-md mt-6"/>
<div className="flex flex-col bg-mineshaft-800 border border-mineshaft-600 w-full p-4 max-w-lg mt-6 rounded-md">
<div className="flex flex-row items-center"><FontAwesomeIcon icon={faCircleInfo} className="text-mineshaft-200 text-xl"/> <span className="ml-3 text-md text-mineshaft-100">Pro Tips</span></div>
<span className="text-mineshaft-300 text-sm mt-4">After creating an integration, your secrets will start syncing immediately. This might cause an unexpected override of current secrets in Vault with secrets from Infisical.</span>
<div className="mt-6 w-full max-w-md border-t border-mineshaft-800" />
<div className="mt-6 flex w-full max-w-lg flex-col rounded-md border border-mineshaft-600 bg-mineshaft-800 p-4">
<div className="flex flex-row items-center">
<FontAwesomeIcon icon={faCircleInfo} className="text-xl text-mineshaft-200" />{" "}
<span className="text-md ml-3 text-mineshaft-100">Pro Tips</span>
</div>
<span className="mt-4 text-sm text-mineshaft-300">
After creating an integration, your secrets will start syncing immediately. This might
cause an unexpected override of current secrets in Vault with secrets from Infisical.
</span>
</div>
</div>
) : (
<div className="flex justify-center items-center w-full h-full">
<div className="flex h-full w-full items-center justify-center">
<Head>
<title>Set Up Vault Integration</title>
<link rel='icon' href='/infisical.ico' />
<link rel="icon" href="/infisical.ico" />
</Head>
{isintegrationAuthLoading ? <img src="/images/loading/loading.gif" height={70} width={120} alt="infisical loading indicator" /> : <div className="max-w-md h-max p-6 border border-mineshaft-600 rounded-md bg-mineshaft-800 text-mineshaft-200 flex flex-col text-center">
<FontAwesomeIcon icon={faBugs} className="text-6xl my-2 inlineli"/>
<p>
Something went wrong. Please contact <a
className="inline underline underline-offset-4 decoration-primary-500 opacity-80 hover:opacity-100 text-mineshaft-100 duration-200 cursor-pointer"
target="_blank"
rel="noopener noreferrer"
href="mailto:support@infisical.com"
>
support@infisical.com
</a> if the issue persists.
</p>
</div>}
{isintegrationAuthLoading ? (
<img
src="/images/loading/loading.gif"
height={70}
width={120}
alt="infisical loading indicator"
/>
) : (
<div className="flex h-max max-w-md flex-col rounded-md border border-mineshaft-600 bg-mineshaft-800 p-6 text-center text-mineshaft-200">
<FontAwesomeIcon icon={faBugs} className="inlineli my-2 text-6xl" />
<p>
Something went wrong. Please contact{" "}
<a
className="inline cursor-pointer text-mineshaft-100 underline decoration-primary-500 underline-offset-4 opacity-80 duration-200 hover:opacity-100"
target="_blank"
rel="noopener noreferrer"
href="mailto:support@infisical.com"
>
support@infisical.com
</a>{" "}
if the issue persists.
</p>
</div>
)}
</div>
);
}

View File

@@ -2,9 +2,7 @@ import { useEffect, useState } from "react";
import { useRouter } from "next/router";
import queryString from "query-string";
import {
useCreateIntegration
} from "@app/hooks/api";
import { useCreateIntegration } from "@app/hooks/api";
import {
Button,

View File

@@ -2,9 +2,7 @@ import { useEffect } from "react";
import { useRouter } from "next/router";
import queryString from "query-string";
import {
useAuthorizeIntegration
} from "@app/hooks/api";
import { useAuthorizeIntegration } from "@app/hooks/api";
export default function HerokuOAuth2CallbackPage() {
const router = useRouter();

View File

@@ -1,9 +1,7 @@
import { useState } from "react";
import { useRouter } from "next/router";
import {
useSaveIntegrationAccessToken
} from "@app/hooks/api";
import { useSaveIntegrationAccessToken } from "@app/hooks/api";
import { Button, Card, CardTitle, FormControl, Input } from "../../../components/v2";
@@ -26,7 +24,7 @@ export default function LaravelForgeCreateIntegrationPage() {
setApiKeyErrorText("Access Token cannot be blank");
return;
}
if (serverId.length === 0) {
setServerIdErrorText("Server Id cannot be blank");
return;
@@ -58,14 +56,22 @@ export default function LaravelForgeCreateIntegrationPage() {
errorText={apiKeyErrorText}
isError={apiKeyErrorText !== "" ?? false}
>
<Input placeholder="Access Token" value={apiKey} onChange={(e) => setApiKey(e.target.value)} />
<Input
placeholder="Access Token"
value={apiKey}
onChange={(e) => setApiKey(e.target.value)}
/>
</FormControl>
<FormControl
label="Laravel Forge Server ID"
errorText={serverIdErrorText}
isError={serverIdErrorText !== "" ?? false}
>
<Input placeholder="123456" value={serverId} onChange={(e) => setServerId(e.target.value)} />
<Input
placeholder="123456"
value={serverId}
onChange={(e) => setServerId(e.target.value)}
/>
</FormControl>
<Button
onClick={handleButtonClick}

View File

@@ -2,9 +2,7 @@ import { useEffect, useState } from "react";
import { useRouter } from "next/router";
import queryString from "query-string";
import {
useCreateIntegration
} from "@app/hooks/api";
import { useCreateIntegration } from "@app/hooks/api";
import {
Button,
@@ -64,7 +62,10 @@ export default function LaravelForgeCreateIntegrationPage() {
integrationAuthId: integrationAuth?.id,
isActive: true,
app: targetApp,
appId: String(integrationAuthApps?.find((integrationAuthApp) => integrationAuthApp.name === targetApp)?.appId),
appId: String(
integrationAuthApps?.find((integrationAuthApp) => integrationAuthApp.name === targetApp)
?.appId
),
sourceEnvironment: selectedSourceEnvironment,
secretPath
});

View File

@@ -2,9 +2,7 @@ import { useEffect, useState } from "react";
import { useRouter } from "next/router";
import queryString from "query-string";
import {
useCreateIntegration
} from "@app/hooks/api";
import { useCreateIntegration } from "@app/hooks/api";
import {
Button,
@@ -73,7 +71,9 @@ export default function NetlifyCreateIntegrationPage() {
integrationAuthId: integrationAuth?.id,
isActive: true,
app: targetApp,
appId: integrationAuthApps?.find((integrationAuthApp) => integrationAuthApp.name === targetApp)?.appId,
appId: integrationAuthApps?.find(
(integrationAuthApp) => integrationAuthApp.name === targetApp
)?.appId,
sourceEnvironment: selectedSourceEnvironment,
targetEnvironment,
secretPath

View File

@@ -2,9 +2,7 @@ import { useEffect } from "react";
import { useRouter } from "next/router";
import queryString from "query-string";
import {
useAuthorizeIntegration
} from "@app/hooks/api";
import { useAuthorizeIntegration } from "@app/hooks/api";
export default function NetlifyOAuth2CallbackPage() {
const router = useRouter();

View File

@@ -1,9 +1,7 @@
import { useState } from "react";
import { useRouter } from "next/router";
import {
useSaveIntegrationAccessToken
} from "@app/hooks/api";
import { useSaveIntegrationAccessToken } from "@app/hooks/api";
import { Button, Card, CardTitle, FormControl, Input } from "../../../components/v2";

View File

@@ -2,9 +2,7 @@ import { useEffect, useState } from "react";
import { useRouter } from "next/router";
import queryString from "query-string";
import {
useCreateIntegration
} from "@app/hooks/api";
import { useCreateIntegration } from "@app/hooks/api";
import {
Button,
@@ -44,7 +42,7 @@ export default function NorthflankCreateIntegrationPage() {
integrationAuthId: (integrationAuthId as string) ?? "",
appId: targetAppId
});
useEffect(() => {
if (workspace) {
setSelectedSourceEnvironment(workspace.environments[0].slug);
@@ -62,7 +60,7 @@ export default function NorthflankCreateIntegrationPage() {
}
}
}, [integrationAuthApps]);
useEffect(() => {
if (integrationAuthSecretGroups) {
if (integrationAuthSecretGroups.length > 0) {
@@ -73,9 +71,8 @@ export default function NorthflankCreateIntegrationPage() {
setTargetSecretGroupId("none");
}
}
}, [integrationAuthSecretGroups]);
const handleButtonClick = async () => {
try {
if (!integrationAuth?.id) return;
@@ -85,7 +82,9 @@ export default function NorthflankCreateIntegrationPage() {
await mutateAsync({
integrationAuthId: integrationAuth?.id,
isActive: true,
app: integrationAuthApps?.find((integrationAuthApp) => integrationAuthApp.appId === targetAppId)?.name,
app: integrationAuthApps?.find(
(integrationAuthApp) => integrationAuthApp.appId === targetAppId
)?.name,
appId: targetAppId,
sourceEnvironment: selectedSourceEnvironment,
targetServiceId: targetSecretGroupId,
@@ -99,7 +98,7 @@ export default function NorthflankCreateIntegrationPage() {
console.error(err);
}
};
return integrationAuth &&
workspace &&
selectedSourceEnvironment &&

View File

@@ -6,9 +6,7 @@ import { useRouter } from "next/router";
import { faArrowUpRightFromSquare, faBookOpen } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import {
useSaveIntegrationAccessToken
} from "@app/hooks/api";
import { useSaveIntegrationAccessToken } from "@app/hooks/api";
import { Button, Card, CardTitle, FormControl, Input } from "../../../components/v2";
@@ -48,11 +46,11 @@ export default function QoveryCreateIntegrationPage() {
<div className="flex h-full w-full items-center justify-center">
<Head>
<title>Authorize Qovery Integration</title>
<link rel='icon' href='/infisical.ico' />
<link rel="icon" href="/infisical.ico" />
</Head>
<Card className="max-w-lg rounded-md border border-mineshaft-600 mb-12">
<CardTitle
className="text-left px-6 text-xl"
<Card className="mb-12 max-w-lg rounded-md border border-mineshaft-600">
<CardTitle
className="px-6 text-left text-xl"
subTitle="After adding your API key, you will be prompted to set up an integration for a particular Infisical project and environment."
>
<div className="flex flex-row items-center">
@@ -67,10 +65,13 @@ export default function QoveryCreateIntegrationPage() {
<span className="ml-2.5">Qovery Integration </span>
<Link href="https://infisical.com/docs/integrations/cloud/qovery" passHref>
<a target="_blank" rel="noopener noreferrer">
<div className="ml-2 mb-1 rounded-md text-yellow text-sm inline-block bg-yellow/20 px-1.5 pb-[0.03rem] pt-[0.04rem] opacity-80 hover:opacity-100 cursor-default">
<FontAwesomeIcon icon={faBookOpen} className="mr-1.5"/>
<div className="ml-2 mb-1 inline-block cursor-default rounded-md bg-yellow/20 px-1.5 pb-[0.03rem] pt-[0.04rem] text-sm text-yellow opacity-80 hover:opacity-100">
<FontAwesomeIcon icon={faBookOpen} className="mr-1.5" />
Docs
<FontAwesomeIcon icon={faArrowUpRightFromSquare} className="ml-1.5 text-xxs mb-[0.07rem]"/>
<FontAwesomeIcon
icon={faArrowUpRightFromSquare}
className="ml-1.5 mb-[0.07rem] text-xxs"
/>
</div>
</a>
</Link>

View File

@@ -21,14 +21,12 @@ import {
TabPanel,
Tabs
} from "@app/components/v2";
import { useCreateIntegration } from "@app/hooks/api";
import {
useCreateIntegration
} from "@app/hooks/api";
import {
useGetIntegrationAuthQoveryEnvironments,
useGetIntegrationAuthQoveryOrgs,
useGetIntegrationAuthQoveryProjects,
useGetIntegrationAuthQoveryScopes
useGetIntegrationAuthQoveryEnvironments,
useGetIntegrationAuthQoveryOrgs,
useGetIntegrationAuthQoveryProjects,
useGetIntegrationAuthQoveryScopes
} from "@app/hooks/api/integrationAuth/queries";
import { useGetIntegrationAuthById } from "../../../hooks/api/integrationAuth";
@@ -52,7 +50,7 @@ enum TabSections {
* -> Get projects belonging to the organization - select project
* -> Get environments belonging to the project - select environmnet
* -> Get qovery scopes / application (this is the application to sync to)
*
*
* Do we even need to get organizations?
*/
@@ -69,9 +67,11 @@ export default function QoveryCreateIntegrationPage() {
const [selectedSourceEnvironment, setSelectedSourceEnvironment] = useState("");
const [secretPath, setSecretPath] = useState("/");
const { data: integrationAuthOrgs } = useGetIntegrationAuthQoveryOrgs((integrationAuthId as string) ?? "");
const { data: integrationAuthOrgs } = useGetIntegrationAuthQoveryOrgs(
(integrationAuthId as string) ?? ""
);
const [targetOrgId, setTargetOrgId] = useState("");
const { data: integrationAuthProjects } = useGetIntegrationAuthQoveryProjects({
integrationAuthId: (integrationAuthId as string) ?? "",
orgId: targetOrgId
@@ -84,11 +84,12 @@ export default function QoveryCreateIntegrationPage() {
});
const [targetEnvironmentId, setTargetEnvironmentId] = useState("");
const { data: integrationAuthApps, isLoading: isIntegrationAuthAppsLoading } = useGetIntegrationAuthQoveryScopes({
integrationAuthId: (integrationAuthId as string) ?? "",
environmentId: targetEnvironmentId,
scope: (scope as ("job" | "application" | "container"))
});
const { data: integrationAuthApps, isLoading: isIntegrationAuthAppsLoading } =
useGetIntegrationAuthQoveryScopes({
integrationAuthId: (integrationAuthId as string) ?? "",
environmentId: targetEnvironmentId,
scope: scope as "job" | "application" | "container"
});
const [targetAppId, setTargetAppId] = useState("");
const [isLoading, setIsLoading] = useState(false);
@@ -145,10 +146,19 @@ export default function QoveryCreateIntegrationPage() {
setIsLoading(true);
const targetOrg = integrationAuthOrgs?.find((integrationAuthOrg) => integrationAuthOrg.orgId === targetOrgId)?.name;
const targetProject = integrationAuthProjects?.find((integrationAuthProject) => integrationAuthProject.projectId === targetProjectId)?.name;
const targetEnvironment = integrationAuthEnvironments?.find((integrationAuthEnvironment) => integrationAuthEnvironment.environmentId === targetEnvironmentId)?.name;
const targetApp = integrationAuthApps?.find((integrationAuthApp) => integrationAuthApp.appId === targetAppId)?.name;
const targetOrg = integrationAuthOrgs?.find(
(integrationAuthOrg) => integrationAuthOrg.orgId === targetOrgId
)?.name;
const targetProject = integrationAuthProjects?.find(
(integrationAuthProject) => integrationAuthProject.projectId === targetProjectId
)?.name;
const targetEnvironment = integrationAuthEnvironments?.find(
(integrationAuthEnvironment) =>
integrationAuthEnvironment.environmentId === targetEnvironmentId
)?.name;
const targetApp = integrationAuthApps?.find(
(integrationAuthApp) => integrationAuthApp.appId === targetAppId
)?.name;
await mutateAsync({
integrationAuthId: integrationAuth?.id,
@@ -172,18 +182,16 @@ export default function QoveryCreateIntegrationPage() {
console.error(err);
}
};
return integrationAuth &&
workspace &&
selectedSourceEnvironment ? (
<div className="flex flex-col h-full w-full items-center justify-center bg-gradient-to-tr from-mineshaft-900 to-bunker-900">
return integrationAuth && workspace && selectedSourceEnvironment ? (
<div className="flex h-full w-full flex-col items-center justify-center bg-gradient-to-tr from-mineshaft-900 to-bunker-900">
<Head>
<title>Set Up Qovery Integration</title>
<link rel='icon' href='/infisical.ico' />
<link rel="icon" href="/infisical.ico" />
</Head>
<Card className="max-w-lg rounded-md border border-mineshaft-600 p-0">
<CardTitle
className="text-left px-6 text-xl"
<CardTitle
className="px-6 text-left text-xl"
subTitle="Choose which environment in Infisical you want to sync to Checkly environment variables."
>
<div className="flex flex-row items-center">
@@ -198,10 +206,13 @@ export default function QoveryCreateIntegrationPage() {
<span className="ml-2.5">Qovery Integration </span>
<Link href="https://infisical.com/docs/integrations/cloud/qovery" passHref>
<a target="_blank" rel="noopener noreferrer">
<div className="ml-2 mb-1 rounded-md text-yellow text-sm inline-block bg-yellow/20 px-1.5 pb-[0.03rem] pt-[0.04rem] opacity-80 hover:opacity-100 cursor-default">
<FontAwesomeIcon icon={faBookOpen} className="mr-1.5"/>
<div className="ml-2 mb-1 inline-block cursor-default rounded-md bg-yellow/20 px-1.5 pb-[0.03rem] pt-[0.04rem] text-sm text-yellow opacity-80 hover:opacity-100">
<FontAwesomeIcon icon={faBookOpen} className="mr-1.5" />
Docs
<FontAwesomeIcon icon={faArrowUpRightFromSquare} className="ml-1.5 text-xxs mb-[0.07rem]"/>
<FontAwesomeIcon
icon={faArrowUpRightFromSquare}
className="ml-1.5 mb-[0.07rem] text-xxs"
/>
</div>
</a>
</Link>
@@ -209,7 +220,7 @@ export default function QoveryCreateIntegrationPage() {
</CardTitle>
<Tabs defaultValue={TabSections.InfisicalSettings} className="px-6">
<TabList>
<div className="flex flex-row border-b border-mineshaft-600 w-full">
<div className="flex w-full flex-row border-b border-mineshaft-600">
<Tab value={TabSections.InfisicalSettings}>Infisical Settings</Tab>
<Tab value={TabSections.QoverySettings}>Qovery Settings</Tab>
</div>
@@ -262,107 +273,112 @@ export default function QoveryCreateIntegrationPage() {
className="w-full border border-mineshaft-500"
>
{qoveryScopes.map((qoveryScope) => (
<SelectItem
value={qoveryScope.value}
key={`target-app-${qoveryScope.value}`}
>
<SelectItem value={qoveryScope.value} key={`target-app-${qoveryScope.value}`}>
{qoveryScope.label}
</SelectItem>
))}
</Select>
</FormControl>
{integrationAuthOrgs && <FormControl label="Qovery Organization">
<Select
value={targetOrgId}
onValueChange={(val) => setTargetOrgId(val)}
className="w-full border border-mineshaft-500"
isDisabled={integrationAuthOrgs.length === 0}
>
{integrationAuthOrgs.length > 0 ? (
integrationAuthOrgs.map((integrationAuthOrg) => (
<SelectItem
value={integrationAuthOrg.orgId}
key={`target-app-${integrationAuthOrg.orgId}`}
>
{integrationAuthOrg.name}
{integrationAuthOrgs && (
<FormControl label="Qovery Organization">
<Select
value={targetOrgId}
onValueChange={(val) => setTargetOrgId(val)}
className="w-full border border-mineshaft-500"
isDisabled={integrationAuthOrgs.length === 0}
>
{integrationAuthOrgs.length > 0 ? (
integrationAuthOrgs.map((integrationAuthOrg) => (
<SelectItem
value={integrationAuthOrg.orgId}
key={`target-app-${integrationAuthOrg.orgId}`}
>
{integrationAuthOrg.name}
</SelectItem>
))
) : (
<SelectItem value="none" key="target-app-none">
No organizaztions found
</SelectItem>
))
) : (
<SelectItem value="none" key="target-app-none">
No organizaztions found
</SelectItem>
)}
</Select>
</FormControl>}
{integrationAuthProjects && <FormControl label="Qovery Project">
<Select
value={targetProjectId}
onValueChange={(val) => setTargetProjectId(val)}
className="w-full border border-mineshaft-500"
isDisabled={integrationAuthProjects.length === 0}
>
{integrationAuthProjects.length > 0 ? (
integrationAuthProjects.map((integrationAuthProject) => (
<SelectItem
value={integrationAuthProject.projectId}
key={`target-app-${integrationAuthProject.projectId}`}
>
{integrationAuthProject.name}
)}
</Select>
</FormControl>
)}
{integrationAuthProjects && (
<FormControl label="Qovery Project">
<Select
value={targetProjectId}
onValueChange={(val) => setTargetProjectId(val)}
className="w-full border border-mineshaft-500"
isDisabled={integrationAuthProjects.length === 0}
>
{integrationAuthProjects.length > 0 ? (
integrationAuthProjects.map((integrationAuthProject) => (
<SelectItem
value={integrationAuthProject.projectId}
key={`target-app-${integrationAuthProject.projectId}`}
>
{integrationAuthProject.name}
</SelectItem>
))
) : (
<SelectItem value="none" key="target-app-none">
No projects found
</SelectItem>
))
) : (
<SelectItem value="none" key="target-app-none">
No projects found
</SelectItem>
)}
</Select>
</FormControl>}
{integrationAuthEnvironments && <FormControl label="Qovery Environment">
<Select
value={targetEnvironmentId}
onValueChange={(val) => setTargetEnvironmentId(val)}
className="w-full border border-mineshaft-500"
isDisabled={integrationAuthEnvironments.length === 0}
>
{integrationAuthEnvironments.length > 0 ? (
integrationAuthEnvironments.map((integrationAuthEnvironment) => (
<SelectItem
value={integrationAuthEnvironment.environmentId}
key={`target-app-${integrationAuthEnvironment.environmentId}`}
>
{integrationAuthEnvironment.name}
)}
</Select>
</FormControl>
)}
{integrationAuthEnvironments && (
<FormControl label="Qovery Environment">
<Select
value={targetEnvironmentId}
onValueChange={(val) => setTargetEnvironmentId(val)}
className="w-full border border-mineshaft-500"
isDisabled={integrationAuthEnvironments.length === 0}
>
{integrationAuthEnvironments.length > 0 ? (
integrationAuthEnvironments.map((integrationAuthEnvironment) => (
<SelectItem
value={integrationAuthEnvironment.environmentId}
key={`target-app-${integrationAuthEnvironment.environmentId}`}
>
{integrationAuthEnvironment.name}
</SelectItem>
))
) : (
<SelectItem value="none" key="target-app-none">
No environments found
</SelectItem>
))
) : (
<SelectItem value="none" key="target-app-none">
No environments found
</SelectItem>
)}
</Select>
</FormControl>}
{(scope && integrationAuthApps) && <FormControl label={`Qovery ${scope.charAt(0).toUpperCase() + scope.slice(1)}`}>
<Select
value={targetAppId}
onValueChange={(val) => setTargetAppId(val)}
className="w-full border border-mineshaft-500"
isDisabled={integrationAuthApps.length === 0}
>
{integrationAuthApps.length > 0 ? (
integrationAuthApps.map((integrationAuthApp) => (
<SelectItem
value={(integrationAuthApp.appId as string)}
key={`target-app-${integrationAuthApp.appId}`}
>
{integrationAuthApp.name}
)}
</Select>
</FormControl>
)}
{scope && integrationAuthApps && (
<FormControl label={`Qovery ${scope.charAt(0).toUpperCase() + scope.slice(1)}`}>
<Select
value={targetAppId}
onValueChange={(val) => setTargetAppId(val)}
className="w-full border border-mineshaft-500"
isDisabled={integrationAuthApps.length === 0}
>
{integrationAuthApps.length > 0 ? (
integrationAuthApps.map((integrationAuthApp) => (
<SelectItem
value={integrationAuthApp.appId as string}
key={`target-app-${integrationAuthApp.appId}`}
>
{integrationAuthApp.name}
</SelectItem>
))
) : (
<SelectItem value="none" key="target-app-none">
No {scope}s found
</SelectItem>
))
) : (
<SelectItem value="none" key="target-app-none">
No {scope}s found
</SelectItem>
)}
</Select>
</FormControl>}
)}
</Select>
</FormControl>
)}
</motion.div>
</TabPanel>
</Tabs>
@@ -384,24 +400,35 @@ export default function QoveryCreateIntegrationPage() {
</div> */}
</div>
) : (
<div className="flex justify-center items-center w-full h-full">
<div className="flex h-full w-full items-center justify-center">
<Head>
<title>Set Up Qovery Integration</title>
<link rel='icon' href='/infisical.ico' />
<link rel="icon" href="/infisical.ico" />
</Head>
{isIntegrationAuthAppsLoading ? <img src="/images/loading/loading.gif" height={70} width={120} alt="infisical loading indicator" /> : <div className="max-w-md h-max p-6 border border-mineshaft-600 rounded-md bg-mineshaft-800 text-mineshaft-200 flex flex-col text-center">
<FontAwesomeIcon icon={faBugs} className="text-6xl my-2 inlineli"/>
<p>
Something went wrong. Please contact <a
className="inline underline underline-offset-4 decoration-primary-500 opacity-80 hover:opacity-100 text-mineshaft-100 duration-200 cursor-pointer"
target="_blank"
rel="noopener noreferrer"
href="mailto:support@infisical.com"
>
support@infisical.com
</a> if the issue persists.
</p>
</div>}
{isIntegrationAuthAppsLoading ? (
<img
src="/images/loading/loading.gif"
height={70}
width={120}
alt="infisical loading indicator"
/>
) : (
<div className="flex h-max max-w-md flex-col rounded-md border border-mineshaft-600 bg-mineshaft-800 p-6 text-center text-mineshaft-200">
<FontAwesomeIcon icon={faBugs} className="inlineli my-2 text-6xl" />
<p>
Something went wrong. Please contact{" "}
<a
className="inline cursor-pointer text-mineshaft-100 underline decoration-primary-500 underline-offset-4 opacity-80 duration-200 hover:opacity-100"
target="_blank"
rel="noopener noreferrer"
href="mailto:support@infisical.com"
>
support@infisical.com
</a>{" "}
if the issue persists.
</p>
</div>
)}
</div>
);
}

View File

@@ -1,9 +1,7 @@
import { useState } from "react";
import { useRouter } from "next/router";
import {
useSaveIntegrationAccessToken
} from "@app/hooks/api";
import { useSaveIntegrationAccessToken } from "@app/hooks/api";
import { Button, Card, CardTitle, FormControl, Input } from "../../../components/v2";

View File

@@ -2,9 +2,7 @@ import { useEffect, useState } from "react";
import { useRouter } from "next/router";
import queryString from "query-string";
import {
useCreateIntegration
} from "@app/hooks/api";
import { useCreateIntegration } from "@app/hooks/api";
import {
Button,

View File

@@ -6,7 +6,7 @@ import { useRouter } from "next/router";
import { faArrowUpRightFromSquare, faBookOpen } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { useSaveIntegrationAccessToken} from "@app/hooks/api";
import { useSaveIntegrationAccessToken } from "@app/hooks/api";
import { Button, Card, CardTitle, FormControl, Input } from "../../../components/v2";
@@ -46,11 +46,11 @@ export default function RenderCreateIntegrationPage() {
<div className="flex h-full w-full items-center justify-center">
<Head>
<title>Authorize Render Integration</title>
<link rel='icon' href='/infisical.ico' />
<link rel="icon" href="/infisical.ico" />
</Head>
<Card className="max-w-lg rounded-md border border-mineshaft-600 mb-12">
<CardTitle
className="text-left px-6 text-xl"
<Card className="mb-12 max-w-lg rounded-md border border-mineshaft-600">
<CardTitle
className="px-6 text-left text-xl"
subTitle="After adding your API key, you will be prompted to set up an integration for a particular Infisical project and environment."
>
<div className="flex flex-row items-center">
@@ -65,10 +65,13 @@ export default function RenderCreateIntegrationPage() {
<span className="ml-2.5">Render Integration </span>
<Link href="https://infisical.com/docs/integrations/cloud/render" passHref>
<a target="_blank" rel="noopener noreferrer">
<div className="ml-2 mb-1 rounded-md text-yellow text-sm inline-block bg-yellow/20 px-1.5 pb-[0.03rem] pt-[0.04rem] opacity-80 hover:opacity-100 cursor-default">
<FontAwesomeIcon icon={faBookOpen} className="mr-1.5"/>
<div className="ml-2 mb-1 inline-block cursor-default rounded-md bg-yellow/20 px-1.5 pb-[0.03rem] pt-[0.04rem] text-sm text-yellow opacity-80 hover:opacity-100">
<FontAwesomeIcon icon={faBookOpen} className="mr-1.5" />
Docs
<FontAwesomeIcon icon={faArrowUpRightFromSquare} className="ml-1.5 text-xxs mb-[0.07rem]"/>
<FontAwesomeIcon
icon={faArrowUpRightFromSquare}
className="ml-1.5 mb-[0.07rem] text-xxs"
/>
</div>
</a>
</Link>

View File

@@ -3,13 +3,16 @@ import Head from "next/head";
import Image from "next/image";
import Link from "next/link";
import { useRouter } from "next/router";
import { faArrowUpRightFromSquare, faBookOpen, faBugs, faCircleInfo } from "@fortawesome/free-solid-svg-icons";
import {
faArrowUpRightFromSquare,
faBookOpen,
faBugs,
faCircleInfo
} from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import queryString from "query-string";
import {
useCreateIntegration
} from "@app/hooks/api";
import { useCreateIntegration } from "@app/hooks/api";
import {
Button,
@@ -33,10 +36,13 @@ export default function RenderCreateIntegrationPage() {
const { integrationAuthId } = queryString.parse(router.asPath.split("?")[1]);
const { data: workspace } = useGetWorkspaceById(localStorage.getItem("projectData.id") ?? "");
const { data: integrationAuth, isLoading: isIntegrationAuthLoading } = useGetIntegrationAuthById((integrationAuthId as string) ?? "");
const { data: integrationAuthApps, isLoading: isIntegrationAuthAppsLoading } = useGetIntegrationAuthApps({
integrationAuthId: (integrationAuthId as string) ?? ""
});
const { data: integrationAuth, isLoading: isIntegrationAuthLoading } = useGetIntegrationAuthById(
(integrationAuthId as string) ?? ""
);
const { data: integrationAuthApps, isLoading: isIntegrationAuthAppsLoading } =
useGetIntegrationAuthApps({
integrationAuthId: (integrationAuthId as string) ?? ""
});
const [selectedSourceEnvironment, setSelectedSourceEnvironment] = useState("");
const [targetApp, setTargetApp] = useState("");
@@ -69,7 +75,9 @@ export default function RenderCreateIntegrationPage() {
integrationAuthId: integrationAuth?.id,
isActive: true,
app: targetApp,
appId: integrationAuthApps?.find((integrationAuthApp) => integrationAuthApp.name === targetApp)?.appId,
appId: integrationAuthApps?.find(
(integrationAuthApp) => integrationAuthApp.name === targetApp
)?.appId,
sourceEnvironment: selectedSourceEnvironment,
secretPath
});
@@ -87,14 +95,14 @@ export default function RenderCreateIntegrationPage() {
selectedSourceEnvironment &&
integrationAuthApps &&
targetApp ? (
<div className="flex flex-col h-full w-full items-center justify-center">
<div className="flex h-full w-full flex-col items-center justify-center">
<Head>
<title>Set Up Render Integration</title>
<link rel='icon' href='/infisical.ico' />
<link rel="icon" href="/infisical.ico" />
</Head>
<Card className="max-w-lg rounded-md border border-mineshaft-600">
<CardTitle
className="text-left px-6 text-xl"
<CardTitle
className="px-6 text-left text-xl"
subTitle="Choose which environment or folder in Infisical you want to sync to Render environment variables."
>
<div className="flex flex-row items-center">
@@ -109,10 +117,13 @@ export default function RenderCreateIntegrationPage() {
<span className="ml-2.5">Render Integration </span>
<Link href="https://infisical.com/docs/integrations/cloud/render" passHref>
<a target="_blank" rel="noopener noreferrer">
<div className="ml-2 mb-1 rounded-md text-yellow text-sm inline-block bg-yellow/20 px-1.5 pb-[0.03rem] pt-[0.04rem] opacity-80 hover:opacity-100 cursor-default">
<FontAwesomeIcon icon={faBookOpen} className="mr-1.5"/>
<div className="ml-2 mb-1 inline-block cursor-default rounded-md bg-yellow/20 px-1.5 pb-[0.03rem] pt-[0.04rem] text-sm text-yellow opacity-80 hover:opacity-100">
<FontAwesomeIcon icon={faBookOpen} className="mr-1.5" />
Docs
<FontAwesomeIcon icon={faArrowUpRightFromSquare} className="ml-1.5 text-xxs mb-[0.07rem]"/>
<FontAwesomeIcon
icon={faArrowUpRightFromSquare}
className="ml-1.5 mb-[0.07rem] text-xxs"
/>
</div>
</a>
</Link>
@@ -175,31 +186,48 @@ export default function RenderCreateIntegrationPage() {
Create Integration
</Button>
</Card>
<div className="border-t border-mineshaft-800 w-full max-w-md mt-6"/>
<div className="flex flex-col bg-mineshaft-800 border border-mineshaft-600 w-full p-4 max-w-lg mt-6 rounded-md">
<div className="flex flex-row items-center"><FontAwesomeIcon icon={faCircleInfo} className="text-mineshaft-200 text-xl"/> <span className="ml-3 text-md text-mineshaft-100">Pro Tips</span></div>
<span className="text-mineshaft-300 text-sm mt-4">After creating an integration, your secrets will start syncing immediately. This might cause an unexpected override of current secrets in Render with secrets from Infisical.</span>
<div className="mt-6 w-full max-w-md border-t border-mineshaft-800" />
<div className="mt-6 flex w-full max-w-lg flex-col rounded-md border border-mineshaft-600 bg-mineshaft-800 p-4">
<div className="flex flex-row items-center">
<FontAwesomeIcon icon={faCircleInfo} className="text-xl text-mineshaft-200" />{" "}
<span className="text-md ml-3 text-mineshaft-100">Pro Tips</span>
</div>
<span className="mt-4 text-sm text-mineshaft-300">
After creating an integration, your secrets will start syncing immediately. This might
cause an unexpected override of current secrets in Render with secrets from Infisical.
</span>
</div>
</div>
) : (
<div className="flex justify-center items-center w-full h-full">
<div className="flex h-full w-full items-center justify-center">
<Head>
<title>Set Up Render Integration</title>
<link rel='icon' href='/infisical.ico' />
<link rel="icon" href="/infisical.ico" />
</Head>
{isIntegrationAuthLoading || isIntegrationAuthAppsLoading ? <img src="/images/loading/loading.gif" height={70} width={120} alt="infisical loading indicator" /> : <div className="max-w-md h-max p-6 border border-mineshaft-600 rounded-md bg-mineshaft-800 text-mineshaft-200 flex flex-col text-center">
<FontAwesomeIcon icon={faBugs} className="text-6xl my-2 inlineli"/>
<p>
Something went wrong. Please contact <a
className="inline underline underline-offset-4 decoration-primary-500 opacity-80 hover:opacity-100 text-mineshaft-100 duration-200 cursor-pointer"
target="_blank"
rel="noopener noreferrer"
href="mailto:support@infisical.com"
>
support@infisical.com
</a> if the issue persists.
</p>
</div>}
{isIntegrationAuthLoading || isIntegrationAuthAppsLoading ? (
<img
src="/images/loading/loading.gif"
height={70}
width={120}
alt="infisical loading indicator"
/>
) : (
<div className="flex h-max max-w-md flex-col rounded-md border border-mineshaft-600 bg-mineshaft-800 p-6 text-center text-mineshaft-200">
<FontAwesomeIcon icon={faBugs} className="inlineli my-2 text-6xl" />
<p>
Something went wrong. Please contact{" "}
<a
className="inline cursor-pointer text-mineshaft-100 underline decoration-primary-500 underline-offset-4 opacity-80 duration-200 hover:opacity-100"
target="_blank"
rel="noopener noreferrer"
href="mailto:support@infisical.com"
>
support@infisical.com
</a>{" "}
if the issue persists.
</p>
</div>
)}
</div>
);
}

View File

@@ -1,9 +1,7 @@
import { useState } from "react";
import { useRouter } from "next/router";
import {
useSaveIntegrationAccessToken
} from "@app/hooks/api";
import { useSaveIntegrationAccessToken } from "@app/hooks/api";
import { Button, Card, CardTitle, FormControl, Input } from "../../../components/v2";

View File

@@ -2,9 +2,7 @@ import { useEffect, useState } from "react";
import { useRouter } from "next/router";
import queryString from "query-string";
import {
useCreateIntegration
} from "@app/hooks/api";
import { useCreateIntegration } from "@app/hooks/api";
import {
Button,
@@ -65,7 +63,9 @@ export default function SupabaseCreateIntegrationPage() {
integrationAuthId: integrationAuth?.id,
isActive: true,
app: targetApp,
appId: integrationAuthApps?.find((integrationAuthApp) => integrationAuthApp.name === targetApp)?.appId,
appId: integrationAuthApps?.find(
(integrationAuthApp) => integrationAuthApp.name === targetApp
)?.appId,
sourceEnvironment: selectedSourceEnvironment,
secretPath
});

View File

@@ -6,9 +6,7 @@ import { useRouter } from "next/router";
import { faArrowUpRightFromSquare, faBookOpen } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import {
useSaveIntegrationAccessToken
} from "@app/hooks/api";
import { useSaveIntegrationAccessToken } from "@app/hooks/api";
import { Button, Card, CardTitle, FormControl, Input } from "../../../components/v2";
@@ -43,7 +41,7 @@ export default function TeamCityCreateIntegrationPage() {
workspaceId: localStorage.getItem("projectData.id"),
integration: "teamcity",
accessToken: apiKey,
url: serverUrl,
url: serverUrl
});
setIsLoading(false);
@@ -58,11 +56,11 @@ export default function TeamCityCreateIntegrationPage() {
<div className="flex h-full w-full items-center justify-center">
<Head>
<title>Authorize TeamCity Integration</title>
<link rel='icon' href='/infisical.ico' />
<link rel="icon" href="/infisical.ico" />
</Head>
<Card className="max-w-lg rounded-md border border-mineshaft-600 mb-12">
<CardTitle
className="text-left px-6 text-xl"
<Card className="mb-12 max-w-lg rounded-md border border-mineshaft-600">
<CardTitle
className="px-6 text-left text-xl"
subTitle="After adding the details below, you will be prompted to set up an integration for a particular Infisical project and environment."
>
<div className="flex flex-row items-center">
@@ -77,10 +75,13 @@ export default function TeamCityCreateIntegrationPage() {
<span className="ml-2">TeamCity Integration</span>
<Link href="https://infisical.com/docs/integrations/cloud/teamcity" passHref>
<a target="_blank" rel="noopener noreferrer">
<div className="ml-2 mb-1 rounded-md text-yellow text-sm inline-block bg-yellow/20 px-1.5 pb-[0.03rem] pt-[0.04rem] opacity-80 hover:opacity-100 cursor-default">
<FontAwesomeIcon icon={faBookOpen} className="mr-1.5"/>
<div className="ml-2 mb-1 inline-block cursor-default rounded-md bg-yellow/20 px-1.5 pb-[0.03rem] pt-[0.04rem] text-sm text-yellow opacity-80 hover:opacity-100">
<FontAwesomeIcon icon={faBookOpen} className="mr-1.5" />
Docs
<FontAwesomeIcon icon={faArrowUpRightFromSquare} className="ml-1.5 text-xxs mb-[0.07rem]"/>
<FontAwesomeIcon
icon={faArrowUpRightFromSquare}
className="ml-1.5 mb-[0.07rem] text-xxs"
/>
</div>
</a>
</Link>

View File

@@ -7,9 +7,7 @@ import { faArrowUpRightFromSquare, faBookOpen, faBugs } from "@fortawesome/free-
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import queryString from "query-string";
import {
useCreateIntegration
} from "@app/hooks/api";
import { useCreateIntegration } from "@app/hooks/api";
import {
Button,
@@ -30,7 +28,7 @@ import { useGetWorkspaceById } from "../../../hooks/api/workspace";
export default function TeamCityCreateIntegrationPage() {
const router = useRouter();
const { mutateAsync } = useCreateIntegration();
const [selectedSourceEnvironment, setSelectedSourceEnvironment] = useState("");
const [targetAppId, setTargetAppId] = useState("");
const [targetBuildConfigId, setTargetBuildConfigId] = useState<string>("");
@@ -40,16 +38,19 @@ export default function TeamCityCreateIntegrationPage() {
const { integrationAuthId } = queryString.parse(router.asPath.split("?")[1]);
const { data: workspace } = useGetWorkspaceById(localStorage.getItem("projectData.id") ?? "");
const { data: integrationAuth, isLoading: isIntegrationAuthLoading } = useGetIntegrationAuthById((integrationAuthId as string) ?? "");
const { data: integrationAuthApps, isLoading: isIntegrationAuthAppsLoading } = useGetIntegrationAuthApps({
integrationAuthId: (integrationAuthId as string) ?? ""
});
const { data: integrationAuth, isLoading: isIntegrationAuthLoading } = useGetIntegrationAuthById(
(integrationAuthId as string) ?? ""
);
const { data: integrationAuthApps, isLoading: isIntegrationAuthAppsLoading } =
useGetIntegrationAuthApps({
integrationAuthId: (integrationAuthId as string) ?? ""
});
const { data: targetBuildConfigs } = useGetIntegrationAuthTeamCityBuildConfigs({
integrationAuthId: (integrationAuthId as string) ?? "",
appId: targetAppId
});
useEffect(() => {
if (workspace) {
setSelectedSourceEnvironment(workspace.environments[0].slug);
@@ -65,21 +66,23 @@ export default function TeamCityCreateIntegrationPage() {
}
}
}, [integrationAuthApps]);
const handleButtonClick = async () => {
try {
if (!integrationAuth?.id) return;
setIsLoading(true);
const targetEnvironment = targetBuildConfigs?.find(
(buildConfig) => buildConfig.buildConfigId === targetBuildConfigId
);
await mutateAsync({
integrationAuthId: integrationAuth?.id,
isActive: true,
app: integrationAuthApps?.find((integrationAuthApp) => integrationAuthApp.appId === targetAppId)?.name,
app: integrationAuthApps?.find(
(integrationAuthApp) => integrationAuthApp.appId === targetAppId
)?.name,
appId: targetAppId,
sourceEnvironment: selectedSourceEnvironment,
targetEnvironment: targetEnvironment?.name,
@@ -109,11 +112,11 @@ export default function TeamCityCreateIntegrationPage() {
<div className="flex h-full w-full items-center justify-center">
<Head>
<title>Set Up TeamCity Integration</title>
<link rel='icon' href='/infisical.ico' />
<link rel="icon" href="/infisical.ico" />
</Head>
<Card className="max-w-lg rounded-md border border-mineshaft-600 mb-12">
<CardTitle
className="text-left px-6 text-xl"
<Card className="mb-12 max-w-lg rounded-md border border-mineshaft-600">
<CardTitle
className="px-6 text-left text-xl"
subTitle="Choose which environment or folders in Infisical you want to sync to which project in TeamCity."
>
<div className="flex flex-row items-center">
@@ -128,10 +131,13 @@ export default function TeamCityCreateIntegrationPage() {
<span className="ml-2">TeamCity Integration</span>
<Link href="https://infisical.com/docs/integrations/cloud/teamcity" passHref>
<a target="_blank" rel="noopener noreferrer">
<div className="ml-2 mb-1 rounded-md text-yellow text-sm inline-block bg-yellow/20 px-1.5 pb-[0.03rem] pt-[0.04rem] opacity-80 hover:opacity-100 cursor-default">
<FontAwesomeIcon icon={faBookOpen} className="mr-1.5"/>
<div className="ml-2 mb-1 inline-block cursor-default rounded-md bg-yellow/20 px-1.5 pb-[0.03rem] pt-[0.04rem] text-sm text-yellow opacity-80 hover:opacity-100">
<FontAwesomeIcon icon={faBookOpen} className="mr-1.5" />
Docs
<FontAwesomeIcon icon={faArrowUpRightFromSquare} className="ml-1.5 text-xxs mb-[0.07rem]"/>
<FontAwesomeIcon
icon={faArrowUpRightFromSquare}
className="ml-1.5 mb-[0.07rem] text-xxs"
/>
</div>
</a>
</Link>
@@ -183,7 +189,7 @@ export default function TeamCityCreateIntegrationPage() {
)}
</Select>
</FormControl>
<FormControl label="Team City Build Config (Optional)" className="px-6">
<FormControl label="Team City Build Config (Optional)" className="px-6">
<Select
value={targetBuildConfigId}
onValueChange={(val) => setTargetBuildConfigId(val)}
@@ -212,24 +218,35 @@ export default function TeamCityCreateIntegrationPage() {
</Card>
</div>
) : (
<div className="flex justify-center items-center w-full h-full">
<div className="flex h-full w-full items-center justify-center">
<Head>
<title>Set Up TeamCity Integration</title>
<link rel='icon' href='/infisical.ico' />
<link rel="icon" href="/infisical.ico" />
</Head>
{isIntegrationAuthLoading || isIntegrationAuthAppsLoading ? <img src="/images/loading/loading.gif" height={70} width={120} alt="infisical loading indicator" /> : <div className="max-w-md h-max p-6 border border-mineshaft-600 rounded-md bg-mineshaft-800 text-mineshaft-200 flex flex-col text-center">
<FontAwesomeIcon icon={faBugs} className="text-6xl my-2 inlineli"/>
<p>
Something went wrong. Please contact <a
className="inline underline underline-offset-4 decoration-primary-500 opacity-80 hover:opacity-100 text-mineshaft-100 duration-200 cursor-pointer"
target="_blank"
rel="noopener noreferrer"
href="mailto:support@infisical.com"
>
support@infisical.com
</a> if the issue persists.
</p>
</div>}
{isIntegrationAuthLoading || isIntegrationAuthAppsLoading ? (
<img
src="/images/loading/loading.gif"
height={70}
width={120}
alt="infisical loading indicator"
/>
) : (
<div className="flex h-max max-w-md flex-col rounded-md border border-mineshaft-600 bg-mineshaft-800 p-6 text-center text-mineshaft-200">
<FontAwesomeIcon icon={faBugs} className="inlineli my-2 text-6xl" />
<p>
Something went wrong. Please contact{" "}
<a
className="inline cursor-pointer text-mineshaft-100 underline decoration-primary-500 underline-offset-4 opacity-80 duration-200 hover:opacity-100"
target="_blank"
rel="noopener noreferrer"
href="mailto:support@infisical.com"
>
support@infisical.com
</a>{" "}
if the issue persists.
</p>
</div>
)}
</div>
);
}

View File

@@ -1,9 +1,7 @@
import { useState } from "react";
import { useRouter } from "next/router";
import {
useSaveIntegrationAccessToken
} from "@app/hooks/api";
import { useSaveIntegrationAccessToken } from "@app/hooks/api";
import { Button, Card, CardTitle, FormControl, Input } from "../../../components/v2";
@@ -26,7 +24,7 @@ export default function TerraformCloudCreateIntegrationPage() {
setApiKeyErrorText("API Token cannot be blank");
return;
}
if (workspacesId.length === 0) {
setWorkspacesIdErrorText("Workspace Id cannot be blank");
return;
@@ -58,14 +56,22 @@ export default function TerraformCloudCreateIntegrationPage() {
errorText={apiKeyErrorText}
isError={apiKeyErrorText !== "" ?? false}
>
<Input placeholder="API Token" value={apiKey} onChange={(e) => setApiKey(e.target.value)} />
<Input
placeholder="API Token"
value={apiKey}
onChange={(e) => setApiKey(e.target.value)}
/>
</FormControl>
<FormControl
label="Terraform Cloud Workspace ID"
errorText={workspacesIdErrorText}
isError={workspacesIdErrorText !== "" ?? false}
>
<Input placeholder="Workspace Id" value={workspacesId} onChange={(e) => setWorkSpacesId(e.target.value)} />
<Input
placeholder="Workspace Id"
value={workspacesId}
onChange={(e) => setWorkSpacesId(e.target.value)}
/>
</FormControl>
<Button
onClick={handleButtonClick}

View File

@@ -19,10 +19,7 @@ import {
} from "../../../hooks/api/integrationAuth";
import { useGetWorkspaceById } from "../../../hooks/api/workspace";
const variableTypes = [
{ name: "env" },
{ name: "terraform" }
];
const variableTypes = [{ name: "env" }, { name: "terraform" }];
export default function TerraformCloudCreateIntegrationPage() {
const router = useRouter();
@@ -65,9 +62,9 @@ export default function TerraformCloudCreateIntegrationPage() {
if (!integrationAuth?.id) return;
setVariableTypeErrorText("");
if (variableType.length === 0 ) {
setVariableTypeErrorText("Variable Type cannot be blank!")
return;
if (variableType.length === 0) {
setVariableTypeErrorText("Variable Type cannot be blank!");
return;
}
setIsLoading(true);
@@ -76,7 +73,9 @@ export default function TerraformCloudCreateIntegrationPage() {
integrationAuthId: integrationAuth?.id,
isActive: true,
app: targetApp,
appId: integrationAuthApps?.find((integrationAuthApp) => integrationAuthApp.name === targetApp)?.appId,
appId: integrationAuthApps?.find(
(integrationAuthApp) => integrationAuthApp.name === targetApp
)?.appId,
sourceEnvironment: selectedSourceEnvironment,
targetService: variableType,
secretPath
@@ -90,7 +89,6 @@ export default function TerraformCloudCreateIntegrationPage() {
}
};
return integrationAuth &&
workspace &&
selectedSourceEnvironment &&
@@ -122,23 +120,22 @@ export default function TerraformCloudCreateIntegrationPage() {
placeholder="Provide a path, default is /"
/>
</FormControl>
<FormControl label="Category" className="mt-4" errorText={variableTypeErrorText}
isError={variableTypeErrorText !== "" ?? false}>
<FormControl
label="Category"
className="mt-4"
errorText={variableTypeErrorText}
isError={variableTypeErrorText !== "" ?? false}
>
<Select
value={variableType}
onValueChange={(val) => setVariableType(val)}
className="w-full border border-mineshaft-500"
>
{
variableTypes.map((variable) => (
<SelectItem
value={variable.name}
key={`target-app-${variable.name}`}
>
{variable.name}
</SelectItem>
))
}
{variableTypes.map((variable) => (
<SelectItem value={variable.name} key={`target-app-${variable.name}`}>
{variable.name}
</SelectItem>
))}
</Select>
</FormControl>
<FormControl label="Terraform Cloud Project" className="mt-4">

View File

@@ -1,9 +1,7 @@
import { useState } from "react";
import { useRouter } from "next/router";
import {
useSaveIntegrationAccessToken
} from "@app/hooks/api";
import { useSaveIntegrationAccessToken } from "@app/hooks/api";
import { Button, Card, CardTitle, FormControl, Input } from "../../../components/v2";

View File

@@ -2,9 +2,7 @@ import { useEffect, useState } from "react";
import { useRouter } from "next/router";
import queryString from "query-string";
import {
useCreateIntegration
} from "@app/hooks/api";
import { useCreateIntegration } from "@app/hooks/api";
import {
Button,
@@ -64,7 +62,9 @@ export default function TravisCICreateIntegrationPage() {
integrationAuthId: integrationAuth?.id,
isActive: true,
app: targetApp,
appId: integrationAuthApps?.find((integrationAuthApp) => integrationAuthApp.name === targetApp)?.appId,
appId: integrationAuthApps?.find(
(integrationAuthApp) => integrationAuthApp.name === targetApp
)?.appId,
sourceEnvironment: selectedSourceEnvironment,
secretPath
});

View File

@@ -3,13 +3,16 @@ import Head from "next/head";
import Image from "next/image";
import Link from "next/link";
import { useRouter } from "next/router";
import { faArrowUpRightFromSquare, faBookOpen, faBugs, faCircleInfo } from "@fortawesome/free-solid-svg-icons";
import {
faArrowUpRightFromSquare,
faBookOpen,
faBugs,
faCircleInfo
} from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import queryString from "query-string";
import {
useCreateIntegration
} from "@app/hooks/api";
import { useCreateIntegration } from "@app/hooks/api";
import {
Button,
@@ -47,9 +50,10 @@ export default function VercelCreateIntegrationPage() {
const { integrationAuthId } = queryString.parse(router.asPath.split("?")[1]);
const { data: workspace } = useGetWorkspaceById(localStorage.getItem("projectData.id") ?? "");
const { data: integrationAuth } = useGetIntegrationAuthById((integrationAuthId as string) ?? "");
const { data: integrationAuthApps, isLoading: isIntegrationAuthAppsLoading } = useGetIntegrationAuthApps({
integrationAuthId: (integrationAuthId as string) ?? ""
});
const { data: integrationAuthApps, isLoading: isIntegrationAuthAppsLoading } =
useGetIntegrationAuthApps({
integrationAuthId: (integrationAuthId as string) ?? ""
});
const { data: branches } = useGetIntegrationAuthVercelBranches({
integrationAuthId: integrationAuthId as string,
@@ -88,7 +92,8 @@ export default function VercelCreateIntegrationPage() {
if (!targetApp || !targetApp.appId) return;
const path = targetEnvironment === "preview" && targetBranch !== "" ? targetBranch : undefined;
const path =
targetEnvironment === "preview" && targetBranch !== "" ? targetBranch : undefined;
await mutateAsync({
integrationAuthId: integrationAuth?.id,
@@ -114,14 +119,14 @@ export default function VercelCreateIntegrationPage() {
integrationAuthApps &&
targetAppId &&
targetEnvironment ? (
<div className="flex flex-col h-full w-full items-center justify-center">
<div className="flex h-full w-full flex-col items-center justify-center">
<Head>
<title>Set Up Vercel Integration</title>
<link rel='icon' href='/infisical.ico' />
<link rel="icon" href="/infisical.ico" />
</Head>
<Card className="max-w-lg rounded-md border border-mineshaft-600 p-0">
<CardTitle
className="text-left px-6 text-xl"
<CardTitle
className="px-6 text-left text-xl"
subTitle="Select which environment or folder in Infisical you want to sync to Vercel's environment variables."
>
<div className="flex flex-row items-center">
@@ -136,10 +141,13 @@ export default function VercelCreateIntegrationPage() {
<span className="ml-2">Vercel Integration </span>
<Link href="https://infisical.com/docs/integrations/cloud/vercel" passHref>
<a target="_blank" rel="noopener noreferrer">
<div className="ml-2 mb-1 rounded-md text-yellow text-sm inline-block bg-yellow/20 px-1.5 pb-[0.03rem] pt-[0.04rem] opacity-80 hover:opacity-100 cursor-default">
<FontAwesomeIcon icon={faBookOpen} className="mr-1.5"/>
<div className="ml-2 mb-1 inline-block cursor-default rounded-md bg-yellow/20 px-1.5 pb-[0.03rem] pt-[0.04rem] text-sm text-yellow opacity-80 hover:opacity-100">
<FontAwesomeIcon icon={faBookOpen} className="mr-1.5" />
Docs
<FontAwesomeIcon icon={faArrowUpRightFromSquare} className="ml-1.5 text-xxs mb-[0.07rem]"/>
<FontAwesomeIcon
icon={faArrowUpRightFromSquare}
className="ml-1.5 mb-[0.07rem] text-xxs"
/>
</div>
</a>
</Link>
@@ -233,31 +241,48 @@ export default function VercelCreateIntegrationPage() {
Create Integration
</Button>
</Card>
<div className="border-t border-mineshaft-800 w-full max-w-md mt-6"/>
<div className="flex flex-col bg-mineshaft-800 border border-mineshaft-600 w-full p-4 max-w-lg mt-6 rounded-md">
<div className="flex flex-row items-center"><FontAwesomeIcon icon={faCircleInfo} className="text-mineshaft-200 text-xl"/> <span className="ml-3 text-md text-mineshaft-100">Pro Tips</span></div>
<span className="text-mineshaft-300 text-sm mt-4">After creating an integration, your secrets will start syncing immediately. This might cause an unexpected override of current secrets in Vercel with secrets from Infisical.</span>
<div className="mt-6 w-full max-w-md border-t border-mineshaft-800" />
<div className="mt-6 flex w-full max-w-lg flex-col rounded-md border border-mineshaft-600 bg-mineshaft-800 p-4">
<div className="flex flex-row items-center">
<FontAwesomeIcon icon={faCircleInfo} className="text-xl text-mineshaft-200" />{" "}
<span className="text-md ml-3 text-mineshaft-100">Pro Tips</span>
</div>
<span className="mt-4 text-sm text-mineshaft-300">
After creating an integration, your secrets will start syncing immediately. This might
cause an unexpected override of current secrets in Vercel with secrets from Infisical.
</span>
</div>
</div>
) : (
<div className="flex justify-center items-center w-full h-full">
<div className="flex h-full w-full items-center justify-center">
<Head>
<title>Set Up Vercel Integration</title>
<link rel='icon' href='/infisical.ico' />
<link rel="icon" href="/infisical.ico" />
</Head>
{isIntegrationAuthAppsLoading ? <img src="/images/loading/loading.gif" height={70} width={120} alt="infisical loading indicator" /> : <div className="max-w-md h-max p-6 border border-mineshaft-600 rounded-md bg-mineshaft-800 text-mineshaft-200 flex flex-col text-center">
<FontAwesomeIcon icon={faBugs} className="text-6xl my-2 inlineli"/>
<p>
Something went wrong. Please contact <a
className="inline underline underline-offset-4 decoration-primary-500 opacity-80 hover:opacity-100 text-mineshaft-100 duration-200 cursor-pointer"
target="_blank"
rel="noopener noreferrer"
href="mailto:support@infisical.com"
>
support@infisical.com
</a> if the issue persists.
</p>
</div>}
{isIntegrationAuthAppsLoading ? (
<img
src="/images/loading/loading.gif"
height={70}
width={120}
alt="infisical loading indicator"
/>
) : (
<div className="flex h-max max-w-md flex-col rounded-md border border-mineshaft-600 bg-mineshaft-800 p-6 text-center text-mineshaft-200">
<FontAwesomeIcon icon={faBugs} className="inlineli my-2 text-6xl" />
<p>
Something went wrong. Please contact{" "}
<a
className="inline cursor-pointer text-mineshaft-100 underline decoration-primary-500 underline-offset-4 opacity-80 duration-200 hover:opacity-100"
target="_blank"
rel="noopener noreferrer"
href="mailto:support@infisical.com"
>
support@infisical.com
</a>{" "}
if the issue persists.
</p>
</div>
)}
</div>
);
}

View File

@@ -2,9 +2,7 @@ import { useEffect } from "react";
import { useRouter } from "next/router";
import queryString from "query-string";
import {
useAuthorizeIntegration
} from "@app/hooks/api";
import { useAuthorizeIntegration } from "@app/hooks/api";
export default function VercelOAuth2CallbackPage() {
const router = useRouter();
@@ -18,7 +16,7 @@ export default function VercelOAuth2CallbackPage() {
// validate state
if (state !== localStorage.getItem("latestCSRFToken")) return;
localStorage.removeItem("latestCSRFToken");
const integrationAuth = await mutateAsync({
workspaceId: localStorage.getItem("projectData.id") as string,
code: code as string,

View File

@@ -1,13 +1,10 @@
import { useState } from "react";
import { useRouter } from "next/router";
import {
useSaveIntegrationAccessToken
} from "@app/hooks/api";
import { useSaveIntegrationAccessToken } from "@app/hooks/api";
import { Button, Card, CardTitle, FormControl, Input } from "../../../components/v2";
export default function WindmillCreateIntegrationPage() {
const router = useRouter();
const { mutateAsync } = useSaveIntegrationAccessToken();
@@ -15,7 +12,7 @@ export default function WindmillCreateIntegrationPage() {
const [apiKey, setApiKey] = useState("");
const [apiKeyErrorText, setApiKeyErrorText] = useState("");
const [isLoading, setIsLoading] = useState(false);
const handleButtonClick = async () => {
try {
setApiKeyErrorText("");
@@ -23,17 +20,17 @@ export default function WindmillCreateIntegrationPage() {
setApiKeyErrorText("API Key cannot be blank");
return;
}
setIsLoading(true);
const integrationAuth = await mutateAsync({
workspaceId: localStorage.getItem("projectData.id"),
integration: "windmill",
accessToken: apiKey
});
setIsLoading(false);
router.push(`/integrations/windmill/create?integrationAuthId=${integrationAuth.id}`);
} catch (err) {
console.error(err);
@@ -41,27 +38,27 @@ export default function WindmillCreateIntegrationPage() {
};
return (
<div className="flex h-full w-full items-center justify-center">
<Card className="max-w-md rounded-md p-8">
<CardTitle className="text-center">Windmill Integration</CardTitle>
<FormControl
label="Windmill Access Token"
errorText={apiKeyErrorText}
isError={apiKeyErrorText !== "" ?? false}
>
<Input placeholder="" value={apiKey} onChange={(e) => setApiKey(e.target.value)} />
</FormControl>
<Button
onClick={handleButtonClick}
color="mineshaft"
className="mt-4"
isLoading={isLoading}
>
Connect to Windmill
</Button>
</Card>
</div>
);
<div className="flex h-full w-full items-center justify-center">
<Card className="max-w-md rounded-md p-8">
<CardTitle className="text-center">Windmill Integration</CardTitle>
<FormControl
label="Windmill Access Token"
errorText={apiKeyErrorText}
isError={apiKeyErrorText !== "" ?? false}
>
<Input placeholder="" value={apiKey} onChange={(e) => setApiKey(e.target.value)} />
</FormControl>
<Button
onClick={handleButtonClick}
color="mineshaft"
className="mt-4"
isLoading={isLoading}
>
Connect to Windmill
</Button>
</Card>
</div>
);
}
WindmillCreateIntegrationPage.requireAuth = true;
WindmillCreateIntegrationPage.requireAuth = true;

View File

@@ -2,9 +2,7 @@ import { useEffect, useState } from "react";
import { useRouter } from "next/router";
import queryString from "query-string";
import {
useCreateIntegration
} from "@app/hooks/api";
import { useCreateIntegration } from "@app/hooks/api";
import {
Button,
@@ -65,7 +63,9 @@ export default function WindmillCreateIntegrationPage() {
integrationAuthId: integrationAuth?.id,
isActive: true,
app: targetApp,
appId: integrationAuthApps?.find((integrationAuthApp) => integrationAuthApp.name === targetApp)?.appId,
appId: integrationAuthApps?.find(
(integrationAuthApp) => integrationAuthApp.name === targetApp
)?.appId,
sourceEnvironment: selectedSourceEnvironment,
secretPath
});

View File

@@ -68,7 +68,7 @@ import { usePopUp } from "@app/hooks/usePopUp";
const features = [
{
_id: 0,
id: 0,
name: "Kubernetes Operator",
link: "https://infisical.com/docs/documentation/getting-started/kubernetes",
description:
@@ -519,7 +519,7 @@ const OrganizationPage = withPermission(
try {
const {
data: {
workspace: { _id: newWorkspaceId }
workspace: { id: newWorkspaceId }
}
} = await createWs.mutateAsync({
organizationId: currentOrg,
@@ -537,7 +537,7 @@ const OrganizationPage = withPermission(
await uploadWsKey.mutateAsync({
encryptedKey: ciphertext,
nonce,
userId: user?._id,
userId: user?.id,
workspaceId: newWorkspaceId
});
@@ -553,7 +553,7 @@ const OrganizationPage = withPermission(
.filter(
({ status, user: orgUser }) => status === "accepted" && user.email !== orgUser.email
)
.map(({ user: orgUser, _id: orgMembershipId }) => ({
.map(({ user: orgUser, id: orgMembershipId }) => ({
userPublicKey: orgUser.publicKey,
orgMembershipId
}))
@@ -682,7 +682,7 @@ const OrganizationPage = withPermission(
.filter((ws) => ws?.name?.toLowerCase().includes(searchFilter.toLowerCase()))
.map((workspace) => (
<div
key={workspace._id}
key={workspace.id}
className="min-w-72 flex h-40 flex-col justify-between rounded-md border border-mineshaft-600 bg-mineshaft-800 p-4"
>
<div className="mt-0 text-lg text-mineshaft-100">{workspace.name}</div>
@@ -692,8 +692,8 @@ const OrganizationPage = withPermission(
<button
type="button"
onClick={() => {
router.push(`/project/${workspace._id}/secrets/overview`);
localStorage.setItem("projectData.id", workspace._id);
router.push(`/project/${workspace.id}/secrets/overview`);
localStorage.setItem("projectData.id", workspace.id);
}}
>
<div className="group ml-auto w-max cursor-pointer rounded-full border border-mineshaft-600 bg-mineshaft-900 py-2 px-4 text-sm text-mineshaft-300 hover:border-primary-500/80 hover:bg-primary-800/20 hover:text-mineshaft-200">
@@ -782,7 +782,7 @@ const OrganizationPage = withPermission(
icon={faPlus}
time="1 min"
userAction="first_time_secrets_pushed"
link={`/project/${orgWorkspaces[0]?._id}/secrets/overview`}
link={`/project/${orgWorkspaces[0]?.id}/secrets/overview`}
/>
<LearningItemSquare
text="Invite your teammates"

View File

@@ -63,20 +63,20 @@ const SecretScanning = withPermission(
<link rel="icon" href="/infisical.ico" />
<meta property="og:image" content="/images/message.png" />
</Head>
<div className="flex justify-center bg-bunker-800 text-white w-full h-full">
<div className="max-w-7xl px-6 w-full">
<div className="flex h-full w-full justify-center bg-bunker-800 text-white">
<div className="w-full max-w-7xl px-6">
<div className="mt-6 text-3xl font-semibold text-gray-200">Secret Scanning</div>
<div className="mb-6 text-lg text-mineshaft-300">
Automatically monitor your GitHub activity and prevent secret leaks
</div>
<div className="relative flex justify-between bg-mineshaft-800 border border-mineshaft-600 rounded-md p-6 mb-6">
<div className="relative mb-6 flex justify-between rounded-md border border-mineshaft-600 bg-mineshaft-800 p-6">
<div className="flex flex-col items-start">
<div className="flex flex-row mb-1">
<div className="mb-1 flex flex-row">
Secret Scanning Status:{" "}
{integrationEnabled ? (
<p className="text-green ml-1.5 font-semibold">Enabled</p>
<p className="ml-1.5 font-semibold text-green">Enabled</p>
) : (
<p className="text-red ml-1.5 font-semibold">Not enabled</p>
<p className="ml-1.5 font-semibold text-red">Not enabled</p>
)}
</div>
<div>
@@ -94,12 +94,12 @@ const SecretScanning = withPermission(
</div>
{integrationEnabled ? (
<div>
<div className="absolute right-[2.5rem] top-[2.5rem] animate-ping rounded-full h-6 w-6 bg-green flex items-center justify-center" />
<div className="absolute right-[2.63rem] top-[2.63rem] animate-ping rounded-full h-5 w-5 bg-green flex items-center justify-center" />
<div className="absolute right-[2.82rem] top-[2.82rem] animate-ping rounded-full h-3.5 w-3.5 bg-green flex items-center justify-center" />
<div className="absolute right-[2.5rem] top-[2.5rem] flex h-6 w-6 animate-ping items-center justify-center rounded-full bg-green" />
<div className="absolute right-[2.63rem] top-[2.63rem] flex h-5 w-5 animate-ping items-center justify-center rounded-full bg-green" />
<div className="absolute right-[2.82rem] top-[2.82rem] flex h-3.5 w-3.5 animate-ping items-center justify-center rounded-full bg-green" />
</div>
) : (
<div className="flex items-center h-[3.25rem]">
<div className="flex h-[3.25rem] items-center">
<OrgPermissionCan
I={OrgPermissionActions.Create}
a={OrgPermissionSubjects.SecretScanning}
@@ -109,7 +109,7 @@ const SecretScanning = withPermission(
variant="solid"
colorSchema="primary"
onClick={generateNewIntegrationSession}
className="py-2 h-min"
className="h-min py-2"
isDisabled={!isAllowed}
>
Integrate with GitHub

View File

@@ -153,7 +153,7 @@ export default function SignUp() {
};
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 pb-28 ">
<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 pb-28 ">
<Head>
<title>{t("common.head-title", { title: t("signup.title") })}</title>
<link rel="icon" href="/infisical.ico" />

View File

@@ -162,7 +162,8 @@ export const IntegrationsSection = ({
</div>
</div>
)}
{((integration.integration === "checkly") || (integration.integration === "github")) && (
{(integration.integration === "checkly" ||
integration.integration === "github") && (
<>
{integration.targetService && (
<div className="ml-2">

View File

@@ -3,22 +3,22 @@ import { NextRouter } from "next/router";
import { fetchOrganizations } from "@app/hooks/api/organization/queries";
export const navigateUserToOrg = async (router: NextRouter, organizationId?: string) => {
const userOrgs = await fetchOrganizations();
const userOrgs = await fetchOrganizations();
if (organizationId) {
localStorage.setItem("orgData.id", organizationId);
router.push(`/org/${organizationId}/overview`);
return;
}
if (organizationId) {
localStorage.setItem("orgData.id", organizationId);
router.push(`/org/${organizationId}/overview`);
return;
}
if (userOrgs.length > 0) {
// user is part of at least 1 org
const userOrg = userOrgs[0] && userOrgs[0].id;
localStorage.setItem("orgData.id", userOrg);
router.push(`/org/${userOrg}/overview`);
} else {
// user is not part of any org
localStorage.removeItem("orgData.id");
router.push("/org/none");
}
}
if (userOrgs.length > 0) {
// user is part of at least 1 org
const userOrg = userOrgs[0] && userOrgs[0].id;
localStorage.setItem("orgData.id", userOrg);
router.push(`/org/${userOrg}/overview`);
} else {
// user is not part of any org
localStorage.removeItem("orgData.id");
router.push("/org/none");
}
};

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