Skip to content

Commit 36300cd

Browse files
committed
Begin personal access token-based integrations
1 parent 6c7d232 commit 36300cd

File tree

3 files changed

+143
-11
lines changed

3 files changed

+143
-11
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
import { Fragment } from "react";
2+
import { Dialog, Transition } from "@headlessui/react";
3+
import getLatestFileKey from "../../../pages/api/workspace/getLatestFileKey";
4+
import setBotActiveStatus from "../../../pages/api/bot/setBotActiveStatus";
5+
import {
6+
decryptAssymmetric,
7+
encryptAssymmetric
8+
} from "../../utilities/cryptography/crypto";
9+
import Button from "../buttons/Button";
10+
import InputField from "../InputField";
11+
12+
const IntegrationAccessTokenDialog = ({
13+
isOpen,
14+
closeModal,
15+
selectedIntegrationOption,
16+
handleBotActivate,
17+
handleIntegrationOption
18+
}) => {
19+
20+
const submit = async () => {
21+
try {
22+
// 1. activate bot
23+
await handleBotActivate();
24+
25+
// 2. start integration
26+
await handleIntegrationOption({
27+
integrationOption: selectedIntegrationOption
28+
});
29+
} catch (err) {
30+
console.log(err);
31+
}
32+
33+
closeModal();
34+
}
35+
36+
return (
37+
<div>
38+
<Transition appear show={isOpen} as={Fragment}>
39+
<Dialog as="div" className="relative z-10" onClose={closeModal}>
40+
<Transition.Child
41+
as={Fragment}
42+
enter="ease-out duration-300"
43+
enterFrom="opacity-0"
44+
enterTo="opacity-100"
45+
leave="ease-in duration-200"
46+
leaveFrom="opacity-100"
47+
leaveTo="opacity-0"
48+
>
49+
<div className="fixed inset-0 bg-black bg-opacity-70" />
50+
</Transition.Child>
51+
<div className="fixed inset-0 overflow-y-auto">
52+
<div className="flex min-h-full items-center justify-center p-4 text-center">
53+
<Transition.Child
54+
as={Fragment}
55+
enter="ease-out duration-300"
56+
enterFrom="opacity-0 scale-95"
57+
enterTo="opacity-100 scale-100"
58+
leave="ease-in duration-200"
59+
leaveFrom="opacity-100 scale-100"
60+
leaveTo="opacity-0 scale-95"
61+
>
62+
<Dialog.Panel className="w-full max-w-md transform overflow-hidden rounded-md bg-bunker-800 border border-gray-700 p-6 text-left align-middle shadow-xl transition-all">
63+
<Dialog.Title
64+
as="h3"
65+
className="text-lg font-medium leading-6 text-gray-400"
66+
>
67+
Grant Infisical access to your secrets
68+
</Dialog.Title>
69+
<div className="mt-2 mb-2">
70+
<p className="text-sm text-gray-500">
71+
Most cloud integrations require Infisical to be able to decrypt your secrets so they can be forwarded over.
72+
</p>
73+
</div>
74+
<div className="mt-6 max-w-max">
75+
{/* <Button
76+
onButtonPressed={submit}
77+
color="mineshaft"
78+
text="Grant access"
79+
size="md"
80+
/> */}
81+
<InputField
82+
label="Access token"
83+
onChangeHandler={() => {}}
84+
type="varName"
85+
value={"Hello"}
86+
placeholder=""
87+
isRequired
88+
/>
89+
</div>
90+
</Dialog.Panel>
91+
</Transition.Child>
92+
</div>
93+
</div>
94+
</Dialog>
95+
</Transition>
96+
</div>
97+
);
98+
}
99+
100+
export default IntegrationAccessTokenDialog;

frontend/pages/integrations/[id].js

+18-3
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import getBot from "../api/bot/getBot";
1515
import setBotActiveStatus from "../api/bot/setBotActiveStatus";
1616
import getLatestFileKey from "../api/workspace/getLatestFileKey";
1717
import ActivateBotDialog from "~/components/basic/dialog/ActivateBotDialog";
18+
import IntegrationAccessTokenDialog from "~/components/basic/dialog/IntegrationAccessTokenDialog";
1819
const {
1920
decryptAssymmetric,
2021
encryptAssymmetric
@@ -27,7 +28,8 @@ export default function Integrations() {
2728
const [integrationAuths, setIntegrationAuths] = useState([]);
2829
const [integrations, setIntegrations] = useState([]);
2930
const [bot, setBot] = useState(null);
30-
const [isActivateBotOpen, setIsActivateBotOpen] = useState(false);
31+
const [isActivateBotDialogOpen, setIsActivateBotDialogOpen] = useState(false);
32+
const [isIntegrationAccessTokenDialogOpen, setIntegrationAccessTokenDialogOpen] = useState(true);
3133
const [selectedIntegrationOption, setSelectedIntegrationOption] = useState(null);
3234

3335
const router = useRouter();
@@ -120,6 +122,8 @@ export default function Integrations() {
120122
const state = crypto.randomBytes(16).toString("hex");
121123
localStorage.setItem('latestCSRFToken', state);
122124

125+
// TODO: Add CircleCI, Render, Fly.io
126+
123127
switch (integrationOption.name) {
124128
case 'Heroku':
125129
window.location = `https://id.heroku.com/oauth/authorize?client_id=${integrationOption.clientId}&response_type=code&scope=write-protected&state=${state}`;
@@ -130,6 +134,10 @@ export default function Integrations() {
130134
case 'Netlify':
131135
window.location = `https://app.netlify.com/authorize?client_id=${integrationOption.clientId}&response_type=code&redirect_uri=${integrationOption.redirectURL}&state=${state}`;
132136
break;
137+
case 'Fly.io':
138+
console.log('fly.io');
139+
setIntegrationAccessTokenDialogOpen(true);
140+
break;
133141
}
134142
} catch (err) {
135143
console.log(err);
@@ -179,8 +187,15 @@ export default function Integrations() {
179187
isProjectRelated={true}
180188
/>
181189
<ActivateBotDialog
182-
isOpen={isActivateBotOpen}
183-
closeModal={() => setIsActivateBotOpen(false)}
190+
isOpen={isActivateBotDialogOpen}
191+
closeModal={() => setIsActivateBotDialogOpen(false)}
192+
selectedIntegrationOption={selectedIntegrationOption}
193+
handleBotActivate={handleBotActivate}
194+
handleIntegrationOption={handleIntegrationOption}
195+
/>
196+
<IntegrationAccessTokenDialog
197+
isOpen={isIntegrationAccessTokenDialogOpen}
198+
closeModal={() => setIntegrationAccessTokenDialogOpen(false)}
184199
selectedIntegrationOption={selectedIntegrationOption}
185200
handleBotActivate={handleBotActivate}
186201
handleIntegrationOption={handleIntegrationOption}

frontend/public/json/cloudIntegrations.json

+25-8
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,17 @@
55
"image": "Heroku",
66
"isAvailable": true,
77
"type": "oauth2",
8-
"clientId": "7b1311a1-1cb2-4938-8adf-f37a399ec41b"
8+
"clientId": "7b1311a1-1cb2-4938-8adf-f37a399ec41b",
9+
"docsLink": ""
910
},
1011
{
1112
"name": "Vercel",
1213
"slug": "vercel",
1314
"image": "Vercel",
1415
"isAvailable": true,
1516
"type": "vercel",
16-
"clientId": ""
17+
"clientId": "",
18+
"docsLink": ""
1719
},
1820
{
1921
"name": "Netlify",
@@ -22,46 +24,61 @@
2224
"isAvailable": true,
2325
"type": "oauth2",
2426
"clientId": "fYWBhD3gt0pT62UIwYrlGRcy--pPVLYIQad6ORrES9o",
25-
"redirectURL": "http://localhost:8080/netlify"
27+
"redirectURL": "http://localhost:8080/netlify",
28+
"docsLink": ""
29+
},
30+
{
31+
"name": "Fly.io",
32+
"slug": "flyio",
33+
"image": "Google Cloud Platform",
34+
"isAvailable": true,
35+
"type": "accessToken",
36+
"clientId": "",
37+
"docsLink": ""
2638
},
2739
{
2840
"name": "Google Cloud Platform",
2941
"slug": "gcp",
3042
"image": "Google Cloud Platform",
3143
"isAvailable": false,
3244
"type": "",
33-
"clientId": ""
45+
"clientId": "",
46+
"docsLink": ""
3447
},
3548
{
3649
"name": "Amazon Web Services",
3750
"slug": "aws",
3851
"image": "Amazon Web Services",
3952
"isAvailable": false,
4053
"type": "",
41-
"clientId": ""
54+
"clientId": "",
55+
"docsLink": ""
4256
},
4357
{
4458
"name": "Microsoft Azure",
4559
"slug": "azure",
4660
"image": "Microsoft Azure",
4761
"isAvailable": false,
4862
"type": "",
49-
"clientId": ""
63+
"clientId": "",
64+
"docsLink": ""
5065
},
5166
{
5267
"name": "Travis CI",
5368
"slug": "travisci",
5469
"image": "Travis CI",
5570
"isAvailable": false,
5671
"type": "",
57-
"clientId": ""
72+
"clientId": "",
73+
"docsLink": ""
5874
},
5975
{
6076
"name": "Circle CI",
6177
"slug": "circleci",
6278
"image": "Circle CI",
6379
"isAvailable": false,
6480
"type": "",
65-
"clientId": ""
81+
"clientId": "",
82+
"docsLink": ""
6683
}
6784
]

0 commit comments

Comments
 (0)