mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-03 18:26:04 +00:00
feat(infisical-pg): changed frontend api types _id to normal id
This commit is contained in:
@@ -8,7 +8,7 @@
|
|||||||
"start:docker": "next build && next start",
|
"start:docker": "next build && next start",
|
||||||
"lint": "eslint --ext js,ts,tsx ./src",
|
"lint": "eslint --ext js,ts,tsx ./src",
|
||||||
"lint:fix": "eslint --fix --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",
|
"storybook": "storybook dev -p 6006 -s ./public",
|
||||||
"build-storybook": "storybook build"
|
"build-storybook": "storybook build"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
export interface Tag {
|
export interface Tag {
|
||||||
_id: string;
|
id: string;
|
||||||
name: string;
|
name: string;
|
||||||
slug: string;
|
slug: string;
|
||||||
user: string;
|
user: string;
|
||||||
@@ -16,4 +16,4 @@ export interface SecretDataProps {
|
|||||||
idOverride?: string;
|
idOverride?: string;
|
||||||
comment: string;
|
comment: string;
|
||||||
tags: Tag[];
|
tags: Tag[];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,18 +31,18 @@ const AddTagPopoverContent = ({
|
|||||||
return (
|
return (
|
||||||
<PopoverContent
|
<PopoverContent
|
||||||
side="left"
|
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
|
hideCloseBtn
|
||||||
>
|
>
|
||||||
<div className=" text-center text-sm font-medium text-bunker-200">
|
<div className=" text-center text-sm font-medium text-bunker-200">
|
||||||
Add tags to {secKey || "this secret"}
|
Add tags to {secKey || "this secret"}
|
||||||
</div>
|
</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">
|
<div className="flex flex-col space-y-1.5">
|
||||||
{wsTags?.map((wsTag: WsTag) => (
|
{wsTags?.map((wsTag: WsTag) => (
|
||||||
<div
|
<div
|
||||||
key={`tag-${wsTag.id}`}
|
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)}
|
onClick={() => handleSelectTag(wsTag)}
|
||||||
onMouseEnter={() => handleTagOnMouseEnter(wsTag)}
|
onMouseEnter={() => handleTagOnMouseEnter(wsTag)}
|
||||||
onMouseLeave={() => handleTagOnMouseLeave()}
|
onMouseLeave={() => handleTagOnMouseLeave()}
|
||||||
@@ -54,7 +54,7 @@ const AddTagPopoverContent = ({
|
|||||||
<Checkbox
|
<Checkbox
|
||||||
id="autoCapitalization"
|
id="autoCapitalization"
|
||||||
isChecked={selectedTagIds?.[wsTag.slug]}
|
isChecked={selectedTagIds?.[wsTag.slug]}
|
||||||
className="absolute top-[50%] translate-y-[-50%] left-[10px] "
|
className="absolute top-[50%] left-[10px] translate-y-[-50%] "
|
||||||
checkIndicatorBg={`${
|
checkIndicatorBg={`${
|
||||||
!selectedTagIds?.[wsTag.slug] ? "text-transparent" : "text-mineshaft-800"
|
!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="ml-7 flex items-center gap-3">
|
||||||
<div
|
<div
|
||||||
className="w-[10px] h-[10px] rounded-full"
|
className="h-[10px] w-[10px] rounded-full"
|
||||||
style={{ background: wsTag?.tagColor ? wsTag.tagColor : "#bec2c8" }}
|
style={{ background: wsTag?.tagColor ? wsTag.tagColor : "#bec2c8" }}
|
||||||
>
|
>
|
||||||
{" "}
|
{" "}
|
||||||
|
|||||||
@@ -4,73 +4,64 @@ import { Dialog, Transition } from "@headlessui/react";
|
|||||||
|
|
||||||
import { useOrganization } from "@app/context";
|
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 = {
|
type Props = {
|
||||||
isOpen?: boolean;
|
isOpen?: boolean;
|
||||||
onClose: ()=>void;
|
onClose: () => void;
|
||||||
text: string;
|
text: string;
|
||||||
}
|
};
|
||||||
|
|
||||||
const UpgradePlanModal = ({
|
const UpgradePlanModal = ({ isOpen, onClose, text }: Props) => {
|
||||||
isOpen,
|
|
||||||
onClose,
|
|
||||||
text,
|
|
||||||
}:Props) => {
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { currentOrg } = useOrganization();
|
const { currentOrg } = useOrganization();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<Transition appear show={isOpen} as={Fragment}>
|
<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
|
<Transition.Child
|
||||||
as={Fragment}
|
as={Fragment}
|
||||||
enter='ease-out duration-300'
|
enter="ease-out duration-300"
|
||||||
enterFrom='opacity-0'
|
enterFrom="opacity-0"
|
||||||
enterTo='opacity-100'
|
enterTo="opacity-100"
|
||||||
leave='ease-in duration-150'
|
leave="ease-in duration-150"
|
||||||
leaveFrom='opacity-100'
|
leaveFrom="opacity-100"
|
||||||
leaveTo='opacity-0'
|
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>
|
</Transition.Child>
|
||||||
<div className='fixed inset-0 overflow-y-auto'>
|
<div className="fixed inset-0 overflow-y-auto">
|
||||||
<div className='flex min-h-full items-center justify-center p-4 text-center'>
|
<div className="flex min-h-full items-center justify-center p-4 text-center">
|
||||||
<Transition.Child
|
<Transition.Child
|
||||||
as={Fragment}
|
as={Fragment}
|
||||||
enter='ease-out duration-300'
|
enter="ease-out duration-300"
|
||||||
enterFrom='opacity-0 scale-95'
|
enterFrom="opacity-0 scale-95"
|
||||||
enterTo='opacity-100 scale-100'
|
enterTo="opacity-100 scale-100"
|
||||||
leave='ease-in duration-200'
|
leave="ease-in duration-200"
|
||||||
leaveFrom='opacity-100 scale-100'
|
leaveFrom="opacity-100 scale-100"
|
||||||
leaveTo='opacity-0 scale-95'
|
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.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
|
<Dialog.Title as="h3" className="text-xl font-medium leading-6 text-primary">
|
||||||
as='h3'
|
|
||||||
className='text-xl font-medium leading-6 text-primary'
|
|
||||||
>
|
|
||||||
Unleash Infisical's Full Power
|
Unleash Infisical's Full Power
|
||||||
</Dialog.Title>
|
</Dialog.Title>
|
||||||
<div className='mt-2'>
|
<div className="mt-2">
|
||||||
<p className='text-sm text-bunker-300 mb-1'>
|
<p className="mb-1 text-sm text-bunker-300">{text}</p>
|
||||||
{text}
|
<p className="text-sm text-bunker-300">
|
||||||
</p>
|
|
||||||
<p className='text-sm text-bunker-300'>
|
|
||||||
Upgrade and get access to this, as well as to other powerful enhancements.
|
Upgrade and get access to this, as well as to other powerful enhancements.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div className='mt-4'>
|
<div className="mt-4">
|
||||||
<button
|
<button
|
||||||
type='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'
|
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`)}
|
onClick={() => router.push(`/org/${currentOrg?.id}/billing`)}
|
||||||
>
|
>
|
||||||
Upgrade Now
|
Upgrade Now
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
type='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'
|
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}
|
onClick={onClose}
|
||||||
>
|
>
|
||||||
Maybe Later
|
Maybe Later
|
||||||
|
|||||||
@@ -10,7 +10,8 @@ import {
|
|||||||
useDeleteUserFromWorkspace,
|
useDeleteUserFromWorkspace,
|
||||||
useGetUserWsKey,
|
useGetUserWsKey,
|
||||||
useUpdateUserWorkspaceRole,
|
useUpdateUserWorkspaceRole,
|
||||||
useUploadWsKey} from "@app/hooks/api";
|
useUploadWsKey
|
||||||
|
} from "@app/hooks/api";
|
||||||
|
|
||||||
import { decryptAssymmetric, encryptAssymmetric } from "../../utilities/cryptography/crypto";
|
import { decryptAssymmetric, encryptAssymmetric } from "../../utilities/cryptography/crypto";
|
||||||
import guidGenerator from "../../utilities/randomId";
|
import guidGenerator from "../../utilities/randomId";
|
||||||
@@ -64,7 +65,7 @@ const ProjectUsersTable = ({ userData, changeData, myUser, filter, isUserListLoa
|
|||||||
|
|
||||||
const handleRoleUpdate = async (index: number, e: string) => {
|
const handleRoleUpdate = async (index: number, e: string) => {
|
||||||
await updateUserWorkspaceRoleMutateAsync({
|
await updateUserWorkspaceRoleMutateAsync({
|
||||||
membershipId: userData[index].membershipId,
|
membershipId: userData[index].membershipId,
|
||||||
role: e.toLowerCase()
|
role: e.toLowerCase()
|
||||||
});
|
});
|
||||||
createNotification({
|
createNotification({
|
||||||
@@ -191,11 +192,15 @@ const ProjectUsersTable = ({ userData, changeData, myUser, filter, isUserListLoa
|
|||||||
<UpgradePlanModal
|
<UpgradePlanModal
|
||||||
isOpen={isUpgradeModalOpen}
|
isOpen={isUpgradeModalOpen}
|
||||||
onClose={closeUpgradeModal}
|
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">
|
<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>
|
<tr>
|
||||||
<th className="py-3.5 pl-4 text-left">NAME</th>
|
<th className="py-3.5 pl-4 text-left">NAME</th>
|
||||||
<th className="py-3.5 pl-4 text-left">EMAIL</th>
|
<th className="py-3.5 pl-4 text-left">EMAIL</th>
|
||||||
@@ -213,12 +218,13 @@ const ProjectUsersTable = ({ userData, changeData, myUser, filter, isUserListLoa
|
|||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{!isUserListLoading && userData?.filter(
|
{!isUserListLoading &&
|
||||||
(user) =>
|
userData?.filter(
|
||||||
user.firstName?.toLowerCase().includes(filter) ||
|
(user) =>
|
||||||
user.lastName?.toLowerCase().includes(filter) ||
|
user.firstName?.toLowerCase().includes(filter) ||
|
||||||
user.email?.toLowerCase().includes(filter)
|
user.lastName?.toLowerCase().includes(filter) ||
|
||||||
).length > 0 &&
|
user.email?.toLowerCase().includes(filter)
|
||||||
|
).length > 0 &&
|
||||||
userData
|
userData
|
||||||
?.filter(
|
?.filter(
|
||||||
(user) =>
|
(user) =>
|
||||||
@@ -373,10 +379,18 @@ const ProjectUsersTable = ({ userData, changeData, myUser, filter, isUserListLoa
|
|||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
))}
|
))}
|
||||||
{isUserListLoading && <>
|
{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"/>
|
<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>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -13,17 +13,27 @@ import { Tag } from "public/data/frequentInterfaces";
|
|||||||
* @param {function} obj.modifyTags - modify tags for a certain secret
|
* @param {function} obj.modifyTags - modify tags for a certain secret
|
||||||
* @param {Tag[]} obj.position - currently selected 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();
|
const router = useRouter();
|
||||||
return (
|
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
|
<Menu.Button
|
||||||
as="div"
|
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'>
|
<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]"/>
|
<FontAwesomeIcon icon={faPlus} className="p-[0.28rem]" />
|
||||||
{currentTags?.length > 2 && <span className='pr-2'>{currentTags.length - 2}</span>}
|
{currentTags?.length > 2 && <span className="pr-2">{currentTags.length - 2}</span>}
|
||||||
</div>
|
</div>
|
||||||
</Menu.Button>
|
</Menu.Button>
|
||||||
<Transition
|
<Transition
|
||||||
@@ -35,24 +45,40 @@ const AddTagsMenu = ({ allTags, currentTags, modifyTags, id }: { allTags: Tag[];
|
|||||||
leaveFrom="transform opacity-100 scale-100"
|
leaveFrom="transform opacity-100 scale-100"
|
||||||
leaveTo="transform opacity-0 scale-95"
|
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">
|
<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 (
|
{allTags?.map((tag) => {
|
||||||
<Menu.Item key={tag.id}>
|
return (
|
||||||
<button
|
<Menu.Item key={tag.id}>
|
||||||
type="button"
|
<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`}
|
type="button"
|
||||||
onClick={() => {if (!currentTags?.map(currentTag => currentTag.name).includes(tag.name)) {modifyTags(currentTags.concat([tag]), id)}}}
|
className={`${
|
||||||
>
|
currentTags?.map((currentTag) => currentTag.name).includes(tag.name)
|
||||||
{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}
|
? "cursor-default opacity-30"
|
||||||
</button>
|
: "hover:bg-mineshaft-700"
|
||||||
</Menu.Item>
|
} 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
|
<button
|
||||||
type="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`)}
|
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>
|
</button>
|
||||||
</Menu.Items>
|
</Menu.Items>
|
||||||
</Transition>
|
</Transition>
|
||||||
|
|||||||
@@ -38,8 +38,7 @@ const colors = [
|
|||||||
"bg-[#6F1AB6]/40",
|
"bg-[#6F1AB6]/40",
|
||||||
"bg-[#C40B13]/40",
|
"bg-[#C40B13]/40",
|
||||||
"bg-[#332FD0]/40"
|
"bg-[#332FD0]/40"
|
||||||
]
|
];
|
||||||
|
|
||||||
|
|
||||||
const colorsText = [
|
const colorsText = [
|
||||||
"text-[#fcf0c3]/70",
|
"text-[#fcf0c3]/70",
|
||||||
@@ -50,7 +49,7 @@ const colorsText = [
|
|||||||
"text-[#FFE5F1]/70",
|
"text-[#FFE5F1]/70",
|
||||||
"text-[#FFDEDE]/70",
|
"text-[#FFDEDE]/70",
|
||||||
"text-[#DFF6FF]/70"
|
"text-[#DFF6FF]/70"
|
||||||
]
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This component represent a single row for an environemnt variable on the dashboard
|
* This component represent a single row for an environemnt variable on the dashboard
|
||||||
@@ -83,117 +82,160 @@ const KeyPair = ({
|
|||||||
toggleSidebar,
|
toggleSidebar,
|
||||||
sidebarSecretId,
|
sidebarSecretId,
|
||||||
isCapitalized,
|
isCapitalized,
|
||||||
isSnapshot,
|
isSnapshot,
|
||||||
deleteRow,
|
deleteRow,
|
||||||
togglePITSidebar,
|
togglePITSidebar,
|
||||||
tags
|
tags
|
||||||
}: KeyPairProps) => {
|
}: KeyPairProps) => {
|
||||||
const tagData = (tags.map((tag, index) => {return {
|
const tagData = tags.map((tag, index) => {
|
||||||
...tag,
|
return {
|
||||||
color: colors[index%colors.length],
|
...tag,
|
||||||
colorText: colorsText[index%colorsText.length]
|
color: colors[index % colors.length],
|
||||||
}}));
|
colorText: colorsText[index % colorsText.length]
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={`group flex flex-col items-center border-b border-mineshaft-500 hover:bg-white/[0.03] duration-100 ${isSnapshot && "pointer-events-none"} ${
|
className={`group flex flex-col items-center border-b border-mineshaft-500 duration-100 hover:bg-white/[0.03] ${
|
||||||
keyPair.id === sidebarSecretId && "bg-mineshaft-700 duration-200"
|
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="relative mr-auto flex max-h-14 w-full flex-row items-center justify-between">
|
||||||
<div className="w-[23%] border-r border-mineshaft-600 flex flex-row items-center">
|
<div className="flex w-[23%] flex-row items-center border-r border-mineshaft-600">
|
||||||
<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 h-10 w-14 cursor-default items-center justify-center text-xs text-bunker-400">
|
||||||
<div className="flex items-center max-h-16 w-full">
|
{keyPair.pos + 1}
|
||||||
<DashboardInputField
|
</div>
|
||||||
isCapitalized = {isCapitalized}
|
<div className="flex max-h-16 w-full items-center">
|
||||||
onChangeHandler={modifyKey}
|
<DashboardInputField
|
||||||
type="varName"
|
isCapitalized={isCapitalized}
|
||||||
id={keyPair.id ? keyPair.id : (keyPair.idOverride || "")}
|
onChangeHandler={modifyKey}
|
||||||
value={keyPair.key}
|
type="varName"
|
||||||
isDuplicate={isDuplicate}
|
id={keyPair.id ? keyPair.id : keyPair.idOverride || ""}
|
||||||
overrideEnabled={keyPair.valueOverride !== undefined}
|
value={keyPair.key}
|
||||||
modifyValueOverride={modifyValueOverride}
|
isDuplicate={isDuplicate}
|
||||||
isSideBarOpen={keyPair.id === sidebarSecretId}
|
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>
|
|
||||||
<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
|
<div
|
||||||
onKeyDown={() => null}
|
onKeyDown={() => null}
|
||||||
role="button"
|
role="button"
|
||||||
tabIndex={0}
|
tabIndex={0}
|
||||||
onClick={() => { if (deleteRow) {
|
onClick={() => {
|
||||||
deleteRow({ ids: [keyPair.id], secretName: keyPair?.key })
|
if (togglePITSidebar) {
|
||||||
}}}
|
togglePITSidebar(false);
|
||||||
className="invisible group-hover:visible"
|
}
|
||||||
|
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>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
);
|
||||||
)};
|
};
|
||||||
|
|
||||||
export default KeyPair;
|
export default KeyPair;
|
||||||
|
|||||||
@@ -157,7 +157,7 @@ export default function NavHeader({
|
|||||||
})}
|
})}
|
||||||
{isProtectedBranch && (
|
{isProtectedBranch && (
|
||||||
<Tooltip content={`Protected by policy ${protectionPolicyName}`}>
|
<Tooltip content={`Protected by policy ${protectionPolicyName}`}>
|
||||||
<FontAwesomeIcon icon={faLock} className="text-primary ml-2" />
|
<FontAwesomeIcon icon={faLock} className="ml-2 text-primary" />
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -119,9 +119,9 @@ export const CreateTagModal = ({ isOpen, onToggle }: Props): JSX.Element => {
|
|||||||
const [showHexInput, setShowHexInput] = useState<boolean>(false);
|
const [showHexInput, setShowHexInput] = useState<boolean>(false);
|
||||||
const selectedTagColor = watch("color", secretTagsColors[0].hex);
|
const selectedTagColor = watch("color", secretTagsColors[0].hex);
|
||||||
|
|
||||||
useEffect(()=>{
|
useEffect(() => {
|
||||||
if(!isOpen) reset();
|
if (!isOpen) reset();
|
||||||
},[isOpen])
|
}, [isOpen]);
|
||||||
|
|
||||||
const onFormSubmit = async ({ name, color }: FormData) => {
|
const onFormSubmit = async ({ name, color }: FormData) => {
|
||||||
try {
|
try {
|
||||||
@@ -168,21 +168,21 @@ export const CreateTagModal = ({ isOpen, onToggle }: Props): JSX.Element => {
|
|||||||
Tag Color
|
Tag Color
|
||||||
</div>
|
</div>
|
||||||
<div className="flex space-x-2">
|
<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
|
<div
|
||||||
className="w-6 h-6 rounded-full"
|
className="h-6 w-6 rounded-full"
|
||||||
style={{ background: `${selectedTagColor}` }}
|
style={{ background: `${selectedTagColor}` }}
|
||||||
/>
|
/>
|
||||||
</div>
|
</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 ? (
|
{!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) => {
|
{secretTagsColors.map(($tagColor: TagColor) => {
|
||||||
return (
|
return (
|
||||||
<div key={`tag-color-${$tagColor.id}`}>
|
<div key={`tag-color-${$tagColor.id}`}>
|
||||||
<Tooltip content={`${$tagColor.name}`}>
|
<Tooltip content={`${$tagColor.name}`}>
|
||||||
<div
|
<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}`}
|
key={`tag-${$tagColor.id}`}
|
||||||
style={{ backgroundColor: `${$tagColor.hex}` }}
|
style={{ backgroundColor: `${$tagColor.hex}` }}
|
||||||
onClick={() => setValue("color", $tagColor.hex)}
|
onClick={() => setValue("color", $tagColor.hex)}
|
||||||
@@ -200,18 +200,18 @@ export const CreateTagModal = ({ isOpen, onToggle }: Props): JSX.Element => {
|
|||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div className="flex flex-grow items-center px-2 tags-hex-wrapper">
|
<div className="tags-hex-wrapper flex flex-grow items-center px-2">
|
||||||
<div className="flex items-center relative rounded-md ">
|
<div className="relative flex items-center rounded-md ">
|
||||||
{isValidHexColor(selectedTagColor) && (
|
{isValidHexColor(selectedTagColor) && (
|
||||||
<div
|
<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}` }}
|
style={{ background: `${selectedTagColor}` }}
|
||||||
>
|
>
|
||||||
<FontAwesomeIcon icon={faCheck} style={{ color: "#00000070" }} />
|
<FontAwesomeIcon icon={faCheck} style={{ color: "#00000070" }} />
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{!isValidHexColor(selectedTagColor) && (
|
{!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>
|
||||||
<div className="flex-grow">
|
<div className="flex-grow">
|
||||||
@@ -225,10 +225,10 @@ export const CreateTagModal = ({ isOpen, onToggle }: Props): JSX.Element => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<div className="border-mineshaft-500 border h-8 mx-4" />
|
<div className="mx-4 h-8 border border-mineshaft-500" />
|
||||||
<div className="w-7 h-7 flex items-center justify-center">
|
<div className="flex h-7 w-7 items-center justify-center">
|
||||||
<div
|
<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" : ""
|
showHexInput ? "tags-conic-bg rounded-full" : ""
|
||||||
}`}
|
}`}
|
||||||
onClick={() => setShowHexInput((prev) => !prev)}
|
onClick={() => setShowHexInput((prev) => !prev)}
|
||||||
|
|||||||
@@ -1,12 +1,6 @@
|
|||||||
const ENV = process.env.NEXT_PUBLIC_ENV! || "development"; // investigate
|
const ENV = process.env.NEXT_PUBLIC_ENV! || "development"; // investigate
|
||||||
const POSTHOG_API_KEY = process.env.NEXT_PUBLIC_POSTHOG_API_KEY!;
|
const POSTHOG_API_KEY = process.env.NEXT_PUBLIC_POSTHOG_API_KEY!;
|
||||||
const POSTHOG_HOST =
|
const POSTHOG_HOST = process.env.NEXT_PUBLIC_POSTHOG_HOST! || "https://app.posthog.com";
|
||||||
process.env.NEXT_PUBLIC_POSTHOG_HOST! || "https://app.posthog.com";
|
|
||||||
const INTERCOMid = process.env.NEXT_PUBLIC_INTERCOMid!;
|
const INTERCOMid = process.env.NEXT_PUBLIC_INTERCOMid!;
|
||||||
|
|
||||||
export {
|
export { ENV, INTERCOMid, POSTHOG_API_KEY, POSTHOG_HOST };
|
||||||
ENV,
|
|
||||||
INTERCOMid,
|
|
||||||
POSTHOG_API_KEY,
|
|
||||||
POSTHOG_HOST
|
|
||||||
};
|
|
||||||
|
|||||||
@@ -54,11 +54,9 @@ export const load = () => {
|
|||||||
|
|
||||||
// Initializes Intercom
|
// Initializes Intercom
|
||||||
export const boot = (options = {}) => {
|
export const boot = (options = {}) => {
|
||||||
window &&
|
window && window.Intercom && window.Intercom("boot", { appid: APPid, ...options });
|
||||||
window.Intercom &&
|
|
||||||
window.Intercom("boot", { appid: APPid, ...options });
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export const update = () => {
|
export const update = () => {
|
||||||
window && window.Intercom && window.Intercom("update");
|
window && window.Intercom && window.Intercom("update");
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ export const OrgPermissionProvider = ({ children }: Props): JSX.Element => {
|
|||||||
|
|
||||||
if (isLoading) {
|
if (isLoading) {
|
||||||
return (
|
return (
|
||||||
<div className="flex items-center justify-center w-screen h-screen bg-bunker-800">
|
<div className="flex h-screen w-screen items-center justify-center bg-bunker-800">
|
||||||
<img
|
<img
|
||||||
src="/images/loading/loading.gif"
|
src="/images/loading/loading.gif"
|
||||||
height={70}
|
height={70}
|
||||||
@@ -35,7 +35,7 @@ export const OrgPermissionProvider = ({ children }: Props): JSX.Element => {
|
|||||||
|
|
||||||
if (!permission) {
|
if (!permission) {
|
||||||
return (
|
return (
|
||||||
<div className="flex items-center justify-center w-screen h-screen bg-bunker-800">
|
<div className="flex h-screen w-screen items-center justify-center bg-bunker-800">
|
||||||
Failed to load user permissions
|
Failed to load user permissions
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ import { createContext, ReactNode, useContext, useMemo } from "react";
|
|||||||
import { useGetOrganizations } from "@app/hooks/api";
|
import { useGetOrganizations } from "@app/hooks/api";
|
||||||
import { Organization } from "@app/hooks/api/types";
|
import { Organization } from "@app/hooks/api/types";
|
||||||
|
|
||||||
|
|
||||||
type TOrgContext = {
|
type TOrgContext = {
|
||||||
orgs?: Organization[];
|
orgs?: Organization[];
|
||||||
currentOrg?: Organization;
|
currentOrg?: Organization;
|
||||||
@@ -18,7 +17,7 @@ type Props = {
|
|||||||
|
|
||||||
export const OrgProvider = ({ children }: Props): JSX.Element => {
|
export const OrgProvider = ({ children }: Props): JSX.Element => {
|
||||||
const { data: userOrgs, isLoading } = useGetOrganizations();
|
const { data: userOrgs, isLoading } = useGetOrganizations();
|
||||||
|
|
||||||
// const currentWsOrgID = currentWorkspace?.organization;
|
// const currentWsOrgID = currentWorkspace?.organization;
|
||||||
const currentWsOrgID = localStorage.getItem("orgData.id");
|
const currentWsOrgID = localStorage.getItem("orgData.id");
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ export const ProjectPermissionProvider = ({ children }: Props): JSX.Element => {
|
|||||||
|
|
||||||
if ((isLoading && currentWorkspace) || isWsLoading) {
|
if ((isLoading && currentWorkspace) || isWsLoading) {
|
||||||
return (
|
return (
|
||||||
<div className="flex items-center justify-center w-screen h-screen bg-bunker-800">
|
<div className="flex h-screen w-screen items-center justify-center bg-bunker-800">
|
||||||
<img
|
<img
|
||||||
src="/images/loading/loading.gif"
|
src="/images/loading/loading.gif"
|
||||||
height={70}
|
height={70}
|
||||||
@@ -31,7 +31,7 @@ export const ProjectPermissionProvider = ({ children }: Props): JSX.Element => {
|
|||||||
|
|
||||||
if (!permission && currentWorkspace) {
|
if (!permission && currentWorkspace) {
|
||||||
return (
|
return (
|
||||||
<div className="flex items-center justify-center w-screen h-screen bg-bunker-800">
|
<div className="flex h-screen w-screen items-center justify-center bg-bunker-800">
|
||||||
Failed to load user permissions
|
Failed to load user permissions
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -72,9 +72,9 @@ export const ServerConfigProvider = ({ children }: Props): JSX.Element => {
|
|||||||
|
|
||||||
export const useServerConfig = () => {
|
export const useServerConfig = () => {
|
||||||
const ctx = useContext(ServerConfigContext);
|
const ctx = useContext(ServerConfigContext);
|
||||||
// if (!ctx) {
|
if (!ctx) {
|
||||||
// throw new Error("useServerConfig has to be used within <UserContext.Provider>");
|
throw new Error("useServerConfig has to be used within <UserContext.Provider>");
|
||||||
// }
|
}
|
||||||
|
|
||||||
return ctx || { config: { allowSignUp: true } };
|
return ctx;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import { createContext, ReactNode, useContext, useMemo } from "react";
|
import { createContext, ReactNode, useContext, useMemo } from "react";
|
||||||
|
|
||||||
import { useGetUser } from "@app/hooks/api";
|
import { useGetUser } from "@app/hooks/api";
|
||||||
import { User } from "@app/hooks/api/types";
|
import { User, UserEnc } from "@app/hooks/api/types";
|
||||||
|
|
||||||
type TUserContext = {
|
type TUserContext = {
|
||||||
user: User;
|
user: User & UserEnc;
|
||||||
isLoading: boolean;
|
isLoading: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ export const WorkspaceProvider = ({ children }: Props): JSX.Element => {
|
|||||||
const wsId = workspaceId || localStorage.getItem("projectData.id");
|
const wsId = workspaceId || localStorage.getItem("projectData.id");
|
||||||
return {
|
return {
|
||||||
workspaces: ws || [],
|
workspaces: ws || [],
|
||||||
currentWorkspace: (ws || []).find(({ id: id }) => id === wsId),
|
currentWorkspace: (ws || []).find(({ id }) => id === wsId),
|
||||||
isLoading
|
isLoading
|
||||||
};
|
};
|
||||||
}, [ws, workspaceId, isLoading]);
|
}, [ws, workspaceId, isLoading]);
|
||||||
|
|||||||
@@ -112,8 +112,8 @@ const initProjectHelper = async ({
|
|||||||
});
|
});
|
||||||
|
|
||||||
await uploadWsKey({
|
await uploadWsKey({
|
||||||
workspaceId: workspace._id,
|
workspaceId: workspace.id,
|
||||||
userId: user._id,
|
userId: user.id,
|
||||||
encryptedKey: ciphertext,
|
encryptedKey: ciphertext,
|
||||||
nonce
|
nonce
|
||||||
});
|
});
|
||||||
@@ -121,13 +121,13 @@ const initProjectHelper = async ({
|
|||||||
// encrypt and upload secrets to new project
|
// encrypt and upload secrets to new project
|
||||||
const secrets = await encryptSecrets({
|
const secrets = await encryptSecrets({
|
||||||
secretsToEncrypt: secretsToBeAdded,
|
secretsToEncrypt: secretsToBeAdded,
|
||||||
workspaceId: workspace._id,
|
workspaceId: workspace.id,
|
||||||
env: "dev"
|
env: "dev"
|
||||||
});
|
});
|
||||||
|
|
||||||
secrets?.forEach((secret) => {
|
secrets?.forEach((secret) => {
|
||||||
createSecret({
|
createSecret({
|
||||||
workspaceId: workspace._id,
|
workspaceId: workspace.id,
|
||||||
environment: secret.environment,
|
environment: secret.environment,
|
||||||
type: secret.type,
|
type: secret.type,
|
||||||
secretKey: secret.secretName,
|
secretKey: secret.secretName,
|
||||||
|
|||||||
@@ -1,27 +1,27 @@
|
|||||||
export type APIKeyDataV2 = {
|
export type APIKeyDataV2 = {
|
||||||
id: string;
|
id: string;
|
||||||
name: string;
|
name: string;
|
||||||
user: string;
|
user: string;
|
||||||
lastUsed?: string;
|
lastUsed?: string;
|
||||||
usageCount: number;
|
usageCount: number;
|
||||||
createdAt: string;
|
createdAt: string;
|
||||||
updatedAt: string;
|
updatedAt: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type CreateAPIKeyDataV2DTO = {
|
export type CreateAPIKeyDataV2DTO = {
|
||||||
name: string;
|
name: string;
|
||||||
}
|
};
|
||||||
|
|
||||||
export type CreateServiceTokenDataV3Res = {
|
export type CreateServiceTokenDataV3Res = {
|
||||||
apiKeyData: APIKeyDataV2;
|
apiKeyData: APIKeyDataV2;
|
||||||
apiKey: string;
|
apiKey: string;
|
||||||
}
|
};
|
||||||
|
|
||||||
export type UpdateAPIKeyDataV2DTO = {
|
export type UpdateAPIKeyDataV2DTO = {
|
||||||
apiKeyDataId: string;
|
apiKeyDataId: string;
|
||||||
name: string;
|
name: string;
|
||||||
}
|
};
|
||||||
|
|
||||||
export type DeleteAPIKeyDataV2DTO = {
|
export type DeleteAPIKeyDataV2DTO = {
|
||||||
apiKeyDataId: string;
|
apiKeyDataId: string;
|
||||||
}
|
};
|
||||||
|
|||||||
@@ -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;
|
type: EventType.CREATE_IDENTITY;
|
||||||
metadata: {
|
metadata: {
|
||||||
identityId: string;
|
identityId: string;
|
||||||
@@ -218,7 +219,7 @@ interface DeleteIdentityEvent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface LoginIdentityUniversalAuthEvent {
|
interface LoginIdentityUniversalAuthEvent {
|
||||||
type: EventType.LOGIN_IDENTITY_UNIVERSAL_AUTH ;
|
type: EventType.LOGIN_IDENTITY_UNIVERSAL_AUTH;
|
||||||
metadata: {
|
metadata: {
|
||||||
identityId: string;
|
identityId: string;
|
||||||
identityUniversalAuthId: string;
|
identityUniversalAuthId: string;
|
||||||
@@ -259,7 +260,7 @@ interface GetIdentityUniversalAuthEvent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface CreateIdentityUniversalAuthClientSecretEvent {
|
interface CreateIdentityUniversalAuthClientSecretEvent {
|
||||||
type: EventType.CREATE_IDENTITY_UNIVERSAL_AUTH_CLIENT_SECRET ;
|
type: EventType.CREATE_IDENTITY_UNIVERSAL_AUTH_CLIENT_SECRET;
|
||||||
metadata: {
|
metadata: {
|
||||||
identityId: string;
|
identityId: string;
|
||||||
clientSecretId: string;
|
clientSecretId: string;
|
||||||
@@ -273,9 +274,8 @@ interface GetIdentityUniversalAuthClientSecretsEvent {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
interface RevokeIdentityUniversalAuthClientSecretEvent {
|
interface RevokeIdentityUniversalAuthClientSecretEvent {
|
||||||
type: EventType.REVOKE_IDENTITY_UNIVERSAL_AUTH_CLIENT_SECRET ;
|
type: EventType.REVOKE_IDENTITY_UNIVERSAL_AUTH_CLIENT_SECRET;
|
||||||
metadata: {
|
metadata: {
|
||||||
identityId: string;
|
identityId: string;
|
||||||
clientSecretId: string;
|
clientSecretId: string;
|
||||||
@@ -507,7 +507,7 @@ export type Event =
|
|||||||
| UpdateUserDeniedPermissions;
|
| UpdateUserDeniedPermissions;
|
||||||
|
|
||||||
export type AuditLog = {
|
export type AuditLog = {
|
||||||
_id: string;
|
id: string;
|
||||||
actor: Actor;
|
actor: Actor;
|
||||||
organization: string;
|
organization: string;
|
||||||
workspace: string;
|
workspace: string;
|
||||||
|
|||||||
@@ -55,14 +55,14 @@ export type BitBucketWorkspace = {
|
|||||||
uuid: string;
|
uuid: string;
|
||||||
name: string;
|
name: string;
|
||||||
slug: string;
|
slug: string;
|
||||||
}
|
};
|
||||||
|
|
||||||
export type NorthflankSecretGroup = {
|
export type NorthflankSecretGroup = {
|
||||||
name: string;
|
name: string;
|
||||||
groupId: string;
|
groupId: string;
|
||||||
}
|
};
|
||||||
|
|
||||||
export type TeamCityBuildConfig = {
|
export type TeamCityBuildConfig = {
|
||||||
name: string;
|
name: string;
|
||||||
buildConfigId: string;
|
buildConfigId: string;
|
||||||
}
|
};
|
||||||
|
|||||||
@@ -32,9 +32,9 @@ export type TIntegration = {
|
|||||||
__v: number;
|
__v: number;
|
||||||
metadata?: {
|
metadata?: {
|
||||||
secretSuffix?: string;
|
secretSuffix?: string;
|
||||||
scope: string;
|
scope: string;
|
||||||
org: string;
|
org: string;
|
||||||
project: string;
|
project: string;
|
||||||
environment: string;
|
environment: string;
|
||||||
}
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ export type RenameOrgDTO = {
|
|||||||
export type BillingDetails = {
|
export type BillingDetails = {
|
||||||
name: string;
|
name: string;
|
||||||
email: string;
|
email: string;
|
||||||
}
|
};
|
||||||
|
|
||||||
export type PlanBillingInfo = {
|
export type PlanBillingInfo = {
|
||||||
amount: number;
|
amount: number;
|
||||||
@@ -22,7 +22,7 @@ export type PlanBillingInfo = {
|
|||||||
interval: "month" | "year";
|
interval: "month" | "year";
|
||||||
intervalCount: number;
|
intervalCount: number;
|
||||||
quantity: number;
|
quantity: number;
|
||||||
}
|
};
|
||||||
|
|
||||||
export type Invoice = {
|
export type Invoice = {
|
||||||
id: string;
|
id: string;
|
||||||
@@ -31,23 +31,23 @@ export type Invoice = {
|
|||||||
number: string;
|
number: string;
|
||||||
paid: boolean;
|
paid: boolean;
|
||||||
total: number;
|
total: number;
|
||||||
}
|
};
|
||||||
|
|
||||||
export type PmtMethod = {
|
export type PmtMethod = {
|
||||||
id: string;
|
id: string;
|
||||||
brand: string;
|
brand: string;
|
||||||
exp_month: number;
|
exp_month: number;
|
||||||
exp_year: number;
|
exp_year: number;
|
||||||
funding: string;
|
funding: string;
|
||||||
last4: string;
|
last4: string;
|
||||||
}
|
};
|
||||||
|
|
||||||
export type TaxID = {
|
export type TaxID = {
|
||||||
id: string;
|
id: string;
|
||||||
country: string;
|
country: string;
|
||||||
type: string;
|
type: string;
|
||||||
value: string;
|
value: string;
|
||||||
}
|
};
|
||||||
|
|
||||||
export type License = {
|
export type License = {
|
||||||
id: string;
|
id: string;
|
||||||
@@ -58,22 +58,22 @@ export type License = {
|
|||||||
expiresAt: string;
|
expiresAt: string;
|
||||||
createdAt: string;
|
createdAt: string;
|
||||||
updatedAt: string;
|
updatedAt: string;
|
||||||
}
|
};
|
||||||
|
|
||||||
export type OrgPlanTableHead = {
|
export type OrgPlanTableHead = {
|
||||||
name: string;
|
name: string;
|
||||||
}
|
};
|
||||||
|
|
||||||
export type OrgPlanTableRow = {
|
export type OrgPlanTableRow = {
|
||||||
name: string;
|
name: string;
|
||||||
allowed: number | boolean | null;
|
allowed: number | boolean | null;
|
||||||
used: string;
|
used: string;
|
||||||
}
|
};
|
||||||
|
|
||||||
export type OrgPlanTable = {
|
export type OrgPlanTable = {
|
||||||
head: OrgPlanTableHead[];
|
head: OrgPlanTableHead[];
|
||||||
rows: OrgPlanTableRow[];
|
rows: OrgPlanTableRow[];
|
||||||
}
|
};
|
||||||
|
|
||||||
export type ProductsTableHead = {
|
export type ProductsTableHead = {
|
||||||
name: string;
|
name: string;
|
||||||
@@ -82,7 +82,7 @@ export type ProductsTableHead = {
|
|||||||
productId: string;
|
productId: string;
|
||||||
slug: string;
|
slug: string;
|
||||||
tier: number;
|
tier: number;
|
||||||
}
|
};
|
||||||
|
|
||||||
export type ProductsTableRow = {
|
export type ProductsTableRow = {
|
||||||
name: string;
|
name: string;
|
||||||
@@ -90,9 +90,9 @@ export type ProductsTableRow = {
|
|||||||
team: number | boolean | null;
|
team: number | boolean | null;
|
||||||
pro: number | boolean | null;
|
pro: number | boolean | null;
|
||||||
enterprise: number | boolean | null;
|
enterprise: number | boolean | null;
|
||||||
}
|
};
|
||||||
|
|
||||||
export type ProductsTable = {
|
export type ProductsTable = {
|
||||||
head: ProductsTableHead[];
|
head: ProductsTableHead[];
|
||||||
rows: ProductsTableRow[];
|
rows: ProductsTableRow[];
|
||||||
}
|
};
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ export type ServiceTokenScope = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export type ServiceToken = {
|
export type ServiceToken = {
|
||||||
_id: string;
|
id: string;
|
||||||
name: string;
|
name: string;
|
||||||
workspace: string;
|
workspace: string;
|
||||||
scopes: ServiceTokenScope[];
|
scopes: ServiceTokenScope[];
|
||||||
@@ -32,4 +32,4 @@ export type CreateServiceTokenRes = {
|
|||||||
serviceTokenData: ServiceToken;
|
serviceTokenData: ServiceToken;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type DeleteServiceTokenRes = { serviceTokenData: ServiceToken };
|
export type DeleteServiceTokenRes = { serviceTokenData: ServiceToken };
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ export type WsTag = {
|
|||||||
createdAt: string;
|
createdAt: string;
|
||||||
updatedAt: string;
|
updatedAt: string;
|
||||||
__v: number;
|
__v: number;
|
||||||
}
|
};
|
||||||
|
|
||||||
export type WorkspaceTag = { id: string; name: string; slug: string };
|
export type WorkspaceTag = { id: string; name: string; slug: string };
|
||||||
|
|
||||||
@@ -30,7 +30,7 @@ export type CreateTagRes = {
|
|||||||
id: string;
|
id: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type DeleteTagDTO = { tagID: string; };
|
export type DeleteTagDTO = { tagID: string };
|
||||||
|
|
||||||
export type DeleteWsTagRes = {
|
export type DeleteWsTagRes = {
|
||||||
name: string;
|
name: string;
|
||||||
@@ -41,17 +41,16 @@ export type DeleteWsTagRes = {
|
|||||||
id: string;
|
id: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type SecretTags = {
|
export type SecretTags = {
|
||||||
id: string;
|
|
||||||
id: string;
|
id: string;
|
||||||
slug: string;
|
slug: string;
|
||||||
tagColor: string;
|
tagColor: string;
|
||||||
}
|
};
|
||||||
|
|
||||||
export type TagColor = {
|
export type TagColor = {
|
||||||
id: number;
|
id: number;
|
||||||
hex: string
|
hex: string;
|
||||||
rgba: string
|
rgba: string;
|
||||||
name: string
|
name: string;
|
||||||
selected: boolean
|
selected: boolean;
|
||||||
}
|
};
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
export type TrustedIp = {
|
export type TrustedIp = {
|
||||||
id: string;
|
id: string;
|
||||||
workspace: string;
|
workspace: string;
|
||||||
ipAddress: string;
|
ipAddress: string;
|
||||||
type: "ipv4" | "ipv6";
|
type: "ipv4" | "ipv6";
|
||||||
isActive: boolean;
|
isActive: boolean;
|
||||||
comment: string;
|
comment: string;
|
||||||
prefix?: number;
|
prefix?: number;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ export * from "./secrets/types";
|
|||||||
export type { CreateServiceTokenDTO, ServiceToken } from "./serviceTokens/types";
|
export type { CreateServiceTokenDTO, ServiceToken } from "./serviceTokens/types";
|
||||||
export type { SubscriptionPlan } from "./subscriptions/types";
|
export type { SubscriptionPlan } from "./subscriptions/types";
|
||||||
export type { WsTag } from "./tags/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 { TWebhook } from "./webhooks/types";
|
||||||
export type {
|
export type {
|
||||||
CreateEnvironmentDTO,
|
CreateEnvironmentDTO,
|
||||||
|
|||||||
@@ -14,7 +14,8 @@ import {
|
|||||||
RenameUserDTO,
|
RenameUserDTO,
|
||||||
TokenVersion,
|
TokenVersion,
|
||||||
UpdateOrgUserRoleDTO,
|
UpdateOrgUserRoleDTO,
|
||||||
User
|
User,
|
||||||
|
UserEnc
|
||||||
} from "./types";
|
} from "./types";
|
||||||
|
|
||||||
export const userKeys = {
|
export const userKeys = {
|
||||||
@@ -29,7 +30,7 @@ export const userKeys = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const fetchUserDetails = async () => {
|
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;
|
return data.user;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -19,6 +19,12 @@ export type User = {
|
|||||||
lastName?: string;
|
lastName?: string;
|
||||||
authProvider?: AuthMethod;
|
authProvider?: AuthMethod;
|
||||||
authMethods: AuthMethod[];
|
authMethods: AuthMethod[];
|
||||||
|
isMfaEnabled: boolean;
|
||||||
|
seenIps: string[];
|
||||||
|
id: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type UserEnc = {
|
||||||
encryptionVersion?: number;
|
encryptionVersion?: number;
|
||||||
protectedKey?: string;
|
protectedKey?: string;
|
||||||
protectedKeyIV?: string;
|
protectedKeyIV?: string;
|
||||||
@@ -27,19 +33,15 @@ export type User = {
|
|||||||
encryptedPrivateKey?: string;
|
encryptedPrivateKey?: string;
|
||||||
iv?: string;
|
iv?: string;
|
||||||
tag?: string;
|
tag?: string;
|
||||||
isMfaEnabled: boolean;
|
|
||||||
seenIps: string[];
|
|
||||||
_id: string;
|
|
||||||
__v: number;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export type OrgUser = {
|
export type OrgUser = {
|
||||||
_id: string;
|
id: string;
|
||||||
user: {
|
user: {
|
||||||
email: string;
|
email: string;
|
||||||
firstName: string;
|
firstName: string;
|
||||||
lastName: string;
|
lastName: string;
|
||||||
_id: string;
|
id: string;
|
||||||
publicKey: string;
|
publicKey: string;
|
||||||
};
|
};
|
||||||
inviteEmail: string;
|
inviteEmail: string;
|
||||||
@@ -88,7 +90,7 @@ export type RenameUserDTO = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export type APIKeyData = {
|
export type APIKeyData = {
|
||||||
_id: string;
|
id: string;
|
||||||
name: string;
|
name: string;
|
||||||
user: string;
|
user: string;
|
||||||
lastUsed: string;
|
lastUsed: string;
|
||||||
@@ -97,7 +99,7 @@ export type APIKeyData = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export type TokenVersion = {
|
export type TokenVersion = {
|
||||||
_id: string;
|
id: string;
|
||||||
user: string;
|
user: string;
|
||||||
userAgent: string;
|
userAgent: string;
|
||||||
ip: string;
|
ip: string;
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ export type NameWorkspaceSecretsDTO = {
|
|||||||
secretName: string;
|
secretName: string;
|
||||||
id: string;
|
id: string;
|
||||||
}[];
|
}[];
|
||||||
}
|
};
|
||||||
|
|
||||||
// mutation dto
|
// mutation dto
|
||||||
export type CreateWorkspaceDTO = {
|
export type CreateWorkspaceDTO = {
|
||||||
@@ -47,7 +47,6 @@ export type ReorderEnvironmentsDTO = {
|
|||||||
environmentName: string;
|
environmentName: string;
|
||||||
otherEnvironmentSlug: string;
|
otherEnvironmentSlug: string;
|
||||||
otherEnvironmentName: string;
|
otherEnvironmentName: string;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export type UpdateEnvironmentDTO = {
|
export type UpdateEnvironmentDTO = {
|
||||||
@@ -57,4 +56,4 @@ export type UpdateEnvironmentDTO = {
|
|||||||
environmentName: string;
|
environmentName: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type DeleteEnvironmentDTO = { workspaceID: string; environmentSlug: string };
|
export type DeleteEnvironmentDTO = { workspaceID: string; environmentSlug: string };
|
||||||
|
|||||||
@@ -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]">
|
<nav className="items-between flex h-full flex-col justify-between overflow-y-auto dark:[color-scheme:dark]">
|
||||||
<div>
|
<div>
|
||||||
{!router.asPath.includes("personal") && (
|
{!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`}>
|
<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">
|
<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" />
|
<FontAwesomeIcon icon={faArrowLeft} className="pr-3" />
|
||||||
@@ -179,7 +179,7 @@ export const AdminLayout = ({ children }: LayoutProps) => {
|
|||||||
<div
|
<div
|
||||||
className={`${
|
className={`${
|
||||||
!updateClosed ? "block" : "hidden"
|
!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">
|
<div className="text-md mt-2 w-full font-semibold text-mineshaft-100">
|
||||||
Infisical December update
|
Infisical December update
|
||||||
|
|||||||
@@ -120,7 +120,7 @@ export const AppLayout = ({ children }: LayoutProps) => {
|
|||||||
|
|
||||||
const { user } = useUser();
|
const { user } = useUser();
|
||||||
const { subscription } = useSubscription();
|
const { subscription } = useSubscription();
|
||||||
const workspaceId = currentWorkspace?._id || "";
|
const workspaceId = currentWorkspace?.id || "";
|
||||||
const { data: updateClosed } = useGetUserAction("december_update_closed");
|
const { data: updateClosed } = useGetUserAction("december_update_closed");
|
||||||
|
|
||||||
const { data: secretApprovalReqCount } = useGetSecretApprovalRequestCount({ workspaceId });
|
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
|
// Put a user in an org if they're not in one yet
|
||||||
const putUserInOrg = async () => {
|
const putUserInOrg = async () => {
|
||||||
if (tempLocalStorage("orgData.id") === "") {
|
if (tempLocalStorage("orgData.id") === "") {
|
||||||
localStorage.setItem("orgData.id", orgs[0]?._id);
|
localStorage.setItem("orgData.id", orgs[0]?.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
currentOrg &&
|
currentOrg &&
|
||||||
((workspaces?.length === 0 && router.asPath.includes("project")) ||
|
((workspaces?.length === 0 && router.asPath.includes("project")) ||
|
||||||
router.asPath.includes("/project/undefined") ||
|
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("project") &&
|
||||||
!router.asPath.includes("personal") &&
|
!router.asPath.includes("personal") &&
|
||||||
!router.asPath.includes("integration")))
|
!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")) {
|
// 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) => {
|
const onCreateProject = async ({ name, addMembers }: TAddProjectFormData) => {
|
||||||
// type check
|
// type check
|
||||||
if (!currentOrg?._id) return;
|
if (!currentOrg?.id) return;
|
||||||
try {
|
try {
|
||||||
const {
|
const {
|
||||||
data: {
|
data: {
|
||||||
workspace: { _id: newWorkspaceId }
|
workspace: { id: newWorkspaceId }
|
||||||
}
|
}
|
||||||
} = await createWs.mutateAsync({
|
} = await createWs.mutateAsync({
|
||||||
organizationId: currentOrg?._id,
|
organizationId: currentOrg?.id,
|
||||||
workspaceName: name
|
workspaceName: name
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -243,13 +243,13 @@ export const AppLayout = ({ children }: LayoutProps) => {
|
|||||||
await uploadWsKey.mutateAsync({
|
await uploadWsKey.mutateAsync({
|
||||||
encryptedKey: ciphertext,
|
encryptedKey: ciphertext,
|
||||||
nonce,
|
nonce,
|
||||||
userId: user?._id,
|
userId: user?.id,
|
||||||
workspaceId: newWorkspaceId
|
workspaceId: newWorkspaceId
|
||||||
});
|
});
|
||||||
|
|
||||||
if (addMembers) {
|
if (addMembers) {
|
||||||
// not using hooks because need at this point only
|
// 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);
|
const decryptKey = await fetchUserWsKey(newWorkspaceId);
|
||||||
await addWsUser.mutateAsync({
|
await addWsUser.mutateAsync({
|
||||||
workspaceId: newWorkspaceId,
|
workspaceId: newWorkspaceId,
|
||||||
@@ -259,7 +259,7 @@ export const AppLayout = ({ children }: LayoutProps) => {
|
|||||||
.filter(
|
.filter(
|
||||||
({ status, user: orgUser }) => status === "accepted" && user.email !== orgUser.email
|
({ status, user: orgUser }) => status === "accepted" && user.email !== orgUser.email
|
||||||
)
|
)
|
||||||
.map(({ user: orgUser, _id: orgMembershipId }) => ({
|
.map(({ user: orgUser, id: orgMembershipId }) => ({
|
||||||
userPublicKey: orgUser.publicKey,
|
userPublicKey: orgUser.publicKey,
|
||||||
orgMembershipId
|
orgMembershipId
|
||||||
}))
|
}))
|
||||||
@@ -285,7 +285,7 @@ export const AppLayout = ({ children }: LayoutProps) => {
|
|||||||
<div className="flex h-12 cursor-default items-center px-3 pt-6">
|
<div className="flex h-12 cursor-default items-center px-3 pt-6">
|
||||||
{(router.asPath.includes("project") ||
|
{(router.asPath.includes("project") ||
|
||||||
router.asPath.includes("integrations")) && (
|
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">
|
<div className="pl-1 pr-2 text-mineshaft-400 duration-200 hover:text-mineshaft-100">
|
||||||
<FontAwesomeIcon icon={faArrowLeft} />
|
<FontAwesomeIcon icon={faArrowLeft} />
|
||||||
</div>
|
</div>
|
||||||
@@ -298,7 +298,7 @@ export const AppLayout = ({ children }: LayoutProps) => {
|
|||||||
{currentOrg?.name.charAt(0)}
|
{currentOrg?.name.charAt(0)}
|
||||||
</div>
|
</div>
|
||||||
<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" }}
|
style={{ maxWidth: "140px" }}
|
||||||
>
|
>
|
||||||
{currentOrg?.name}
|
{currentOrg?.name}
|
||||||
@@ -312,15 +312,15 @@ export const AppLayout = ({ children }: LayoutProps) => {
|
|||||||
<DropdownMenuContent align="start" className="p-1">
|
<DropdownMenuContent align="start" className="p-1">
|
||||||
<div className="px-2 py-1 text-xs text-mineshaft-400">{user?.email}</div>
|
<div className="px-2 py-1 text-xs text-mineshaft-400">{user?.email}</div>
|
||||||
{orgs?.map((org) => (
|
{orgs?.map((org) => (
|
||||||
<DropdownMenuItem key={org._id}>
|
<DropdownMenuItem key={org.id}>
|
||||||
<Button
|
<Button
|
||||||
onClick={() => changeOrg(org?._id)}
|
onClick={() => changeOrg(org?.id)}
|
||||||
variant="plain"
|
variant="plain"
|
||||||
colorSchema="secondary"
|
colorSchema="secondary"
|
||||||
size="xs"
|
size="xs"
|
||||||
className="flex w-full items-center justify-start p-0 font-normal"
|
className="flex w-full items-center justify-start p-0 font-normal"
|
||||||
leftIcon={
|
leftIcon={
|
||||||
currentOrg._id === org._id && (
|
currentOrg.id === org.id && (
|
||||||
<FontAwesomeIcon icon={faCheck} className="mr-3 text-primary" />
|
<FontAwesomeIcon icon={faCheck} className="mr-3 text-primary" />
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -421,8 +421,8 @@ export const AppLayout = ({ children }: LayoutProps) => {
|
|||||||
Project
|
Project
|
||||||
</p>
|
</p>
|
||||||
<Select
|
<Select
|
||||||
defaultValue={currentWorkspace?._id}
|
defaultValue={currentWorkspace?.id}
|
||||||
value={currentWorkspace?._id}
|
value={currentWorkspace?.id}
|
||||||
className="w-full truncate bg-mineshaft-600 py-2.5 font-medium"
|
className="w-full truncate bg-mineshaft-600 py-2.5 font-medium"
|
||||||
onValueChange={(value) => {
|
onValueChange={(value) => {
|
||||||
router.push(`/project/${value}/secrets/overview`);
|
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">
|
<div className="no-scrollbar::-webkit-scrollbar h-full no-scrollbar">
|
||||||
{workspaces
|
{workspaces
|
||||||
.filter((ws) => ws.organization === currentOrg?._id)
|
.filter((ws) => ws.organization === currentOrg?.id)
|
||||||
.map(({ _id, name }) => (
|
.map(({ id, name }) => (
|
||||||
<SelectItem
|
<SelectItem
|
||||||
key={`ws-layout-list-${_id}`}
|
key={`ws-layout-list-${id}`}
|
||||||
value={_id}
|
value={id}
|
||||||
className={`${currentWorkspace?._id === _id && "bg-mineshaft-600"}`}
|
className={`${currentWorkspace?.id === id && "bg-mineshaft-600"}`}
|
||||||
>
|
>
|
||||||
{name}
|
{name}
|
||||||
</SelectItem>
|
</SelectItem>
|
||||||
@@ -474,7 +474,7 @@ export const AppLayout = ({ children }: LayoutProps) => {
|
|||||||
</Select>
|
</Select>
|
||||||
</div>
|
</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">
|
<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" />
|
<FontAwesomeIcon icon={faArrowLeft} className="pr-3" />
|
||||||
Back to organization
|
Back to organization
|
||||||
@@ -485,11 +485,11 @@ export const AppLayout = ({ children }: LayoutProps) => {
|
|||||||
{(router.asPath.includes("project") || router.asPath.includes("integrations")) &&
|
{(router.asPath.includes("project") || router.asPath.includes("integrations")) &&
|
||||||
currentWorkspace ? (
|
currentWorkspace ? (
|
||||||
<Menu>
|
<Menu>
|
||||||
<Link href={`/project/${currentWorkspace?._id}/secrets/overview`} passHref>
|
<Link href={`/project/${currentWorkspace?.id}/secrets/overview`} passHref>
|
||||||
<a>
|
<a>
|
||||||
<MenuItem
|
<MenuItem
|
||||||
isSelected={router.asPath.includes(
|
isSelected={router.asPath.includes(
|
||||||
`/project/${currentWorkspace?._id}/secrets`
|
`/project/${currentWorkspace?.id}/secrets`
|
||||||
)}
|
)}
|
||||||
icon="system-outline-90-lock-closed"
|
icon="system-outline-90-lock-closed"
|
||||||
>
|
>
|
||||||
@@ -497,11 +497,11 @@ export const AppLayout = ({ children }: LayoutProps) => {
|
|||||||
</MenuItem>
|
</MenuItem>
|
||||||
</a>
|
</a>
|
||||||
</Link>
|
</Link>
|
||||||
<Link href={`/project/${currentWorkspace?._id}/members`} passHref>
|
<Link href={`/project/${currentWorkspace?.id}/members`} passHref>
|
||||||
<a>
|
<a>
|
||||||
<MenuItem
|
<MenuItem
|
||||||
isSelected={
|
isSelected={
|
||||||
router.asPath === `/project/${currentWorkspace?._id}/members`
|
router.asPath === `/project/${currentWorkspace?.id}/members`
|
||||||
}
|
}
|
||||||
icon="system-outline-96-groups"
|
icon="system-outline-96-groups"
|
||||||
>
|
>
|
||||||
@@ -509,7 +509,7 @@ export const AppLayout = ({ children }: LayoutProps) => {
|
|||||||
</MenuItem>
|
</MenuItem>
|
||||||
</a>
|
</a>
|
||||||
</Link>
|
</Link>
|
||||||
<Link href={`/integrations/${currentWorkspace?._id}`} passHref>
|
<Link href={`/integrations/${currentWorkspace?.id}`} passHref>
|
||||||
<a>
|
<a>
|
||||||
<MenuItem
|
<MenuItem
|
||||||
isSelected={router.asPath.includes("/integrations")}
|
isSelected={router.asPath.includes("/integrations")}
|
||||||
@@ -519,11 +519,11 @@ export const AppLayout = ({ children }: LayoutProps) => {
|
|||||||
</MenuItem>
|
</MenuItem>
|
||||||
</a>
|
</a>
|
||||||
</Link>
|
</Link>
|
||||||
<Link href={`/project/${currentWorkspace?._id}/secret-rotation`} passHref>
|
<Link href={`/project/${currentWorkspace?.id}/secret-rotation`} passHref>
|
||||||
<a className="relative">
|
<a className="relative">
|
||||||
<MenuItem
|
<MenuItem
|
||||||
isSelected={
|
isSelected={
|
||||||
router.asPath === `/project/${currentWorkspace?._id}/secret-rotation`
|
router.asPath === `/project/${currentWorkspace?.id}/secret-rotation`
|
||||||
}
|
}
|
||||||
icon="rotation"
|
icon="rotation"
|
||||||
>
|
>
|
||||||
@@ -531,11 +531,11 @@ export const AppLayout = ({ children }: LayoutProps) => {
|
|||||||
</MenuItem>
|
</MenuItem>
|
||||||
</a>
|
</a>
|
||||||
</Link>
|
</Link>
|
||||||
<Link href={`/project/${currentWorkspace?._id}/approval`} passHref>
|
<Link href={`/project/${currentWorkspace?.id}/approval`} passHref>
|
||||||
<a className="relative">
|
<a className="relative">
|
||||||
<MenuItem
|
<MenuItem
|
||||||
isSelected={
|
isSelected={
|
||||||
router.asPath === `/project/${currentWorkspace?._id}/approval`
|
router.asPath === `/project/${currentWorkspace?.id}/approval`
|
||||||
}
|
}
|
||||||
icon="system-outline-189-domain-verification"
|
icon="system-outline-189-domain-verification"
|
||||||
>
|
>
|
||||||
@@ -548,11 +548,11 @@ export const AppLayout = ({ children }: LayoutProps) => {
|
|||||||
</MenuItem>
|
</MenuItem>
|
||||||
</a>
|
</a>
|
||||||
</Link>
|
</Link>
|
||||||
<Link href={`/project/${currentWorkspace?._id}/audit-logs`} passHref>
|
<Link href={`/project/${currentWorkspace?.id}/audit-logs`} passHref>
|
||||||
<a>
|
<a>
|
||||||
<MenuItem
|
<MenuItem
|
||||||
isSelected={
|
isSelected={
|
||||||
router.asPath === `/project/${currentWorkspace?._id}/audit-logs`
|
router.asPath === `/project/${currentWorkspace?.id}/audit-logs`
|
||||||
}
|
}
|
||||||
icon="system-outline-168-view-headline"
|
icon="system-outline-168-view-headline"
|
||||||
>
|
>
|
||||||
@@ -560,11 +560,11 @@ export const AppLayout = ({ children }: LayoutProps) => {
|
|||||||
</MenuItem>
|
</MenuItem>
|
||||||
</a>
|
</a>
|
||||||
</Link>
|
</Link>
|
||||||
<Link href={`/project/${currentWorkspace?._id}/settings`} passHref>
|
<Link href={`/project/${currentWorkspace?.id}/settings`} passHref>
|
||||||
<a>
|
<a>
|
||||||
<MenuItem
|
<MenuItem
|
||||||
isSelected={
|
isSelected={
|
||||||
router.asPath === `/project/${currentWorkspace?._id}/settings`
|
router.asPath === `/project/${currentWorkspace?.id}/settings`
|
||||||
}
|
}
|
||||||
icon="system-outline-109-slider-toggle-settings"
|
icon="system-outline-109-slider-toggle-settings"
|
||||||
>
|
>
|
||||||
@@ -575,7 +575,7 @@ export const AppLayout = ({ children }: LayoutProps) => {
|
|||||||
</Menu>
|
</Menu>
|
||||||
) : (
|
) : (
|
||||||
<Menu className="mt-4">
|
<Menu className="mt-4">
|
||||||
<Link href={`/org/${currentOrg?._id}/overview`} passHref>
|
<Link href={`/org/${currentOrg?.id}/overview`} passHref>
|
||||||
<a>
|
<a>
|
||||||
<MenuItem
|
<MenuItem
|
||||||
isSelected={router.asPath.includes("/overview")}
|
isSelected={router.asPath.includes("/overview")}
|
||||||
@@ -585,40 +585,40 @@ export const AppLayout = ({ children }: LayoutProps) => {
|
|||||||
</MenuItem>
|
</MenuItem>
|
||||||
</a>
|
</a>
|
||||||
</Link>
|
</Link>
|
||||||
<Link href={`/org/${currentOrg?._id}/members`} passHref>
|
<Link href={`/org/${currentOrg?.id}/members`} passHref>
|
||||||
<a>
|
<a>
|
||||||
<MenuItem
|
<MenuItem
|
||||||
isSelected={router.asPath === `/org/${currentOrg?._id}/members`}
|
isSelected={router.asPath === `/org/${currentOrg?.id}/members`}
|
||||||
icon="system-outline-96-groups"
|
icon="system-outline-96-groups"
|
||||||
>
|
>
|
||||||
Access Control
|
Access Control
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
</a>
|
</a>
|
||||||
</Link>
|
</Link>
|
||||||
<Link href={`/org/${currentOrg?._id}/secret-scanning`} passHref>
|
<Link href={`/org/${currentOrg?.id}/secret-scanning`} passHref>
|
||||||
<a>
|
<a>
|
||||||
<MenuItem
|
<MenuItem
|
||||||
isSelected={router.asPath === `/org/${currentOrg?._id}/secret-scanning`}
|
isSelected={router.asPath === `/org/${currentOrg?.id}/secret-scanning`}
|
||||||
icon="system-outline-69-document-scan"
|
icon="system-outline-69-document-scan"
|
||||||
>
|
>
|
||||||
Secret Scanning
|
Secret Scanning
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
</a>
|
</a>
|
||||||
</Link>
|
</Link>
|
||||||
<Link href={`/org/${currentOrg?._id}/billing`} passHref>
|
<Link href={`/org/${currentOrg?.id}/billing`} passHref>
|
||||||
<a>
|
<a>
|
||||||
<MenuItem
|
<MenuItem
|
||||||
isSelected={router.asPath === `/org/${currentOrg?._id}/billing`}
|
isSelected={router.asPath === `/org/${currentOrg?.id}/billing`}
|
||||||
icon="system-outline-103-coin-cash-monetization"
|
icon="system-outline-103-coin-cash-monetization"
|
||||||
>
|
>
|
||||||
Usage & Billing
|
Usage & Billing
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
</a>
|
</a>
|
||||||
</Link>
|
</Link>
|
||||||
<Link href={`/org/${currentOrg?._id}/settings`} passHref>
|
<Link href={`/org/${currentOrg?.id}/settings`} passHref>
|
||||||
<a>
|
<a>
|
||||||
<MenuItem
|
<MenuItem
|
||||||
isSelected={router.asPath === `/org/${currentOrg?._id}/settings`}
|
isSelected={router.asPath === `/org/${currentOrg?.id}/settings`}
|
||||||
icon="system-outline-109-slider-toggle-settings"
|
icon="system-outline-109-slider-toggle-settings"
|
||||||
>
|
>
|
||||||
Organization Settings
|
Organization Settings
|
||||||
@@ -717,7 +717,7 @@ export const AppLayout = ({ children }: LayoutProps) => {
|
|||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
))}
|
))}
|
||||||
{infisicalPlatformVersion && (
|
{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]" />
|
<FontAwesomeIcon icon={faInfo} className="mr-4 px-[0.1rem]" />
|
||||||
Version: {infisicalPlatformVersion}
|
Version: {infisicalPlatformVersion}
|
||||||
</div>
|
</div>
|
||||||
@@ -734,7 +734,7 @@ export const AppLayout = ({ children }: LayoutProps) => {
|
|||||||
|
|
||||||
// direct user to start pro trial
|
// direct user to start pro trial
|
||||||
const url = await mutateAsync({
|
const url = await mutateAsync({
|
||||||
orgId: currentOrg._id,
|
orgId: currentOrg.id,
|
||||||
success_url: window.location.href
|
success_url: window.location.href
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -17,13 +17,11 @@ import {
|
|||||||
} from "@fortawesome/free-solid-svg-icons";
|
} from "@fortawesome/free-solid-svg-icons";
|
||||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||||
import { Menu, Transition } from "@headlessui/react";
|
import { Menu, Transition } from "@headlessui/react";
|
||||||
import {TFunction} from "i18next";
|
import { TFunction } from "i18next";
|
||||||
|
|
||||||
import guidGenerator from "@app/components/utilities/randomId";
|
import guidGenerator from "@app/components/utilities/randomId";
|
||||||
import { useOrganization, useSubscription,useUser } from "@app/context";
|
import { useOrganization, useSubscription, useUser } from "@app/context";
|
||||||
import {
|
import { useGetOrgTrialUrl, useLogoutUser } from "@app/hooks/api";
|
||||||
useGetOrgTrialUrl,
|
|
||||||
useLogoutUser} from "@app/hooks/api";
|
|
||||||
|
|
||||||
const supportOptions = (t: TFunction) => [
|
const supportOptions = (t: TFunction) => [
|
||||||
[
|
[
|
||||||
@@ -80,7 +78,7 @@ export const Navbar = () => {
|
|||||||
|
|
||||||
const closeApp = async () => {
|
const closeApp = async () => {
|
||||||
try {
|
try {
|
||||||
console.log("Logging out...")
|
console.log("Logging out...");
|
||||||
await logout.mutateAsync();
|
await logout.mutateAsync();
|
||||||
localStorage.removeItem("protectedKey");
|
localStorage.removeItem("protectedKey");
|
||||||
localStorage.removeItem("protectedKeyIV");
|
localStorage.removeItem("protectedKeyIV");
|
||||||
@@ -101,243 +99,245 @@ export const Navbar = () => {
|
|||||||
return (
|
return (
|
||||||
<div className="z-[70] border-b border-mineshaft-500 bg-mineshaft-900 text-white">
|
<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 w-full justify-between px-4">
|
||||||
<div className="flex flex-row items-center">
|
<div className="flex flex-row items-center">
|
||||||
<div className="flex justify-center py-4">
|
<div className="flex justify-center py-4">
|
||||||
<Image src="/images/logotransparent.png" height={23} width={57} alt="logo" />
|
<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>
|
</div>
|
||||||
<a href="#" className="mx-2 text-2xl font-semibold text-white">
|
<div className="relative z-40 mx-2 flex items-center justify-start">
|
||||||
Infisical
|
<a
|
||||||
</a>
|
href="https://infisical.com/docs/documentation/getting-started/introduction"
|
||||||
</div>
|
target="_blank"
|
||||||
<div className="relative z-40 mx-2 flex items-center justify-start">
|
rel="noopener noreferrer"
|
||||||
<a
|
className="mr-4 flex items-center rounded-md px-3 py-2 text-sm text-gray-200 duration-200 hover:bg-white/10"
|
||||||
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"
|
|
||||||
>
|
>
|
||||||
<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">
|
<FontAwesomeIcon icon={faBook} className="mr-2 text-xl" />
|
||||||
{supportOptionsList.map(([icon, text, url]) => (
|
Docs
|
||||||
<a
|
</a>
|
||||||
key={guidGenerator()}
|
<Menu as="div" className="relative inline-block text-left">
|
||||||
target="_blank"
|
<div className="mr-4">
|
||||||
rel="noopener noreferrer"
|
<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">
|
||||||
href={String(url)}
|
<FontAwesomeIcon className="text-xl" icon={faCircleQuestion} />
|
||||||
className="flex w-full items-center rounded-md py-0.5 font-normal text-gray-300 duration-200"
|
</Menu.Button>
|
||||||
>
|
</div>
|
||||||
<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">
|
<Transition
|
||||||
{icon}
|
as={Fragment}
|
||||||
<div className="text-sm">{text}</div>
|
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>
|
||||||
</a>
|
<div
|
||||||
))}
|
onKeyDown={() => null}
|
||||||
</Menu.Items>
|
role="button"
|
||||||
</Transition>
|
tabIndex={0}
|
||||||
</Menu>
|
onClick={() => router.push("/personal-settings")}
|
||||||
<Menu as="div" className="relative mr-4 inline-block text-left">
|
className="mx-1 my-1 flex cursor-pointer flex-row items-center rounded-md px-1 hover:bg-white/5"
|
||||||
<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">
|
<div className="flex h-8 w-9 items-center justify-center rounded-full bg-white/10 text-gray-300">
|
||||||
{user?.firstName} {user?.lastName}
|
{user?.firstName?.charAt(0)}
|
||||||
<FontAwesomeIcon
|
</div>
|
||||||
icon={faAngleDown}
|
<div className="flex w-full items-center justify-between">
|
||||||
className="ml-2 mt-1 text-sm text-gray-300 hover:text-lime-100"
|
<div>
|
||||||
/>
|
<p className="px-2 pt-1 text-sm text-gray-300">
|
||||||
</Menu.Button>
|
{" "}
|
||||||
</div>
|
{user?.firstName} {user?.lastName}
|
||||||
<Transition
|
</p>
|
||||||
as={Fragment}
|
<p className="px-2 pb-1 text-xs text-gray-400">{user?.email}</p>
|
||||||
enter="transition ease-out duration-100"
|
</div>
|
||||||
enterFrom="transform opacity-0 scale-95"
|
<FontAwesomeIcon
|
||||||
enterTo="transform opacity-100 scale-100"
|
icon={faGear}
|
||||||
leave="transition ease-in duration-75"
|
className="mr-1 cursor-pointer rounded-md p-2 text-lg text-gray-400 hover:bg-white/10"
|
||||||
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>
|
|
||||||
</div>
|
</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>
|
||||||
</div>
|
<div className="px-2 pt-2">
|
||||||
<div className="px-2 pt-2">
|
<div className="ml-2 mt-2 self-start text-xs font-semibold tracking-wide text-gray-400">
|
||||||
<div className="ml-2 mt-2 self-start text-xs font-semibold tracking-wide text-gray-400">
|
{t("nav.user.current-organization")}
|
||||||
{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>
|
</div>
|
||||||
<div className="flex w-full items-center justify-between">
|
<div
|
||||||
<p className="px-2 text-sm text-gray-300">{currentOrg?.name}</p>
|
onKeyDown={() => null}
|
||||||
<FontAwesomeIcon
|
role="button"
|
||||||
icon={faGear}
|
tabIndex={0}
|
||||||
className="cursor-pointer rounded-md p-2 text-lg text-gray-400 hover:bg-white/10"
|
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>
|
||||||
</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
|
<button
|
||||||
// onClick={buttonAction}
|
|
||||||
type="button"
|
type="button"
|
||||||
className="w-full cursor-pointer"
|
// onClick={buttonAction}
|
||||||
|
className="mb-2 w-full cursor-pointer"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
onKeyDown={() => null}
|
onKeyDown={() => null}
|
||||||
role="button"
|
role="button"
|
||||||
tabIndex={0}
|
tabIndex={0}
|
||||||
onClick={() => router.push(`/settings/billing/${router.query.id}`)}
|
onClick={() => router.push(`/settings/org/${router.query.id}?invite`)}
|
||||||
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"
|
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} />
|
<span className="absolute inset-y-0 left-0 flex items-center rounded-lg pl-3 pr-4">
|
||||||
<div className="text-sm">{t("nav.user.usage-billing")}</div>
|
<FontAwesomeIcon icon={faPlus} className="ml-1" />
|
||||||
|
</span>
|
||||||
|
<div className="ml-1 text-sm">{t("nav.user.invite")}</div>
|
||||||
</div>
|
</div>
|
||||||
</button>
|
</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>
|
||||||
)}
|
{orgs && orgs?.length > 1 && (
|
||||||
<div className="px-1 py-1">
|
<div className="px-1 pt-1">
|
||||||
<Menu.Item>
|
<div className="ml-2 mt-2 self-start text-xs font-semibold tracking-wide text-gray-400">
|
||||||
{({ active }) => (
|
{t("nav.user.other-organizations")}
|
||||||
<button
|
</div>
|
||||||
type="button"
|
<div className="mt-3 mb-2 flex flex-col items-start px-1">
|
||||||
onClick={closeApp}
|
{orgs
|
||||||
className={`${
|
?.filter((org: { id: string }) => org.id !== currentOrg?.id)
|
||||||
active ? "bg-red font-semibold text-white" : "text-gray-400"
|
.map((org: { id: string; name: string }) => (
|
||||||
} group flex w-full items-center rounded-md px-2 py-2 text-sm`}
|
<div
|
||||||
>
|
onKeyDown={() => null}
|
||||||
<div className="relative flex cursor-pointer select-none items-center justify-start">
|
role="button"
|
||||||
<FontAwesomeIcon
|
tabIndex={0}
|
||||||
className="ml-1.5 mr-3 text-lg"
|
key={guidGenerator()}
|
||||||
icon={faRightFromBracket}
|
onClick={() => {
|
||||||
/>
|
localStorage.setItem("orgData.id", org.id);
|
||||||
{t("common.logout")}
|
router.reload();
|
||||||
</div>
|
}}
|
||||||
</button>
|
className="flex w-full cursor-pointer flex-row items-center justify-start rounded-md p-1.5 hover:bg-white/5"
|
||||||
)}
|
>
|
||||||
</Menu.Item>
|
<div className="flex h-7 w-8 items-center justify-center rounded-md bg-white/10 text-gray-300">
|
||||||
</div>
|
{org.name.charAt(0)}
|
||||||
</Menu.Items>
|
</div>
|
||||||
</Transition>
|
<div className="flex w-full items-center justify-between">
|
||||||
</Menu>
|
<p className="px-2 text-sm text-gray-300">{org.name}</p>
|
||||||
</div>
|
</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>
|
</div>
|
||||||
{subscription && subscription.slug === "starter" && !subscription.has_used_trial && (
|
{subscription && subscription.slug === "starter" && !subscription.has_used_trial && (
|
||||||
<div className="w-full mx-auto border-t border-mineshaft-500 text-center">
|
<div className="mx-auto w-full border-t border-mineshaft-500 text-center">
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={async () => {
|
onClick={async () => {
|
||||||
if (!subscription || !currentOrg) return;
|
if (!subscription || !currentOrg) return;
|
||||||
|
|
||||||
// direct user to start pro trial
|
// direct user to start pro trial
|
||||||
const url = await mutateAsync({
|
const url = await mutateAsync({
|
||||||
orgId: currentOrg.id,
|
orgId: currentOrg._id,
|
||||||
success_url: window.location.href
|
success_url: window.location.href
|
||||||
});
|
});
|
||||||
|
|
||||||
window.location.href = url;
|
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 →</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 →</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -25,28 +25,28 @@ export type IGitRisks = {
|
|||||||
isFalsePositive: boolean; // New field for marking risks as false positives
|
isFalsePositive: boolean; // New field for marking risks as false positives
|
||||||
isResolved: boolean; // New field for marking risks as resolved
|
isResolved: boolean; // New field for marking risks as resolved
|
||||||
riskOwner: string | null; // New field for setting a risk owner (nullable string)
|
riskOwner: string | null; // New field for setting a risk owner (nullable string)
|
||||||
installationId: string,
|
installationId: string;
|
||||||
repositoryId: string,
|
repositoryId: string;
|
||||||
repositoryLink: string
|
repositoryLink: string;
|
||||||
repositoryFullName: string
|
repositoryFullName: string;
|
||||||
pusher: {
|
pusher: {
|
||||||
name: string,
|
name: string;
|
||||||
email: string
|
email: string;
|
||||||
},
|
};
|
||||||
createdAt: string,
|
createdAt: string;
|
||||||
organization: string,
|
organization: string;
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Will create a new integration session and return it for the given org
|
* Will create a new integration session and return it for the given org
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
const getRisksByOrganization = (oranizationId: string): Promise<IGitRisks[]> =>
|
const getRisksByOrganization = (oranizationId: string): Promise<IGitRisks[]> =>
|
||||||
SecurityClient.fetchCall(`/api/v1/secret-scanning/organization/${oranizationId}/risks`, {
|
SecurityClient.fetchCall(`/api/v1/secret-scanning/organization/${oranizationId}/risks`, {
|
||||||
method: "GET",
|
method: "GET",
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json"
|
"Content-Type": "application/json"
|
||||||
},
|
}
|
||||||
}).then(async (res) => {
|
}).then(async (res) => {
|
||||||
if (res && res.status === 200) {
|
if (res && res.status === 200) {
|
||||||
return (await res.json()).risks;
|
return (await res.json()).risks;
|
||||||
|
|||||||
@@ -18,9 +18,9 @@ export default function DashboardRedirect() {
|
|||||||
if (localStorage.getItem("orgData.id")) {
|
if (localStorage.getItem("orgData.id")) {
|
||||||
router.push(`/org/${localStorage.getItem("orgData.id")}/overview`);
|
router.push(`/org/${localStorage.getItem("orgData.id")}/overview`);
|
||||||
} else if (userOrgs) {
|
} else if (userOrgs) {
|
||||||
userOrg = userOrgs[0].id;
|
userOrg = userOrgs[0].id;
|
||||||
router.push(`/org/${userOrg}/overview`);
|
router.push(`/org/${userOrg}/overview`);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log("Error - Not logged in yet");
|
console.log("Error - Not logged in yet");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,16 +6,14 @@ import { useRouter } from "next/router";
|
|||||||
import { faArrowUpRightFromSquare, faBookOpen } from "@fortawesome/free-solid-svg-icons";
|
import { faArrowUpRightFromSquare, faBookOpen } from "@fortawesome/free-solid-svg-icons";
|
||||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||||
|
|
||||||
import {
|
import { useSaveIntegrationAccessToken } from "@app/hooks/api";
|
||||||
useSaveIntegrationAccessToken
|
|
||||||
} from "@app/hooks/api";
|
|
||||||
|
|
||||||
import { Button, Card, CardTitle, FormControl, Input } from "../../../components/v2";
|
import { Button, Card, CardTitle, FormControl, Input } from "../../../components/v2";
|
||||||
|
|
||||||
export default function AWSParameterStoreAuthorizeIntegrationPage() {
|
export default function AWSParameterStoreAuthorizeIntegrationPage() {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { mutateAsync } = useSaveIntegrationAccessToken();
|
const { mutateAsync } = useSaveIntegrationAccessToken();
|
||||||
|
|
||||||
const [isLoading, setIsLoading] = useState(false);
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
|
|
||||||
const [accessKey, setAccessKey] = useState("");
|
const [accessKey, setAccessKey] = useState("");
|
||||||
@@ -63,11 +61,11 @@ export default function AWSParameterStoreAuthorizeIntegrationPage() {
|
|||||||
<div className="flex h-full w-full items-center justify-center">
|
<div className="flex h-full w-full items-center justify-center">
|
||||||
<Head>
|
<Head>
|
||||||
<title>Authorize AWS Parameter Integration</title>
|
<title>Authorize AWS Parameter Integration</title>
|
||||||
<link rel='icon' href='/infisical.ico' />
|
<link rel="icon" href="/infisical.ico" />
|
||||||
</Head>
|
</Head>
|
||||||
<Card className="max-w-lg rounded-md border border-mineshaft-600">
|
<Card className="max-w-lg rounded-md border border-mineshaft-600">
|
||||||
<CardTitle
|
<CardTitle
|
||||||
className="text-left px-6 text-xl"
|
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."
|
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">
|
<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>
|
<span className="ml-1.5">AWS Parameter Store Integration </span>
|
||||||
<Link href="https://infisical.com/docs/integrations/cloud/aws-parameter-store" passHref>
|
<Link href="https://infisical.com/docs/integrations/cloud/aws-parameter-store" passHref>
|
||||||
<a target="_blank" rel="noopener noreferrer">
|
<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">
|
<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"/>
|
<FontAwesomeIcon icon={faBookOpen} className="mr-1.5" />
|
||||||
Docs
|
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>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
</Link>
|
</Link>
|
||||||
@@ -97,11 +98,7 @@ export default function AWSParameterStoreAuthorizeIntegrationPage() {
|
|||||||
isError={accessKeyErrorText !== "" ?? false}
|
isError={accessKeyErrorText !== "" ?? false}
|
||||||
className="px-6"
|
className="px-6"
|
||||||
>
|
>
|
||||||
<Input
|
<Input placeholder="" value={accessKey} onChange={(e) => setAccessKey(e.target.value)} />
|
||||||
placeholder=""
|
|
||||||
value={accessKey}
|
|
||||||
onChange={(e) => setAccessKey(e.target.value)}
|
|
||||||
/>
|
|
||||||
</FormControl>
|
</FormControl>
|
||||||
<FormControl
|
<FormControl
|
||||||
label="Secret Access Key"
|
label="Secret Access Key"
|
||||||
|
|||||||
@@ -3,13 +3,16 @@ import Head from "next/head";
|
|||||||
import Image from "next/image";
|
import Image from "next/image";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import { 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 { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||||
import queryString from "query-string";
|
import queryString from "query-string";
|
||||||
|
|
||||||
import {
|
import { useCreateIntegration } from "@app/hooks/api";
|
||||||
useCreateIntegration
|
|
||||||
} from "@app/hooks/api";
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
@@ -62,7 +65,9 @@ export default function AWSParameterStoreCreateIntegrationPage() {
|
|||||||
const { integrationAuthId } = queryString.parse(router.asPath.split("?")[1]);
|
const { integrationAuthId } = queryString.parse(router.asPath.split("?")[1]);
|
||||||
|
|
||||||
const { data: workspace } = useGetWorkspaceById(localStorage.getItem("projectData.id") ?? "");
|
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 [selectedSourceEnvironment, setSelectedSourceEnvironment] = useState("");
|
||||||
const [secretPath, setSecretPath] = useState("/");
|
const [secretPath, setSecretPath] = useState("/");
|
||||||
@@ -118,14 +123,14 @@ export default function AWSParameterStoreCreateIntegrationPage() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return integrationAuth && workspace && selectedSourceEnvironment ? (
|
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>
|
<Head>
|
||||||
<title>Set Up AWS Parameter Integration</title>
|
<title>Set Up AWS Parameter Integration</title>
|
||||||
<link rel='icon' href='/infisical.ico' />
|
<link rel="icon" href="/infisical.ico" />
|
||||||
</Head>
|
</Head>
|
||||||
<Card className="max-w-lg rounded-md border border-mineshaft-600">
|
<Card className="max-w-lg rounded-md border border-mineshaft-600">
|
||||||
<CardTitle
|
<CardTitle
|
||||||
className="text-left px-6 text-xl"
|
className="px-6 text-left text-xl"
|
||||||
subTitle="Choose which environment in Infisical you want to sync to secerts in AWS Parameter Store."
|
subTitle="Choose which environment in Infisical you want to sync to secerts in AWS Parameter Store."
|
||||||
>
|
>
|
||||||
<div className="flex flex-row items-center">
|
<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>
|
<span className="ml-1.5">AWS Parameter Store Integration </span>
|
||||||
<Link href="https://infisical.com/docs/integrations/cloud/aws-parameter-store" passHref>
|
<Link href="https://infisical.com/docs/integrations/cloud/aws-parameter-store" passHref>
|
||||||
<a target="_blank" rel="noopener noreferrer">
|
<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">
|
<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"/>
|
<FontAwesomeIcon icon={faBookOpen} className="mr-1.5" />
|
||||||
Docs
|
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>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
</Link>
|
</Link>
|
||||||
@@ -185,7 +193,12 @@ export default function AWSParameterStoreCreateIntegrationPage() {
|
|||||||
))}
|
))}
|
||||||
</Select>
|
</Select>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
<FormControl label="Path" errorText={pathErrorText} isError={pathErrorText !== "" ?? false} className="px-6">
|
<FormControl
|
||||||
|
label="Path"
|
||||||
|
errorText={pathErrorText}
|
||||||
|
isError={pathErrorText !== "" ?? false}
|
||||||
|
className="px-6"
|
||||||
|
>
|
||||||
<Input
|
<Input
|
||||||
placeholder={`/${workspace.name
|
placeholder={`/${workspace.name
|
||||||
.toLowerCase()
|
.toLowerCase()
|
||||||
@@ -204,31 +217,49 @@ export default function AWSParameterStoreCreateIntegrationPage() {
|
|||||||
Create Integration
|
Create Integration
|
||||||
</Button>
|
</Button>
|
||||||
</Card>
|
</Card>
|
||||||
<div className="border-t border-mineshaft-800 w-full max-w-md mt-6"/>
|
<div className="mt-6 w-full max-w-md border-t border-mineshaft-800" />
|
||||||
<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="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-mineshaft-200 text-xl"/> <span className="ml-3 text-md text-mineshaft-100">Pro Tips</span></div>
|
<div className="flex flex-row items-center">
|
||||||
<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>
|
<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>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div className="flex justify-center items-center w-full h-full">
|
<div className="flex h-full w-full items-center justify-center">
|
||||||
<Head>
|
<Head>
|
||||||
<title>Set Up AWS Parameter Store Integration</title>
|
<title>Set Up AWS Parameter Store Integration</title>
|
||||||
<link rel='icon' href='/infisical.ico' />
|
<link rel="icon" href="/infisical.ico" />
|
||||||
</Head>
|
</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">
|
{isintegrationAuthLoading ? (
|
||||||
<FontAwesomeIcon icon={faBugs} className="text-6xl my-2 inlineli"/>
|
<img
|
||||||
<p>
|
src="/images/loading/loading.gif"
|
||||||
Something went wrong. Please contact <a
|
height={70}
|
||||||
className="inline underline underline-offset-4 decoration-primary-500 opacity-80 hover:opacity-100 text-mineshaft-100 duration-200 cursor-pointer"
|
width={120}
|
||||||
target="_blank"
|
alt="infisical loading indicator"
|
||||||
rel="noopener noreferrer"
|
/>
|
||||||
href="mailto:[email protected]"
|
) : (
|
||||||
>
|
<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">
|
||||||
support@infisical.com
|
<FontAwesomeIcon icon={faBugs} className="inlineli my-2 text-6xl" />
|
||||||
</a> if the issue persists.
|
<p>
|
||||||
</p>
|
Something went wrong. Please contact{" "}
|
||||||
</div>}
|
<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:[email protected]"
|
||||||
|
>
|
||||||
|
support@infisical.com
|
||||||
|
</a>{" "}
|
||||||
|
if the issue persists.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -61,11 +61,11 @@ export default function AWSSecretManagerCreateIntegrationPage() {
|
|||||||
<div className="flex h-full w-full items-center justify-center">
|
<div className="flex h-full w-full items-center justify-center">
|
||||||
<Head>
|
<Head>
|
||||||
<title>Authorize AWS Secrets Manager Integration</title>
|
<title>Authorize AWS Secrets Manager Integration</title>
|
||||||
<link rel='icon' href='/infisical.ico' />
|
<link rel="icon" href="/infisical.ico" />
|
||||||
</Head>
|
</Head>
|
||||||
<Card className="max-w-lg rounded-md border border-mineshaft-600">
|
<Card className="max-w-lg rounded-md border border-mineshaft-600">
|
||||||
<CardTitle
|
<CardTitle
|
||||||
className="text-left px-6 text-xl"
|
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."
|
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">
|
<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>
|
<span className="ml-1.5">AWS Secrets Manager Integration </span>
|
||||||
<Link href="https://infisical.com/docs/integrations/cloud/aws-secret-manager" passHref>
|
<Link href="https://infisical.com/docs/integrations/cloud/aws-secret-manager" passHref>
|
||||||
<a target="_blank" rel="noopener noreferrer">
|
<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">
|
<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"/>
|
<FontAwesomeIcon icon={faBookOpen} className="mr-1.5" />
|
||||||
Docs
|
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>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
</Link>
|
</Link>
|
||||||
|
|||||||
@@ -3,13 +3,16 @@ import Head from "next/head";
|
|||||||
import Image from "next/image";
|
import Image from "next/image";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import { 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 { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||||
import queryString from "query-string";
|
import queryString from "query-string";
|
||||||
|
|
||||||
import {
|
import { useCreateIntegration } from "@app/hooks/api";
|
||||||
useCreateIntegration
|
|
||||||
} from "@app/hooks/api";
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
@@ -62,7 +65,9 @@ export default function AWSSecretManagerCreateIntegrationPage() {
|
|||||||
const { integrationAuthId } = queryString.parse(router.asPath.split("?")[1]);
|
const { integrationAuthId } = queryString.parse(router.asPath.split("?")[1]);
|
||||||
|
|
||||||
const { data: workspace } = useGetWorkspaceById(localStorage.getItem("projectData.id") ?? "");
|
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 [selectedSourceEnvironment, setSelectedSourceEnvironment] = useState("");
|
||||||
const [secretPath, setSecretPath] = useState("/");
|
const [secretPath, setSecretPath] = useState("/");
|
||||||
@@ -117,14 +122,14 @@ export default function AWSSecretManagerCreateIntegrationPage() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return integrationAuth && workspace && selectedSourceEnvironment ? (
|
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>
|
<Head>
|
||||||
<title>Set Up AWS Secrets Manager Integration</title>
|
<title>Set Up AWS Secrets Manager Integration</title>
|
||||||
<link rel='icon' href='/infisical.ico' />
|
<link rel="icon" href="/infisical.ico" />
|
||||||
</Head>
|
</Head>
|
||||||
<Card className="max-w-lg rounded-md border border-mineshaft-600">
|
<Card className="max-w-lg rounded-md border border-mineshaft-600">
|
||||||
<CardTitle
|
<CardTitle
|
||||||
className="text-left px-6 text-xl"
|
className="px-6 text-left text-xl"
|
||||||
subTitle="Choose which environment in Infisical you want to sync to secerts in AWS Secrets Manager."
|
subTitle="Choose which environment in Infisical you want to sync to secerts in AWS Secrets Manager."
|
||||||
>
|
>
|
||||||
<div className="flex flex-row items-center">
|
<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>
|
<span className="ml-1.5">AWS Secrets Manager Integration </span>
|
||||||
<Link href="https://infisical.com/docs/integrations/cloud/aws-secret-manager" passHref>
|
<Link href="https://infisical.com/docs/integrations/cloud/aws-secret-manager" passHref>
|
||||||
<a target="_blank" rel="noopener noreferrer">
|
<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">
|
<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"/>
|
<FontAwesomeIcon icon={faBookOpen} className="mr-1.5" />
|
||||||
Docs
|
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>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
</Link>
|
</Link>
|
||||||
@@ -208,31 +216,49 @@ export default function AWSSecretManagerCreateIntegrationPage() {
|
|||||||
Create Integration
|
Create Integration
|
||||||
</Button>
|
</Button>
|
||||||
</Card>
|
</Card>
|
||||||
<div className="border-t border-mineshaft-800 w-full max-w-md mt-6"/>
|
<div className="mt-6 w-full max-w-md border-t border-mineshaft-800" />
|
||||||
<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="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-mineshaft-200 text-xl"/> <span className="ml-3 text-md text-mineshaft-100">Pro Tips</span></div>
|
<div className="flex flex-row items-center">
|
||||||
<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>
|
<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>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div className="flex justify-center items-center w-full h-full">
|
<div className="flex h-full w-full items-center justify-center">
|
||||||
<Head>
|
<Head>
|
||||||
<title>Set Up AWS Secrets Manager Integration</title>
|
<title>Set Up AWS Secrets Manager Integration</title>
|
||||||
<link rel='icon' href='/infisical.ico' />
|
<link rel="icon" href="/infisical.ico" />
|
||||||
</Head>
|
</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">
|
{isintegrationAuthLoading ? (
|
||||||
<FontAwesomeIcon icon={faBugs} className="text-6xl my-2 inlineli"/>
|
<img
|
||||||
<p>
|
src="/images/loading/loading.gif"
|
||||||
Something went wrong. Please contact <a
|
height={70}
|
||||||
className="inline underline underline-offset-4 decoration-primary-500 opacity-80 hover:opacity-100 text-mineshaft-100 duration-200 cursor-pointer"
|
width={120}
|
||||||
target="_blank"
|
alt="infisical loading indicator"
|
||||||
rel="noopener noreferrer"
|
/>
|
||||||
href="mailto:[email protected]"
|
) : (
|
||||||
>
|
<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">
|
||||||
support@infisical.com
|
<FontAwesomeIcon icon={faBugs} className="inlineli my-2 text-6xl" />
|
||||||
</a> if the issue persists.
|
<p>
|
||||||
</p>
|
Something went wrong. Please contact{" "}
|
||||||
</div>}
|
<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:[email protected]"
|
||||||
|
>
|
||||||
|
support@infisical.com
|
||||||
|
</a>{" "}
|
||||||
|
if the issue persists.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,9 +2,7 @@ import { useEffect, useState } from "react";
|
|||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import queryString from "query-string";
|
import queryString from "query-string";
|
||||||
|
|
||||||
import {
|
import { useCreateIntegration } from "@app/hooks/api";
|
||||||
useCreateIntegration
|
|
||||||
} from "@app/hooks/api";
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
|
|||||||
@@ -2,9 +2,7 @@ import { useEffect } from "react";
|
|||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import queryString from "query-string";
|
import queryString from "query-string";
|
||||||
|
|
||||||
import {
|
import { useAuthorizeIntegration } from "@app/hooks/api";
|
||||||
useAuthorizeIntegration
|
|
||||||
} from "@app/hooks/api";
|
|
||||||
|
|
||||||
export default function AzureKeyVaultOAuth2CallbackPage() {
|
export default function AzureKeyVaultOAuth2CallbackPage() {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
@@ -25,9 +23,7 @@ export default function AzureKeyVaultOAuth2CallbackPage() {
|
|||||||
integration: "azure-key-vault"
|
integration: "azure-key-vault"
|
||||||
});
|
});
|
||||||
|
|
||||||
router.push(
|
router.push(`/integrations/azure-key-vault/create?integrationAuthId=${integrationAuth.id}`);
|
||||||
`/integrations/azure-key-vault/create?integrationAuthId=${integrationAuth.id}`
|
|
||||||
);
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,9 +2,7 @@ import { useEffect, useState } from "react";
|
|||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import queryString from "query-string";
|
import queryString from "query-string";
|
||||||
|
|
||||||
import {
|
import { useCreateIntegration } from "@app/hooks/api";
|
||||||
useCreateIntegration
|
|
||||||
} from "@app/hooks/api";
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
@@ -18,7 +16,7 @@ import {
|
|||||||
import {
|
import {
|
||||||
useGetIntegrationAuthApps,
|
useGetIntegrationAuthApps,
|
||||||
useGetIntegrationAuthBitBucketWorkspaces,
|
useGetIntegrationAuthBitBucketWorkspaces,
|
||||||
useGetIntegrationAuthById,
|
useGetIntegrationAuthById
|
||||||
} from "../../../hooks/api/integrationAuth";
|
} from "../../../hooks/api/integrationAuth";
|
||||||
import { useGetWorkspaceById } from "../../../hooks/api/workspace";
|
import { useGetWorkspaceById } from "../../../hooks/api/workspace";
|
||||||
|
|
||||||
@@ -36,7 +34,9 @@ export default function BitBucketCreateIntegrationPage() {
|
|||||||
const { integrationAuthId } = queryString.parse(router.asPath.split("?")[1]);
|
const { integrationAuthId } = queryString.parse(router.asPath.split("?")[1]);
|
||||||
const { data: integrationAuth } = useGetIntegrationAuthById((integrationAuthId as string) ?? "");
|
const { data: integrationAuth } = useGetIntegrationAuthById((integrationAuthId as string) ?? "");
|
||||||
const { data: workspace } = useGetWorkspaceById(localStorage.getItem("projectData.id") ?? "");
|
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({
|
const { data: integrationAuthApps } = useGetIntegrationAuthApps({
|
||||||
integrationAuthId: (integrationAuthId as string) ?? "",
|
integrationAuthId: (integrationAuthId as string) ?? "",
|
||||||
workspaceSlug: targetEnvironmentId
|
workspaceSlug: targetEnvironmentId
|
||||||
|
|||||||
@@ -2,9 +2,7 @@ import { useEffect } from "react";
|
|||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import queryString from "query-string";
|
import queryString from "query-string";
|
||||||
|
|
||||||
import {
|
import { useAuthorizeIntegration } from "@app/hooks/api";
|
||||||
useAuthorizeIntegration
|
|
||||||
} from "@app/hooks/api";
|
|
||||||
|
|
||||||
export default function BitBucketOAuth2CallbackPage() {
|
export default function BitBucketOAuth2CallbackPage() {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|||||||
@@ -6,9 +6,7 @@ import { useRouter } from "next/router";
|
|||||||
import { faArrowUpRightFromSquare, faBookOpen } from "@fortawesome/free-solid-svg-icons";
|
import { faArrowUpRightFromSquare, faBookOpen } from "@fortawesome/free-solid-svg-icons";
|
||||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||||
|
|
||||||
import {
|
import { useSaveIntegrationAccessToken } from "@app/hooks/api";
|
||||||
useSaveIntegrationAccessToken
|
|
||||||
} from "@app/hooks/api";
|
|
||||||
|
|
||||||
import { Button, Card, CardTitle, FormControl, Input } from "../../../components/v2";
|
import { Button, Card, CardTitle, FormControl, Input } from "../../../components/v2";
|
||||||
|
|
||||||
@@ -48,11 +46,11 @@ export default function ChecklyCreateIntegrationPage() {
|
|||||||
<div className="flex h-full w-full items-center justify-center">
|
<div className="flex h-full w-full items-center justify-center">
|
||||||
<Head>
|
<Head>
|
||||||
<title>Authorize Checkly Integration</title>
|
<title>Authorize Checkly Integration</title>
|
||||||
<link rel='icon' href='/infisical.ico' />
|
<link rel="icon" href="/infisical.ico" />
|
||||||
</Head>
|
</Head>
|
||||||
<Card className="max-w-lg rounded-md border border-mineshaft-600 mb-12">
|
<Card className="mb-12 max-w-lg rounded-md border border-mineshaft-600">
|
||||||
<CardTitle
|
<CardTitle
|
||||||
className="text-left px-6 text-xl"
|
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."
|
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="flex flex-row items-center">
|
||||||
@@ -67,10 +65,13 @@ export default function ChecklyCreateIntegrationPage() {
|
|||||||
<span className="ml-2.5">Checkly Integration </span>
|
<span className="ml-2.5">Checkly Integration </span>
|
||||||
<Link href="https://infisical.com/docs/integrations/cloud/checkly" passHref>
|
<Link href="https://infisical.com/docs/integrations/cloud/checkly" passHref>
|
||||||
<a target="_blank" rel="noopener noreferrer">
|
<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">
|
<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"/>
|
<FontAwesomeIcon icon={faBookOpen} className="mr-1.5" />
|
||||||
Docs
|
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>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
</Link>
|
</Link>
|
||||||
|
|||||||
@@ -21,9 +21,7 @@ import {
|
|||||||
TabPanel,
|
TabPanel,
|
||||||
Tabs
|
Tabs
|
||||||
} from "@app/components/v2";
|
} from "@app/components/v2";
|
||||||
import {
|
import { useCreateIntegration } from "@app/hooks/api";
|
||||||
useCreateIntegration
|
|
||||||
} from "@app/hooks/api";
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
useGetIntegrationAuthApps,
|
useGetIntegrationAuthApps,
|
||||||
@@ -54,13 +52,15 @@ export default function ChecklyCreateIntegrationPage() {
|
|||||||
|
|
||||||
const { data: workspace } = useGetWorkspaceById(localStorage.getItem("projectData.id") ?? "");
|
const { data: workspace } = useGetWorkspaceById(localStorage.getItem("projectData.id") ?? "");
|
||||||
const { data: integrationAuth } = useGetIntegrationAuthById((integrationAuthId as string) ?? "");
|
const { data: integrationAuth } = useGetIntegrationAuthById((integrationAuthId as string) ?? "");
|
||||||
const { data: integrationAuthApps, isLoading: isIntegrationAuthAppsLoading } = useGetIntegrationAuthApps({
|
const { data: integrationAuthApps, isLoading: isIntegrationAuthAppsLoading } =
|
||||||
integrationAuthId: (integrationAuthId as string) ?? ""
|
useGetIntegrationAuthApps({
|
||||||
});
|
integrationAuthId: (integrationAuthId as string) ?? ""
|
||||||
const { data: integrationAuthGroups, isLoading: isintegrationAuthGroupsLoading } = useGetIntegrationAuthChecklyGroups({
|
});
|
||||||
integrationAuthId: (integrationAuthId as string) ?? "",
|
const { data: integrationAuthGroups, isLoading: isintegrationAuthGroupsLoading } =
|
||||||
accountId: targetAppId
|
useGetIntegrationAuthChecklyGroups({
|
||||||
});
|
integrationAuthId: (integrationAuthId as string) ?? "",
|
||||||
|
accountId: targetAppId
|
||||||
|
});
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (workspace) {
|
if (workspace) {
|
||||||
@@ -90,9 +90,9 @@ export default function ChecklyCreateIntegrationPage() {
|
|||||||
const targetGroup = integrationAuthGroups?.find(
|
const targetGroup = integrationAuthGroups?.find(
|
||||||
(group) => group.groupId === Number(targetGroupId)
|
(group) => group.groupId === Number(targetGroupId)
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!targetApp) return;
|
if (!targetApp) return;
|
||||||
|
|
||||||
await mutateAsync({
|
await mutateAsync({
|
||||||
integrationAuthId: integrationAuth?.id,
|
integrationAuthId: integrationAuth?.id,
|
||||||
isActive: true,
|
isActive: true,
|
||||||
@@ -118,17 +118,17 @@ export default function ChecklyCreateIntegrationPage() {
|
|||||||
return integrationAuth &&
|
return integrationAuth &&
|
||||||
workspace &&
|
workspace &&
|
||||||
selectedSourceEnvironment &&
|
selectedSourceEnvironment &&
|
||||||
integrationAuthApps &&
|
integrationAuthApps &&
|
||||||
integrationAuthGroups &&
|
integrationAuthGroups &&
|
||||||
targetAppId ? (
|
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>
|
<Head>
|
||||||
<title>Set Up Checkly Integration</title>
|
<title>Set Up Checkly Integration</title>
|
||||||
<link rel='icon' href='/infisical.ico' />
|
<link rel="icon" href="/infisical.ico" />
|
||||||
</Head>
|
</Head>
|
||||||
<Card className="max-w-lg rounded-md border border-mineshaft-600 p-0">
|
<Card className="max-w-lg rounded-md border border-mineshaft-600 p-0">
|
||||||
<CardTitle
|
<CardTitle
|
||||||
className="text-left px-6 text-xl"
|
className="px-6 text-left text-xl"
|
||||||
subTitle="Choose which environment in Infisical you want to sync to Checkly environment variables."
|
subTitle="Choose which environment in Infisical you want to sync to Checkly environment variables."
|
||||||
>
|
>
|
||||||
<div className="flex flex-row items-center">
|
<div className="flex flex-row items-center">
|
||||||
@@ -143,10 +143,13 @@ export default function ChecklyCreateIntegrationPage() {
|
|||||||
<span className="ml-2.5">Checkly Integration </span>
|
<span className="ml-2.5">Checkly Integration </span>
|
||||||
<Link href="https://infisical.com/docs/integrations/cloud/checkly" passHref>
|
<Link href="https://infisical.com/docs/integrations/cloud/checkly" passHref>
|
||||||
<a target="_blank" rel="noopener noreferrer">
|
<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">
|
<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"/>
|
<FontAwesomeIcon icon={faBookOpen} className="mr-1.5" />
|
||||||
Docs
|
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>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
</Link>
|
</Link>
|
||||||
@@ -154,7 +157,7 @@ export default function ChecklyCreateIntegrationPage() {
|
|||||||
</CardTitle>
|
</CardTitle>
|
||||||
<Tabs defaultValue={TabSections.Connection} className="px-6">
|
<Tabs defaultValue={TabSections.Connection} className="px-6">
|
||||||
<TabList>
|
<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.Connection}>Connection</Tab>
|
||||||
<Tab value={TabSections.Options}>Options</Tab>
|
<Tab value={TabSections.Options}>Options</Tab>
|
||||||
</div>
|
</div>
|
||||||
@@ -268,24 +271,35 @@ export default function ChecklyCreateIntegrationPage() {
|
|||||||
</Card>
|
</Card>
|
||||||
</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>
|
<Head>
|
||||||
<title>Set Up Checkly Integration</title>
|
<title>Set Up Checkly Integration</title>
|
||||||
<link rel='icon' href='/infisical.ico' />
|
<link rel="icon" href="/infisical.ico" />
|
||||||
</Head>
|
</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">
|
{isIntegrationAuthAppsLoading || isintegrationAuthGroupsLoading ? (
|
||||||
<FontAwesomeIcon icon={faBugs} className="text-6xl my-2 inlineli"/>
|
<img
|
||||||
<p>
|
src="/images/loading/loading.gif"
|
||||||
Something went wrong. Please contact <a
|
height={70}
|
||||||
className="inline underline underline-offset-4 decoration-primary-500 opacity-80 hover:opacity-100 text-mineshaft-100 duration-200 cursor-pointer"
|
width={120}
|
||||||
target="_blank"
|
alt="infisical loading indicator"
|
||||||
rel="noopener noreferrer"
|
/>
|
||||||
href="mailto:[email protected]"
|
) : (
|
||||||
>
|
<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">
|
||||||
support@infisical.com
|
<FontAwesomeIcon icon={faBugs} className="inlineli my-2 text-6xl" />
|
||||||
</a> if the issue persists.
|
<p>
|
||||||
</p>
|
Something went wrong. Please contact{" "}
|
||||||
</div>}
|
<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:[email protected]"
|
||||||
|
>
|
||||||
|
support@infisical.com
|
||||||
|
</a>{" "}
|
||||||
|
if the issue persists.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,9 +6,7 @@ import { useRouter } from "next/router";
|
|||||||
import { faArrowUpRightFromSquare, faBookOpen } from "@fortawesome/free-solid-svg-icons";
|
import { faArrowUpRightFromSquare, faBookOpen } from "@fortawesome/free-solid-svg-icons";
|
||||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||||
|
|
||||||
import {
|
import { useSaveIntegrationAccessToken } from "@app/hooks/api";
|
||||||
useSaveIntegrationAccessToken
|
|
||||||
} from "@app/hooks/api";
|
|
||||||
|
|
||||||
import { Button, Card, CardTitle, FormControl, Input } from "../../../components/v2";
|
import { Button, Card, CardTitle, FormControl, Input } from "../../../components/v2";
|
||||||
|
|
||||||
@@ -48,11 +46,11 @@ export default function CircleCICreateIntegrationPage() {
|
|||||||
<div className="flex h-full w-full items-center justify-center">
|
<div className="flex h-full w-full items-center justify-center">
|
||||||
<Head>
|
<Head>
|
||||||
<title>Authorize CircleCI Integration</title>
|
<title>Authorize CircleCI Integration</title>
|
||||||
<link rel='icon' href='/infisical.ico' />
|
<link rel="icon" href="/infisical.ico" />
|
||||||
</Head>
|
</Head>
|
||||||
<Card className="max-w-lg rounded-md border border-mineshaft-600 mb-12">
|
<Card className="mb-12 max-w-lg rounded-md border border-mineshaft-600">
|
||||||
<CardTitle
|
<CardTitle
|
||||||
className="text-left px-6 text-xl"
|
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."
|
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">
|
<div className="flex flex-row items-center">
|
||||||
@@ -67,10 +65,13 @@ export default function CircleCICreateIntegrationPage() {
|
|||||||
<span className="ml-1.5">CircleCI Integration </span>
|
<span className="ml-1.5">CircleCI Integration </span>
|
||||||
<Link href="https://infisical.com/docs/integrations/cicd/circleci" passHref>
|
<Link href="https://infisical.com/docs/integrations/cicd/circleci" passHref>
|
||||||
<a target="_blank" rel="noopener noreferrer">
|
<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">
|
<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"/>
|
<FontAwesomeIcon icon={faBookOpen} className="mr-1.5" />
|
||||||
Docs
|
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>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
</Link>
|
</Link>
|
||||||
|
|||||||
@@ -3,13 +3,16 @@ import Head from "next/head";
|
|||||||
import Image from "next/image";
|
import Image from "next/image";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import { 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 { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||||
import queryString from "query-string";
|
import queryString from "query-string";
|
||||||
|
|
||||||
import {
|
import { useCreateIntegration } from "@app/hooks/api";
|
||||||
useCreateIntegration
|
|
||||||
} from "@app/hooks/api";
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
@@ -33,10 +36,13 @@ export default function CircleCICreateIntegrationPage() {
|
|||||||
const { integrationAuthId } = queryString.parse(router.asPath.split("?")[1]);
|
const { integrationAuthId } = queryString.parse(router.asPath.split("?")[1]);
|
||||||
|
|
||||||
const { data: workspace } = useGetWorkspaceById(localStorage.getItem("projectData.id") ?? "");
|
const { data: workspace } = useGetWorkspaceById(localStorage.getItem("projectData.id") ?? "");
|
||||||
const { data: integrationAuth, isLoading: isintegrationAuthLoading } = useGetIntegrationAuthById((integrationAuthId as string) ?? "");
|
const { data: integrationAuth, isLoading: isintegrationAuthLoading } = useGetIntegrationAuthById(
|
||||||
const { data: integrationAuthApps, isLoading: isIntegrationAuthAppsLoading } = useGetIntegrationAuthApps({
|
(integrationAuthId as string) ?? ""
|
||||||
integrationAuthId: (integrationAuthId as string) ?? ""
|
);
|
||||||
});
|
const { data: integrationAuthApps, isLoading: isIntegrationAuthAppsLoading } =
|
||||||
|
useGetIntegrationAuthApps({
|
||||||
|
integrationAuthId: (integrationAuthId as string) ?? ""
|
||||||
|
});
|
||||||
|
|
||||||
const [selectedSourceEnvironment, setSelectedSourceEnvironment] = useState("");
|
const [selectedSourceEnvironment, setSelectedSourceEnvironment] = useState("");
|
||||||
const [secretPath, setSecretPath] = useState("/");
|
const [secretPath, setSecretPath] = useState("/");
|
||||||
@@ -71,7 +77,9 @@ export default function CircleCICreateIntegrationPage() {
|
|||||||
integrationAuthId: integrationAuth?.id,
|
integrationAuthId: integrationAuth?.id,
|
||||||
isActive: true,
|
isActive: true,
|
||||||
app: targetApp,
|
app: targetApp,
|
||||||
appId: integrationAuthApps?.find((integrationAuthApp) => integrationAuthApp.name === targetApp)?.appId,
|
appId: integrationAuthApps?.find(
|
||||||
|
(integrationAuthApp) => integrationAuthApp.name === targetApp
|
||||||
|
)?.appId,
|
||||||
sourceEnvironment: selectedSourceEnvironment,
|
sourceEnvironment: selectedSourceEnvironment,
|
||||||
secretPath
|
secretPath
|
||||||
});
|
});
|
||||||
@@ -89,14 +97,14 @@ export default function CircleCICreateIntegrationPage() {
|
|||||||
selectedSourceEnvironment &&
|
selectedSourceEnvironment &&
|
||||||
integrationAuthApps &&
|
integrationAuthApps &&
|
||||||
targetApp ? (
|
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>
|
<Head>
|
||||||
<title>Set Up CircleCI Integration</title>
|
<title>Set Up CircleCI Integration</title>
|
||||||
<link rel='icon' href='/infisical.ico' />
|
<link rel="icon" href="/infisical.ico" />
|
||||||
</Head>
|
</Head>
|
||||||
<Card className="max-w-lg rounded-md border border-mineshaft-600">
|
<Card className="max-w-lg rounded-md border border-mineshaft-600">
|
||||||
<CardTitle
|
<CardTitle
|
||||||
className="text-left px-6 text-xl"
|
className="px-6 text-left text-xl"
|
||||||
subTitle="Choose which environment or folder in Infisical you want to sync to CircleCI environment variables."
|
subTitle="Choose which environment or folder in Infisical you want to sync to CircleCI environment variables."
|
||||||
>
|
>
|
||||||
<div className="flex flex-row items-center">
|
<div className="flex flex-row items-center">
|
||||||
@@ -111,10 +119,13 @@ export default function CircleCICreateIntegrationPage() {
|
|||||||
<span className="ml-1.5">CircleCI Integration </span>
|
<span className="ml-1.5">CircleCI Integration </span>
|
||||||
<Link href="https://infisical.com/docs/integrations/cicd/circleci" passHref>
|
<Link href="https://infisical.com/docs/integrations/cicd/circleci" passHref>
|
||||||
<a target="_blank" rel="noopener noreferrer">
|
<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">
|
<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"/>
|
<FontAwesomeIcon icon={faBookOpen} className="mr-1.5" />
|
||||||
Docs
|
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>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
</Link>
|
</Link>
|
||||||
@@ -177,31 +188,48 @@ export default function CircleCICreateIntegrationPage() {
|
|||||||
Create Integration
|
Create Integration
|
||||||
</Button>
|
</Button>
|
||||||
</Card>
|
</Card>
|
||||||
<div className="border-t border-mineshaft-800 w-full max-w-md mt-6"/>
|
<div className="mt-6 w-full max-w-md border-t border-mineshaft-800" />
|
||||||
<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="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-mineshaft-200 text-xl"/> <span className="ml-3 text-md text-mineshaft-100">Pro Tips</span></div>
|
<div className="flex flex-row items-center">
|
||||||
<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>
|
<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>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div className="flex justify-center items-center w-full h-full">
|
<div className="flex h-full w-full items-center justify-center">
|
||||||
<Head>
|
<Head>
|
||||||
<title>Set Up CircleCI Integration</title>
|
<title>Set Up CircleCI Integration</title>
|
||||||
<link rel='icon' href='/infisical.ico' />
|
<link rel="icon" href="/infisical.ico" />
|
||||||
</Head>
|
</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">
|
{isIntegrationAuthAppsLoading || isintegrationAuthLoading ? (
|
||||||
<FontAwesomeIcon icon={faBugs} className="text-6xl my-2 inlineli"/>
|
<img
|
||||||
<p>
|
src="/images/loading/loading.gif"
|
||||||
Something went wrong. Please contact <a
|
height={70}
|
||||||
className="inline underline underline-offset-4 decoration-primary-500 opacity-80 hover:opacity-100 text-mineshaft-100 duration-200 cursor-pointer"
|
width={120}
|
||||||
target="_blank"
|
alt="infisical loading indicator"
|
||||||
rel="noopener noreferrer"
|
/>
|
||||||
href="mailto:[email protected]"
|
) : (
|
||||||
>
|
<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">
|
||||||
support@infisical.com
|
<FontAwesomeIcon icon={faBugs} className="inlineli my-2 text-6xl" />
|
||||||
</a> if the issue persists.
|
<p>
|
||||||
</p>
|
Something went wrong. Please contact{" "}
|
||||||
</div>}
|
<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:[email protected]"
|
||||||
|
>
|
||||||
|
support@infisical.com
|
||||||
|
</a>{" "}
|
||||||
|
if the issue persists.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,7 @@
|
|||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
|
|
||||||
import {
|
import { useSaveIntegrationAccessToken } from "@app/hooks/api";
|
||||||
useSaveIntegrationAccessToken
|
|
||||||
} from "@app/hooks/api";
|
|
||||||
|
|
||||||
import { Button, Card, CardTitle, FormControl, Input } from "../../../components/v2";
|
import { Button, Card, CardTitle, FormControl, Input } from "../../../components/v2";
|
||||||
|
|
||||||
|
|||||||
@@ -2,9 +2,7 @@ import { useEffect, useState } from "react";
|
|||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import queryString from "query-string";
|
import queryString from "query-string";
|
||||||
|
|
||||||
import {
|
import { useCreateIntegration } from "@app/hooks/api";
|
||||||
useCreateIntegration
|
|
||||||
} from "@app/hooks/api";
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
@@ -16,8 +14,8 @@ import {
|
|||||||
SelectItem
|
SelectItem
|
||||||
} from "../../../components/v2";
|
} from "../../../components/v2";
|
||||||
import {
|
import {
|
||||||
useGetIntegrationAuthApps,
|
useGetIntegrationAuthApps,
|
||||||
useGetIntegrationAuthById,
|
useGetIntegrationAuthById
|
||||||
} from "../../../hooks/api/integrationAuth";
|
} from "../../../hooks/api/integrationAuth";
|
||||||
import { useGetWorkspaceById } from "../../../hooks/api/workspace";
|
import { useGetWorkspaceById } from "../../../hooks/api/workspace";
|
||||||
|
|
||||||
@@ -64,7 +62,9 @@ export default function Cloud66CreateIntegrationPage() {
|
|||||||
integrationAuthId: integrationAuth?.id,
|
integrationAuthId: integrationAuth?.id,
|
||||||
isActive: true,
|
isActive: true,
|
||||||
app: targetApp,
|
app: targetApp,
|
||||||
appId: integrationAuthApps?.find((integrationAuthApp) => integrationAuthApp.name === targetApp)?.appId,
|
appId: integrationAuthApps?.find(
|
||||||
|
(integrationAuthApp) => integrationAuthApp.name === targetApp
|
||||||
|
)?.appId,
|
||||||
sourceEnvironment: selectedSourceEnvironment,
|
sourceEnvironment: selectedSourceEnvironment,
|
||||||
secretPath
|
secretPath
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,92 +1,102 @@
|
|||||||
import { useState } from "react";
|
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 { useRouter } from "next/router";
|
||||||
|
import { faArrowUpRightFromSquare, faBookOpen } from "@fortawesome/free-solid-svg-icons";
|
||||||
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||||
|
|
||||||
import {
|
import { useSaveIntegrationAccessToken } from "@app/hooks/api";
|
||||||
useSaveIntegrationAccessToken
|
|
||||||
} from "@app/hooks/api";
|
|
||||||
|
|
||||||
import { Button,Card, CardTitle, FormControl, Input } from "../../../components/v2";
|
import { Button, Card, CardTitle, FormControl, Input } from "../../../components/v2";
|
||||||
|
|
||||||
export default function CloudflarePagesIntegrationPage() {
|
export default function RenderCreateIntegrationPage() {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { mutateAsync } = useSaveIntegrationAccessToken();
|
const { mutateAsync } = useSaveIntegrationAccessToken();
|
||||||
|
|
||||||
const [accessKey, setAccessKey] = useState("");
|
const [apiKey, setApiKey] = useState("");
|
||||||
const [accessKeyErrorText, setAccessKeyErrorText] = useState("");
|
const [apiKeyErrorText, setApiKeyErrorText] = useState("");
|
||||||
const [accountId, setAccountId] = useState("");
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
const [accountIdErrorText, setAccountIdErrorText] = useState("");
|
|
||||||
const [isLoading, setIsLoading] = useState(false);
|
|
||||||
|
|
||||||
const handleButtonClick = async () => {
|
const handleButtonClick = async () => {
|
||||||
try {
|
try {
|
||||||
setAccessKeyErrorText("");
|
setApiKeyErrorText("");
|
||||||
setAccountIdErrorText("");
|
if (apiKey.length === 0) {
|
||||||
if (accessKey.length === 0 || accountId.length === 0) {
|
setApiKeyErrorText("API Key cannot be blank");
|
||||||
if (accessKey.length === 0) setAccessKeyErrorText("API token cannot be blank!");
|
return;
|
||||||
if (accountId.length === 0) setAccountIdErrorText("Account ID cannot be blank!");
|
}
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
|
|
||||||
const integrationAuth = await mutateAsync({
|
const integrationAuth = await mutateAsync({
|
||||||
workspaceId: localStorage.getItem("projectData.id"),
|
workspaceId: localStorage.getItem("projectData.id"),
|
||||||
integration: "cloudflare-pages",
|
integration: "render",
|
||||||
accessId: accountId,
|
accessToken: apiKey
|
||||||
accessToken: accessKey
|
});
|
||||||
});
|
|
||||||
|
|
||||||
setAccessKey("");
|
setIsLoading(false);
|
||||||
setAccountId("");
|
|
||||||
setIsLoading(false);
|
|
||||||
|
|
||||||
router.push(`/integrations/cloudflare-pages/create?integrationAuthId=${integrationAuth.id}`);
|
router.push(`/integrations/render/create?integrationAuthId=${integrationAuth._id}`);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex h-full w-full items-center justify-center">
|
<div className="flex h-full w-full items-center justify-center">
|
||||||
<Card className="max-w-lg rounded-md border border-mineshaft-600 mb-12">
|
<Head>
|
||||||
<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>
|
<title>Authorize Render Integration</title>
|
||||||
<FormControl
|
<link rel="icon" href="/infisical.ico" />
|
||||||
label="Cloudflare Pages API token"
|
</Head>
|
||||||
errorText={accessKeyErrorText}
|
<Card className="mb-12 max-w-lg rounded-md border border-mineshaft-600">
|
||||||
isError={accessKeyErrorText !== "" ?? false}
|
<CardTitle
|
||||||
className="mx-6"
|
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."
|
||||||
<Input
|
>
|
||||||
placeholder=""
|
<div className="flex flex-row items-center">
|
||||||
value={accessKey}
|
<div className="inline flex items-center pb-0.5">
|
||||||
onChange={(e) => setAccessKey(e.target.value)}
|
<Image
|
||||||
/>
|
src="/images/integrations/Render.png"
|
||||||
</FormControl>
|
height={30}
|
||||||
<FormControl
|
width={30}
|
||||||
label="Cloudflare Pages Account ID"
|
alt="Render logo"
|
||||||
errorText={accountIdErrorText}
|
/>
|
||||||
isError={accountIdErrorText !== "" ?? false}
|
</div>
|
||||||
className="mx-6"
|
<span className="ml-2.5">Render Integration </span>
|
||||||
>
|
<Link href="https://infisical.com/docs/integrations/cloud/render" passHref>
|
||||||
<Input
|
<a target="_blank" rel="noopener noreferrer">
|
||||||
placeholder=""
|
<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">
|
||||||
value={accountId}
|
<FontAwesomeIcon icon={faBookOpen} className="mr-1.5" />
|
||||||
onChange={(e) => setAccountId(e.target.value)}
|
Docs
|
||||||
/>
|
<FontAwesomeIcon
|
||||||
</FormControl>
|
icon={faArrowUpRightFromSquare}
|
||||||
<Button
|
className="ml-1.5 mb-[0.07rem] text-xxs"
|
||||||
onClick={handleButtonClick}
|
/>
|
||||||
color="mineshaft"
|
</div>
|
||||||
variant="outline_bg"
|
</a>
|
||||||
className="mb-6 mt-2 ml-auto mr-6 w-min"
|
</Link>
|
||||||
isFullWidth={false}
|
</div>
|
||||||
isLoading={isLoading}
|
</CardTitle>
|
||||||
>
|
<FormControl
|
||||||
Connect to Cloudflare Pages
|
label="Render API Key"
|
||||||
</Button>
|
errorText={apiKeyErrorText}
|
||||||
</Card>
|
isError={apiKeyErrorText !== "" ?? false}
|
||||||
</div>
|
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;
|
||||||
|
|||||||
@@ -1,159 +1,165 @@
|
|||||||
import { useEffect,useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import queryString from "query-string";
|
import queryString from "query-string";
|
||||||
|
|
||||||
import {
|
import { useCreateIntegration, useGetWorkspaceById } from "@app/hooks/api";
|
||||||
useCreateIntegration
|
|
||||||
, useGetWorkspaceById } from "@app/hooks/api";
|
|
||||||
|
|
||||||
import { Button, Card, CardTitle, FormControl, Select, SelectItem } from "../../../components/v2";
|
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 = [
|
const cloudflareEnvironments = [
|
||||||
{ name: "Production", slug: "production" },
|
{ name: "Production", slug: "production" },
|
||||||
{ name: "Preview", slug: "preview" }
|
{ name: "Preview", slug: "preview" }
|
||||||
];
|
];
|
||||||
|
|
||||||
export default function CloudflarePagesIntegrationPage() {
|
export default function CloudflarePagesIntegrationPage() {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { mutateAsync } = useCreateIntegration();
|
const { mutateAsync } = useCreateIntegration();
|
||||||
|
|
||||||
const { integrationAuthId } = queryString.parse(router.asPath.split("?")[1]);
|
const { integrationAuthId } = queryString.parse(router.asPath.split("?")[1]);
|
||||||
const { data: workspace } = useGetWorkspaceById(localStorage.getItem("projectData.id") ?? "");
|
const { data: workspace } = useGetWorkspaceById(localStorage.getItem("projectData.id") ?? "");
|
||||||
const { data: integrationAuth } = useGetIntegrationAuthById((integrationAuthId as string) ?? "");
|
const { data: integrationAuth } = useGetIntegrationAuthById((integrationAuthId as string) ?? "");
|
||||||
const { data: integrationAuthApps } = useGetIntegrationAuthApps({
|
const { data: integrationAuthApps } = useGetIntegrationAuthApps({
|
||||||
integrationAuthId: (integrationAuthId as string) ?? ""
|
integrationAuthId: (integrationAuthId as string) ?? ""
|
||||||
});
|
});
|
||||||
|
|
||||||
const [selectedSourceEnvironment, setSelectedSourceEnvironment] = useState("");
|
const [selectedSourceEnvironment, setSelectedSourceEnvironment] = useState("");
|
||||||
const [targetApp, setTargetApp] = useState("");
|
const [targetApp, setTargetApp] = useState("");
|
||||||
const [targetAppId, setTargetAppId] = useState("");
|
const [targetAppId, setTargetAppId] = useState("");
|
||||||
const [targetEnvironment, setTargetEnvironment] = useState("");
|
const [targetEnvironment, setTargetEnvironment] = useState("");
|
||||||
|
|
||||||
const [isLoading, setIsLoading] = useState(false);
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (workspace) {
|
if (workspace) {
|
||||||
setSelectedSourceEnvironment(workspace.environments[0].slug);
|
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}, [workspace]);
|
||||||
|
|
||||||
return integrationAuth &&
|
useEffect(() => {
|
||||||
workspace &&
|
if (integrationAuthApps) {
|
||||||
selectedSourceEnvironment &&
|
if (integrationAuthApps.length > 0) {
|
||||||
integrationAuthApps &&
|
setTargetApp(integrationAuthApps[0].name);
|
||||||
targetEnvironment &&
|
setTargetAppId(String(integrationAuthApps[0].appId));
|
||||||
targetApp ? (
|
setTargetEnvironment(cloudflareEnvironments[0].slug);
|
||||||
<div className="flex h-full w-full items-center justify-center bg-gradient-to-tr from-mineshaft-900 to-bunker-900">
|
} else {
|
||||||
<Card className="max-w-lg rounded-md p-0 border border-mineshaft-600">
|
setTargetApp("none");
|
||||||
<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>
|
setTargetEnvironment(cloudflareEnvironments[0].slug);
|
||||||
<FormControl label="Infisical Project Environment" className="mt-2 px-6">
|
}
|
||||||
<Select
|
}
|
||||||
value={selectedSourceEnvironment}
|
}, [integrationAuthApps]);
|
||||||
onValueChange={(val) => setSelectedSourceEnvironment(val)}
|
|
||||||
className="w-full border border-mineshaft-500"
|
const handleButtonClick = async () => {
|
||||||
>
|
try {
|
||||||
{workspace?.environments.map((sourceEnvironment) => (
|
if (!integrationAuth?.id) return;
|
||||||
<SelectItem
|
|
||||||
value={sourceEnvironment.slug}
|
setIsLoading(true);
|
||||||
key={`source-environment-${sourceEnvironment.slug}`}
|
|
||||||
>
|
await mutateAsync({
|
||||||
{sourceEnvironment.name}
|
integrationAuthId: integrationAuth?.id,
|
||||||
</SelectItem>
|
isActive: true,
|
||||||
))}
|
app: targetApp,
|
||||||
</Select>
|
appId: targetAppId,
|
||||||
</FormControl>
|
sourceEnvironment: selectedSourceEnvironment,
|
||||||
<FormControl label="Cloudflare Pages Project" className="mt-4 px-6">
|
targetEnvironment,
|
||||||
<Select
|
secretPath: "/"
|
||||||
value={targetApp}
|
});
|
||||||
onValueChange={(val) => setTargetApp(val)}
|
|
||||||
className="w-full border border-mineshaft-500"
|
setIsLoading(false);
|
||||||
isDisabled={integrationAuthApps.length === 0}
|
|
||||||
>
|
router.push(`/integrations/${localStorage.getItem("projectData.id")}`);
|
||||||
{integrationAuthApps.length > 0 ? (
|
} catch (err) {
|
||||||
integrationAuthApps.map((integrationAuthApp) => (
|
console.error(err);
|
||||||
<SelectItem
|
}
|
||||||
value={integrationAuthApp.name}
|
};
|
||||||
key={`target-app-${integrationAuthApp.name}`}
|
|
||||||
>
|
return integrationAuth &&
|
||||||
{integrationAuthApp.name}
|
workspace &&
|
||||||
</SelectItem>
|
selectedSourceEnvironment &&
|
||||||
))
|
integrationAuthApps &&
|
||||||
) : (
|
targetEnvironment &&
|
||||||
<SelectItem value="none" key="target-app-none">
|
targetApp ? (
|
||||||
No apps found
|
<div className="flex h-full w-full items-center justify-center bg-gradient-to-tr from-mineshaft-900 to-bunker-900">
|
||||||
</SelectItem>
|
<Card className="max-w-lg rounded-md border border-mineshaft-600 p-0">
|
||||||
)}
|
<CardTitle
|
||||||
</Select>
|
className="px-6 text-left"
|
||||||
</FormControl>
|
subTitle="Choose which environment in Infisical you want to sync with your Cloudflare Pages project."
|
||||||
<FormControl label="Cloudflare Pages Environment" className="mt-4 px-6">
|
>
|
||||||
<Select
|
Cloudflare Pages Integration
|
||||||
value={targetEnvironment}
|
</CardTitle>
|
||||||
onValueChange={(val) => setTargetEnvironment(val)}
|
<FormControl label="Infisical Project Environment" className="mt-2 px-6">
|
||||||
className="w-full border border-mineshaft-500"
|
<Select
|
||||||
>
|
value={selectedSourceEnvironment}
|
||||||
{cloudflareEnvironments.map((cloudflareEnvironment) => (
|
onValueChange={(val) => setSelectedSourceEnvironment(val)}
|
||||||
<SelectItem
|
className="w-full border border-mineshaft-500"
|
||||||
value={cloudflareEnvironment.slug}
|
>
|
||||||
key={`target-environment-${cloudflareEnvironment.slug}`}
|
{workspace?.environments.map((sourceEnvironment) => (
|
||||||
>
|
<SelectItem
|
||||||
{cloudflareEnvironment.name}
|
value={sourceEnvironment.slug}
|
||||||
</SelectItem>
|
key={`source-environment-${sourceEnvironment.slug}`}
|
||||||
))}
|
>
|
||||||
</Select>
|
{sourceEnvironment.name}
|
||||||
</FormControl>
|
</SelectItem>
|
||||||
<Button
|
))}
|
||||||
onClick={handleButtonClick}
|
</Select>
|
||||||
color="mineshaft"
|
</FormControl>
|
||||||
variant="outline_bg"
|
<FormControl label="Cloudflare Pages Project" className="mt-4 px-6">
|
||||||
className="mt-2 mb-6 ml-auto mr-6"
|
<Select
|
||||||
isFullWidth={false}
|
value={targetApp}
|
||||||
isLoading={isLoading}
|
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
|
{integrationAuthApp.name}
|
||||||
</Button>
|
</SelectItem>
|
||||||
</Card>
|
))
|
||||||
</div>
|
) : (
|
||||||
) : (
|
<SelectItem value="none" key="target-app-none">
|
||||||
<div />
|
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;
|
||||||
|
|||||||
@@ -1,92 +1,89 @@
|
|||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
|
|
||||||
import {
|
import { useSaveIntegrationAccessToken } from "@app/hooks/api";
|
||||||
useSaveIntegrationAccessToken
|
|
||||||
} from "@app/hooks/api";
|
|
||||||
|
|
||||||
import { Button,Card, CardTitle, FormControl, Input } from "../../../components/v2";
|
import { Button, Card, CardTitle, FormControl, Input } from "../../../components/v2";
|
||||||
|
|
||||||
export default function CloudflareWorkersIntegrationPage() {
|
export default function CloudflareWorkersIntegrationPage() {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { mutateAsync } = useSaveIntegrationAccessToken();
|
const { mutateAsync } = useSaveIntegrationAccessToken();
|
||||||
|
|
||||||
const [accessKey, setAccessKey] = useState("");
|
const [accessKey, setAccessKey] = useState("");
|
||||||
const [accessKeyErrorText, setAccessKeyErrorText] = useState("");
|
const [accessKeyErrorText, setAccessKeyErrorText] = useState("");
|
||||||
const [accountId, setAccountId] = useState("");
|
const [accountId, setAccountId] = useState("");
|
||||||
const [accountIdErrorText, setAccountIdErrorText] = useState("");
|
const [accountIdErrorText, setAccountIdErrorText] = useState("");
|
||||||
const [isLoading, setIsLoading] = useState(false);
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
|
|
||||||
const handleButtonClick = async () => {
|
const handleButtonClick = async () => {
|
||||||
try {
|
try {
|
||||||
setAccessKeyErrorText("");
|
setAccessKeyErrorText("");
|
||||||
setAccountIdErrorText("");
|
setAccountIdErrorText("");
|
||||||
if (accessKey.length === 0 || accountId.length === 0) {
|
if (accessKey.length === 0 || accountId.length === 0) {
|
||||||
if (accessKey.length === 0) setAccessKeyErrorText("API token cannot be blank!");
|
if (accessKey.length === 0) setAccessKeyErrorText("API token cannot be blank!");
|
||||||
if (accountId.length === 0) setAccountIdErrorText("Account ID cannot be blank!");
|
if (accountId.length === 0) setAccountIdErrorText("Account ID cannot be blank!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
|
|
||||||
const integrationAuth = await mutateAsync({
|
const integrationAuth = await mutateAsync({
|
||||||
workspaceId: localStorage.getItem("projectData.id"),
|
workspaceId: localStorage.getItem("projectData.id"),
|
||||||
integration: "cloudflare-workers",
|
integration: "cloudflare-workers",
|
||||||
accessId: accountId,
|
accessId: accountId,
|
||||||
accessToken: accessKey
|
accessToken: accessKey
|
||||||
});
|
});
|
||||||
|
|
||||||
setAccessKey("");
|
setAccessKey("");
|
||||||
setAccountId("");
|
setAccountId("");
|
||||||
setIsLoading(false);
|
setIsLoading(false);
|
||||||
|
|
||||||
router.push(`/integrations/cloudflare-workers/create?integrationAuthId=${integrationAuth.id}`);
|
router.push(
|
||||||
} catch (err) {
|
`/integrations/cloudflare-workers/create?integrationAuthId=${integrationAuth.id}`
|
||||||
console.error(err);
|
);
|
||||||
}
|
} catch (err) {
|
||||||
|
console.error(err);
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex h-full w-full items-center justify-center">
|
<div className="flex h-full w-full items-center justify-center">
|
||||||
<Card className="max-w-lg rounded-md border border-mineshaft-600 mb-12">
|
<Card className="mb-12 max-w-lg rounded-md border border-mineshaft-600">
|
||||||
<CardTitle className="text-left px-6" subTitle="After adding your API-key, you will be prompted to set up an integration for a particular Infisical project and environment.">Cloudflare Workers Integration</CardTitle>
|
<CardTitle
|
||||||
<FormControl
|
className="px-6 text-left"
|
||||||
label="Cloudflare Workers API token"
|
subTitle="After adding your API-key, you will be prompted to set up an integration for a particular Infisical project and environment."
|
||||||
errorText={accessKeyErrorText}
|
>
|
||||||
isError={accessKeyErrorText !== "" ?? false}
|
Cloudflare Workers Integration
|
||||||
className="mx-6"
|
</CardTitle>
|
||||||
>
|
<FormControl
|
||||||
<Input
|
label="Cloudflare Workers API token"
|
||||||
placeholder=""
|
errorText={accessKeyErrorText}
|
||||||
value={accessKey}
|
isError={accessKeyErrorText !== "" ?? false}
|
||||||
onChange={(e) => setAccessKey(e.target.value)}
|
className="mx-6"
|
||||||
/>
|
>
|
||||||
</FormControl>
|
<Input placeholder="" value={accessKey} onChange={(e) => setAccessKey(e.target.value)} />
|
||||||
<FormControl
|
</FormControl>
|
||||||
label="Cloudflare Workers Account ID"
|
<FormControl
|
||||||
errorText={accountIdErrorText}
|
label="Cloudflare Workers Account ID"
|
||||||
isError={accountIdErrorText !== "" ?? false}
|
errorText={accountIdErrorText}
|
||||||
className="mx-6"
|
isError={accountIdErrorText !== "" ?? false}
|
||||||
>
|
className="mx-6"
|
||||||
<Input
|
>
|
||||||
placeholder=""
|
<Input placeholder="" value={accountId} onChange={(e) => setAccountId(e.target.value)} />
|
||||||
value={accountId}
|
</FormControl>
|
||||||
onChange={(e) => setAccountId(e.target.value)}
|
<Button
|
||||||
/>
|
onClick={handleButtonClick}
|
||||||
</FormControl>
|
color="mineshaft"
|
||||||
<Button
|
variant="outline_bg"
|
||||||
onClick={handleButtonClick}
|
className="mb-6 mt-2 ml-auto mr-6 w-min"
|
||||||
color="mineshaft"
|
isFullWidth={false}
|
||||||
variant="outline_bg"
|
isLoading={isLoading}
|
||||||
className="mb-6 mt-2 ml-auto mr-6 w-min"
|
>
|
||||||
isFullWidth={false}
|
Connect to Cloudflare Workers
|
||||||
isLoading={isLoading}
|
</Button>
|
||||||
>
|
</Card>
|
||||||
Connect to Cloudflare Workers
|
</div>
|
||||||
</Button>
|
);
|
||||||
</Card>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CloudflareWorkersIntegrationPage.requireAuth = true;
|
CloudflareWorkersIntegrationPage.requireAuth = true;
|
||||||
|
|||||||
@@ -1,133 +1,139 @@
|
|||||||
import { useEffect,useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import queryString from "query-string";
|
import queryString from "query-string";
|
||||||
|
|
||||||
import {
|
import { useCreateIntegration, useGetWorkspaceById } from "@app/hooks/api";
|
||||||
useCreateIntegration
|
|
||||||
, useGetWorkspaceById } from "@app/hooks/api";
|
|
||||||
|
|
||||||
import { Button, Card, CardTitle, FormControl, Select, SelectItem } from "../../../components/v2";
|
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() {
|
export default function CloudflareWorkersIntegrationPage() {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { mutateAsync } = useCreateIntegration();
|
const { mutateAsync } = useCreateIntegration();
|
||||||
|
|
||||||
const { integrationAuthId } = queryString.parse(router.asPath.split("?")[1]);
|
const { integrationAuthId } = queryString.parse(router.asPath.split("?")[1]);
|
||||||
const { data: workspace } = useGetWorkspaceById(localStorage.getItem("projectData.id") ?? "");
|
const { data: workspace } = useGetWorkspaceById(localStorage.getItem("projectData.id") ?? "");
|
||||||
const { data: integrationAuth } = useGetIntegrationAuthById((integrationAuthId as string) ?? "");
|
const { data: integrationAuth } = useGetIntegrationAuthById((integrationAuthId as string) ?? "");
|
||||||
const { data: integrationAuthApps } = useGetIntegrationAuthApps({
|
const { data: integrationAuthApps } = useGetIntegrationAuthApps({
|
||||||
integrationAuthId: (integrationAuthId as string) ?? ""
|
integrationAuthId: (integrationAuthId as string) ?? ""
|
||||||
});
|
});
|
||||||
|
|
||||||
const [selectedSourceEnvironment, setSelectedSourceEnvironment] = useState("");
|
const [selectedSourceEnvironment, setSelectedSourceEnvironment] = useState("");
|
||||||
const [targetApp, setTargetApp] = useState("");
|
const [targetApp, setTargetApp] = useState("");
|
||||||
const [targetAppId, setTargetAppId] = useState("");
|
const [targetAppId, setTargetAppId] = useState("");
|
||||||
|
|
||||||
const [isLoading, setIsLoading] = useState(false);
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (workspace) {
|
if (workspace) {
|
||||||
setSelectedSourceEnvironment(workspace.environments[0].slug);
|
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}, [workspace]);
|
||||||
|
|
||||||
return integrationAuth &&
|
useEffect(() => {
|
||||||
workspace &&
|
if (integrationAuthApps) {
|
||||||
selectedSourceEnvironment &&
|
if (integrationAuthApps.length > 0) {
|
||||||
integrationAuthApps &&
|
setTargetApp(integrationAuthApps[0].name);
|
||||||
targetApp ? (
|
setTargetAppId(String(integrationAuthApps[0].appId));
|
||||||
<div className="flex h-full w-full items-center justify-center bg-gradient-to-tr from-mineshaft-900 to-bunker-900">
|
} else {
|
||||||
<Card className="max-w-lg rounded-md p-0 border border-mineshaft-600">
|
setTargetApp("none");
|
||||||
<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
|
}, [integrationAuthApps]);
|
||||||
value={selectedSourceEnvironment}
|
|
||||||
onValueChange={(val) => setSelectedSourceEnvironment(val)}
|
const handleButtonClick = async () => {
|
||||||
className="w-full border border-mineshaft-500"
|
try {
|
||||||
>
|
if (!integrationAuth?._id) return;
|
||||||
{workspace?.environments.map((sourceEnvironment) => (
|
|
||||||
<SelectItem
|
setIsLoading(true);
|
||||||
value={sourceEnvironment.slug}
|
|
||||||
key={`source-environment-${sourceEnvironment.slug}`}
|
await mutateAsync({
|
||||||
>
|
integrationAuthId: integrationAuth?._id,
|
||||||
{sourceEnvironment.name}
|
isActive: true,
|
||||||
</SelectItem>
|
app: targetApp,
|
||||||
))}
|
appId: targetAppId,
|
||||||
</Select>
|
sourceEnvironment: selectedSourceEnvironment,
|
||||||
</FormControl>
|
secretPath: "/"
|
||||||
<FormControl label="Cloudflare Workers Project" className="mt-4 px-6">
|
});
|
||||||
<Select
|
|
||||||
value={targetApp}
|
setIsLoading(false);
|
||||||
onValueChange={(val) => setTargetApp(val)}
|
|
||||||
className="w-full border border-mineshaft-500"
|
router.push(`/integrations/${localStorage.getItem("projectData.id")}`);
|
||||||
isDisabled={integrationAuthApps.length === 0}
|
} catch (err) {
|
||||||
>
|
console.error(err);
|
||||||
{integrationAuthApps.length > 0 ? (
|
}
|
||||||
integrationAuthApps.map((integrationAuthApp) => (
|
};
|
||||||
<SelectItem
|
|
||||||
value={integrationAuthApp.name}
|
return integrationAuth &&
|
||||||
key={`target-app-${integrationAuthApp.name}`}
|
workspace &&
|
||||||
>
|
selectedSourceEnvironment &&
|
||||||
{integrationAuthApp.name}
|
integrationAuthApps &&
|
||||||
</SelectItem>
|
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">
|
||||||
<SelectItem value="none" key="target-app-none">
|
<CardTitle
|
||||||
No apps found
|
className="px-6 text-left"
|
||||||
</SelectItem>
|
subTitle="Choose which environment in Infisical you want to sync with your Cloudflare Workers project."
|
||||||
)}
|
>
|
||||||
</Select>
|
Cloudflare Workers Integration
|
||||||
</FormControl>
|
</CardTitle>
|
||||||
<Button
|
<FormControl label="Infisical Project Environment" className="mt-2 px-6">
|
||||||
onClick={handleButtonClick}
|
<Select
|
||||||
color="mineshaft"
|
value={selectedSourceEnvironment}
|
||||||
variant="outline_bg"
|
onValueChange={(val) => setSelectedSourceEnvironment(val)}
|
||||||
className="mt-2 mb-6 ml-auto mr-6"
|
className="w-full border border-mineshaft-500"
|
||||||
isFullWidth={false}
|
>
|
||||||
isLoading={isLoading}
|
{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
|
{integrationAuthApp.name}
|
||||||
</Button>
|
</SelectItem>
|
||||||
</Card>
|
))
|
||||||
</div>
|
) : (
|
||||||
) : (
|
<SelectItem value="none" key="target-app-none">
|
||||||
<div />
|
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;
|
||||||
|
|||||||
@@ -1,9 +1,7 @@
|
|||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
|
|
||||||
import {
|
import { useSaveIntegrationAccessToken } from "@app/hooks/api";
|
||||||
useSaveIntegrationAccessToken
|
|
||||||
} from "@app/hooks/api";
|
|
||||||
|
|
||||||
import { Button, Card, CardTitle, FormControl, Input } from "../../../components/v2";
|
import { Button, Card, CardTitle, FormControl, Input } from "../../../components/v2";
|
||||||
|
|
||||||
|
|||||||
@@ -2,9 +2,7 @@ import { useEffect, useState } from "react";
|
|||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import queryString from "query-string";
|
import queryString from "query-string";
|
||||||
|
|
||||||
import {
|
import { useCreateIntegration } from "@app/hooks/api";
|
||||||
useCreateIntegration
|
|
||||||
} from "@app/hooks/api";
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
@@ -64,7 +62,9 @@ export default function CodefreshCreateIntegrationPage() {
|
|||||||
integrationAuthId: integrationAuth?.id,
|
integrationAuthId: integrationAuth?.id,
|
||||||
isActive: true,
|
isActive: true,
|
||||||
app: targetApp,
|
app: targetApp,
|
||||||
appId: integrationAuthApps?.find((integrationAuthApp) => integrationAuthApp.name === targetApp)?.appId,
|
appId: integrationAuthApps?.find(
|
||||||
|
(integrationAuthApp) => integrationAuthApp.name === targetApp
|
||||||
|
)?.appId,
|
||||||
sourceEnvironment: selectedSourceEnvironment,
|
sourceEnvironment: selectedSourceEnvironment,
|
||||||
secretPath
|
secretPath
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,16 +1,14 @@
|
|||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
|
|
||||||
import {
|
import { useSaveIntegrationAccessToken } from "@app/hooks/api";
|
||||||
useSaveIntegrationAccessToken
|
|
||||||
} from "@app/hooks/api";
|
|
||||||
|
|
||||||
import { Button, Card, CardTitle, FormControl, Input } from "../../../components/v2";
|
import { Button, Card, CardTitle, FormControl, Input } from "../../../components/v2";
|
||||||
|
|
||||||
export default function DigitalOceanAppPlatformCreateIntegrationPage() {
|
export default function DigitalOceanAppPlatformCreateIntegrationPage() {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { mutateAsync } = useSaveIntegrationAccessToken();
|
const { mutateAsync } = useSaveIntegrationAccessToken();
|
||||||
|
|
||||||
const [apiKey, setApiKey] = useState("");
|
const [apiKey, setApiKey] = useState("");
|
||||||
const [apiKeyErrorText, setApiKeyErrorText] = useState("");
|
const [apiKeyErrorText, setApiKeyErrorText] = useState("");
|
||||||
const [isLoading, setIsLoading] = useState(false);
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
@@ -33,7 +31,9 @@ export default function DigitalOceanAppPlatformCreateIntegrationPage() {
|
|||||||
|
|
||||||
setIsLoading(false);
|
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) {
|
} catch (err) {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,9 +2,7 @@ import { useEffect, useState } from "react";
|
|||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import queryString from "query-string";
|
import queryString from "query-string";
|
||||||
|
|
||||||
import {
|
import { useCreateIntegration } from "@app/hooks/api";
|
||||||
useCreateIntegration
|
|
||||||
} from "@app/hooks/api";
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
@@ -64,7 +62,9 @@ export default function DigitalOceanAppPlatformCreateIntegrationPage() {
|
|||||||
integrationAuthId: integrationAuth?.id,
|
integrationAuthId: integrationAuth?.id,
|
||||||
isActive: true,
|
isActive: true,
|
||||||
app: targetApp,
|
app: targetApp,
|
||||||
appId: integrationAuthApps?.find((integrationAuthApp) => integrationAuthApp.name === targetApp)?.appId,
|
appId: integrationAuthApps?.find(
|
||||||
|
(integrationAuthApp) => integrationAuthApp.name === targetApp
|
||||||
|
)?.appId,
|
||||||
sourceEnvironment: selectedSourceEnvironment,
|
sourceEnvironment: selectedSourceEnvironment,
|
||||||
secretPath
|
secretPath
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -9,9 +9,7 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
|||||||
import { yupResolver } from "@hookform/resolvers/yup";
|
import { yupResolver } from "@hookform/resolvers/yup";
|
||||||
import * as yup from "yup";
|
import * as yup from "yup";
|
||||||
|
|
||||||
import {
|
import { useSaveIntegrationAccessToken } from "@app/hooks/api";
|
||||||
useSaveIntegrationAccessToken
|
|
||||||
} from "@app/hooks/api";
|
|
||||||
|
|
||||||
import { Button, Card, CardTitle, FormControl, Input } from "../../../components/v2";
|
import { Button, Card, CardTitle, FormControl, Input } from "../../../components/v2";
|
||||||
|
|
||||||
@@ -24,10 +22,7 @@ type FormData = yup.InferType<typeof schema>;
|
|||||||
export default function FlyioAuthorizeIntegrationPage() {
|
export default function FlyioAuthorizeIntegrationPage() {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
const {
|
const { control, handleSubmit } = useForm<FormData>({
|
||||||
control,
|
|
||||||
handleSubmit
|
|
||||||
} = useForm<FormData>({
|
|
||||||
resolver: yupResolver(schema),
|
resolver: yupResolver(schema),
|
||||||
defaultValues: {
|
defaultValues: {
|
||||||
accessToken: ""
|
accessToken: ""
|
||||||
@@ -35,38 +30,36 @@ export default function FlyioAuthorizeIntegrationPage() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const { mutateAsync } = useSaveIntegrationAccessToken();
|
const { mutateAsync } = useSaveIntegrationAccessToken();
|
||||||
|
|
||||||
const [isLoading, setIsLoading] = useState(false);
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
|
|
||||||
const onFormSubmit = async ({
|
const onFormSubmit = async ({ accessToken }: FormData) => {
|
||||||
accessToken
|
|
||||||
}: FormData) => {
|
|
||||||
try {
|
try {
|
||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
|
|
||||||
const integrationAuth = await mutateAsync({
|
const integrationAuth = await mutateAsync({
|
||||||
workspaceId: localStorage.getItem("projectData.id"),
|
workspaceId: localStorage.getItem("projectData.id"),
|
||||||
integration: "flyio",
|
integration: "flyio",
|
||||||
accessToken
|
accessToken
|
||||||
});
|
});
|
||||||
|
|
||||||
setIsLoading(false);
|
setIsLoading(false);
|
||||||
router.push(`/integrations/flyio/create?integrationAuthId=${integrationAuth.id}`);
|
router.push(`/integrations/flyio/create?integrationAuthId=${integrationAuth.id}`);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
setIsLoading(false);
|
setIsLoading(false);
|
||||||
console.error(err);
|
console.error(err);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex h-full w-full items-center justify-center">
|
<div className="flex h-full w-full items-center justify-center">
|
||||||
<Head>
|
<Head>
|
||||||
<title>Authorize Fly.io Integration</title>
|
<title>Authorize Fly.io Integration</title>
|
||||||
<link rel='icon' href='/infisical.ico' />
|
<link rel="icon" href="/infisical.ico" />
|
||||||
</Head>
|
</Head>
|
||||||
<Card className="max-w-lg rounded-md border border-mineshaft-600 mb-12">
|
<Card className="mb-12 max-w-lg rounded-md border border-mineshaft-600">
|
||||||
<CardTitle
|
<CardTitle
|
||||||
className="text-left px-6 text-xl"
|
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."
|
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">
|
<div className="flex flex-row items-center">
|
||||||
@@ -81,19 +74,19 @@ export default function FlyioAuthorizeIntegrationPage() {
|
|||||||
<span className="ml-2.5">Fly.io Integration </span>
|
<span className="ml-2.5">Fly.io Integration </span>
|
||||||
<Link href="https://infisical.com/docs/integrations/cloud/flyio" passHref>
|
<Link href="https://infisical.com/docs/integrations/cloud/flyio" passHref>
|
||||||
<a target="_blank" rel="noopener noreferrer">
|
<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">
|
<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"/>
|
<FontAwesomeIcon icon={faBookOpen} className="mr-1.5" />
|
||||||
Docs
|
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>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
</CardTitle>
|
</CardTitle>
|
||||||
<form
|
<form onSubmit={handleSubmit(onFormSubmit)} className="px-6 pb-8 text-right">
|
||||||
onSubmit={handleSubmit(onFormSubmit)}
|
|
||||||
className="px-6 text-right pb-8"
|
|
||||||
>
|
|
||||||
<Controller
|
<Controller
|
||||||
control={control}
|
control={control}
|
||||||
name="accessToken"
|
name="accessToken"
|
||||||
@@ -103,10 +96,7 @@ export default function FlyioAuthorizeIntegrationPage() {
|
|||||||
errorText={error?.message}
|
errorText={error?.message}
|
||||||
isError={Boolean(error)}
|
isError={Boolean(error)}
|
||||||
>
|
>
|
||||||
<Input
|
<Input {...field} placeholder="" />
|
||||||
{...field}
|
|
||||||
placeholder=""
|
|
||||||
/>
|
|
||||||
</FormControl>
|
</FormControl>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -3,13 +3,16 @@ import Head from "next/head";
|
|||||||
import Image from "next/image";
|
import Image from "next/image";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import { 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 { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||||
import queryString from "query-string";
|
import queryString from "query-string";
|
||||||
|
|
||||||
import {
|
import { useCreateIntegration } from "@app/hooks/api";
|
||||||
useCreateIntegration
|
|
||||||
} from "@app/hooks/api";
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
@@ -28,16 +31,19 @@ import { useGetWorkspaceById } from "../../../hooks/api/workspace";
|
|||||||
|
|
||||||
export default function FlyioCreateIntegrationPage() {
|
export default function FlyioCreateIntegrationPage() {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
const { mutateAsync } = useCreateIntegration();
|
const { mutateAsync } = useCreateIntegration();
|
||||||
|
|
||||||
const { integrationAuthId } = queryString.parse(router.asPath.split("?")[1]);
|
const { integrationAuthId } = queryString.parse(router.asPath.split("?")[1]);
|
||||||
|
|
||||||
const { data: workspace } = useGetWorkspaceById(localStorage.getItem("projectData.id") ?? "");
|
const { data: workspace } = useGetWorkspaceById(localStorage.getItem("projectData.id") ?? "");
|
||||||
const { data: integrationAuth, isLoading: isIntegrationAuthLoading } = useGetIntegrationAuthById((integrationAuthId as string) ?? "");
|
const { data: integrationAuth, isLoading: isIntegrationAuthLoading } = useGetIntegrationAuthById(
|
||||||
const { data: integrationAuthApps, isLoading: isIntegrationAuthAppsLoading } = useGetIntegrationAuthApps({
|
(integrationAuthId as string) ?? ""
|
||||||
integrationAuthId: (integrationAuthId as string) ?? ""
|
);
|
||||||
});
|
const { data: integrationAuthApps, isLoading: isIntegrationAuthAppsLoading } =
|
||||||
|
useGetIntegrationAuthApps({
|
||||||
|
integrationAuthId: (integrationAuthId as string) ?? ""
|
||||||
|
});
|
||||||
|
|
||||||
const [selectedSourceEnvironment, setSelectedSourceEnvironment] = useState("");
|
const [selectedSourceEnvironment, setSelectedSourceEnvironment] = useState("");
|
||||||
const [secretPath, setSecretPath] = useState("/");
|
const [secretPath, setSecretPath] = useState("/");
|
||||||
@@ -90,14 +96,14 @@ export default function FlyioCreateIntegrationPage() {
|
|||||||
selectedSourceEnvironment &&
|
selectedSourceEnvironment &&
|
||||||
integrationAuthApps &&
|
integrationAuthApps &&
|
||||||
targetApp ? (
|
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>
|
<Head>
|
||||||
<title>Set Up Fly.io Integration</title>
|
<title>Set Up Fly.io Integration</title>
|
||||||
<link rel='icon' href='/infisical.ico' />
|
<link rel="icon" href="/infisical.ico" />
|
||||||
</Head>
|
</Head>
|
||||||
<Card className="max-w-lg rounded-md border border-mineshaft-600">
|
<Card className="max-w-lg rounded-md border border-mineshaft-600">
|
||||||
<CardTitle
|
<CardTitle
|
||||||
className="text-left px-6 text-xl"
|
className="px-6 text-left text-xl"
|
||||||
subTitle="Choose which environment or folder in Infisical you want to sync to Fly.io environment variables."
|
subTitle="Choose which environment or folder in Infisical you want to sync to Fly.io environment variables."
|
||||||
>
|
>
|
||||||
<div className="flex flex-row items-center">
|
<div className="flex flex-row items-center">
|
||||||
@@ -112,10 +118,13 @@ export default function FlyioCreateIntegrationPage() {
|
|||||||
<span className="ml-2.5">Fly.io Integration </span>
|
<span className="ml-2.5">Fly.io Integration </span>
|
||||||
<Link href="https://infisical.com/docs/integrations/cloud/flyio" passHref>
|
<Link href="https://infisical.com/docs/integrations/cloud/flyio" passHref>
|
||||||
<a target="_blank" rel="noopener noreferrer">
|
<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">
|
<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"/>
|
<FontAwesomeIcon icon={faBookOpen} className="mr-1.5" />
|
||||||
Docs
|
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>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
</Link>
|
</Link>
|
||||||
@@ -178,31 +187,48 @@ export default function FlyioCreateIntegrationPage() {
|
|||||||
Create Integration
|
Create Integration
|
||||||
</Button>
|
</Button>
|
||||||
</Card>
|
</Card>
|
||||||
<div className="border-t border-mineshaft-800 w-full max-w-md mt-6"/>
|
<div className="mt-6 w-full max-w-md border-t border-mineshaft-800" />
|
||||||
<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="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-mineshaft-200 text-xl"/> <span className="ml-3 text-md text-mineshaft-100">Pro Tips</span></div>
|
<div className="flex flex-row items-center">
|
||||||
<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>
|
<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>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div className="flex justify-center items-center w-full h-full">
|
<div className="flex h-full w-full items-center justify-center">
|
||||||
<Head>
|
<Head>
|
||||||
<title>Set Up Fly.io Integration</title>
|
<title>Set Up Fly.io Integration</title>
|
||||||
<link rel='icon' href='/infisical.ico' />
|
<link rel="icon" href="/infisical.ico" />
|
||||||
</Head>
|
</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">
|
{isIntegrationAuthLoading || isIntegrationAuthAppsLoading ? (
|
||||||
<FontAwesomeIcon icon={faBugs} className="text-6xl my-2 inlineli"/>
|
<img
|
||||||
<p>
|
src="/images/loading/loading.gif"
|
||||||
Something went wrong. Please contact <a
|
height={70}
|
||||||
className="inline underline underline-offset-4 decoration-primary-500 opacity-80 hover:opacity-100 text-mineshaft-100 duration-200 cursor-pointer"
|
width={120}
|
||||||
target="_blank"
|
alt="infisical loading indicator"
|
||||||
rel="noopener noreferrer"
|
/>
|
||||||
href="mailto:[email protected]"
|
) : (
|
||||||
>
|
<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">
|
||||||
support@infisical.com
|
<FontAwesomeIcon icon={faBugs} className="inlineli my-2 text-6xl" />
|
||||||
</a> if the issue persists.
|
<p>
|
||||||
</p>
|
Something went wrong. Please contact{" "}
|
||||||
</div>}
|
<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:[email protected]"
|
||||||
|
>
|
||||||
|
support@infisical.com
|
||||||
|
</a>{" "}
|
||||||
|
if the issue persists.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,9 +12,7 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
|||||||
import { yupResolver } from "@hookform/resolvers/yup";
|
import { yupResolver } from "@hookform/resolvers/yup";
|
||||||
import * as yup from "yup";
|
import * as yup from "yup";
|
||||||
|
|
||||||
import {
|
import { useGetCloudIntegrations, useSaveIntegrationAccessToken } from "@app/hooks/api";
|
||||||
useGetCloudIntegrations,
|
|
||||||
useSaveIntegrationAccessToken} from "@app/hooks/api";
|
|
||||||
|
|
||||||
import { Button, Card, CardTitle, FormControl, TextArea } from "../../../components/v2";
|
import { Button, Card, CardTitle, FormControl, TextArea } from "../../../components/v2";
|
||||||
|
|
||||||
@@ -27,61 +25,60 @@ type FormData = yup.InferType<typeof schema>;
|
|||||||
export default function GCPSecretManagerAuthorizeIntegrationPage() {
|
export default function GCPSecretManagerAuthorizeIntegrationPage() {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
const {
|
const { control, handleSubmit } = useForm<FormData>({
|
||||||
control,
|
|
||||||
handleSubmit
|
|
||||||
} = useForm<FormData>({
|
|
||||||
resolver: yupResolver(schema)
|
resolver: yupResolver(schema)
|
||||||
});
|
});
|
||||||
|
|
||||||
const { data: cloudIntegrations } = useGetCloudIntegrations();
|
const { data: cloudIntegrations } = useGetCloudIntegrations();
|
||||||
|
|
||||||
const { mutateAsync } = useSaveIntegrationAccessToken();
|
const { mutateAsync } = useSaveIntegrationAccessToken();
|
||||||
|
|
||||||
const [isLoading, setIsLoading] = useState(false);
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
|
|
||||||
const handleIntegrateWithOAuth = () => {
|
const handleIntegrateWithOAuth = () => {
|
||||||
if (!cloudIntegrations) return;
|
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;
|
if (!integrationOption) return;
|
||||||
|
|
||||||
const state = crypto.randomBytes(16).toString("hex");
|
const state = crypto.randomBytes(16).toString("hex");
|
||||||
localStorage.setItem("latestCSRFToken", state);
|
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}`;
|
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);
|
window.location.assign(link);
|
||||||
}
|
};
|
||||||
|
|
||||||
const onFormSubmit = async ({
|
const onFormSubmit = async ({ accessToken }: FormData) => {
|
||||||
accessToken
|
|
||||||
}: FormData) => {
|
|
||||||
try {
|
try {
|
||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
|
|
||||||
const integrationAuth = await mutateAsync({
|
const integrationAuth = await mutateAsync({
|
||||||
workspaceId: localStorage.getItem("projectData.id"),
|
workspaceId: localStorage.getItem("projectData.id"),
|
||||||
integration: "gcp-secret-manager",
|
integration: "gcp-secret-manager",
|
||||||
refreshToken: accessToken
|
refreshToken: accessToken
|
||||||
});
|
});
|
||||||
|
|
||||||
setIsLoading(false);
|
setIsLoading(false);
|
||||||
router.push(`/integrations/gcp-secret-manager/create?integrationAuthId=${integrationAuth.id}`);
|
router.push(
|
||||||
|
`/integrations/gcp-secret-manager/create?integrationAuthId=${integrationAuth.id}`
|
||||||
|
);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
setIsLoading(false);
|
setIsLoading(false);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex h-full w-full items-center justify-center">
|
<div className="flex h-full w-full items-center justify-center">
|
||||||
<Head>
|
<Head>
|
||||||
<title>Authorize GCP Secret Manager Integration</title>
|
<title>Authorize GCP Secret Manager Integration</title>
|
||||||
<link rel='icon' href='/infisical.ico' />
|
<link rel="icon" href="/infisical.ico" />
|
||||||
</Head>
|
</Head>
|
||||||
<Card className="max-w-lg rounded-md border border-mineshaft-600 mb-12">
|
<Card className="mb-12 max-w-lg rounded-md border border-mineshaft-600">
|
||||||
<CardTitle
|
<CardTitle
|
||||||
className="text-left px-6 text-xl"
|
className="px-6 text-left text-xl"
|
||||||
subTitle="Connect Infisical to GCP Secret Manager to sync secrets."
|
subTitle="Connect Infisical to GCP Secret Manager to sync secrets."
|
||||||
>
|
>
|
||||||
<div className="flex flex-row items-center">
|
<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>
|
<span className="ml-1.5">GCP Secret Manager Integration </span>
|
||||||
<Link href="https://infisical.com/docs/integrations/cloud/gcp-secret-manager" passHref>
|
<Link href="https://infisical.com/docs/integrations/cloud/gcp-secret-manager" passHref>
|
||||||
<a target="_blank" rel="noopener noreferrer">
|
<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">
|
<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"/>
|
<FontAwesomeIcon icon={faBookOpen} className="mr-1.5" />
|
||||||
Docs
|
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>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
</Link>
|
</Link>
|
||||||
@@ -107,24 +107,21 @@ export default function GCPSecretManagerAuthorizeIntegrationPage() {
|
|||||||
</CardTitle>
|
</CardTitle>
|
||||||
<div className="px-6">
|
<div className="px-6">
|
||||||
<Button
|
<Button
|
||||||
colorSchema="primary"
|
colorSchema="primary"
|
||||||
variant="outline_bg"
|
variant="outline_bg"
|
||||||
onClick={handleIntegrateWithOAuth}
|
onClick={handleIntegrateWithOAuth}
|
||||||
leftIcon={<FontAwesomeIcon icon={faGoogle} className="mr-2" />}
|
leftIcon={<FontAwesomeIcon icon={faGoogle} className="mr-2" />}
|
||||||
className="h-11 w-full mx-0 mt-4"
|
className="mx-0 mt-4 h-11 w-full"
|
||||||
>
|
>
|
||||||
Continue with OAuth
|
Continue with OAuth
|
||||||
</Button>
|
</Button>
|
||||||
<div className='w-full flex flex-row items-center my-4 py-2'>
|
<div className="my-4 flex w-full flex-row items-center py-2">
|
||||||
<div className='w-full border-t border-mineshaft-400/40' />
|
<div className="w-full border-t border-mineshaft-400/40" />
|
||||||
<span className="mx-2 text-mineshaft-400 text-xs">or</span>
|
<span className="mx-2 text-xs text-mineshaft-400">or</span>
|
||||||
<div className='w-full border-t border-mineshaft-400/40' />
|
<div className="w-full border-t border-mineshaft-400/40" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<form
|
<form onSubmit={handleSubmit(onFormSubmit)} className="px-6 pb-8 text-right">
|
||||||
onSubmit={handleSubmit(onFormSubmit)}
|
|
||||||
className="px-6 text-right pb-8"
|
|
||||||
>
|
|
||||||
<Controller
|
<Controller
|
||||||
control={control}
|
control={control}
|
||||||
name="accessToken"
|
name="accessToken"
|
||||||
@@ -134,7 +131,7 @@ export default function GCPSecretManagerAuthorizeIntegrationPage() {
|
|||||||
errorText={error?.message}
|
errorText={error?.message}
|
||||||
isError={Boolean(error)}
|
isError={Boolean(error)}
|
||||||
>
|
>
|
||||||
<TextArea
|
<TextArea
|
||||||
{...field}
|
{...field}
|
||||||
className="h-48 border border-mineshaft-600 bg-bunker-900/80"
|
className="h-48 border border-mineshaft-600 bg-bunker-900/80"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -12,9 +12,7 @@ import queryString from "query-string";
|
|||||||
import * as yup from "yup";
|
import * as yup from "yup";
|
||||||
|
|
||||||
import { usePopUp } from "@app/hooks";
|
import { usePopUp } from "@app/hooks";
|
||||||
import {
|
import { useCreateIntegration } from "@app/hooks/api";
|
||||||
useCreateIntegration
|
|
||||||
} from "@app/hooks/api";
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
@@ -30,7 +28,8 @@ import {
|
|||||||
Tab,
|
Tab,
|
||||||
TabList,
|
TabList,
|
||||||
TabPanel,
|
TabPanel,
|
||||||
Tabs} from "../../../components/v2";
|
Tabs
|
||||||
|
} from "../../../components/v2";
|
||||||
import {
|
import {
|
||||||
useGetIntegrationAuthApps,
|
useGetIntegrationAuthApps,
|
||||||
useGetIntegrationAuthById
|
useGetIntegrationAuthById
|
||||||
@@ -60,13 +59,8 @@ export default function GCPSecretManagerCreateIntegrationPage() {
|
|||||||
const { popUp, handlePopUpOpen, handlePopUpToggle, handlePopUpClose } = usePopUp([
|
const { popUp, handlePopUpOpen, handlePopUpToggle, handlePopUpClose } = usePopUp([
|
||||||
"confirmIntegration"
|
"confirmIntegration"
|
||||||
] as const);
|
] as const);
|
||||||
|
|
||||||
const {
|
const { control, handleSubmit, setValue, watch } = useForm<FormData>({
|
||||||
control,
|
|
||||||
handleSubmit,
|
|
||||||
setValue,
|
|
||||||
watch
|
|
||||||
} = useForm<FormData>({
|
|
||||||
resolver: yupResolver(schema),
|
resolver: yupResolver(schema),
|
||||||
defaultValues: {
|
defaultValues: {
|
||||||
secretPath: "/",
|
secretPath: "/",
|
||||||
@@ -77,7 +71,7 @@ export default function GCPSecretManagerCreateIntegrationPage() {
|
|||||||
labelValue: "infisical"
|
labelValue: "infisical"
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const shouldLabel = watch("shouldLabel");
|
const shouldLabel = watch("shouldLabel");
|
||||||
const selectedSourceEnvironment = watch("selectedSourceEnvironment");
|
const selectedSourceEnvironment = watch("selectedSourceEnvironment");
|
||||||
|
|
||||||
@@ -87,19 +81,20 @@ export default function GCPSecretManagerCreateIntegrationPage() {
|
|||||||
|
|
||||||
const { data: workspace } = useGetWorkspaceById(localStorage.getItem("projectData.id") ?? "");
|
const { data: workspace } = useGetWorkspaceById(localStorage.getItem("projectData.id") ?? "");
|
||||||
const { data: integrationAuth } = useGetIntegrationAuthById((integrationAuthId as string) ?? "");
|
const { data: integrationAuth } = useGetIntegrationAuthById((integrationAuthId as string) ?? "");
|
||||||
const { data: integrationAuthApps, isLoading: isIntegrationAuthAppsLoading } = useGetIntegrationAuthApps({
|
const { data: integrationAuthApps, isLoading: isIntegrationAuthAppsLoading } =
|
||||||
integrationAuthId: (integrationAuthId as string) ?? ""
|
useGetIntegrationAuthApps({
|
||||||
});
|
integrationAuthId: (integrationAuthId as string) ?? ""
|
||||||
|
});
|
||||||
|
|
||||||
const [isLoading, setIsLoading] = useState(false);
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (shouldLabel) {
|
if (shouldLabel) {
|
||||||
setValue("labelName", "managed-by");
|
setValue("labelName", "managed-by");
|
||||||
setValue("labelValue", "infisical");
|
setValue("labelValue", "infisical");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
setValue("labelName", "");
|
setValue("labelName", "");
|
||||||
setValue("labelValue", "");
|
setValue("labelValue", "");
|
||||||
}, [shouldLabel]);
|
}, [shouldLabel]);
|
||||||
@@ -119,7 +114,7 @@ export default function GCPSecretManagerCreateIntegrationPage() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [integrationAuthApps]);
|
}, [integrationAuthApps]);
|
||||||
|
|
||||||
const onFormSubmit = async ({
|
const onFormSubmit = async ({
|
||||||
selectedSourceEnvironment: sce,
|
selectedSourceEnvironment: sce,
|
||||||
secretPath,
|
secretPath,
|
||||||
@@ -134,56 +129,57 @@ export default function GCPSecretManagerCreateIntegrationPage() {
|
|||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
|
|
||||||
if (!integrationAuth?.id) return;
|
if (!integrationAuth?.id) return;
|
||||||
|
|
||||||
await mutateAsync({
|
await mutateAsync({
|
||||||
integrationAuthId: integrationAuth?.id,
|
integrationAuthId: integrationAuth?.id,
|
||||||
isActive: true,
|
isActive: true,
|
||||||
app: integrationAuthApps?.find((integrationAuthApp) => integrationAuthApp.appId === targetAppId)?.name,
|
app: integrationAuthApps?.find(
|
||||||
|
(integrationAuthApp) => integrationAuthApp.appId === targetAppId
|
||||||
|
)?.name,
|
||||||
appId: targetAppId,
|
appId: targetAppId,
|
||||||
sourceEnvironment: sce,
|
sourceEnvironment: sce,
|
||||||
secretPath,
|
secretPath,
|
||||||
metadata: {
|
metadata: {
|
||||||
...(secretPrefix ? { secretPrefix } : {}),
|
...(secretPrefix ? { secretPrefix } : {}),
|
||||||
...(secretSuffix ? { secretSuffix } : {}),
|
...(secretSuffix ? { secretSuffix } : {}),
|
||||||
...(sl ? {
|
...(sl
|
||||||
secretGCPLabel: {
|
? {
|
||||||
labelName,
|
secretGCPLabel: {
|
||||||
labelValue
|
labelName,
|
||||||
}
|
labelValue
|
||||||
} : {})
|
}
|
||||||
|
}
|
||||||
|
: {})
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
setIsLoading(false);
|
setIsLoading(false);
|
||||||
router.push(`/integrations/${localStorage.getItem("projectData.id")}`);
|
router.push(`/integrations/${localStorage.getItem("projectData.id")}`);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
setIsLoading(false);
|
setIsLoading(false);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
return integrationAuth &&
|
return integrationAuth && workspace && selectedSourceEnvironment && integrationAuthApps ? (
|
||||||
workspace &&
|
<form
|
||||||
selectedSourceEnvironment &&
|
|
||||||
integrationAuthApps ? (
|
|
||||||
<form
|
|
||||||
onSubmit={handleSubmit((data: FormData) => {
|
onSubmit={handleSubmit((data: FormData) => {
|
||||||
if (!data.secretPrefix && !data.secretSuffix && !data.shouldLabel) {
|
if (!data.secretPrefix && !data.secretSuffix && !data.shouldLabel) {
|
||||||
handlePopUpOpen("confirmIntegration", data);
|
handlePopUpOpen("confirmIntegration", data);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
onFormSubmit(data);
|
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">
|
<Card className="max-w-lg rounded-md border border-mineshaft-600">
|
||||||
<Head>
|
<Head>
|
||||||
<title>Set Up GCP Secret Manager Integration</title>
|
<title>Set Up GCP Secret Manager Integration</title>
|
||||||
<link rel='icon' href='/infisical.ico' />
|
<link rel="icon" href="/infisical.ico" />
|
||||||
</Head>
|
</Head>
|
||||||
<CardTitle
|
<CardTitle
|
||||||
className="text-left px-6 text-xl mb-2"
|
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."
|
subTitle="Select which environment or folder in Infisical you want to sync to GCP Secret Manager."
|
||||||
>
|
>
|
||||||
<div className="flex flex-row items-center">
|
<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>
|
<span className="ml-1.5">GCP Secret Manager Integration </span>
|
||||||
<Link href="https://infisical.com/docs/integrations/cloud/gcp-secret-manager" passHref>
|
<Link href="https://infisical.com/docs/integrations/cloud/gcp-secret-manager" passHref>
|
||||||
<a target="_blank" rel="noopener noreferrer">
|
<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">
|
<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"/>
|
<FontAwesomeIcon icon={faBookOpen} className="mr-1.5" />
|
||||||
Docs
|
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>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
</Link>
|
</Link>
|
||||||
@@ -209,7 +208,7 @@ export default function GCPSecretManagerCreateIntegrationPage() {
|
|||||||
</CardTitle>
|
</CardTitle>
|
||||||
<Tabs defaultValue={TabSections.Connection} className="px-6">
|
<Tabs defaultValue={TabSections.Connection} className="px-6">
|
||||||
<TabList>
|
<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.Connection}>Connection</Tab>
|
||||||
<Tab value={TabSections.Options}>Options</Tab>
|
<Tab value={TabSections.Options}>Options</Tab>
|
||||||
</div>
|
</div>
|
||||||
@@ -250,26 +249,23 @@ export default function GCPSecretManagerCreateIntegrationPage() {
|
|||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
<Controller
|
<Controller
|
||||||
control={control}
|
control={control}
|
||||||
defaultValue=""
|
defaultValue=""
|
||||||
name="secretPath"
|
name="secretPath"
|
||||||
render={({ field, fieldState: { error } }) => (
|
render={({ field, fieldState: { error } }) => (
|
||||||
<FormControl
|
<FormControl
|
||||||
label="Secrets Path"
|
label="Secrets Path"
|
||||||
isError={Boolean(error)}
|
isError={Boolean(error)}
|
||||||
errorText={error?.message}
|
errorText={error?.message}
|
||||||
>
|
>
|
||||||
<Input
|
<Input {...field} placeholder="/" />
|
||||||
{...field}
|
</FormControl>
|
||||||
placeholder="/"
|
)}
|
||||||
/>
|
|
||||||
</FormControl>
|
|
||||||
)}
|
|
||||||
/>
|
/>
|
||||||
<Controller
|
<Controller
|
||||||
control={control}
|
control={control}
|
||||||
name="targetAppId"
|
name="targetAppId"
|
||||||
render={({ field: { onChange, ...field }, fieldState: { error } }) => {
|
render={({ field: { onChange, ...field }, fieldState: { error } }) => {
|
||||||
return (
|
return (
|
||||||
<FormControl
|
<FormControl
|
||||||
label="GCP Project"
|
label="GCP Project"
|
||||||
@@ -280,7 +276,7 @@ export default function GCPSecretManagerCreateIntegrationPage() {
|
|||||||
{...field}
|
{...field}
|
||||||
onValueChange={(e) => {
|
onValueChange={(e) => {
|
||||||
if (e === "") return;
|
if (e === "") return;
|
||||||
onChange(e)
|
onChange(e);
|
||||||
}}
|
}}
|
||||||
className="w-full"
|
className="w-full"
|
||||||
>
|
>
|
||||||
@@ -300,7 +296,7 @@ export default function GCPSecretManagerCreateIntegrationPage() {
|
|||||||
)}
|
)}
|
||||||
</Select>
|
</Select>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
)
|
);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</motion.div>
|
</motion.div>
|
||||||
@@ -317,32 +313,26 @@ export default function GCPSecretManagerCreateIntegrationPage() {
|
|||||||
control={control}
|
control={control}
|
||||||
name="secretPrefix"
|
name="secretPrefix"
|
||||||
render={({ field, fieldState: { error } }) => (
|
render={({ field, fieldState: { error } }) => (
|
||||||
<FormControl
|
<FormControl
|
||||||
label="Secret Prefix"
|
label="Secret Prefix"
|
||||||
isError={Boolean(error)}
|
isError={Boolean(error)}
|
||||||
errorText={error?.message}
|
errorText={error?.message}
|
||||||
>
|
>
|
||||||
<Input
|
<Input {...field} placeholder="INFISICAL_" />
|
||||||
{...field}
|
</FormControl>
|
||||||
placeholder="INFISICAL_"
|
|
||||||
/>
|
|
||||||
</FormControl>
|
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
<Controller
|
<Controller
|
||||||
control={control}
|
control={control}
|
||||||
name="secretSuffix"
|
name="secretSuffix"
|
||||||
render={({ field, fieldState: { error } }) => (
|
render={({ field, fieldState: { error } }) => (
|
||||||
<FormControl
|
<FormControl
|
||||||
label="Secret Suffix"
|
label="Secret Suffix"
|
||||||
isError={Boolean(error)}
|
isError={Boolean(error)}
|
||||||
errorText={error?.message}
|
errorText={error?.message}
|
||||||
>
|
>
|
||||||
<Input
|
<Input {...field} placeholder="_INFISICAL" />
|
||||||
{...field}
|
</FormControl>
|
||||||
placeholder="_INFISICAL"
|
|
||||||
/>
|
|
||||||
</FormControl>
|
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
<div className="mt-8 mb-[2.36rem]">
|
<div className="mt-8 mb-[2.36rem]">
|
||||||
@@ -366,32 +356,26 @@ export default function GCPSecretManagerCreateIntegrationPage() {
|
|||||||
control={control}
|
control={control}
|
||||||
name="labelName"
|
name="labelName"
|
||||||
render={({ field, fieldState: { error } }) => (
|
render={({ field, fieldState: { error } }) => (
|
||||||
<FormControl
|
<FormControl
|
||||||
label="Label Name"
|
label="Label Name"
|
||||||
isError={Boolean(error)}
|
isError={Boolean(error)}
|
||||||
errorText={error?.message}
|
errorText={error?.message}
|
||||||
>
|
>
|
||||||
<Input
|
<Input {...field} placeholder="managed-by" />
|
||||||
{...field}
|
</FormControl>
|
||||||
placeholder="managed-by"
|
|
||||||
/>
|
|
||||||
</FormControl>
|
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
<Controller
|
<Controller
|
||||||
control={control}
|
control={control}
|
||||||
name="labelValue"
|
name="labelValue"
|
||||||
render={({ field, fieldState: { error } }) => (
|
render={({ field, fieldState: { error } }) => (
|
||||||
<FormControl
|
<FormControl
|
||||||
label="Label Name"
|
label="Label Name"
|
||||||
isError={Boolean(error)}
|
isError={Boolean(error)}
|
||||||
errorText={error?.message}
|
errorText={error?.message}
|
||||||
>
|
>
|
||||||
<Input
|
<Input {...field} placeholder="infisical" />
|
||||||
{...field}
|
</FormControl>
|
||||||
placeholder="infisical"
|
|
||||||
/>
|
|
||||||
</FormControl>
|
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@@ -424,56 +408,66 @@ export default function GCPSecretManagerCreateIntegrationPage() {
|
|||||||
</span>
|
</span>
|
||||||
</div> */}
|
</div> */}
|
||||||
<Modal
|
<Modal
|
||||||
isOpen={popUp.confirmIntegration?.isOpen}
|
isOpen={popUp.confirmIntegration?.isOpen}
|
||||||
onOpenChange={(isOpen) => handlePopUpToggle("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
|
<p>You're about to overwrite any existing secrets in GCP Secret Manager.</p>
|
||||||
title="Heads Up"
|
<p className="mt-4">
|
||||||
footerContent={
|
To avoid this behavior, you may consider adding a secret prefix/suffix or enabling
|
||||||
<div className="flex items-center space-x-2">
|
labeling in the options tab.
|
||||||
<Button onClick={() => onFormSubmit(popUp.confirmIntegration?.data as FormData)}>
|
</p>
|
||||||
Continue Anyway
|
</ModalContent>
|
||||||
</Button>
|
</Modal>
|
||||||
<Button
|
|
||||||
onClick={() => handlePopUpClose("confirmIntegration")}
|
|
||||||
variant="outline_bg"
|
|
||||||
colorSchema="secondary"
|
|
||||||
>
|
|
||||||
Cancel
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<p>
|
|
||||||
You'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>
|
</form>
|
||||||
) : (
|
) : (
|
||||||
<div className="flex justify-center items-center w-full h-full">
|
<div className="flex h-full w-full items-center justify-center">
|
||||||
<Head>
|
<Head>
|
||||||
<title>Set Up GCP Secret Manager Integration</title>
|
<title>Set Up GCP Secret Manager Integration</title>
|
||||||
<link rel='icon' href='/infisical.ico' />
|
<link rel="icon" href="/infisical.ico" />
|
||||||
</Head>
|
</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">
|
{isIntegrationAuthAppsLoading ? (
|
||||||
<FontAwesomeIcon icon={faBugs} className="text-6xl my-2 inlineli"/>
|
<img
|
||||||
<p>
|
src="/images/loading/loading.gif"
|
||||||
Something went wrong. Please contact <a
|
height={70}
|
||||||
className="inline underline underline-offset-4 decoration-primary-500 opacity-80 hover:opacity-100 text-mineshaft-100 duration-200 cursor-pointer"
|
width={120}
|
||||||
target="_blank"
|
alt="infisical loading indicator"
|
||||||
rel="noopener noreferrer"
|
/>
|
||||||
href="mailto:[email protected]"
|
) : (
|
||||||
>
|
<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">
|
||||||
support@infisical.com
|
<FontAwesomeIcon icon={faBugs} className="inlineli my-2 text-6xl" />
|
||||||
</a> if the issue persists.
|
<p>
|
||||||
</p>
|
Something went wrong. Please contact{" "}
|
||||||
</div>}
|
<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:[email protected]"
|
||||||
|
>
|
||||||
|
support@infisical.com
|
||||||
|
</a>{" "}
|
||||||
|
if the issue persists.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
GCPSecretManagerCreateIntegrationPage.requireAuth = true;
|
GCPSecretManagerCreateIntegrationPage.requireAuth = true;
|
||||||
|
|||||||
@@ -2,15 +2,13 @@ import { useEffect } from "react";
|
|||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import queryString from "query-string";
|
import queryString from "query-string";
|
||||||
|
|
||||||
import {
|
import { useAuthorizeIntegration } from "@app/hooks/api";
|
||||||
useAuthorizeIntegration
|
|
||||||
} from "@app/hooks/api";
|
|
||||||
|
|
||||||
export default function GCPSecretManagerOAuth2CallbackPage() {
|
export default function GCPSecretManagerOAuth2CallbackPage() {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { mutateAsync } = useAuthorizeIntegration();
|
const { mutateAsync } = useAuthorizeIntegration();
|
||||||
|
|
||||||
const { code, state } = queryString.parse(router.asPath.split("?")[1]);
|
const { code, state } = queryString.parse(router.asPath.split("?")[1]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
(async () => {
|
(async () => {
|
||||||
@@ -24,8 +22,10 @@ export default function GCPSecretManagerOAuth2CallbackPage() {
|
|||||||
code: code as string,
|
code: code as string,
|
||||||
integration: "gcp-secret-manager"
|
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) {
|
} catch (err) {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,14 +3,19 @@ import Head from "next/head";
|
|||||||
import Image from "next/image";
|
import Image from "next/image";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import { 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 { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||||
import { motion } from "framer-motion";
|
import { motion } from "framer-motion";
|
||||||
import queryString from "query-string";
|
import queryString from "query-string";
|
||||||
|
|
||||||
import {
|
import { useCreateIntegration } from "@app/hooks/api";
|
||||||
useCreateIntegration
|
|
||||||
} from "@app/hooks/api";
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
@@ -48,9 +53,10 @@ export default function GitHubCreateIntegrationPage() {
|
|||||||
|
|
||||||
const { data: workspace } = useGetWorkspaceById(localStorage.getItem("projectData.id") ?? "");
|
const { data: workspace } = useGetWorkspaceById(localStorage.getItem("projectData.id") ?? "");
|
||||||
const { data: integrationAuth } = useGetIntegrationAuthById((integrationAuthId as string) ?? "");
|
const { data: integrationAuth } = useGetIntegrationAuthById((integrationAuthId as string) ?? "");
|
||||||
const { data: integrationAuthApps, isLoading: isIntegrationAuthAppsLoading } = useGetIntegrationAuthApps({
|
const { data: integrationAuthApps, isLoading: isIntegrationAuthAppsLoading } =
|
||||||
integrationAuthId: (integrationAuthId as string) ?? ""
|
useGetIntegrationAuthApps({
|
||||||
});
|
integrationAuthId: (integrationAuthId as string) ?? ""
|
||||||
|
});
|
||||||
|
|
||||||
const [selectedSourceEnvironment, setSelectedSourceEnvironment] = useState("");
|
const [selectedSourceEnvironment, setSelectedSourceEnvironment] = useState("");
|
||||||
const [secretPath, setSecretPath] = useState("/");
|
const [secretPath, setSecretPath] = useState("/");
|
||||||
@@ -81,8 +87,8 @@ export default function GitHubCreateIntegrationPage() {
|
|||||||
|
|
||||||
if (!integrationAuth?.id) return;
|
if (!integrationAuth?.id) return;
|
||||||
|
|
||||||
const targetApps = integrationAuthApps?.filter(
|
const targetApps = integrationAuthApps?.filter((integrationAuthApp) =>
|
||||||
(integrationAuthApp) => targetAppIds.includes(String(integrationAuthApp.appId))
|
targetAppIds.includes(String(integrationAuthApp.appId))
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!targetApps) return;
|
if (!targetApps) return;
|
||||||
@@ -99,7 +105,7 @@ export default function GitHubCreateIntegrationPage() {
|
|||||||
metadata: {
|
metadata: {
|
||||||
secretSuffix
|
secretSuffix
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -115,18 +121,18 @@ export default function GitHubCreateIntegrationPage() {
|
|||||||
selectedSourceEnvironment &&
|
selectedSourceEnvironment &&
|
||||||
integrationAuthApps &&
|
integrationAuthApps &&
|
||||||
targetAppIds ? (
|
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>
|
<Head>
|
||||||
<title>Set Up GitHub Integration</title>
|
<title>Set Up GitHub Integration</title>
|
||||||
<link rel='icon' href='/infisical.ico' />
|
<link rel="icon" href="/infisical.ico" />
|
||||||
</Head>
|
</Head>
|
||||||
<Card className="max-w-lg rounded-md border border-mineshaft-600 p-0">
|
<Card className="max-w-lg rounded-md border border-mineshaft-600 p-0">
|
||||||
<CardTitle
|
<CardTitle
|
||||||
className="text-left px-6 text-xl"
|
className="px-6 text-left text-xl"
|
||||||
subTitle="Choose which environment in Infisical you want to sync to environment variables in GitHub."
|
subTitle="Choose which environment in Infisical you want to sync to environment variables in GitHub."
|
||||||
>
|
>
|
||||||
<div className="flex flex-row items-center">
|
<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
|
<Image
|
||||||
src="/images/integrations/GitHub.png"
|
src="/images/integrations/GitHub.png"
|
||||||
height={30}
|
height={30}
|
||||||
@@ -137,10 +143,13 @@ export default function GitHubCreateIntegrationPage() {
|
|||||||
<span className="ml-2.5">GitHub Integration </span>
|
<span className="ml-2.5">GitHub Integration </span>
|
||||||
<Link href="https://infisical.com/docs/integrations/cicd/githubactions" passHref>
|
<Link href="https://infisical.com/docs/integrations/cicd/githubactions" passHref>
|
||||||
<a target="_blank" rel="noopener noreferrer">
|
<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">
|
<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"/>
|
<FontAwesomeIcon icon={faBookOpen} className="mr-1.5" />
|
||||||
Docs
|
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>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
</Link>
|
</Link>
|
||||||
@@ -148,7 +157,7 @@ export default function GitHubCreateIntegrationPage() {
|
|||||||
</CardTitle>
|
</CardTitle>
|
||||||
<Tabs defaultValue={TabSections.Connection} className="px-6">
|
<Tabs defaultValue={TabSections.Connection} className="px-6">
|
||||||
<TabList>
|
<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.Connection}>Connection</Tab>
|
||||||
<Tab value={TabSections.Options}>Options</Tab>
|
<Tab value={TabSections.Options}>Options</Tab>
|
||||||
</div>
|
</div>
|
||||||
@@ -187,17 +196,27 @@ export default function GitHubCreateIntegrationPage() {
|
|||||||
<FormControl label="GitHub Repo">
|
<FormControl label="GitHub Repo">
|
||||||
<DropdownMenu>
|
<DropdownMenu>
|
||||||
<DropdownMenuTrigger asChild>
|
<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">
|
{integrationAuthApps.length > 0 ? (
|
||||||
{targetAppIds.length === 1 ? integrationAuthApps?.find(
|
<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">
|
||||||
(integrationAuthApp) => targetAppIds[0] === String(integrationAuthApp.appId)
|
{targetAppIds.length === 1
|
||||||
)?.name : `${targetAppIds.length} repositories selected`}
|
? integrationAuthApps?.find(
|
||||||
|
(integrationAuthApp) =>
|
||||||
|
targetAppIds[0] === String(integrationAuthApp.appId)
|
||||||
|
)?.name
|
||||||
|
: `${targetAppIds.length} repositories selected`}
|
||||||
<FontAwesomeIcon icon={faAngleDown} className="text-xs" />
|
<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
|
No repositories found
|
||||||
</div>}
|
</div>
|
||||||
|
)}
|
||||||
</DropdownMenuTrigger>
|
</DropdownMenuTrigger>
|
||||||
<DropdownMenuContent align="start" className="z-[100] max-h-80 overflow-y-scroll thin-scrollbar">
|
<DropdownMenuContent
|
||||||
{(integrationAuthApps.length > 0) ? (
|
align="start"
|
||||||
|
className="thin-scrollbar z-[100] max-h-80 overflow-y-scroll"
|
||||||
|
>
|
||||||
|
{integrationAuthApps.length > 0 ? (
|
||||||
integrationAuthApps.map((integrationAuthApp) => {
|
integrationAuthApps.map((integrationAuthApp) => {
|
||||||
const isSelected = targetAppIds.includes(String(integrationAuthApp.appId));
|
const isSelected = targetAppIds.includes(String(integrationAuthApp.appId));
|
||||||
|
|
||||||
@@ -205,20 +224,39 @@ export default function GitHubCreateIntegrationPage() {
|
|||||||
<DropdownMenuItem
|
<DropdownMenuItem
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
if (targetAppIds.includes(String(integrationAuthApp.appId))) {
|
if (targetAppIds.includes(String(integrationAuthApp.appId))) {
|
||||||
setTargetAppIds(targetAppIds.filter((appId) => appId !== String(integrationAuthApp.appId)));
|
setTargetAppIds(
|
||||||
|
targetAppIds.filter(
|
||||||
|
(appId) => appId !== String(integrationAuthApp.appId)
|
||||||
|
)
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
setTargetAppIds([...targetAppIds, String(integrationAuthApp.appId)]);
|
setTargetAppIds([
|
||||||
|
...targetAppIds,
|
||||||
|
String(integrationAuthApp.appId)
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
key={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"
|
iconPos="left"
|
||||||
className="w-[28.4rem] text-sm"
|
className="w-[28.4rem] text-sm"
|
||||||
>
|
>
|
||||||
{integrationAuthApp.name}
|
{integrationAuthApp.name}
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
)})
|
);
|
||||||
) : <div/>}
|
})
|
||||||
|
) : (
|
||||||
|
<div />
|
||||||
|
)}
|
||||||
</DropdownMenuContent>
|
</DropdownMenuContent>
|
||||||
</DropdownMenu>
|
</DropdownMenu>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
@@ -253,31 +291,48 @@ export default function GitHubCreateIntegrationPage() {
|
|||||||
Create Integration
|
Create Integration
|
||||||
</Button>
|
</Button>
|
||||||
</Card>
|
</Card>
|
||||||
<div className="border-t border-mineshaft-800 w-full max-w-md mt-6"/>
|
<div className="mt-6 w-full max-w-md border-t border-mineshaft-800" />
|
||||||
<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="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-mineshaft-200 text-xl"/> <span className="ml-3 text-md text-mineshaft-100">Pro Tips</span></div>
|
<div className="flex flex-row items-center">
|
||||||
<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>
|
<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>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div className="flex justify-center items-center w-full h-full">
|
<div className="flex h-full w-full items-center justify-center">
|
||||||
<Head>
|
<Head>
|
||||||
<title>Set Up GitHub Integration</title>
|
<title>Set Up GitHub Integration</title>
|
||||||
<link rel='icon' href='/infisical.ico' />
|
<link rel="icon" href="/infisical.ico" />
|
||||||
</Head>
|
</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">
|
{isIntegrationAuthAppsLoading ? (
|
||||||
<FontAwesomeIcon icon={faBugs} className="text-6xl my-2 inlineli"/>
|
<img
|
||||||
<p>
|
src="/images/loading/loading.gif"
|
||||||
Something went wrong. Please contact <a
|
height={70}
|
||||||
className="inline underline underline-offset-4 decoration-primary-500 opacity-80 hover:opacity-100 text-mineshaft-100 duration-200 cursor-pointer"
|
width={120}
|
||||||
target="_blank"
|
alt="infisical loading indicator"
|
||||||
rel="noopener noreferrer"
|
/>
|
||||||
href="mailto:[email protected]"
|
) : (
|
||||||
>
|
<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">
|
||||||
support@infisical.com
|
<FontAwesomeIcon icon={faBugs} className="inlineli my-2 text-6xl" />
|
||||||
</a> if the issue persists.
|
<p>
|
||||||
</p>
|
Something went wrong. Please contact{" "}
|
||||||
</div>}
|
<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:[email protected]"
|
||||||
|
>
|
||||||
|
support@infisical.com
|
||||||
|
</a>{" "}
|
||||||
|
if the issue persists.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,9 +2,7 @@ import { useEffect } from "react";
|
|||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import queryString from "query-string";
|
import queryString from "query-string";
|
||||||
|
|
||||||
import {
|
import { useAuthorizeIntegration } from "@app/hooks/api";
|
||||||
useAuthorizeIntegration
|
|
||||||
} from "@app/hooks/api";
|
|
||||||
|
|
||||||
export default function GitHubOAuth2CallbackPage() {
|
export default function GitHubOAuth2CallbackPage() {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|||||||
@@ -20,10 +20,7 @@ const schema = yup.object({
|
|||||||
type FormData = yup.InferType<typeof schema>;
|
type FormData = yup.InferType<typeof schema>;
|
||||||
|
|
||||||
export default function GitLabAuthorizeIntegrationPage() {
|
export default function GitLabAuthorizeIntegrationPage() {
|
||||||
const {
|
const { control, handleSubmit } = useForm<FormData>({
|
||||||
control,
|
|
||||||
handleSubmit
|
|
||||||
} = useForm<FormData>({
|
|
||||||
resolver: yupResolver(schema),
|
resolver: yupResolver(schema),
|
||||||
defaultValues: {
|
defaultValues: {
|
||||||
gitLabURL: ""
|
gitLabURL: ""
|
||||||
@@ -31,35 +28,38 @@ export default function GitLabAuthorizeIntegrationPage() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const { data: cloudIntegrations } = useGetCloudIntegrations();
|
const { data: cloudIntegrations } = useGetCloudIntegrations();
|
||||||
|
|
||||||
const onFormSubmit = ({
|
const onFormSubmit = ({ gitLabURL }: FormData) => {
|
||||||
gitLabURL
|
|
||||||
}: FormData) => {
|
|
||||||
if (!cloudIntegrations) return;
|
if (!cloudIntegrations) return;
|
||||||
const integrationOption = cloudIntegrations.find((integration) => integration.slug === "gitlab");
|
const integrationOption = cloudIntegrations.find(
|
||||||
|
(integration) => integration.slug === "gitlab"
|
||||||
|
);
|
||||||
|
|
||||||
if (!integrationOption) return;
|
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");
|
const csrfToken = crypto.randomBytes(16).toString("hex");
|
||||||
localStorage.setItem("latestCSRFToken", csrfToken);
|
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}`;
|
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);
|
window.location.assign(link);
|
||||||
}
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex h-full w-full items-center justify-center">
|
<div className="flex h-full w-full items-center justify-center">
|
||||||
<Head>
|
<Head>
|
||||||
<title>Authorize GitLab Integration</title>
|
<title>Authorize GitLab Integration</title>
|
||||||
<link rel='icon' href='/infisical.ico' />
|
<link rel="icon" href="/infisical.ico" />
|
||||||
</Head>
|
</Head>
|
||||||
<Card className="max-w-lg rounded-md border border-mineshaft-600 mb-12">
|
<Card className="mb-12 max-w-lg rounded-md border border-mineshaft-600">
|
||||||
<CardTitle
|
<CardTitle
|
||||||
className="text-left px-6 text-xl"
|
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."
|
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">
|
<div className="flex flex-row items-center">
|
||||||
@@ -74,19 +74,19 @@ export default function GitLabAuthorizeIntegrationPage() {
|
|||||||
<span className="ml-2.5">GitLab Integration </span>
|
<span className="ml-2.5">GitLab Integration </span>
|
||||||
<Link href="https://infisical.com/docs/integrations/cicd/gitlab" passHref>
|
<Link href="https://infisical.com/docs/integrations/cicd/gitlab" passHref>
|
||||||
<a target="_blank" rel="noopener noreferrer">
|
<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">
|
<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"/>
|
<FontAwesomeIcon icon={faBookOpen} className="mr-1.5" />
|
||||||
Docs
|
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>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
</CardTitle>
|
</CardTitle>
|
||||||
<form
|
<form onSubmit={handleSubmit(onFormSubmit)} className="px-6 pb-8 text-right">
|
||||||
onSubmit={handleSubmit(onFormSubmit)}
|
|
||||||
className="px-6 text-right pb-8"
|
|
||||||
>
|
|
||||||
<Controller
|
<Controller
|
||||||
control={control}
|
control={control}
|
||||||
name="gitLabURL"
|
name="gitLabURL"
|
||||||
@@ -96,10 +96,7 @@ export default function GitLabAuthorizeIntegrationPage() {
|
|||||||
errorText={error?.message}
|
errorText={error?.message}
|
||||||
isError={Boolean(error)}
|
isError={Boolean(error)}
|
||||||
>
|
>
|
||||||
<Input
|
<Input {...field} placeholder="https://self-hosted-gitlab.com" />
|
||||||
{...field}
|
|
||||||
placeholder="https://self-hosted-gitlab.com"
|
|
||||||
/>
|
|
||||||
</FormControl>
|
</FormControl>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -12,9 +12,7 @@ import queryString from "query-string";
|
|||||||
import * as yup from "yup";
|
import * as yup from "yup";
|
||||||
|
|
||||||
import { usePopUp } from "@app/hooks";
|
import { usePopUp } from "@app/hooks";
|
||||||
import {
|
import { useCreateIntegration } from "@app/hooks/api";
|
||||||
useCreateIntegration
|
|
||||||
} from "@app/hooks/api";
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
@@ -49,7 +47,10 @@ enum TabSections {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const schema = yup.object({
|
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(),
|
targetTeamId: yup.string(),
|
||||||
selectedSourceEnvironment: yup.string().required("Source environment is required"),
|
selectedSourceEnvironment: yup.string().required("Source environment is required"),
|
||||||
secretPath: yup.string().required("Secret path is required"),
|
secretPath: yup.string().required("Secret path is required"),
|
||||||
@@ -66,20 +67,15 @@ export default function GitLabCreateIntegrationPage() {
|
|||||||
const { popUp, handlePopUpOpen, handlePopUpToggle, handlePopUpClose } = usePopUp([
|
const { popUp, handlePopUpOpen, handlePopUpToggle, handlePopUpClose } = usePopUp([
|
||||||
"confirmIntegration"
|
"confirmIntegration"
|
||||||
] as const);
|
] as const);
|
||||||
|
|
||||||
const {
|
const { control, handleSubmit, setValue, watch } = useForm<FormData>({
|
||||||
control,
|
resolver: yupResolver(schema),
|
||||||
handleSubmit,
|
defaultValues: {
|
||||||
setValue,
|
targetEntity: "individual",
|
||||||
watch
|
secretPath: "/",
|
||||||
} = useForm<FormData>({
|
secretPrefix: "",
|
||||||
resolver: yupResolver(schema),
|
secretSuffix: ""
|
||||||
defaultValues: {
|
}
|
||||||
targetEntity: "individual",
|
|
||||||
secretPath: "/",
|
|
||||||
secretPrefix: "",
|
|
||||||
secretSuffix: ""
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
const selectedSourceEnvironment = watch("selectedSourceEnvironment");
|
const selectedSourceEnvironment = watch("selectedSourceEnvironment");
|
||||||
const targetEntity = watch("targetEntity");
|
const targetEntity = watch("targetEntity");
|
||||||
@@ -93,17 +89,16 @@ export default function GitLabCreateIntegrationPage() {
|
|||||||
const { data: workspace } = useGetWorkspaceById(localStorage.getItem("projectData.id") ?? "");
|
const { data: workspace } = useGetWorkspaceById(localStorage.getItem("projectData.id") ?? "");
|
||||||
const { data: integrationAuth } = useGetIntegrationAuthById((integrationAuthId as string) ?? "");
|
const { data: integrationAuth } = useGetIntegrationAuthById((integrationAuthId as string) ?? "");
|
||||||
|
|
||||||
const { data: integrationAuthApps, isLoading: isIntegrationAuthAppsLoading } = useGetIntegrationAuthApps({
|
const { data: integrationAuthApps, isLoading: isIntegrationAuthAppsLoading } =
|
||||||
|
useGetIntegrationAuthApps({
|
||||||
integrationAuthId: (integrationAuthId as string) ?? "",
|
integrationAuthId: (integrationAuthId as string) ?? "",
|
||||||
...(targetTeamId ? { teamId: targetTeamId } : {})
|
...(targetTeamId ? { teamId: targetTeamId } : {})
|
||||||
});
|
});
|
||||||
const { data: integrationAuthTeams, isLoading: isintegrationAuthTeamsLoading } = useGetIntegrationAuthTeams(
|
const { data: integrationAuthTeams, isLoading: isintegrationAuthTeamsLoading } =
|
||||||
(integrationAuthId as string) ?? ""
|
useGetIntegrationAuthTeams((integrationAuthId as string) ?? "");
|
||||||
);
|
|
||||||
|
|
||||||
const [isLoading, setIsLoading] = useState(false);
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (workspace) {
|
if (workspace) {
|
||||||
setValue("selectedSourceEnvironment", workspace.environments[0].slug);
|
setValue("selectedSourceEnvironment", workspace.environments[0].slug);
|
||||||
@@ -147,11 +142,13 @@ export default function GitLabCreateIntegrationPage() {
|
|||||||
try {
|
try {
|
||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
if (!integrationAuth?.id) return;
|
if (!integrationAuth?.id) return;
|
||||||
|
|
||||||
await mutateAsync({
|
await mutateAsync({
|
||||||
integrationAuthId: integrationAuth?.id,
|
integrationAuthId: integrationAuth?.id,
|
||||||
isActive: true,
|
isActive: true,
|
||||||
app: integrationAuthApps?.find((integrationAuthApp) => String(integrationAuthApp.appId) === targetAppId)?.name,
|
app: integrationAuthApps?.find(
|
||||||
|
(integrationAuthApp) => String(integrationAuthApp.appId) === targetAppId
|
||||||
|
)?.name,
|
||||||
appId: String(targetAppId),
|
appId: String(targetAppId),
|
||||||
sourceEnvironment: sse,
|
sourceEnvironment: sse,
|
||||||
targetEnvironment: targetEnvironment === "" ? "*" : targetEnvironment,
|
targetEnvironment: targetEnvironment === "" ? "*" : targetEnvironment,
|
||||||
@@ -168,31 +165,31 @@ export default function GitLabCreateIntegrationPage() {
|
|||||||
console.error(err);
|
console.error(err);
|
||||||
setIsLoading(false);
|
setIsLoading(false);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
return integrationAuth &&
|
return integrationAuth &&
|
||||||
workspace &&
|
workspace &&
|
||||||
selectedSourceEnvironment &&
|
selectedSourceEnvironment &&
|
||||||
integrationAuthApps &&
|
integrationAuthApps &&
|
||||||
integrationAuthTeams ? (
|
integrationAuthTeams ? (
|
||||||
<form
|
<form
|
||||||
onSubmit={handleSubmit((data: FormData) => {
|
onSubmit={handleSubmit((data: FormData) => {
|
||||||
if (!data.secretPrefix && !data.secretSuffix) {
|
if (!data.secretPrefix && !data.secretSuffix) {
|
||||||
handlePopUpOpen("confirmIntegration", data);
|
handlePopUpOpen("confirmIntegration", data);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
onFormSubmit(data);
|
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>
|
<Head>
|
||||||
<title>Set Up GitLab Integration</title>
|
<title>Set Up GitLab Integration</title>
|
||||||
<link rel='icon' href='/infisical.ico' />
|
<link rel="icon" href="/infisical.ico" />
|
||||||
</Head>
|
</Head>
|
||||||
<Card className="max-w-lg rounded-md border border-mineshaft-600">
|
<Card className="max-w-lg rounded-md border border-mineshaft-600">
|
||||||
<CardTitle
|
<CardTitle
|
||||||
className="text-left px-6 text-xl"
|
className="px-6 text-left text-xl"
|
||||||
subTitle="Select which environment or folder in Infisical you want to sync to GitLab's environment variables."
|
subTitle="Select which environment or folder in Infisical you want to sync to GitLab's environment variables."
|
||||||
>
|
>
|
||||||
<div className="flex flex-row items-center">
|
<div className="flex flex-row items-center">
|
||||||
@@ -207,10 +204,13 @@ export default function GitLabCreateIntegrationPage() {
|
|||||||
<span className="ml-2.5">GitLab Integration </span>
|
<span className="ml-2.5">GitLab Integration </span>
|
||||||
<Link href="https://infisical.com/docs/integrations/cicd/gitlab" passHref>
|
<Link href="https://infisical.com/docs/integrations/cicd/gitlab" passHref>
|
||||||
<a target="_blank" rel="noopener noreferrer">
|
<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">
|
<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"/>
|
<FontAwesomeIcon icon={faBookOpen} className="mr-1.5" />
|
||||||
Docs
|
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>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
</Link>
|
</Link>
|
||||||
@@ -218,7 +218,7 @@ export default function GitLabCreateIntegrationPage() {
|
|||||||
</CardTitle>
|
</CardTitle>
|
||||||
<Tabs defaultValue={TabSections.Connection} className="px-6">
|
<Tabs defaultValue={TabSections.Connection} className="px-6">
|
||||||
<TabList>
|
<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.Connection}>Connection</Tab>
|
||||||
<Tab value={TabSections.Options}>Options</Tab>
|
<Tab value={TabSections.Options}>Options</Tab>
|
||||||
</div>
|
</div>
|
||||||
@@ -259,21 +259,18 @@ export default function GitLabCreateIntegrationPage() {
|
|||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
<Controller
|
<Controller
|
||||||
control={control}
|
control={control}
|
||||||
defaultValue=""
|
defaultValue=""
|
||||||
name="secretPath"
|
name="secretPath"
|
||||||
render={({ field, fieldState: { error } }) => (
|
render={({ field, fieldState: { error } }) => (
|
||||||
<FormControl
|
<FormControl
|
||||||
label="Secrets Path"
|
label="Secrets Path"
|
||||||
isError={Boolean(error)}
|
isError={Boolean(error)}
|
||||||
errorText={error?.message}
|
errorText={error?.message}
|
||||||
>
|
>
|
||||||
<Input
|
<Input {...field} placeholder="/" />
|
||||||
{...field}
|
</FormControl>
|
||||||
placeholder="/"
|
)}
|
||||||
/>
|
|
||||||
</FormControl>
|
|
||||||
)}
|
|
||||||
/>
|
/>
|
||||||
<Controller
|
<Controller
|
||||||
control={control}
|
control={control}
|
||||||
@@ -284,11 +281,7 @@ export default function GitLabCreateIntegrationPage() {
|
|||||||
errorText={error?.message}
|
errorText={error?.message}
|
||||||
isError={Boolean(error)}
|
isError={Boolean(error)}
|
||||||
>
|
>
|
||||||
<Select
|
<Select {...field} onValueChange={(e) => onChange(e)} className="w-full">
|
||||||
{...field}
|
|
||||||
onValueChange={(e) => onChange(e)}
|
|
||||||
className="w-full"
|
|
||||||
>
|
|
||||||
{gitLabEntities.map((entity) => {
|
{gitLabEntities.map((entity) => {
|
||||||
return (
|
return (
|
||||||
<SelectItem value={entity.value} key={`target-entity-${entity.value}`}>
|
<SelectItem value={entity.value} key={`target-entity-${entity.value}`}>
|
||||||
@@ -310,14 +303,9 @@ export default function GitLabCreateIntegrationPage() {
|
|||||||
errorText={error?.message}
|
errorText={error?.message}
|
||||||
isError={Boolean(error)}
|
isError={Boolean(error)}
|
||||||
>
|
>
|
||||||
<Select
|
<Select {...field} onValueChange={(e) => onChange(e)} className="w-full">
|
||||||
{...field}
|
|
||||||
onValueChange={(e) => onChange(e)}
|
|
||||||
className="w-full"
|
|
||||||
>
|
|
||||||
{integrationAuthTeams.length > 0 ? (
|
{integrationAuthTeams.length > 0 ? (
|
||||||
integrationAuthTeams.map((integrationAuthTeam) =>
|
integrationAuthTeams.map((integrationAuthTeam) => (
|
||||||
(
|
|
||||||
<SelectItem
|
<SelectItem
|
||||||
value={String(integrationAuthTeam.teamId as string)}
|
value={String(integrationAuthTeam.teamId as string)}
|
||||||
key={`target-team-${String(integrationAuthTeam.teamId)}`}
|
key={`target-team-${String(integrationAuthTeam.teamId)}`}
|
||||||
@@ -349,7 +337,7 @@ export default function GitLabCreateIntegrationPage() {
|
|||||||
{...field}
|
{...field}
|
||||||
onValueChange={(e) => {
|
onValueChange={(e) => {
|
||||||
if (e === "") return;
|
if (e === "") return;
|
||||||
onChange(e)
|
onChange(e);
|
||||||
}}
|
}}
|
||||||
className="w-full"
|
className="w-full"
|
||||||
>
|
>
|
||||||
@@ -369,24 +357,22 @@ export default function GitLabCreateIntegrationPage() {
|
|||||||
)}
|
)}
|
||||||
</Select>
|
</Select>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
)}}
|
);
|
||||||
/>
|
}}
|
||||||
<Controller
|
/>
|
||||||
control={control}
|
<Controller
|
||||||
defaultValue=""
|
control={control}
|
||||||
name="targetEnvironment"
|
defaultValue=""
|
||||||
render={({ field, fieldState: { error } }) => (
|
name="targetEnvironment"
|
||||||
<FormControl
|
render={({ field, fieldState: { error } }) => (
|
||||||
label="GitLab Environment Scope (Optional)"
|
<FormControl
|
||||||
isError={Boolean(error)}
|
label="GitLab Environment Scope (Optional)"
|
||||||
errorText={error?.message}
|
isError={Boolean(error)}
|
||||||
>
|
errorText={error?.message}
|
||||||
<Input
|
>
|
||||||
{...field}
|
<Input {...field} placeholder="*" />
|
||||||
placeholder="*"
|
</FormControl>
|
||||||
/>
|
)}
|
||||||
</FormControl>
|
|
||||||
)}
|
|
||||||
/>
|
/>
|
||||||
</motion.div>
|
</motion.div>
|
||||||
</TabPanel>
|
</TabPanel>
|
||||||
@@ -403,32 +389,26 @@ export default function GitLabCreateIntegrationPage() {
|
|||||||
control={control}
|
control={control}
|
||||||
name="secretPrefix"
|
name="secretPrefix"
|
||||||
render={({ field, fieldState: { error } }) => (
|
render={({ field, fieldState: { error } }) => (
|
||||||
<FormControl
|
<FormControl
|
||||||
label="Secret Prefix"
|
label="Secret Prefix"
|
||||||
isError={Boolean(error)}
|
isError={Boolean(error)}
|
||||||
errorText={error?.message}
|
errorText={error?.message}
|
||||||
>
|
>
|
||||||
<Input
|
<Input {...field} placeholder="INFISICAL_" />
|
||||||
{...field}
|
</FormControl>
|
||||||
placeholder="INFISICAL_"
|
|
||||||
/>
|
|
||||||
</FormControl>
|
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
<Controller
|
<Controller
|
||||||
control={control}
|
control={control}
|
||||||
name="secretSuffix"
|
name="secretSuffix"
|
||||||
render={({ field, fieldState: { error } }) => (
|
render={({ field, fieldState: { error } }) => (
|
||||||
<FormControl
|
<FormControl
|
||||||
label="Secret Suffix"
|
label="Secret Suffix"
|
||||||
isError={Boolean(error)}
|
isError={Boolean(error)}
|
||||||
errorText={error?.message}
|
errorText={error?.message}
|
||||||
>
|
>
|
||||||
<Input
|
<Input {...field} placeholder="_INFISICAL" />
|
||||||
{...field}
|
</FormControl>
|
||||||
placeholder="_INFISICAL"
|
|
||||||
/>
|
|
||||||
</FormControl>
|
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
</motion.div>
|
</motion.div>
|
||||||
@@ -445,61 +425,71 @@ export default function GitLabCreateIntegrationPage() {
|
|||||||
>
|
>
|
||||||
Create Integration
|
Create Integration
|
||||||
</Button>
|
</Button>
|
||||||
</Card>
|
</Card>
|
||||||
{/* <div className="border-t border-mineshaft-800 w-full max-w-md mt-6"/>
|
{/* <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-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>
|
<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>
|
<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> */}
|
</div> */}
|
||||||
<Modal
|
<Modal
|
||||||
isOpen={popUp.confirmIntegration?.isOpen}
|
isOpen={popUp.confirmIntegration?.isOpen}
|
||||||
onOpenChange={(isOpen) => handlePopUpToggle("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
|
<p>You're about to overwrite any existing secrets in GitLab.</p>
|
||||||
title="Heads Up"
|
<p className="mt-4">
|
||||||
footerContent={
|
To avoid this behavior, you may consider adding a secret prefix/suffix in the options
|
||||||
<div className="flex items-center space-x-2">
|
tab.
|
||||||
<Button onClick={() => onFormSubmit(popUp.confirmIntegration?.data as FormData)}>
|
</p>
|
||||||
Continue Anyway
|
</ModalContent>
|
||||||
</Button>
|
</Modal>
|
||||||
<Button
|
|
||||||
onClick={() => handlePopUpClose("confirmIntegration")}
|
|
||||||
variant="outline_bg"
|
|
||||||
colorSchema="secondary"
|
|
||||||
>
|
|
||||||
Cancel
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<p>
|
|
||||||
You'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>
|
</form>
|
||||||
) : (
|
) : (
|
||||||
<div className="flex justify-center items-center w-full h-full">
|
<div className="flex h-full w-full items-center justify-center">
|
||||||
<Head>
|
<Head>
|
||||||
<title>Set Up GitLab Integration</title>
|
<title>Set Up GitLab Integration</title>
|
||||||
<link rel='icon' href='/infisical.ico' />
|
<link rel="icon" href="/infisical.ico" />
|
||||||
</Head>
|
</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">
|
{isIntegrationAuthAppsLoading || isintegrationAuthTeamsLoading ? (
|
||||||
<FontAwesomeIcon icon={faBugs} className="text-6xl my-2 inlineli"/>
|
<img
|
||||||
<p>
|
src="/images/loading/loading.gif"
|
||||||
Something went wrong. Please contact <a
|
height={70}
|
||||||
className="inline underline underline-offset-4 decoration-primary-500 opacity-80 hover:opacity-100 text-mineshaft-100 duration-200 cursor-pointer"
|
width={120}
|
||||||
target="_blank"
|
alt="infisical loading indicator"
|
||||||
rel="noopener noreferrer"
|
/>
|
||||||
href="mailto:[email protected]"
|
) : (
|
||||||
>
|
<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">
|
||||||
support@infisical.com
|
<FontAwesomeIcon icon={faBugs} className="inlineli my-2 text-6xl" />
|
||||||
</a> if the issue persists.
|
<p>
|
||||||
</p>
|
Something went wrong. Please contact{" "}
|
||||||
</div>}
|
<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:[email protected]"
|
||||||
|
>
|
||||||
|
support@infisical.com
|
||||||
|
</a>{" "}
|
||||||
|
if the issue persists.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,9 +2,7 @@ import { useEffect } from "react";
|
|||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import queryString from "query-string";
|
import queryString from "query-string";
|
||||||
|
|
||||||
import {
|
import { useAuthorizeIntegration } from "@app/hooks/api";
|
||||||
useAuthorizeIntegration
|
|
||||||
} from "@app/hooks/api";
|
|
||||||
|
|
||||||
export default function GitLabOAuth2CallbackPage() {
|
export default function GitLabOAuth2CallbackPage() {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
@@ -16,7 +14,7 @@ export default function GitLabOAuth2CallbackPage() {
|
|||||||
try {
|
try {
|
||||||
// validate state
|
// validate state
|
||||||
const [csrfToken, url] = (state as string).split("|", 2);
|
const [csrfToken, url] = (state as string).split("|", 2);
|
||||||
|
|
||||||
if (csrfToken !== localStorage.getItem("latestCSRFToken")) return;
|
if (csrfToken !== localStorage.getItem("latestCSRFToken")) return;
|
||||||
localStorage.removeItem("latestCSRFToken");
|
localStorage.removeItem("latestCSRFToken");
|
||||||
|
|
||||||
@@ -24,9 +22,11 @@ export default function GitLabOAuth2CallbackPage() {
|
|||||||
workspaceId: localStorage.getItem("projectData.id") as string,
|
workspaceId: localStorage.getItem("projectData.id") as string,
|
||||||
code: code as string,
|
code: code as string,
|
||||||
integration: "gitlab",
|
integration: "gitlab",
|
||||||
...(url === "" ? {} : {
|
...(url === ""
|
||||||
url
|
? {}
|
||||||
})
|
: {
|
||||||
|
url
|
||||||
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
router.push(`/integrations/gitlab/create?integrationAuthId=${integrationAuth.id}`);
|
router.push(`/integrations/gitlab/create?integrationAuthId=${integrationAuth.id}`);
|
||||||
|
|||||||
@@ -6,9 +6,7 @@ import { useRouter } from "next/router";
|
|||||||
import { faArrowUpRightFromSquare, faBookOpen } from "@fortawesome/free-solid-svg-icons";
|
import { faArrowUpRightFromSquare, faBookOpen } from "@fortawesome/free-solid-svg-icons";
|
||||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||||
|
|
||||||
import {
|
import { useSaveIntegrationAccessToken } from "@app/hooks/api";
|
||||||
useSaveIntegrationAccessToken
|
|
||||||
} from "@app/hooks/api";
|
|
||||||
|
|
||||||
import { Button, Card, CardTitle, FormControl, Input } from "../../../components/v2";
|
import { Button, Card, CardTitle, FormControl, Input } from "../../../components/v2";
|
||||||
|
|
||||||
@@ -18,7 +16,7 @@ export default function HashiCorpVaultAuthorizeIntegrationPage() {
|
|||||||
|
|
||||||
const [vaultURL, setVaultURL] = useState("");
|
const [vaultURL, setVaultURL] = useState("");
|
||||||
const [vaultURLErrorText, setVaultURLErrorText] = useState("");
|
const [vaultURLErrorText, setVaultURLErrorText] = useState("");
|
||||||
|
|
||||||
const [vaultNamespace, setVaultNamespace] = useState("");
|
const [vaultNamespace, setVaultNamespace] = useState("");
|
||||||
const [vaultNamespaceErrorText, setVaultNamespaceErrorText] = useState("");
|
const [vaultNamespaceErrorText, setVaultNamespaceErrorText] = useState("");
|
||||||
|
|
||||||
@@ -35,44 +33,44 @@ export default function HashiCorpVaultAuthorizeIntegrationPage() {
|
|||||||
if (vaultURL.length === 0) {
|
if (vaultURL.length === 0) {
|
||||||
setVaultURLErrorText("Vault Cluster URL cannot be blank");
|
setVaultURLErrorText("Vault Cluster URL cannot be blank");
|
||||||
} else {
|
} else {
|
||||||
setVaultURLErrorText("");
|
setVaultURLErrorText("");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vaultNamespace.length === 0) {
|
if (vaultNamespace.length === 0) {
|
||||||
setVaultNamespaceErrorText("Vault Namespace cannot be blank");
|
setVaultNamespaceErrorText("Vault Namespace cannot be blank");
|
||||||
} else {
|
} else {
|
||||||
setVaultNamespaceErrorText("");
|
setVaultNamespaceErrorText("");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vaultRoleID.length === 0) {
|
if (vaultRoleID.length === 0) {
|
||||||
setVaultRoleIDErrorText("Vault Role ID cannot be blank");
|
setVaultRoleIDErrorText("Vault Role ID cannot be blank");
|
||||||
} else {
|
} else {
|
||||||
setVaultRoleIDErrorText("");
|
setVaultRoleIDErrorText("");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vaultSecretID.length === 0) {
|
if (vaultSecretID.length === 0) {
|
||||||
setVaultSecretIDErrorText("Vault Secret ID cannot be blank");
|
setVaultSecretIDErrorText("Vault Secret ID cannot be blank");
|
||||||
} else {
|
} else {
|
||||||
setVaultSecretIDErrorText("");
|
setVaultSecretIDErrorText("");
|
||||||
}
|
}
|
||||||
if (
|
if (
|
||||||
vaultURL.length === 0 ||
|
vaultURL.length === 0 ||
|
||||||
vaultNamespace.length === 0 ||
|
vaultNamespace.length === 0 ||
|
||||||
vaultRoleID.length === 0 ||
|
vaultRoleID.length === 0 ||
|
||||||
vaultSecretID.length === 0
|
vaultSecretID.length === 0
|
||||||
) {
|
) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
|
|
||||||
const integrationAuth = await mutateAsync({
|
const integrationAuth = await mutateAsync({
|
||||||
workspaceId: localStorage.getItem("projectData.id"),
|
workspaceId: localStorage.getItem("projectData.id"),
|
||||||
integration: "hashicorp-vault",
|
integration: "hashicorp-vault",
|
||||||
accessId: vaultRoleID,
|
accessId: vaultRoleID,
|
||||||
accessToken: vaultSecretID,
|
accessToken: vaultSecretID,
|
||||||
url: vaultURL,
|
url: vaultURL,
|
||||||
namespace: vaultNamespace
|
namespace: vaultNamespace
|
||||||
});
|
});
|
||||||
|
|
||||||
setIsLoading(false);
|
setIsLoading(false);
|
||||||
@@ -87,11 +85,11 @@ export default function HashiCorpVaultAuthorizeIntegrationPage() {
|
|||||||
<div className="flex h-full w-full items-center justify-center">
|
<div className="flex h-full w-full items-center justify-center">
|
||||||
<Head>
|
<Head>
|
||||||
<title>Authorize Vault Integration</title>
|
<title>Authorize Vault Integration</title>
|
||||||
<link rel='icon' href='/infisical.ico' />
|
<link rel="icon" href="/infisical.ico" />
|
||||||
</Head>
|
</Head>
|
||||||
<Card className="max-w-lg rounded-md border border-mineshaft-600 mb-12">
|
<Card className="mb-12 max-w-lg rounded-md border border-mineshaft-600">
|
||||||
<CardTitle
|
<CardTitle
|
||||||
className="text-left px-6 text-xl"
|
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."
|
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">
|
<div className="flex flex-row items-center">
|
||||||
@@ -106,10 +104,13 @@ export default function HashiCorpVaultAuthorizeIntegrationPage() {
|
|||||||
<span className="ml-2.5">HashiCorp Vault Integration</span>
|
<span className="ml-2.5">HashiCorp Vault Integration</span>
|
||||||
<Link href="https://infisical.com/docs/integrations/cloud/hashicorp-vault" passHref>
|
<Link href="https://infisical.com/docs/integrations/cloud/hashicorp-vault" passHref>
|
||||||
<a target="_blank" rel="noopener noreferrer">
|
<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">
|
<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"/>
|
<FontAwesomeIcon icon={faBookOpen} className="mr-1.5" />
|
||||||
Docs
|
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>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
</Link>
|
</Link>
|
||||||
@@ -129,11 +130,11 @@ export default function HashiCorpVaultAuthorizeIntegrationPage() {
|
|||||||
isError={vaultNamespaceErrorText !== "" ?? false}
|
isError={vaultNamespaceErrorText !== "" ?? false}
|
||||||
className="px-6"
|
className="px-6"
|
||||||
>
|
>
|
||||||
<Input
|
<Input
|
||||||
placeholder="admin/education"
|
placeholder="admin/education"
|
||||||
value={vaultNamespace}
|
value={vaultNamespace}
|
||||||
onChange={(e) => setVaultNamespace(e.target.value)}
|
onChange={(e) => setVaultNamespace(e.target.value)}
|
||||||
/>
|
/>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
<FormControl
|
<FormControl
|
||||||
label="Vault RoleID"
|
label="Vault RoleID"
|
||||||
@@ -141,7 +142,11 @@ export default function HashiCorpVaultAuthorizeIntegrationPage() {
|
|||||||
isError={vaultRoleIDErrorText !== "" ?? false}
|
isError={vaultRoleIDErrorText !== "" ?? false}
|
||||||
className="px-6"
|
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>
|
||||||
<FormControl
|
<FormControl
|
||||||
label="Vault SecretID"
|
label="Vault SecretID"
|
||||||
@@ -149,11 +154,11 @@ export default function HashiCorpVaultAuthorizeIntegrationPage() {
|
|||||||
isError={vaultSecretIDErrorText !== "" ?? false}
|
isError={vaultSecretIDErrorText !== "" ?? false}
|
||||||
className="px-6"
|
className="px-6"
|
||||||
>
|
>
|
||||||
<Input
|
<Input
|
||||||
placeholder=""
|
placeholder=""
|
||||||
value={vaultSecretID}
|
value={vaultSecretID}
|
||||||
onChange={(e) => setVaultSecretID(e.target.value)}
|
onChange={(e) => setVaultSecretID(e.target.value)}
|
||||||
/>
|
/>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
<Button
|
<Button
|
||||||
onClick={handleButtonClick}
|
onClick={handleButtonClick}
|
||||||
@@ -169,4 +174,4 @@ export default function HashiCorpVaultAuthorizeIntegrationPage() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
HashiCorpVaultAuthorizeIntegrationPage.requireAuth = true;
|
HashiCorpVaultAuthorizeIntegrationPage.requireAuth = true;
|
||||||
|
|||||||
@@ -3,13 +3,16 @@ import Head from "next/head";
|
|||||||
import Image from "next/image";
|
import Image from "next/image";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import { 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 { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||||
import queryString from "query-string";
|
import queryString from "query-string";
|
||||||
|
|
||||||
import {
|
import { useCreateIntegration } from "@app/hooks/api";
|
||||||
useCreateIntegration
|
|
||||||
} from "@app/hooks/api";
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
@@ -30,7 +33,9 @@ export default function HashiCorpVaultCreateIntegrationPage() {
|
|||||||
const { integrationAuthId } = queryString.parse(router.asPath.split("?")[1]);
|
const { integrationAuthId } = queryString.parse(router.asPath.split("?")[1]);
|
||||||
|
|
||||||
const { data: workspace } = useGetWorkspaceById(localStorage.getItem("projectData.id") ?? "");
|
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 [vaultEnginePath, setVaultEnginePath] = useState("");
|
||||||
const [vaultEnginePathErrorText, setVaultEnginePathErrorText] = useState("");
|
const [vaultEnginePathErrorText, setVaultEnginePathErrorText] = useState("");
|
||||||
@@ -84,14 +89,14 @@ export default function HashiCorpVaultCreateIntegrationPage() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return integrationAuth && workspace ? (
|
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>
|
<Head>
|
||||||
<title>Set Up Vault Integration</title>
|
<title>Set Up Vault Integration</title>
|
||||||
<link rel='icon' href='/infisical.ico' />
|
<link rel="icon" href="/infisical.ico" />
|
||||||
</Head>
|
</Head>
|
||||||
<Card className="max-w-lg rounded-md border border-mineshaft-600">
|
<Card className="max-w-lg rounded-md border border-mineshaft-600">
|
||||||
<CardTitle
|
<CardTitle
|
||||||
className="text-left px-6 text-xl"
|
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."
|
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">
|
<div className="flex flex-row items-center">
|
||||||
@@ -106,10 +111,13 @@ export default function HashiCorpVaultCreateIntegrationPage() {
|
|||||||
<span className="ml-2.5">HashiCorp Vault Integration</span>
|
<span className="ml-2.5">HashiCorp Vault Integration</span>
|
||||||
<Link href="https://infisical.com/docs/integrations/cloud/hashicorp-vault" passHref>
|
<Link href="https://infisical.com/docs/integrations/cloud/hashicorp-vault" passHref>
|
||||||
<a target="_blank" rel="noopener noreferrer">
|
<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">
|
<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"/>
|
<FontAwesomeIcon icon={faBookOpen} className="mr-1.5" />
|
||||||
Docs
|
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>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
</Link>
|
</Link>
|
||||||
@@ -173,31 +181,48 @@ export default function HashiCorpVaultCreateIntegrationPage() {
|
|||||||
Create Integration
|
Create Integration
|
||||||
</Button>
|
</Button>
|
||||||
</Card>
|
</Card>
|
||||||
<div className="border-t border-mineshaft-800 w-full max-w-md mt-6"/>
|
<div className="mt-6 w-full max-w-md border-t border-mineshaft-800" />
|
||||||
<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="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-mineshaft-200 text-xl"/> <span className="ml-3 text-md text-mineshaft-100">Pro Tips</span></div>
|
<div className="flex flex-row items-center">
|
||||||
<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>
|
<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>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div className="flex justify-center items-center w-full h-full">
|
<div className="flex h-full w-full items-center justify-center">
|
||||||
<Head>
|
<Head>
|
||||||
<title>Set Up Vault Integration</title>
|
<title>Set Up Vault Integration</title>
|
||||||
<link rel='icon' href='/infisical.ico' />
|
<link rel="icon" href="/infisical.ico" />
|
||||||
</Head>
|
</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">
|
{isintegrationAuthLoading ? (
|
||||||
<FontAwesomeIcon icon={faBugs} className="text-6xl my-2 inlineli"/>
|
<img
|
||||||
<p>
|
src="/images/loading/loading.gif"
|
||||||
Something went wrong. Please contact <a
|
height={70}
|
||||||
className="inline underline underline-offset-4 decoration-primary-500 opacity-80 hover:opacity-100 text-mineshaft-100 duration-200 cursor-pointer"
|
width={120}
|
||||||
target="_blank"
|
alt="infisical loading indicator"
|
||||||
rel="noopener noreferrer"
|
/>
|
||||||
href="mailto:[email protected]"
|
) : (
|
||||||
>
|
<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">
|
||||||
support@infisical.com
|
<FontAwesomeIcon icon={faBugs} className="inlineli my-2 text-6xl" />
|
||||||
</a> if the issue persists.
|
<p>
|
||||||
</p>
|
Something went wrong. Please contact{" "}
|
||||||
</div>}
|
<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:[email protected]"
|
||||||
|
>
|
||||||
|
support@infisical.com
|
||||||
|
</a>{" "}
|
||||||
|
if the issue persists.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,9 +2,7 @@ import { useEffect, useState } from "react";
|
|||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import queryString from "query-string";
|
import queryString from "query-string";
|
||||||
|
|
||||||
import {
|
import { useCreateIntegration } from "@app/hooks/api";
|
||||||
useCreateIntegration
|
|
||||||
} from "@app/hooks/api";
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
|
|||||||
@@ -2,9 +2,7 @@ import { useEffect } from "react";
|
|||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import queryString from "query-string";
|
import queryString from "query-string";
|
||||||
|
|
||||||
import {
|
import { useAuthorizeIntegration } from "@app/hooks/api";
|
||||||
useAuthorizeIntegration
|
|
||||||
} from "@app/hooks/api";
|
|
||||||
|
|
||||||
export default function HerokuOAuth2CallbackPage() {
|
export default function HerokuOAuth2CallbackPage() {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|||||||
@@ -1,9 +1,7 @@
|
|||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
|
|
||||||
import {
|
import { useSaveIntegrationAccessToken } from "@app/hooks/api";
|
||||||
useSaveIntegrationAccessToken
|
|
||||||
} from "@app/hooks/api";
|
|
||||||
|
|
||||||
import { Button, Card, CardTitle, FormControl, Input } from "../../../components/v2";
|
import { Button, Card, CardTitle, FormControl, Input } from "../../../components/v2";
|
||||||
|
|
||||||
@@ -26,7 +24,7 @@ export default function LaravelForgeCreateIntegrationPage() {
|
|||||||
setApiKeyErrorText("Access Token cannot be blank");
|
setApiKeyErrorText("Access Token cannot be blank");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (serverId.length === 0) {
|
if (serverId.length === 0) {
|
||||||
setServerIdErrorText("Server Id cannot be blank");
|
setServerIdErrorText("Server Id cannot be blank");
|
||||||
return;
|
return;
|
||||||
@@ -58,14 +56,22 @@ export default function LaravelForgeCreateIntegrationPage() {
|
|||||||
errorText={apiKeyErrorText}
|
errorText={apiKeyErrorText}
|
||||||
isError={apiKeyErrorText !== "" ?? false}
|
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>
|
||||||
<FormControl
|
<FormControl
|
||||||
label="Laravel Forge Server ID"
|
label="Laravel Forge Server ID"
|
||||||
errorText={serverIdErrorText}
|
errorText={serverIdErrorText}
|
||||||
isError={serverIdErrorText !== "" ?? false}
|
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>
|
</FormControl>
|
||||||
<Button
|
<Button
|
||||||
onClick={handleButtonClick}
|
onClick={handleButtonClick}
|
||||||
|
|||||||
@@ -2,9 +2,7 @@ import { useEffect, useState } from "react";
|
|||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import queryString from "query-string";
|
import queryString from "query-string";
|
||||||
|
|
||||||
import {
|
import { useCreateIntegration } from "@app/hooks/api";
|
||||||
useCreateIntegration
|
|
||||||
} from "@app/hooks/api";
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
@@ -64,7 +62,10 @@ export default function LaravelForgeCreateIntegrationPage() {
|
|||||||
integrationAuthId: integrationAuth?.id,
|
integrationAuthId: integrationAuth?.id,
|
||||||
isActive: true,
|
isActive: true,
|
||||||
app: targetApp,
|
app: targetApp,
|
||||||
appId: String(integrationAuthApps?.find((integrationAuthApp) => integrationAuthApp.name === targetApp)?.appId),
|
appId: String(
|
||||||
|
integrationAuthApps?.find((integrationAuthApp) => integrationAuthApp.name === targetApp)
|
||||||
|
?.appId
|
||||||
|
),
|
||||||
sourceEnvironment: selectedSourceEnvironment,
|
sourceEnvironment: selectedSourceEnvironment,
|
||||||
secretPath
|
secretPath
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -2,9 +2,7 @@ import { useEffect, useState } from "react";
|
|||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import queryString from "query-string";
|
import queryString from "query-string";
|
||||||
|
|
||||||
import {
|
import { useCreateIntegration } from "@app/hooks/api";
|
||||||
useCreateIntegration
|
|
||||||
} from "@app/hooks/api";
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
@@ -73,7 +71,9 @@ export default function NetlifyCreateIntegrationPage() {
|
|||||||
integrationAuthId: integrationAuth?.id,
|
integrationAuthId: integrationAuth?.id,
|
||||||
isActive: true,
|
isActive: true,
|
||||||
app: targetApp,
|
app: targetApp,
|
||||||
appId: integrationAuthApps?.find((integrationAuthApp) => integrationAuthApp.name === targetApp)?.appId,
|
appId: integrationAuthApps?.find(
|
||||||
|
(integrationAuthApp) => integrationAuthApp.name === targetApp
|
||||||
|
)?.appId,
|
||||||
sourceEnvironment: selectedSourceEnvironment,
|
sourceEnvironment: selectedSourceEnvironment,
|
||||||
targetEnvironment,
|
targetEnvironment,
|
||||||
secretPath
|
secretPath
|
||||||
|
|||||||
@@ -2,9 +2,7 @@ import { useEffect } from "react";
|
|||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import queryString from "query-string";
|
import queryString from "query-string";
|
||||||
|
|
||||||
import {
|
import { useAuthorizeIntegration } from "@app/hooks/api";
|
||||||
useAuthorizeIntegration
|
|
||||||
} from "@app/hooks/api";
|
|
||||||
|
|
||||||
export default function NetlifyOAuth2CallbackPage() {
|
export default function NetlifyOAuth2CallbackPage() {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|||||||
@@ -1,9 +1,7 @@
|
|||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
|
|
||||||
import {
|
import { useSaveIntegrationAccessToken } from "@app/hooks/api";
|
||||||
useSaveIntegrationAccessToken
|
|
||||||
} from "@app/hooks/api";
|
|
||||||
|
|
||||||
import { Button, Card, CardTitle, FormControl, Input } from "../../../components/v2";
|
import { Button, Card, CardTitle, FormControl, Input } from "../../../components/v2";
|
||||||
|
|
||||||
|
|||||||
@@ -2,9 +2,7 @@ import { useEffect, useState } from "react";
|
|||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import queryString from "query-string";
|
import queryString from "query-string";
|
||||||
|
|
||||||
import {
|
import { useCreateIntegration } from "@app/hooks/api";
|
||||||
useCreateIntegration
|
|
||||||
} from "@app/hooks/api";
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
@@ -44,7 +42,7 @@ export default function NorthflankCreateIntegrationPage() {
|
|||||||
integrationAuthId: (integrationAuthId as string) ?? "",
|
integrationAuthId: (integrationAuthId as string) ?? "",
|
||||||
appId: targetAppId
|
appId: targetAppId
|
||||||
});
|
});
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (workspace) {
|
if (workspace) {
|
||||||
setSelectedSourceEnvironment(workspace.environments[0].slug);
|
setSelectedSourceEnvironment(workspace.environments[0].slug);
|
||||||
@@ -62,7 +60,7 @@ export default function NorthflankCreateIntegrationPage() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [integrationAuthApps]);
|
}, [integrationAuthApps]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (integrationAuthSecretGroups) {
|
if (integrationAuthSecretGroups) {
|
||||||
if (integrationAuthSecretGroups.length > 0) {
|
if (integrationAuthSecretGroups.length > 0) {
|
||||||
@@ -73,9 +71,8 @@ export default function NorthflankCreateIntegrationPage() {
|
|||||||
setTargetSecretGroupId("none");
|
setTargetSecretGroupId("none");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}, [integrationAuthSecretGroups]);
|
}, [integrationAuthSecretGroups]);
|
||||||
|
|
||||||
const handleButtonClick = async () => {
|
const handleButtonClick = async () => {
|
||||||
try {
|
try {
|
||||||
if (!integrationAuth?.id) return;
|
if (!integrationAuth?.id) return;
|
||||||
@@ -85,7 +82,9 @@ export default function NorthflankCreateIntegrationPage() {
|
|||||||
await mutateAsync({
|
await mutateAsync({
|
||||||
integrationAuthId: integrationAuth?.id,
|
integrationAuthId: integrationAuth?.id,
|
||||||
isActive: true,
|
isActive: true,
|
||||||
app: integrationAuthApps?.find((integrationAuthApp) => integrationAuthApp.appId === targetAppId)?.name,
|
app: integrationAuthApps?.find(
|
||||||
|
(integrationAuthApp) => integrationAuthApp.appId === targetAppId
|
||||||
|
)?.name,
|
||||||
appId: targetAppId,
|
appId: targetAppId,
|
||||||
sourceEnvironment: selectedSourceEnvironment,
|
sourceEnvironment: selectedSourceEnvironment,
|
||||||
targetServiceId: targetSecretGroupId,
|
targetServiceId: targetSecretGroupId,
|
||||||
@@ -99,7 +98,7 @@ export default function NorthflankCreateIntegrationPage() {
|
|||||||
console.error(err);
|
console.error(err);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return integrationAuth &&
|
return integrationAuth &&
|
||||||
workspace &&
|
workspace &&
|
||||||
selectedSourceEnvironment &&
|
selectedSourceEnvironment &&
|
||||||
|
|||||||
@@ -6,9 +6,7 @@ import { useRouter } from "next/router";
|
|||||||
import { faArrowUpRightFromSquare, faBookOpen } from "@fortawesome/free-solid-svg-icons";
|
import { faArrowUpRightFromSquare, faBookOpen } from "@fortawesome/free-solid-svg-icons";
|
||||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||||
|
|
||||||
import {
|
import { useSaveIntegrationAccessToken } from "@app/hooks/api";
|
||||||
useSaveIntegrationAccessToken
|
|
||||||
} from "@app/hooks/api";
|
|
||||||
|
|
||||||
import { Button, Card, CardTitle, FormControl, Input } from "../../../components/v2";
|
import { Button, Card, CardTitle, FormControl, Input } from "../../../components/v2";
|
||||||
|
|
||||||
@@ -48,11 +46,11 @@ export default function QoveryCreateIntegrationPage() {
|
|||||||
<div className="flex h-full w-full items-center justify-center">
|
<div className="flex h-full w-full items-center justify-center">
|
||||||
<Head>
|
<Head>
|
||||||
<title>Authorize Qovery Integration</title>
|
<title>Authorize Qovery Integration</title>
|
||||||
<link rel='icon' href='/infisical.ico' />
|
<link rel="icon" href="/infisical.ico" />
|
||||||
</Head>
|
</Head>
|
||||||
<Card className="max-w-lg rounded-md border border-mineshaft-600 mb-12">
|
<Card className="mb-12 max-w-lg rounded-md border border-mineshaft-600">
|
||||||
<CardTitle
|
<CardTitle
|
||||||
className="text-left px-6 text-xl"
|
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."
|
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="flex flex-row items-center">
|
||||||
@@ -67,10 +65,13 @@ export default function QoveryCreateIntegrationPage() {
|
|||||||
<span className="ml-2.5">Qovery Integration </span>
|
<span className="ml-2.5">Qovery Integration </span>
|
||||||
<Link href="https://infisical.com/docs/integrations/cloud/qovery" passHref>
|
<Link href="https://infisical.com/docs/integrations/cloud/qovery" passHref>
|
||||||
<a target="_blank" rel="noopener noreferrer">
|
<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">
|
<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"/>
|
<FontAwesomeIcon icon={faBookOpen} className="mr-1.5" />
|
||||||
Docs
|
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>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
</Link>
|
</Link>
|
||||||
|
|||||||
@@ -21,14 +21,12 @@ import {
|
|||||||
TabPanel,
|
TabPanel,
|
||||||
Tabs
|
Tabs
|
||||||
} from "@app/components/v2";
|
} from "@app/components/v2";
|
||||||
|
import { useCreateIntegration } from "@app/hooks/api";
|
||||||
import {
|
import {
|
||||||
useCreateIntegration
|
useGetIntegrationAuthQoveryEnvironments,
|
||||||
} from "@app/hooks/api";
|
useGetIntegrationAuthQoveryOrgs,
|
||||||
import {
|
useGetIntegrationAuthQoveryProjects,
|
||||||
useGetIntegrationAuthQoveryEnvironments,
|
useGetIntegrationAuthQoveryScopes
|
||||||
useGetIntegrationAuthQoveryOrgs,
|
|
||||||
useGetIntegrationAuthQoveryProjects,
|
|
||||||
useGetIntegrationAuthQoveryScopes
|
|
||||||
} from "@app/hooks/api/integrationAuth/queries";
|
} from "@app/hooks/api/integrationAuth/queries";
|
||||||
|
|
||||||
import { useGetIntegrationAuthById } from "../../../hooks/api/integrationAuth";
|
import { useGetIntegrationAuthById } from "../../../hooks/api/integrationAuth";
|
||||||
@@ -52,7 +50,7 @@ enum TabSections {
|
|||||||
* -> Get projects belonging to the organization - select project
|
* -> Get projects belonging to the organization - select project
|
||||||
* -> Get environments belonging to the project - select environmnet
|
* -> Get environments belonging to the project - select environmnet
|
||||||
* -> Get qovery scopes / application (this is the application to sync to)
|
* -> Get qovery scopes / application (this is the application to sync to)
|
||||||
*
|
*
|
||||||
* Do we even need to get organizations?
|
* Do we even need to get organizations?
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -69,9 +67,11 @@ export default function QoveryCreateIntegrationPage() {
|
|||||||
const [selectedSourceEnvironment, setSelectedSourceEnvironment] = useState("");
|
const [selectedSourceEnvironment, setSelectedSourceEnvironment] = useState("");
|
||||||
const [secretPath, setSecretPath] = useState("/");
|
const [secretPath, setSecretPath] = useState("/");
|
||||||
|
|
||||||
const { data: integrationAuthOrgs } = useGetIntegrationAuthQoveryOrgs((integrationAuthId as string) ?? "");
|
const { data: integrationAuthOrgs } = useGetIntegrationAuthQoveryOrgs(
|
||||||
|
(integrationAuthId as string) ?? ""
|
||||||
|
);
|
||||||
const [targetOrgId, setTargetOrgId] = useState("");
|
const [targetOrgId, setTargetOrgId] = useState("");
|
||||||
|
|
||||||
const { data: integrationAuthProjects } = useGetIntegrationAuthQoveryProjects({
|
const { data: integrationAuthProjects } = useGetIntegrationAuthQoveryProjects({
|
||||||
integrationAuthId: (integrationAuthId as string) ?? "",
|
integrationAuthId: (integrationAuthId as string) ?? "",
|
||||||
orgId: targetOrgId
|
orgId: targetOrgId
|
||||||
@@ -84,11 +84,12 @@ export default function QoveryCreateIntegrationPage() {
|
|||||||
});
|
});
|
||||||
const [targetEnvironmentId, setTargetEnvironmentId] = useState("");
|
const [targetEnvironmentId, setTargetEnvironmentId] = useState("");
|
||||||
|
|
||||||
const { data: integrationAuthApps, isLoading: isIntegrationAuthAppsLoading } = useGetIntegrationAuthQoveryScopes({
|
const { data: integrationAuthApps, isLoading: isIntegrationAuthAppsLoading } =
|
||||||
integrationAuthId: (integrationAuthId as string) ?? "",
|
useGetIntegrationAuthQoveryScopes({
|
||||||
environmentId: targetEnvironmentId,
|
integrationAuthId: (integrationAuthId as string) ?? "",
|
||||||
scope: (scope as ("job" | "application" | "container"))
|
environmentId: targetEnvironmentId,
|
||||||
});
|
scope: scope as "job" | "application" | "container"
|
||||||
|
});
|
||||||
const [targetAppId, setTargetAppId] = useState("");
|
const [targetAppId, setTargetAppId] = useState("");
|
||||||
|
|
||||||
const [isLoading, setIsLoading] = useState(false);
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
@@ -145,10 +146,19 @@ export default function QoveryCreateIntegrationPage() {
|
|||||||
|
|
||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
|
|
||||||
const targetOrg = integrationAuthOrgs?.find((integrationAuthOrg) => integrationAuthOrg.orgId === targetOrgId)?.name;
|
const targetOrg = integrationAuthOrgs?.find(
|
||||||
const targetProject = integrationAuthProjects?.find((integrationAuthProject) => integrationAuthProject.projectId === targetProjectId)?.name;
|
(integrationAuthOrg) => integrationAuthOrg.orgId === targetOrgId
|
||||||
const targetEnvironment = integrationAuthEnvironments?.find((integrationAuthEnvironment) => integrationAuthEnvironment.environmentId === targetEnvironmentId)?.name;
|
)?.name;
|
||||||
const targetApp = integrationAuthApps?.find((integrationAuthApp) => integrationAuthApp.appId === targetAppId)?.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({
|
await mutateAsync({
|
||||||
integrationAuthId: integrationAuth?.id,
|
integrationAuthId: integrationAuth?.id,
|
||||||
@@ -172,18 +182,16 @@ export default function QoveryCreateIntegrationPage() {
|
|||||||
console.error(err);
|
console.error(err);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return integrationAuth &&
|
return integrationAuth && workspace && selectedSourceEnvironment ? (
|
||||||
workspace &&
|
<div className="flex h-full w-full flex-col items-center justify-center bg-gradient-to-tr from-mineshaft-900 to-bunker-900">
|
||||||
selectedSourceEnvironment ? (
|
|
||||||
<div className="flex flex-col h-full w-full items-center justify-center bg-gradient-to-tr from-mineshaft-900 to-bunker-900">
|
|
||||||
<Head>
|
<Head>
|
||||||
<title>Set Up Qovery Integration</title>
|
<title>Set Up Qovery Integration</title>
|
||||||
<link rel='icon' href='/infisical.ico' />
|
<link rel="icon" href="/infisical.ico" />
|
||||||
</Head>
|
</Head>
|
||||||
<Card className="max-w-lg rounded-md border border-mineshaft-600 p-0">
|
<Card className="max-w-lg rounded-md border border-mineshaft-600 p-0">
|
||||||
<CardTitle
|
<CardTitle
|
||||||
className="text-left px-6 text-xl"
|
className="px-6 text-left text-xl"
|
||||||
subTitle="Choose which environment in Infisical you want to sync to Checkly environment variables."
|
subTitle="Choose which environment in Infisical you want to sync to Checkly environment variables."
|
||||||
>
|
>
|
||||||
<div className="flex flex-row items-center">
|
<div className="flex flex-row items-center">
|
||||||
@@ -198,10 +206,13 @@ export default function QoveryCreateIntegrationPage() {
|
|||||||
<span className="ml-2.5">Qovery Integration </span>
|
<span className="ml-2.5">Qovery Integration </span>
|
||||||
<Link href="https://infisical.com/docs/integrations/cloud/qovery" passHref>
|
<Link href="https://infisical.com/docs/integrations/cloud/qovery" passHref>
|
||||||
<a target="_blank" rel="noopener noreferrer">
|
<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">
|
<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"/>
|
<FontAwesomeIcon icon={faBookOpen} className="mr-1.5" />
|
||||||
Docs
|
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>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
</Link>
|
</Link>
|
||||||
@@ -209,7 +220,7 @@ export default function QoveryCreateIntegrationPage() {
|
|||||||
</CardTitle>
|
</CardTitle>
|
||||||
<Tabs defaultValue={TabSections.InfisicalSettings} className="px-6">
|
<Tabs defaultValue={TabSections.InfisicalSettings} className="px-6">
|
||||||
<TabList>
|
<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.InfisicalSettings}>Infisical Settings</Tab>
|
||||||
<Tab value={TabSections.QoverySettings}>Qovery Settings</Tab>
|
<Tab value={TabSections.QoverySettings}>Qovery Settings</Tab>
|
||||||
</div>
|
</div>
|
||||||
@@ -262,107 +273,112 @@ export default function QoveryCreateIntegrationPage() {
|
|||||||
className="w-full border border-mineshaft-500"
|
className="w-full border border-mineshaft-500"
|
||||||
>
|
>
|
||||||
{qoveryScopes.map((qoveryScope) => (
|
{qoveryScopes.map((qoveryScope) => (
|
||||||
<SelectItem
|
<SelectItem value={qoveryScope.value} key={`target-app-${qoveryScope.value}`}>
|
||||||
value={qoveryScope.value}
|
|
||||||
key={`target-app-${qoveryScope.value}`}
|
|
||||||
>
|
|
||||||
{qoveryScope.label}
|
{qoveryScope.label}
|
||||||
</SelectItem>
|
</SelectItem>
|
||||||
))}
|
))}
|
||||||
</Select>
|
</Select>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
{integrationAuthOrgs && <FormControl label="Qovery Organization">
|
{integrationAuthOrgs && (
|
||||||
<Select
|
<FormControl label="Qovery Organization">
|
||||||
value={targetOrgId}
|
<Select
|
||||||
onValueChange={(val) => setTargetOrgId(val)}
|
value={targetOrgId}
|
||||||
className="w-full border border-mineshaft-500"
|
onValueChange={(val) => setTargetOrgId(val)}
|
||||||
isDisabled={integrationAuthOrgs.length === 0}
|
className="w-full border border-mineshaft-500"
|
||||||
>
|
isDisabled={integrationAuthOrgs.length === 0}
|
||||||
{integrationAuthOrgs.length > 0 ? (
|
>
|
||||||
integrationAuthOrgs.map((integrationAuthOrg) => (
|
{integrationAuthOrgs.length > 0 ? (
|
||||||
<SelectItem
|
integrationAuthOrgs.map((integrationAuthOrg) => (
|
||||||
value={integrationAuthOrg.orgId}
|
<SelectItem
|
||||||
key={`target-app-${integrationAuthOrg.orgId}`}
|
value={integrationAuthOrg.orgId}
|
||||||
>
|
key={`target-app-${integrationAuthOrg.orgId}`}
|
||||||
{integrationAuthOrg.name}
|
>
|
||||||
|
{integrationAuthOrg.name}
|
||||||
|
</SelectItem>
|
||||||
|
))
|
||||||
|
) : (
|
||||||
|
<SelectItem value="none" key="target-app-none">
|
||||||
|
No organizaztions found
|
||||||
</SelectItem>
|
</SelectItem>
|
||||||
))
|
)}
|
||||||
) : (
|
</Select>
|
||||||
<SelectItem value="none" key="target-app-none">
|
</FormControl>
|
||||||
No organizaztions found
|
)}
|
||||||
</SelectItem>
|
{integrationAuthProjects && (
|
||||||
)}
|
<FormControl label="Qovery Project">
|
||||||
</Select>
|
<Select
|
||||||
</FormControl>}
|
value={targetProjectId}
|
||||||
{integrationAuthProjects && <FormControl label="Qovery Project">
|
onValueChange={(val) => setTargetProjectId(val)}
|
||||||
<Select
|
className="w-full border border-mineshaft-500"
|
||||||
value={targetProjectId}
|
isDisabled={integrationAuthProjects.length === 0}
|
||||||
onValueChange={(val) => setTargetProjectId(val)}
|
>
|
||||||
className="w-full border border-mineshaft-500"
|
{integrationAuthProjects.length > 0 ? (
|
||||||
isDisabled={integrationAuthProjects.length === 0}
|
integrationAuthProjects.map((integrationAuthProject) => (
|
||||||
>
|
<SelectItem
|
||||||
{integrationAuthProjects.length > 0 ? (
|
value={integrationAuthProject.projectId}
|
||||||
integrationAuthProjects.map((integrationAuthProject) => (
|
key={`target-app-${integrationAuthProject.projectId}`}
|
||||||
<SelectItem
|
>
|
||||||
value={integrationAuthProject.projectId}
|
{integrationAuthProject.name}
|
||||||
key={`target-app-${integrationAuthProject.projectId}`}
|
</SelectItem>
|
||||||
>
|
))
|
||||||
{integrationAuthProject.name}
|
) : (
|
||||||
|
<SelectItem value="none" key="target-app-none">
|
||||||
|
No projects found
|
||||||
</SelectItem>
|
</SelectItem>
|
||||||
))
|
)}
|
||||||
) : (
|
</Select>
|
||||||
<SelectItem value="none" key="target-app-none">
|
</FormControl>
|
||||||
No projects found
|
)}
|
||||||
</SelectItem>
|
{integrationAuthEnvironments && (
|
||||||
)}
|
<FormControl label="Qovery Environment">
|
||||||
</Select>
|
<Select
|
||||||
</FormControl>}
|
value={targetEnvironmentId}
|
||||||
{integrationAuthEnvironments && <FormControl label="Qovery Environment">
|
onValueChange={(val) => setTargetEnvironmentId(val)}
|
||||||
<Select
|
className="w-full border border-mineshaft-500"
|
||||||
value={targetEnvironmentId}
|
isDisabled={integrationAuthEnvironments.length === 0}
|
||||||
onValueChange={(val) => setTargetEnvironmentId(val)}
|
>
|
||||||
className="w-full border border-mineshaft-500"
|
{integrationAuthEnvironments.length > 0 ? (
|
||||||
isDisabled={integrationAuthEnvironments.length === 0}
|
integrationAuthEnvironments.map((integrationAuthEnvironment) => (
|
||||||
>
|
<SelectItem
|
||||||
{integrationAuthEnvironments.length > 0 ? (
|
value={integrationAuthEnvironment.environmentId}
|
||||||
integrationAuthEnvironments.map((integrationAuthEnvironment) => (
|
key={`target-app-${integrationAuthEnvironment.environmentId}`}
|
||||||
<SelectItem
|
>
|
||||||
value={integrationAuthEnvironment.environmentId}
|
{integrationAuthEnvironment.name}
|
||||||
key={`target-app-${integrationAuthEnvironment.environmentId}`}
|
</SelectItem>
|
||||||
>
|
))
|
||||||
{integrationAuthEnvironment.name}
|
) : (
|
||||||
|
<SelectItem value="none" key="target-app-none">
|
||||||
|
No environments found
|
||||||
</SelectItem>
|
</SelectItem>
|
||||||
))
|
)}
|
||||||
) : (
|
</Select>
|
||||||
<SelectItem value="none" key="target-app-none">
|
</FormControl>
|
||||||
No environments found
|
)}
|
||||||
</SelectItem>
|
{scope && integrationAuthApps && (
|
||||||
)}
|
<FormControl label={`Qovery ${scope.charAt(0).toUpperCase() + scope.slice(1)}`}>
|
||||||
</Select>
|
<Select
|
||||||
</FormControl>}
|
value={targetAppId}
|
||||||
{(scope && integrationAuthApps) && <FormControl label={`Qovery ${scope.charAt(0).toUpperCase() + scope.slice(1)}`}>
|
onValueChange={(val) => setTargetAppId(val)}
|
||||||
<Select
|
className="w-full border border-mineshaft-500"
|
||||||
value={targetAppId}
|
isDisabled={integrationAuthApps.length === 0}
|
||||||
onValueChange={(val) => setTargetAppId(val)}
|
>
|
||||||
className="w-full border border-mineshaft-500"
|
{integrationAuthApps.length > 0 ? (
|
||||||
isDisabled={integrationAuthApps.length === 0}
|
integrationAuthApps.map((integrationAuthApp) => (
|
||||||
>
|
<SelectItem
|
||||||
{integrationAuthApps.length > 0 ? (
|
value={integrationAuthApp.appId as string}
|
||||||
integrationAuthApps.map((integrationAuthApp) => (
|
key={`target-app-${integrationAuthApp.appId}`}
|
||||||
<SelectItem
|
>
|
||||||
value={(integrationAuthApp.appId as string)}
|
{integrationAuthApp.name}
|
||||||
key={`target-app-${integrationAuthApp.appId}`}
|
</SelectItem>
|
||||||
>
|
))
|
||||||
{integrationAuthApp.name}
|
) : (
|
||||||
|
<SelectItem value="none" key="target-app-none">
|
||||||
|
No {scope}s found
|
||||||
</SelectItem>
|
</SelectItem>
|
||||||
))
|
)}
|
||||||
) : (
|
</Select>
|
||||||
<SelectItem value="none" key="target-app-none">
|
</FormControl>
|
||||||
No {scope}s found
|
)}
|
||||||
</SelectItem>
|
|
||||||
)}
|
|
||||||
</Select>
|
|
||||||
</FormControl>}
|
|
||||||
</motion.div>
|
</motion.div>
|
||||||
</TabPanel>
|
</TabPanel>
|
||||||
</Tabs>
|
</Tabs>
|
||||||
@@ -384,24 +400,35 @@ export default function QoveryCreateIntegrationPage() {
|
|||||||
</div> */}
|
</div> */}
|
||||||
</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>
|
<Head>
|
||||||
<title>Set Up Qovery Integration</title>
|
<title>Set Up Qovery Integration</title>
|
||||||
<link rel='icon' href='/infisical.ico' />
|
<link rel="icon" href="/infisical.ico" />
|
||||||
</Head>
|
</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">
|
{isIntegrationAuthAppsLoading ? (
|
||||||
<FontAwesomeIcon icon={faBugs} className="text-6xl my-2 inlineli"/>
|
<img
|
||||||
<p>
|
src="/images/loading/loading.gif"
|
||||||
Something went wrong. Please contact <a
|
height={70}
|
||||||
className="inline underline underline-offset-4 decoration-primary-500 opacity-80 hover:opacity-100 text-mineshaft-100 duration-200 cursor-pointer"
|
width={120}
|
||||||
target="_blank"
|
alt="infisical loading indicator"
|
||||||
rel="noopener noreferrer"
|
/>
|
||||||
href="mailto:[email protected]"
|
) : (
|
||||||
>
|
<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">
|
||||||
support@infisical.com
|
<FontAwesomeIcon icon={faBugs} className="inlineli my-2 text-6xl" />
|
||||||
</a> if the issue persists.
|
<p>
|
||||||
</p>
|
Something went wrong. Please contact{" "}
|
||||||
</div>}
|
<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:[email protected]"
|
||||||
|
>
|
||||||
|
support@infisical.com
|
||||||
|
</a>{" "}
|
||||||
|
if the issue persists.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,7 @@
|
|||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
|
|
||||||
import {
|
import { useSaveIntegrationAccessToken } from "@app/hooks/api";
|
||||||
useSaveIntegrationAccessToken
|
|
||||||
} from "@app/hooks/api";
|
|
||||||
|
|
||||||
import { Button, Card, CardTitle, FormControl, Input } from "../../../components/v2";
|
import { Button, Card, CardTitle, FormControl, Input } from "../../../components/v2";
|
||||||
|
|
||||||
|
|||||||
@@ -2,9 +2,7 @@ import { useEffect, useState } from "react";
|
|||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import queryString from "query-string";
|
import queryString from "query-string";
|
||||||
|
|
||||||
import {
|
import { useCreateIntegration } from "@app/hooks/api";
|
||||||
useCreateIntegration
|
|
||||||
} from "@app/hooks/api";
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import { useRouter } from "next/router";
|
|||||||
import { faArrowUpRightFromSquare, faBookOpen } from "@fortawesome/free-solid-svg-icons";
|
import { faArrowUpRightFromSquare, faBookOpen } from "@fortawesome/free-solid-svg-icons";
|
||||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
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";
|
||||||
|
|
||||||
@@ -46,11 +46,11 @@ export default function RenderCreateIntegrationPage() {
|
|||||||
<div className="flex h-full w-full items-center justify-center">
|
<div className="flex h-full w-full items-center justify-center">
|
||||||
<Head>
|
<Head>
|
||||||
<title>Authorize Render Integration</title>
|
<title>Authorize Render Integration</title>
|
||||||
<link rel='icon' href='/infisical.ico' />
|
<link rel="icon" href="/infisical.ico" />
|
||||||
</Head>
|
</Head>
|
||||||
<Card className="max-w-lg rounded-md border border-mineshaft-600 mb-12">
|
<Card className="mb-12 max-w-lg rounded-md border border-mineshaft-600">
|
||||||
<CardTitle
|
<CardTitle
|
||||||
className="text-left px-6 text-xl"
|
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."
|
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="flex flex-row items-center">
|
||||||
@@ -65,10 +65,13 @@ export default function RenderCreateIntegrationPage() {
|
|||||||
<span className="ml-2.5">Render Integration </span>
|
<span className="ml-2.5">Render Integration </span>
|
||||||
<Link href="https://infisical.com/docs/integrations/cloud/render" passHref>
|
<Link href="https://infisical.com/docs/integrations/cloud/render" passHref>
|
||||||
<a target="_blank" rel="noopener noreferrer">
|
<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">
|
<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"/>
|
<FontAwesomeIcon icon={faBookOpen} className="mr-1.5" />
|
||||||
Docs
|
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>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
</Link>
|
</Link>
|
||||||
|
|||||||
@@ -3,13 +3,16 @@ import Head from "next/head";
|
|||||||
import Image from "next/image";
|
import Image from "next/image";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import { 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 { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||||
import queryString from "query-string";
|
import queryString from "query-string";
|
||||||
|
|
||||||
import {
|
import { useCreateIntegration } from "@app/hooks/api";
|
||||||
useCreateIntegration
|
|
||||||
} from "@app/hooks/api";
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
@@ -33,10 +36,13 @@ export default function RenderCreateIntegrationPage() {
|
|||||||
const { integrationAuthId } = queryString.parse(router.asPath.split("?")[1]);
|
const { integrationAuthId } = queryString.parse(router.asPath.split("?")[1]);
|
||||||
|
|
||||||
const { data: workspace } = useGetWorkspaceById(localStorage.getItem("projectData.id") ?? "");
|
const { data: workspace } = useGetWorkspaceById(localStorage.getItem("projectData.id") ?? "");
|
||||||
const { data: integrationAuth, isLoading: isIntegrationAuthLoading } = useGetIntegrationAuthById((integrationAuthId as string) ?? "");
|
const { data: integrationAuth, isLoading: isIntegrationAuthLoading } = useGetIntegrationAuthById(
|
||||||
const { data: integrationAuthApps, isLoading: isIntegrationAuthAppsLoading } = useGetIntegrationAuthApps({
|
(integrationAuthId as string) ?? ""
|
||||||
integrationAuthId: (integrationAuthId as string) ?? ""
|
);
|
||||||
});
|
const { data: integrationAuthApps, isLoading: isIntegrationAuthAppsLoading } =
|
||||||
|
useGetIntegrationAuthApps({
|
||||||
|
integrationAuthId: (integrationAuthId as string) ?? ""
|
||||||
|
});
|
||||||
|
|
||||||
const [selectedSourceEnvironment, setSelectedSourceEnvironment] = useState("");
|
const [selectedSourceEnvironment, setSelectedSourceEnvironment] = useState("");
|
||||||
const [targetApp, setTargetApp] = useState("");
|
const [targetApp, setTargetApp] = useState("");
|
||||||
@@ -69,7 +75,9 @@ export default function RenderCreateIntegrationPage() {
|
|||||||
integrationAuthId: integrationAuth?.id,
|
integrationAuthId: integrationAuth?.id,
|
||||||
isActive: true,
|
isActive: true,
|
||||||
app: targetApp,
|
app: targetApp,
|
||||||
appId: integrationAuthApps?.find((integrationAuthApp) => integrationAuthApp.name === targetApp)?.appId,
|
appId: integrationAuthApps?.find(
|
||||||
|
(integrationAuthApp) => integrationAuthApp.name === targetApp
|
||||||
|
)?.appId,
|
||||||
sourceEnvironment: selectedSourceEnvironment,
|
sourceEnvironment: selectedSourceEnvironment,
|
||||||
secretPath
|
secretPath
|
||||||
});
|
});
|
||||||
@@ -87,14 +95,14 @@ export default function RenderCreateIntegrationPage() {
|
|||||||
selectedSourceEnvironment &&
|
selectedSourceEnvironment &&
|
||||||
integrationAuthApps &&
|
integrationAuthApps &&
|
||||||
targetApp ? (
|
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>
|
<Head>
|
||||||
<title>Set Up Render Integration</title>
|
<title>Set Up Render Integration</title>
|
||||||
<link rel='icon' href='/infisical.ico' />
|
<link rel="icon" href="/infisical.ico" />
|
||||||
</Head>
|
</Head>
|
||||||
<Card className="max-w-lg rounded-md border border-mineshaft-600">
|
<Card className="max-w-lg rounded-md border border-mineshaft-600">
|
||||||
<CardTitle
|
<CardTitle
|
||||||
className="text-left px-6 text-xl"
|
className="px-6 text-left text-xl"
|
||||||
subTitle="Choose which environment or folder in Infisical you want to sync to Render environment variables."
|
subTitle="Choose which environment or folder in Infisical you want to sync to Render environment variables."
|
||||||
>
|
>
|
||||||
<div className="flex flex-row items-center">
|
<div className="flex flex-row items-center">
|
||||||
@@ -109,10 +117,13 @@ export default function RenderCreateIntegrationPage() {
|
|||||||
<span className="ml-2.5">Render Integration </span>
|
<span className="ml-2.5">Render Integration </span>
|
||||||
<Link href="https://infisical.com/docs/integrations/cloud/render" passHref>
|
<Link href="https://infisical.com/docs/integrations/cloud/render" passHref>
|
||||||
<a target="_blank" rel="noopener noreferrer">
|
<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">
|
<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"/>
|
<FontAwesomeIcon icon={faBookOpen} className="mr-1.5" />
|
||||||
Docs
|
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>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
</Link>
|
</Link>
|
||||||
@@ -175,31 +186,48 @@ export default function RenderCreateIntegrationPage() {
|
|||||||
Create Integration
|
Create Integration
|
||||||
</Button>
|
</Button>
|
||||||
</Card>
|
</Card>
|
||||||
<div className="border-t border-mineshaft-800 w-full max-w-md mt-6"/>
|
<div className="mt-6 w-full max-w-md border-t border-mineshaft-800" />
|
||||||
<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="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-mineshaft-200 text-xl"/> <span className="ml-3 text-md text-mineshaft-100">Pro Tips</span></div>
|
<div className="flex flex-row items-center">
|
||||||
<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>
|
<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>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div className="flex justify-center items-center w-full h-full">
|
<div className="flex h-full w-full items-center justify-center">
|
||||||
<Head>
|
<Head>
|
||||||
<title>Set Up Render Integration</title>
|
<title>Set Up Render Integration</title>
|
||||||
<link rel='icon' href='/infisical.ico' />
|
<link rel="icon" href="/infisical.ico" />
|
||||||
</Head>
|
</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">
|
{isIntegrationAuthLoading || isIntegrationAuthAppsLoading ? (
|
||||||
<FontAwesomeIcon icon={faBugs} className="text-6xl my-2 inlineli"/>
|
<img
|
||||||
<p>
|
src="/images/loading/loading.gif"
|
||||||
Something went wrong. Please contact <a
|
height={70}
|
||||||
className="inline underline underline-offset-4 decoration-primary-500 opacity-80 hover:opacity-100 text-mineshaft-100 duration-200 cursor-pointer"
|
width={120}
|
||||||
target="_blank"
|
alt="infisical loading indicator"
|
||||||
rel="noopener noreferrer"
|
/>
|
||||||
href="mailto:[email protected]"
|
) : (
|
||||||
>
|
<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">
|
||||||
support@infisical.com
|
<FontAwesomeIcon icon={faBugs} className="inlineli my-2 text-6xl" />
|
||||||
</a> if the issue persists.
|
<p>
|
||||||
</p>
|
Something went wrong. Please contact{" "}
|
||||||
</div>}
|
<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:[email protected]"
|
||||||
|
>
|
||||||
|
support@infisical.com
|
||||||
|
</a>{" "}
|
||||||
|
if the issue persists.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,7 @@
|
|||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
|
|
||||||
import {
|
import { useSaveIntegrationAccessToken } from "@app/hooks/api";
|
||||||
useSaveIntegrationAccessToken
|
|
||||||
} from "@app/hooks/api";
|
|
||||||
|
|
||||||
import { Button, Card, CardTitle, FormControl, Input } from "../../../components/v2";
|
import { Button, Card, CardTitle, FormControl, Input } from "../../../components/v2";
|
||||||
|
|
||||||
|
|||||||
@@ -2,9 +2,7 @@ import { useEffect, useState } from "react";
|
|||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import queryString from "query-string";
|
import queryString from "query-string";
|
||||||
|
|
||||||
import {
|
import { useCreateIntegration } from "@app/hooks/api";
|
||||||
useCreateIntegration
|
|
||||||
} from "@app/hooks/api";
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
@@ -65,7 +63,9 @@ export default function SupabaseCreateIntegrationPage() {
|
|||||||
integrationAuthId: integrationAuth?.id,
|
integrationAuthId: integrationAuth?.id,
|
||||||
isActive: true,
|
isActive: true,
|
||||||
app: targetApp,
|
app: targetApp,
|
||||||
appId: integrationAuthApps?.find((integrationAuthApp) => integrationAuthApp.name === targetApp)?.appId,
|
appId: integrationAuthApps?.find(
|
||||||
|
(integrationAuthApp) => integrationAuthApp.name === targetApp
|
||||||
|
)?.appId,
|
||||||
sourceEnvironment: selectedSourceEnvironment,
|
sourceEnvironment: selectedSourceEnvironment,
|
||||||
secretPath
|
secretPath
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -6,9 +6,7 @@ import { useRouter } from "next/router";
|
|||||||
import { faArrowUpRightFromSquare, faBookOpen } from "@fortawesome/free-solid-svg-icons";
|
import { faArrowUpRightFromSquare, faBookOpen } from "@fortawesome/free-solid-svg-icons";
|
||||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||||
|
|
||||||
import {
|
import { useSaveIntegrationAccessToken } from "@app/hooks/api";
|
||||||
useSaveIntegrationAccessToken
|
|
||||||
} from "@app/hooks/api";
|
|
||||||
|
|
||||||
import { Button, Card, CardTitle, FormControl, Input } from "../../../components/v2";
|
import { Button, Card, CardTitle, FormControl, Input } from "../../../components/v2";
|
||||||
|
|
||||||
@@ -43,7 +41,7 @@ export default function TeamCityCreateIntegrationPage() {
|
|||||||
workspaceId: localStorage.getItem("projectData.id"),
|
workspaceId: localStorage.getItem("projectData.id"),
|
||||||
integration: "teamcity",
|
integration: "teamcity",
|
||||||
accessToken: apiKey,
|
accessToken: apiKey,
|
||||||
url: serverUrl,
|
url: serverUrl
|
||||||
});
|
});
|
||||||
|
|
||||||
setIsLoading(false);
|
setIsLoading(false);
|
||||||
@@ -58,11 +56,11 @@ export default function TeamCityCreateIntegrationPage() {
|
|||||||
<div className="flex h-full w-full items-center justify-center">
|
<div className="flex h-full w-full items-center justify-center">
|
||||||
<Head>
|
<Head>
|
||||||
<title>Authorize TeamCity Integration</title>
|
<title>Authorize TeamCity Integration</title>
|
||||||
<link rel='icon' href='/infisical.ico' />
|
<link rel="icon" href="/infisical.ico" />
|
||||||
</Head>
|
</Head>
|
||||||
<Card className="max-w-lg rounded-md border border-mineshaft-600 mb-12">
|
<Card className="mb-12 max-w-lg rounded-md border border-mineshaft-600">
|
||||||
<CardTitle
|
<CardTitle
|
||||||
className="text-left px-6 text-xl"
|
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."
|
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">
|
<div className="flex flex-row items-center">
|
||||||
@@ -77,10 +75,13 @@ export default function TeamCityCreateIntegrationPage() {
|
|||||||
<span className="ml-2">TeamCity Integration</span>
|
<span className="ml-2">TeamCity Integration</span>
|
||||||
<Link href="https://infisical.com/docs/integrations/cloud/teamcity" passHref>
|
<Link href="https://infisical.com/docs/integrations/cloud/teamcity" passHref>
|
||||||
<a target="_blank" rel="noopener noreferrer">
|
<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">
|
<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"/>
|
<FontAwesomeIcon icon={faBookOpen} className="mr-1.5" />
|
||||||
Docs
|
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>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
</Link>
|
</Link>
|
||||||
|
|||||||
@@ -7,9 +7,7 @@ import { faArrowUpRightFromSquare, faBookOpen, faBugs } from "@fortawesome/free-
|
|||||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||||
import queryString from "query-string";
|
import queryString from "query-string";
|
||||||
|
|
||||||
import {
|
import { useCreateIntegration } from "@app/hooks/api";
|
||||||
useCreateIntegration
|
|
||||||
} from "@app/hooks/api";
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
@@ -30,7 +28,7 @@ import { useGetWorkspaceById } from "../../../hooks/api/workspace";
|
|||||||
export default function TeamCityCreateIntegrationPage() {
|
export default function TeamCityCreateIntegrationPage() {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { mutateAsync } = useCreateIntegration();
|
const { mutateAsync } = useCreateIntegration();
|
||||||
|
|
||||||
const [selectedSourceEnvironment, setSelectedSourceEnvironment] = useState("");
|
const [selectedSourceEnvironment, setSelectedSourceEnvironment] = useState("");
|
||||||
const [targetAppId, setTargetAppId] = useState("");
|
const [targetAppId, setTargetAppId] = useState("");
|
||||||
const [targetBuildConfigId, setTargetBuildConfigId] = useState<string>("");
|
const [targetBuildConfigId, setTargetBuildConfigId] = useState<string>("");
|
||||||
@@ -40,16 +38,19 @@ export default function TeamCityCreateIntegrationPage() {
|
|||||||
const { integrationAuthId } = queryString.parse(router.asPath.split("?")[1]);
|
const { integrationAuthId } = queryString.parse(router.asPath.split("?")[1]);
|
||||||
|
|
||||||
const { data: workspace } = useGetWorkspaceById(localStorage.getItem("projectData.id") ?? "");
|
const { data: workspace } = useGetWorkspaceById(localStorage.getItem("projectData.id") ?? "");
|
||||||
const { data: integrationAuth, isLoading: isIntegrationAuthLoading } = useGetIntegrationAuthById((integrationAuthId as string) ?? "");
|
const { data: integrationAuth, isLoading: isIntegrationAuthLoading } = useGetIntegrationAuthById(
|
||||||
const { data: integrationAuthApps, isLoading: isIntegrationAuthAppsLoading } = useGetIntegrationAuthApps({
|
(integrationAuthId as string) ?? ""
|
||||||
integrationAuthId: (integrationAuthId as string) ?? ""
|
);
|
||||||
});
|
const { data: integrationAuthApps, isLoading: isIntegrationAuthAppsLoading } =
|
||||||
|
useGetIntegrationAuthApps({
|
||||||
|
integrationAuthId: (integrationAuthId as string) ?? ""
|
||||||
|
});
|
||||||
|
|
||||||
const { data: targetBuildConfigs } = useGetIntegrationAuthTeamCityBuildConfigs({
|
const { data: targetBuildConfigs } = useGetIntegrationAuthTeamCityBuildConfigs({
|
||||||
integrationAuthId: (integrationAuthId as string) ?? "",
|
integrationAuthId: (integrationAuthId as string) ?? "",
|
||||||
appId: targetAppId
|
appId: targetAppId
|
||||||
});
|
});
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (workspace) {
|
if (workspace) {
|
||||||
setSelectedSourceEnvironment(workspace.environments[0].slug);
|
setSelectedSourceEnvironment(workspace.environments[0].slug);
|
||||||
@@ -65,21 +66,23 @@ export default function TeamCityCreateIntegrationPage() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [integrationAuthApps]);
|
}, [integrationAuthApps]);
|
||||||
|
|
||||||
const handleButtonClick = async () => {
|
const handleButtonClick = async () => {
|
||||||
try {
|
try {
|
||||||
if (!integrationAuth?.id) return;
|
if (!integrationAuth?.id) return;
|
||||||
|
|
||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
|
|
||||||
const targetEnvironment = targetBuildConfigs?.find(
|
const targetEnvironment = targetBuildConfigs?.find(
|
||||||
(buildConfig) => buildConfig.buildConfigId === targetBuildConfigId
|
(buildConfig) => buildConfig.buildConfigId === targetBuildConfigId
|
||||||
);
|
);
|
||||||
|
|
||||||
await mutateAsync({
|
await mutateAsync({
|
||||||
integrationAuthId: integrationAuth?.id,
|
integrationAuthId: integrationAuth?.id,
|
||||||
isActive: true,
|
isActive: true,
|
||||||
app: integrationAuthApps?.find((integrationAuthApp) => integrationAuthApp.appId === targetAppId)?.name,
|
app: integrationAuthApps?.find(
|
||||||
|
(integrationAuthApp) => integrationAuthApp.appId === targetAppId
|
||||||
|
)?.name,
|
||||||
appId: targetAppId,
|
appId: targetAppId,
|
||||||
sourceEnvironment: selectedSourceEnvironment,
|
sourceEnvironment: selectedSourceEnvironment,
|
||||||
targetEnvironment: targetEnvironment?.name,
|
targetEnvironment: targetEnvironment?.name,
|
||||||
@@ -109,11 +112,11 @@ export default function TeamCityCreateIntegrationPage() {
|
|||||||
<div className="flex h-full w-full items-center justify-center">
|
<div className="flex h-full w-full items-center justify-center">
|
||||||
<Head>
|
<Head>
|
||||||
<title>Set Up TeamCity Integration</title>
|
<title>Set Up TeamCity Integration</title>
|
||||||
<link rel='icon' href='/infisical.ico' />
|
<link rel="icon" href="/infisical.ico" />
|
||||||
</Head>
|
</Head>
|
||||||
<Card className="max-w-lg rounded-md border border-mineshaft-600 mb-12">
|
<Card className="mb-12 max-w-lg rounded-md border border-mineshaft-600">
|
||||||
<CardTitle
|
<CardTitle
|
||||||
className="text-left px-6 text-xl"
|
className="px-6 text-left text-xl"
|
||||||
subTitle="Choose which environment or folders in Infisical you want to sync to which project in TeamCity."
|
subTitle="Choose which environment or folders in Infisical you want to sync to which project in TeamCity."
|
||||||
>
|
>
|
||||||
<div className="flex flex-row items-center">
|
<div className="flex flex-row items-center">
|
||||||
@@ -128,10 +131,13 @@ export default function TeamCityCreateIntegrationPage() {
|
|||||||
<span className="ml-2">TeamCity Integration</span>
|
<span className="ml-2">TeamCity Integration</span>
|
||||||
<Link href="https://infisical.com/docs/integrations/cloud/teamcity" passHref>
|
<Link href="https://infisical.com/docs/integrations/cloud/teamcity" passHref>
|
||||||
<a target="_blank" rel="noopener noreferrer">
|
<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">
|
<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"/>
|
<FontAwesomeIcon icon={faBookOpen} className="mr-1.5" />
|
||||||
Docs
|
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>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
</Link>
|
</Link>
|
||||||
@@ -183,7 +189,7 @@ export default function TeamCityCreateIntegrationPage() {
|
|||||||
)}
|
)}
|
||||||
</Select>
|
</Select>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
<FormControl label="Team City Build Config (Optional)" className="px-6">
|
<FormControl label="Team City Build Config (Optional)" className="px-6">
|
||||||
<Select
|
<Select
|
||||||
value={targetBuildConfigId}
|
value={targetBuildConfigId}
|
||||||
onValueChange={(val) => setTargetBuildConfigId(val)}
|
onValueChange={(val) => setTargetBuildConfigId(val)}
|
||||||
@@ -212,24 +218,35 @@ export default function TeamCityCreateIntegrationPage() {
|
|||||||
</Card>
|
</Card>
|
||||||
</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>
|
<Head>
|
||||||
<title>Set Up TeamCity Integration</title>
|
<title>Set Up TeamCity Integration</title>
|
||||||
<link rel='icon' href='/infisical.ico' />
|
<link rel="icon" href="/infisical.ico" />
|
||||||
</Head>
|
</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">
|
{isIntegrationAuthLoading || isIntegrationAuthAppsLoading ? (
|
||||||
<FontAwesomeIcon icon={faBugs} className="text-6xl my-2 inlineli"/>
|
<img
|
||||||
<p>
|
src="/images/loading/loading.gif"
|
||||||
Something went wrong. Please contact <a
|
height={70}
|
||||||
className="inline underline underline-offset-4 decoration-primary-500 opacity-80 hover:opacity-100 text-mineshaft-100 duration-200 cursor-pointer"
|
width={120}
|
||||||
target="_blank"
|
alt="infisical loading indicator"
|
||||||
rel="noopener noreferrer"
|
/>
|
||||||
href="mailto:[email protected]"
|
) : (
|
||||||
>
|
<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">
|
||||||
support@infisical.com
|
<FontAwesomeIcon icon={faBugs} className="inlineli my-2 text-6xl" />
|
||||||
</a> if the issue persists.
|
<p>
|
||||||
</p>
|
Something went wrong. Please contact{" "}
|
||||||
</div>}
|
<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:[email protected]"
|
||||||
|
>
|
||||||
|
support@infisical.com
|
||||||
|
</a>{" "}
|
||||||
|
if the issue persists.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,7 @@
|
|||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
|
|
||||||
import {
|
import { useSaveIntegrationAccessToken } from "@app/hooks/api";
|
||||||
useSaveIntegrationAccessToken
|
|
||||||
} from "@app/hooks/api";
|
|
||||||
|
|
||||||
import { Button, Card, CardTitle, FormControl, Input } from "../../../components/v2";
|
import { Button, Card, CardTitle, FormControl, Input } from "../../../components/v2";
|
||||||
|
|
||||||
@@ -26,7 +24,7 @@ export default function TerraformCloudCreateIntegrationPage() {
|
|||||||
setApiKeyErrorText("API Token cannot be blank");
|
setApiKeyErrorText("API Token cannot be blank");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (workspacesId.length === 0) {
|
if (workspacesId.length === 0) {
|
||||||
setWorkspacesIdErrorText("Workspace Id cannot be blank");
|
setWorkspacesIdErrorText("Workspace Id cannot be blank");
|
||||||
return;
|
return;
|
||||||
@@ -58,14 +56,22 @@ export default function TerraformCloudCreateIntegrationPage() {
|
|||||||
errorText={apiKeyErrorText}
|
errorText={apiKeyErrorText}
|
||||||
isError={apiKeyErrorText !== "" ?? false}
|
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>
|
||||||
<FormControl
|
<FormControl
|
||||||
label="Terraform Cloud Workspace ID"
|
label="Terraform Cloud Workspace ID"
|
||||||
errorText={workspacesIdErrorText}
|
errorText={workspacesIdErrorText}
|
||||||
isError={workspacesIdErrorText !== "" ?? false}
|
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>
|
</FormControl>
|
||||||
<Button
|
<Button
|
||||||
onClick={handleButtonClick}
|
onClick={handleButtonClick}
|
||||||
|
|||||||
@@ -19,10 +19,7 @@ import {
|
|||||||
} from "../../../hooks/api/integrationAuth";
|
} from "../../../hooks/api/integrationAuth";
|
||||||
import { useGetWorkspaceById } from "../../../hooks/api/workspace";
|
import { useGetWorkspaceById } from "../../../hooks/api/workspace";
|
||||||
|
|
||||||
const variableTypes = [
|
const variableTypes = [{ name: "env" }, { name: "terraform" }];
|
||||||
{ name: "env" },
|
|
||||||
{ name: "terraform" }
|
|
||||||
];
|
|
||||||
|
|
||||||
export default function TerraformCloudCreateIntegrationPage() {
|
export default function TerraformCloudCreateIntegrationPage() {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
@@ -65,9 +62,9 @@ export default function TerraformCloudCreateIntegrationPage() {
|
|||||||
if (!integrationAuth?.id) return;
|
if (!integrationAuth?.id) return;
|
||||||
|
|
||||||
setVariableTypeErrorText("");
|
setVariableTypeErrorText("");
|
||||||
if (variableType.length === 0 ) {
|
if (variableType.length === 0) {
|
||||||
setVariableTypeErrorText("Variable Type cannot be blank!")
|
setVariableTypeErrorText("Variable Type cannot be blank!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
@@ -76,7 +73,9 @@ export default function TerraformCloudCreateIntegrationPage() {
|
|||||||
integrationAuthId: integrationAuth?.id,
|
integrationAuthId: integrationAuth?.id,
|
||||||
isActive: true,
|
isActive: true,
|
||||||
app: targetApp,
|
app: targetApp,
|
||||||
appId: integrationAuthApps?.find((integrationAuthApp) => integrationAuthApp.name === targetApp)?.appId,
|
appId: integrationAuthApps?.find(
|
||||||
|
(integrationAuthApp) => integrationAuthApp.name === targetApp
|
||||||
|
)?.appId,
|
||||||
sourceEnvironment: selectedSourceEnvironment,
|
sourceEnvironment: selectedSourceEnvironment,
|
||||||
targetService: variableType,
|
targetService: variableType,
|
||||||
secretPath
|
secretPath
|
||||||
@@ -90,7 +89,6 @@ export default function TerraformCloudCreateIntegrationPage() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
return integrationAuth &&
|
return integrationAuth &&
|
||||||
workspace &&
|
workspace &&
|
||||||
selectedSourceEnvironment &&
|
selectedSourceEnvironment &&
|
||||||
@@ -122,23 +120,22 @@ export default function TerraformCloudCreateIntegrationPage() {
|
|||||||
placeholder="Provide a path, default is /"
|
placeholder="Provide a path, default is /"
|
||||||
/>
|
/>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
<FormControl label="Category" className="mt-4" errorText={variableTypeErrorText}
|
<FormControl
|
||||||
isError={variableTypeErrorText !== "" ?? false}>
|
label="Category"
|
||||||
|
className="mt-4"
|
||||||
|
errorText={variableTypeErrorText}
|
||||||
|
isError={variableTypeErrorText !== "" ?? false}
|
||||||
|
>
|
||||||
<Select
|
<Select
|
||||||
value={variableType}
|
value={variableType}
|
||||||
onValueChange={(val) => setVariableType(val)}
|
onValueChange={(val) => setVariableType(val)}
|
||||||
className="w-full border border-mineshaft-500"
|
className="w-full border border-mineshaft-500"
|
||||||
>
|
>
|
||||||
{
|
{variableTypes.map((variable) => (
|
||||||
variableTypes.map((variable) => (
|
<SelectItem value={variable.name} key={`target-app-${variable.name}`}>
|
||||||
<SelectItem
|
{variable.name}
|
||||||
value={variable.name}
|
</SelectItem>
|
||||||
key={`target-app-${variable.name}`}
|
))}
|
||||||
>
|
|
||||||
{variable.name}
|
|
||||||
</SelectItem>
|
|
||||||
))
|
|
||||||
}
|
|
||||||
</Select>
|
</Select>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
<FormControl label="Terraform Cloud Project" className="mt-4">
|
<FormControl label="Terraform Cloud Project" className="mt-4">
|
||||||
|
|||||||
@@ -1,9 +1,7 @@
|
|||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
|
|
||||||
import {
|
import { useSaveIntegrationAccessToken } from "@app/hooks/api";
|
||||||
useSaveIntegrationAccessToken
|
|
||||||
} from "@app/hooks/api";
|
|
||||||
|
|
||||||
import { Button, Card, CardTitle, FormControl, Input } from "../../../components/v2";
|
import { Button, Card, CardTitle, FormControl, Input } from "../../../components/v2";
|
||||||
|
|
||||||
|
|||||||
@@ -2,9 +2,7 @@ import { useEffect, useState } from "react";
|
|||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import queryString from "query-string";
|
import queryString from "query-string";
|
||||||
|
|
||||||
import {
|
import { useCreateIntegration } from "@app/hooks/api";
|
||||||
useCreateIntegration
|
|
||||||
} from "@app/hooks/api";
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
@@ -64,7 +62,9 @@ export default function TravisCICreateIntegrationPage() {
|
|||||||
integrationAuthId: integrationAuth?.id,
|
integrationAuthId: integrationAuth?.id,
|
||||||
isActive: true,
|
isActive: true,
|
||||||
app: targetApp,
|
app: targetApp,
|
||||||
appId: integrationAuthApps?.find((integrationAuthApp) => integrationAuthApp.name === targetApp)?.appId,
|
appId: integrationAuthApps?.find(
|
||||||
|
(integrationAuthApp) => integrationAuthApp.name === targetApp
|
||||||
|
)?.appId,
|
||||||
sourceEnvironment: selectedSourceEnvironment,
|
sourceEnvironment: selectedSourceEnvironment,
|
||||||
secretPath
|
secretPath
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -3,13 +3,16 @@ import Head from "next/head";
|
|||||||
import Image from "next/image";
|
import Image from "next/image";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import { 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 { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||||
import queryString from "query-string";
|
import queryString from "query-string";
|
||||||
|
|
||||||
import {
|
import { useCreateIntegration } from "@app/hooks/api";
|
||||||
useCreateIntegration
|
|
||||||
} from "@app/hooks/api";
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
@@ -47,9 +50,10 @@ export default function VercelCreateIntegrationPage() {
|
|||||||
const { integrationAuthId } = queryString.parse(router.asPath.split("?")[1]);
|
const { integrationAuthId } = queryString.parse(router.asPath.split("?")[1]);
|
||||||
const { data: workspace } = useGetWorkspaceById(localStorage.getItem("projectData.id") ?? "");
|
const { data: workspace } = useGetWorkspaceById(localStorage.getItem("projectData.id") ?? "");
|
||||||
const { data: integrationAuth } = useGetIntegrationAuthById((integrationAuthId as string) ?? "");
|
const { data: integrationAuth } = useGetIntegrationAuthById((integrationAuthId as string) ?? "");
|
||||||
const { data: integrationAuthApps, isLoading: isIntegrationAuthAppsLoading } = useGetIntegrationAuthApps({
|
const { data: integrationAuthApps, isLoading: isIntegrationAuthAppsLoading } =
|
||||||
integrationAuthId: (integrationAuthId as string) ?? ""
|
useGetIntegrationAuthApps({
|
||||||
});
|
integrationAuthId: (integrationAuthId as string) ?? ""
|
||||||
|
});
|
||||||
|
|
||||||
const { data: branches } = useGetIntegrationAuthVercelBranches({
|
const { data: branches } = useGetIntegrationAuthVercelBranches({
|
||||||
integrationAuthId: integrationAuthId as string,
|
integrationAuthId: integrationAuthId as string,
|
||||||
@@ -88,7 +92,8 @@ export default function VercelCreateIntegrationPage() {
|
|||||||
|
|
||||||
if (!targetApp || !targetApp.appId) return;
|
if (!targetApp || !targetApp.appId) return;
|
||||||
|
|
||||||
const path = targetEnvironment === "preview" && targetBranch !== "" ? targetBranch : undefined;
|
const path =
|
||||||
|
targetEnvironment === "preview" && targetBranch !== "" ? targetBranch : undefined;
|
||||||
|
|
||||||
await mutateAsync({
|
await mutateAsync({
|
||||||
integrationAuthId: integrationAuth?.id,
|
integrationAuthId: integrationAuth?.id,
|
||||||
@@ -114,14 +119,14 @@ export default function VercelCreateIntegrationPage() {
|
|||||||
integrationAuthApps &&
|
integrationAuthApps &&
|
||||||
targetAppId &&
|
targetAppId &&
|
||||||
targetEnvironment ? (
|
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>
|
<Head>
|
||||||
<title>Set Up Vercel Integration</title>
|
<title>Set Up Vercel Integration</title>
|
||||||
<link rel='icon' href='/infisical.ico' />
|
<link rel="icon" href="/infisical.ico" />
|
||||||
</Head>
|
</Head>
|
||||||
<Card className="max-w-lg rounded-md border border-mineshaft-600 p-0">
|
<Card className="max-w-lg rounded-md border border-mineshaft-600 p-0">
|
||||||
<CardTitle
|
<CardTitle
|
||||||
className="text-left px-6 text-xl"
|
className="px-6 text-left text-xl"
|
||||||
subTitle="Select which environment or folder in Infisical you want to sync to Vercel's environment variables."
|
subTitle="Select which environment or folder in Infisical you want to sync to Vercel's environment variables."
|
||||||
>
|
>
|
||||||
<div className="flex flex-row items-center">
|
<div className="flex flex-row items-center">
|
||||||
@@ -136,10 +141,13 @@ export default function VercelCreateIntegrationPage() {
|
|||||||
<span className="ml-2">Vercel Integration </span>
|
<span className="ml-2">Vercel Integration </span>
|
||||||
<Link href="https://infisical.com/docs/integrations/cloud/vercel" passHref>
|
<Link href="https://infisical.com/docs/integrations/cloud/vercel" passHref>
|
||||||
<a target="_blank" rel="noopener noreferrer">
|
<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">
|
<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"/>
|
<FontAwesomeIcon icon={faBookOpen} className="mr-1.5" />
|
||||||
Docs
|
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>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
</Link>
|
</Link>
|
||||||
@@ -233,31 +241,48 @@ export default function VercelCreateIntegrationPage() {
|
|||||||
Create Integration
|
Create Integration
|
||||||
</Button>
|
</Button>
|
||||||
</Card>
|
</Card>
|
||||||
<div className="border-t border-mineshaft-800 w-full max-w-md mt-6"/>
|
<div className="mt-6 w-full max-w-md border-t border-mineshaft-800" />
|
||||||
<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="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-mineshaft-200 text-xl"/> <span className="ml-3 text-md text-mineshaft-100">Pro Tips</span></div>
|
<div className="flex flex-row items-center">
|
||||||
<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>
|
<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>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div className="flex justify-center items-center w-full h-full">
|
<div className="flex h-full w-full items-center justify-center">
|
||||||
<Head>
|
<Head>
|
||||||
<title>Set Up Vercel Integration</title>
|
<title>Set Up Vercel Integration</title>
|
||||||
<link rel='icon' href='/infisical.ico' />
|
<link rel="icon" href="/infisical.ico" />
|
||||||
</Head>
|
</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">
|
{isIntegrationAuthAppsLoading ? (
|
||||||
<FontAwesomeIcon icon={faBugs} className="text-6xl my-2 inlineli"/>
|
<img
|
||||||
<p>
|
src="/images/loading/loading.gif"
|
||||||
Something went wrong. Please contact <a
|
height={70}
|
||||||
className="inline underline underline-offset-4 decoration-primary-500 opacity-80 hover:opacity-100 text-mineshaft-100 duration-200 cursor-pointer"
|
width={120}
|
||||||
target="_blank"
|
alt="infisical loading indicator"
|
||||||
rel="noopener noreferrer"
|
/>
|
||||||
href="mailto:[email protected]"
|
) : (
|
||||||
>
|
<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">
|
||||||
support@infisical.com
|
<FontAwesomeIcon icon={faBugs} className="inlineli my-2 text-6xl" />
|
||||||
</a> if the issue persists.
|
<p>
|
||||||
</p>
|
Something went wrong. Please contact{" "}
|
||||||
</div>}
|
<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:[email protected]"
|
||||||
|
>
|
||||||
|
support@infisical.com
|
||||||
|
</a>{" "}
|
||||||
|
if the issue persists.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,9 +2,7 @@ import { useEffect } from "react";
|
|||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import queryString from "query-string";
|
import queryString from "query-string";
|
||||||
|
|
||||||
import {
|
import { useAuthorizeIntegration } from "@app/hooks/api";
|
||||||
useAuthorizeIntegration
|
|
||||||
} from "@app/hooks/api";
|
|
||||||
|
|
||||||
export default function VercelOAuth2CallbackPage() {
|
export default function VercelOAuth2CallbackPage() {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
@@ -18,7 +16,7 @@ export default function VercelOAuth2CallbackPage() {
|
|||||||
// validate state
|
// validate state
|
||||||
if (state !== localStorage.getItem("latestCSRFToken")) return;
|
if (state !== localStorage.getItem("latestCSRFToken")) return;
|
||||||
localStorage.removeItem("latestCSRFToken");
|
localStorage.removeItem("latestCSRFToken");
|
||||||
|
|
||||||
const integrationAuth = await mutateAsync({
|
const integrationAuth = await mutateAsync({
|
||||||
workspaceId: localStorage.getItem("projectData.id") as string,
|
workspaceId: localStorage.getItem("projectData.id") as string,
|
||||||
code: code as string,
|
code: code as string,
|
||||||
|
|||||||
@@ -1,13 +1,10 @@
|
|||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
|
|
||||||
import {
|
import { useSaveIntegrationAccessToken } from "@app/hooks/api";
|
||||||
useSaveIntegrationAccessToken
|
|
||||||
} from "@app/hooks/api";
|
|
||||||
|
|
||||||
import { Button, Card, CardTitle, FormControl, Input } from "../../../components/v2";
|
import { Button, Card, CardTitle, FormControl, Input } from "../../../components/v2";
|
||||||
|
|
||||||
|
|
||||||
export default function WindmillCreateIntegrationPage() {
|
export default function WindmillCreateIntegrationPage() {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { mutateAsync } = useSaveIntegrationAccessToken();
|
const { mutateAsync } = useSaveIntegrationAccessToken();
|
||||||
@@ -15,7 +12,7 @@ export default function WindmillCreateIntegrationPage() {
|
|||||||
const [apiKey, setApiKey] = useState("");
|
const [apiKey, setApiKey] = useState("");
|
||||||
const [apiKeyErrorText, setApiKeyErrorText] = useState("");
|
const [apiKeyErrorText, setApiKeyErrorText] = useState("");
|
||||||
const [isLoading, setIsLoading] = useState(false);
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
|
|
||||||
const handleButtonClick = async () => {
|
const handleButtonClick = async () => {
|
||||||
try {
|
try {
|
||||||
setApiKeyErrorText("");
|
setApiKeyErrorText("");
|
||||||
@@ -23,17 +20,17 @@ export default function WindmillCreateIntegrationPage() {
|
|||||||
setApiKeyErrorText("API Key cannot be blank");
|
setApiKeyErrorText("API Key cannot be blank");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
|
|
||||||
const integrationAuth = await mutateAsync({
|
const integrationAuth = await mutateAsync({
|
||||||
workspaceId: localStorage.getItem("projectData.id"),
|
workspaceId: localStorage.getItem("projectData.id"),
|
||||||
integration: "windmill",
|
integration: "windmill",
|
||||||
accessToken: apiKey
|
accessToken: apiKey
|
||||||
});
|
});
|
||||||
|
|
||||||
setIsLoading(false);
|
setIsLoading(false);
|
||||||
|
|
||||||
router.push(`/integrations/windmill/create?integrationAuthId=${integrationAuth.id}`);
|
router.push(`/integrations/windmill/create?integrationAuthId=${integrationAuth.id}`);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
@@ -41,27 +38,27 @@ export default function WindmillCreateIntegrationPage() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex h-full w-full items-center justify-center">
|
<div className="flex h-full w-full items-center justify-center">
|
||||||
<Card className="max-w-md rounded-md p-8">
|
<Card className="max-w-md rounded-md p-8">
|
||||||
<CardTitle className="text-center">Windmill Integration</CardTitle>
|
<CardTitle className="text-center">Windmill Integration</CardTitle>
|
||||||
<FormControl
|
<FormControl
|
||||||
label="Windmill Access Token"
|
label="Windmill Access Token"
|
||||||
errorText={apiKeyErrorText}
|
errorText={apiKeyErrorText}
|
||||||
isError={apiKeyErrorText !== "" ?? false}
|
isError={apiKeyErrorText !== "" ?? false}
|
||||||
>
|
>
|
||||||
<Input placeholder="" value={apiKey} onChange={(e) => setApiKey(e.target.value)} />
|
<Input placeholder="" value={apiKey} onChange={(e) => setApiKey(e.target.value)} />
|
||||||
</FormControl>
|
</FormControl>
|
||||||
<Button
|
<Button
|
||||||
onClick={handleButtonClick}
|
onClick={handleButtonClick}
|
||||||
color="mineshaft"
|
color="mineshaft"
|
||||||
className="mt-4"
|
className="mt-4"
|
||||||
isLoading={isLoading}
|
isLoading={isLoading}
|
||||||
>
|
>
|
||||||
Connect to Windmill
|
Connect to Windmill
|
||||||
</Button>
|
</Button>
|
||||||
</Card>
|
</Card>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
WindmillCreateIntegrationPage.requireAuth = true;
|
WindmillCreateIntegrationPage.requireAuth = true;
|
||||||
|
|||||||
@@ -2,9 +2,7 @@ import { useEffect, useState } from "react";
|
|||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import queryString from "query-string";
|
import queryString from "query-string";
|
||||||
|
|
||||||
import {
|
import { useCreateIntegration } from "@app/hooks/api";
|
||||||
useCreateIntegration
|
|
||||||
} from "@app/hooks/api";
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
@@ -65,7 +63,9 @@ export default function WindmillCreateIntegrationPage() {
|
|||||||
integrationAuthId: integrationAuth?.id,
|
integrationAuthId: integrationAuth?.id,
|
||||||
isActive: true,
|
isActive: true,
|
||||||
app: targetApp,
|
app: targetApp,
|
||||||
appId: integrationAuthApps?.find((integrationAuthApp) => integrationAuthApp.name === targetApp)?.appId,
|
appId: integrationAuthApps?.find(
|
||||||
|
(integrationAuthApp) => integrationAuthApp.name === targetApp
|
||||||
|
)?.appId,
|
||||||
sourceEnvironment: selectedSourceEnvironment,
|
sourceEnvironment: selectedSourceEnvironment,
|
||||||
secretPath
|
secretPath
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ import { usePopUp } from "@app/hooks/usePopUp";
|
|||||||
|
|
||||||
const features = [
|
const features = [
|
||||||
{
|
{
|
||||||
_id: 0,
|
id: 0,
|
||||||
name: "Kubernetes Operator",
|
name: "Kubernetes Operator",
|
||||||
link: "https://infisical.com/docs/documentation/getting-started/kubernetes",
|
link: "https://infisical.com/docs/documentation/getting-started/kubernetes",
|
||||||
description:
|
description:
|
||||||
@@ -519,7 +519,7 @@ const OrganizationPage = withPermission(
|
|||||||
try {
|
try {
|
||||||
const {
|
const {
|
||||||
data: {
|
data: {
|
||||||
workspace: { _id: newWorkspaceId }
|
workspace: { id: newWorkspaceId }
|
||||||
}
|
}
|
||||||
} = await createWs.mutateAsync({
|
} = await createWs.mutateAsync({
|
||||||
organizationId: currentOrg,
|
organizationId: currentOrg,
|
||||||
@@ -537,7 +537,7 @@ const OrganizationPage = withPermission(
|
|||||||
await uploadWsKey.mutateAsync({
|
await uploadWsKey.mutateAsync({
|
||||||
encryptedKey: ciphertext,
|
encryptedKey: ciphertext,
|
||||||
nonce,
|
nonce,
|
||||||
userId: user?._id,
|
userId: user?.id,
|
||||||
workspaceId: newWorkspaceId
|
workspaceId: newWorkspaceId
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -553,7 +553,7 @@ const OrganizationPage = withPermission(
|
|||||||
.filter(
|
.filter(
|
||||||
({ status, user: orgUser }) => status === "accepted" && user.email !== orgUser.email
|
({ status, user: orgUser }) => status === "accepted" && user.email !== orgUser.email
|
||||||
)
|
)
|
||||||
.map(({ user: orgUser, _id: orgMembershipId }) => ({
|
.map(({ user: orgUser, id: orgMembershipId }) => ({
|
||||||
userPublicKey: orgUser.publicKey,
|
userPublicKey: orgUser.publicKey,
|
||||||
orgMembershipId
|
orgMembershipId
|
||||||
}))
|
}))
|
||||||
@@ -682,7 +682,7 @@ const OrganizationPage = withPermission(
|
|||||||
.filter((ws) => ws?.name?.toLowerCase().includes(searchFilter.toLowerCase()))
|
.filter((ws) => ws?.name?.toLowerCase().includes(searchFilter.toLowerCase()))
|
||||||
.map((workspace) => (
|
.map((workspace) => (
|
||||||
<div
|
<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"
|
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>
|
<div className="mt-0 text-lg text-mineshaft-100">{workspace.name}</div>
|
||||||
@@ -692,8 +692,8 @@ const OrganizationPage = withPermission(
|
|||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
router.push(`/project/${workspace._id}/secrets/overview`);
|
router.push(`/project/${workspace.id}/secrets/overview`);
|
||||||
localStorage.setItem("projectData.id", workspace._id);
|
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">
|
<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}
|
icon={faPlus}
|
||||||
time="1 min"
|
time="1 min"
|
||||||
userAction="first_time_secrets_pushed"
|
userAction="first_time_secrets_pushed"
|
||||||
link={`/project/${orgWorkspaces[0]?._id}/secrets/overview`}
|
link={`/project/${orgWorkspaces[0]?.id}/secrets/overview`}
|
||||||
/>
|
/>
|
||||||
<LearningItemSquare
|
<LearningItemSquare
|
||||||
text="Invite your teammates"
|
text="Invite your teammates"
|
||||||
|
|||||||
@@ -63,20 +63,20 @@ const SecretScanning = withPermission(
|
|||||||
<link rel="icon" href="/infisical.ico" />
|
<link rel="icon" href="/infisical.ico" />
|
||||||
<meta property="og:image" content="/images/message.png" />
|
<meta property="og:image" content="/images/message.png" />
|
||||||
</Head>
|
</Head>
|
||||||
<div className="flex justify-center bg-bunker-800 text-white w-full h-full">
|
<div className="flex h-full w-full justify-center bg-bunker-800 text-white">
|
||||||
<div className="max-w-7xl px-6 w-full">
|
<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="mt-6 text-3xl font-semibold text-gray-200">Secret Scanning</div>
|
||||||
<div className="mb-6 text-lg text-mineshaft-300">
|
<div className="mb-6 text-lg text-mineshaft-300">
|
||||||
Automatically monitor your GitHub activity and prevent secret leaks
|
Automatically monitor your GitHub activity and prevent secret leaks
|
||||||
</div>
|
</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-col items-start">
|
||||||
<div className="flex flex-row mb-1">
|
<div className="mb-1 flex flex-row">
|
||||||
Secret Scanning Status:{" "}
|
Secret Scanning Status:{" "}
|
||||||
{integrationEnabled ? (
|
{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>
|
||||||
<div>
|
<div>
|
||||||
@@ -94,12 +94,12 @@ const SecretScanning = withPermission(
|
|||||||
</div>
|
</div>
|
||||||
{integrationEnabled ? (
|
{integrationEnabled ? (
|
||||||
<div>
|
<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.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] animate-ping rounded-full h-5 w-5 bg-green flex items-center justify-center" />
|
<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] animate-ping rounded-full h-3.5 w-3.5 bg-green flex items-center justify-center" />
|
<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>
|
||||||
) : (
|
) : (
|
||||||
<div className="flex items-center h-[3.25rem]">
|
<div className="flex h-[3.25rem] items-center">
|
||||||
<OrgPermissionCan
|
<OrgPermissionCan
|
||||||
I={OrgPermissionActions.Create}
|
I={OrgPermissionActions.Create}
|
||||||
a={OrgPermissionSubjects.SecretScanning}
|
a={OrgPermissionSubjects.SecretScanning}
|
||||||
@@ -109,7 +109,7 @@ const SecretScanning = withPermission(
|
|||||||
variant="solid"
|
variant="solid"
|
||||||
colorSchema="primary"
|
colorSchema="primary"
|
||||||
onClick={generateNewIntegrationSession}
|
onClick={generateNewIntegrationSession}
|
||||||
className="py-2 h-min"
|
className="h-min py-2"
|
||||||
isDisabled={!isAllowed}
|
isDisabled={!isAllowed}
|
||||||
>
|
>
|
||||||
Integrate with GitHub
|
Integrate with GitHub
|
||||||
|
|||||||
@@ -153,7 +153,7 @@ export default function SignUp() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex min-h-screen max-h-screen overflow-y-auto flex-col justify-center bg-gradient-to-tr from-mineshaft-600 via-mineshaft-800 to-bunker-700 px-6 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>
|
<Head>
|
||||||
<title>{t("common.head-title", { title: t("signup.title") })}</title>
|
<title>{t("common.head-title", { title: t("signup.title") })}</title>
|
||||||
<link rel="icon" href="/infisical.ico" />
|
<link rel="icon" href="/infisical.ico" />
|
||||||
|
|||||||
+2
-1
@@ -162,7 +162,8 @@ export const IntegrationsSection = ({
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{((integration.integration === "checkly") || (integration.integration === "github")) && (
|
{(integration.integration === "checkly" ||
|
||||||
|
integration.integration === "github") && (
|
||||||
<>
|
<>
|
||||||
{integration.targetService && (
|
{integration.targetService && (
|
||||||
<div className="ml-2">
|
<div className="ml-2">
|
||||||
|
|||||||
@@ -3,22 +3,22 @@ import { NextRouter } from "next/router";
|
|||||||
import { fetchOrganizations } from "@app/hooks/api/organization/queries";
|
import { fetchOrganizations } from "@app/hooks/api/organization/queries";
|
||||||
|
|
||||||
export const navigateUserToOrg = async (router: NextRouter, organizationId?: string) => {
|
export const navigateUserToOrg = async (router: NextRouter, organizationId?: string) => {
|
||||||
const userOrgs = await fetchOrganizations();
|
const userOrgs = await fetchOrganizations();
|
||||||
|
|
||||||
if (organizationId) {
|
if (organizationId) {
|
||||||
localStorage.setItem("orgData.id", organizationId);
|
localStorage.setItem("orgData.id", organizationId);
|
||||||
router.push(`/org/${organizationId}/overview`);
|
router.push(`/org/${organizationId}/overview`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (userOrgs.length > 0) {
|
if (userOrgs.length > 0) {
|
||||||
// user is part of at least 1 org
|
// user is part of at least 1 org
|
||||||
const userOrg = userOrgs[0] && userOrgs[0].id;
|
const userOrg = userOrgs[0] && userOrgs[0].id;
|
||||||
localStorage.setItem("orgData.id", userOrg);
|
localStorage.setItem("orgData.id", userOrg);
|
||||||
router.push(`/org/${userOrg}/overview`);
|
router.push(`/org/${userOrg}/overview`);
|
||||||
} else {
|
} else {
|
||||||
// user is not part of any org
|
// user is not part of any org
|
||||||
localStorage.removeItem("orgData.id");
|
localStorage.removeItem("orgData.id");
|
||||||
router.push("/org/none");
|
router.push("/org/none");
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user