mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-09-22 13:39:35 +00:00
Merge remote-tracking branch 'origin' into railway
This commit is contained in:
1037
backend/package-lock.json
generated
1037
backend/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@aws-sdk/client-secrets-manager": "^3.281.0",
|
"@aws-sdk/client-secrets-manager": "^3.287.0",
|
||||||
"@godaddy/terminus": "^4.11.2",
|
"@godaddy/terminus": "^4.11.2",
|
||||||
"@octokit/rest": "^19.0.5",
|
"@octokit/rest": "^19.0.5",
|
||||||
"@sentry/tracing": "^7.39.0",
|
"@sentry/tracing": "^7.39.0",
|
||||||
@@ -8,7 +8,7 @@
|
|||||||
"@types/crypto-js": "^4.1.1",
|
"@types/crypto-js": "^4.1.1",
|
||||||
"@types/libsodium-wrappers": "^0.7.10",
|
"@types/libsodium-wrappers": "^0.7.10",
|
||||||
"await-to-js": "^3.0.0",
|
"await-to-js": "^3.0.0",
|
||||||
"aws-sdk": "^2.1324.0",
|
"aws-sdk": "^2.1331.0",
|
||||||
"axios": "^1.1.3",
|
"axios": "^1.1.3",
|
||||||
"axios-retry": "^3.4.0",
|
"axios-retry": "^3.4.0",
|
||||||
"bcrypt": "^5.1.0",
|
"bcrypt": "^5.1.0",
|
||||||
@@ -29,7 +29,7 @@
|
|||||||
"jsrp": "^0.2.4",
|
"jsrp": "^0.2.4",
|
||||||
"libsodium-wrappers": "^0.7.10",
|
"libsodium-wrappers": "^0.7.10",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"mongoose": "^6.10.2",
|
"mongoose": "^6.10.3",
|
||||||
"nodemailer": "^6.8.0",
|
"nodemailer": "^6.8.0",
|
||||||
"posthog-node": "^2.5.4",
|
"posthog-node": "^2.5.4",
|
||||||
"query-string": "^7.1.3",
|
"query-string": "^7.1.3",
|
||||||
|
|||||||
@@ -12,6 +12,10 @@ import {
|
|||||||
getTeams,
|
getTeams,
|
||||||
revokeAccess
|
revokeAccess
|
||||||
} from '../../integrations';
|
} from '../../integrations';
|
||||||
|
import {
|
||||||
|
INTEGRATION_VERCEL_API_URL
|
||||||
|
} from '../../variables';
|
||||||
|
import request from '../../config/request';
|
||||||
|
|
||||||
/***
|
/***
|
||||||
* Return integration authorization with id [integrationAuthId]
|
* Return integration authorization with id [integrationAuthId]
|
||||||
@@ -188,25 +192,60 @@ export const getIntegrationAuthApps = async (req: Request, res: Response) => {
|
|||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
export const getIntegrationAuthTeams = async (req: Request, res: Response) => {
|
export const getIntegrationAuthTeams = async (req: Request, res: Response) => {
|
||||||
let teams;
|
const teams = await getTeams({
|
||||||
try {
|
integrationAuth: req.integrationAuth,
|
||||||
teams = await getTeams({
|
accessToken: req.accessToken
|
||||||
integrationAuth: req.integrationAuth,
|
});
|
||||||
accessToken: req.accessToken
|
|
||||||
});
|
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser({ email: req.user.email });
|
|
||||||
Sentry.captureException(err);
|
|
||||||
return res.status(400).send({
|
|
||||||
message: "Failed to get integration authorization teams"
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return res.status(200).send({
|
return res.status(200).send({
|
||||||
teams
|
teams
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return list of available Vercel (preview) branches
|
||||||
|
* @param req
|
||||||
|
* @param res
|
||||||
|
*/
|
||||||
|
export const getIntegrationAuthVercelBranches = async (req: Request, res: Response) => {
|
||||||
|
const { integrationAuthId } = req.params;
|
||||||
|
const appId = req.query.appId as string;
|
||||||
|
|
||||||
|
interface VercelBranch {
|
||||||
|
ref: string;
|
||||||
|
lastCommit: string;
|
||||||
|
isProtected: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
const params = new URLSearchParams({
|
||||||
|
projectId: appId,
|
||||||
|
...(req.integrationAuth.teamId ? {
|
||||||
|
teamId: req.integrationAuth.teamId
|
||||||
|
} : {})
|
||||||
|
});
|
||||||
|
|
||||||
|
let branches: string[] = [];
|
||||||
|
|
||||||
|
if (appId && appId !== '') {
|
||||||
|
const { data }: { data: VercelBranch[] } = await request.get(
|
||||||
|
`${INTEGRATION_VERCEL_API_URL}/v1/integrations/git-branches`,
|
||||||
|
{
|
||||||
|
params,
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${req.accessToken}`,
|
||||||
|
'Accept-Encoding': 'application/json'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
branches = data.map((b) => b.ref);
|
||||||
|
}
|
||||||
|
|
||||||
|
return res.status(200).send({
|
||||||
|
branches
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete integration authorization with id [integrationAuthId]
|
* Delete integration authorization with id [integrationAuthId]
|
||||||
* @param req
|
* @param req
|
||||||
|
|||||||
@@ -191,6 +191,7 @@ const getAppsVercel = async ({
|
|||||||
|
|
||||||
apps = res.projects.map((a: any) => ({
|
apps = res.projects.map((a: any) => ({
|
||||||
name: a.name,
|
name: a.name,
|
||||||
|
appId: a.id
|
||||||
}));
|
}));
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
Sentry.setUser(null);
|
Sentry.setUser(null);
|
||||||
@@ -277,10 +278,13 @@ const getAppsGithub = async ({ accessToken }: { accessToken: string }) => {
|
|||||||
|
|
||||||
apps = repos
|
apps = repos
|
||||||
.filter((a: any) => a.permissions.admin === true)
|
.filter((a: any) => a.permissions.admin === true)
|
||||||
.map((a: any) => ({
|
.map((a: any) => {
|
||||||
name: a.name,
|
return ({
|
||||||
owner: a.owner.login,
|
appId: a.id,
|
||||||
}));
|
name: a.name,
|
||||||
|
owner: a.owner.login,
|
||||||
|
});
|
||||||
|
});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
Sentry.setUser(null);
|
Sentry.setUser(null);
|
||||||
Sentry.captureException(err);
|
Sentry.captureException(err);
|
||||||
|
|||||||
@@ -608,6 +608,7 @@ const syncSecretsVercel = async ({
|
|||||||
key: string;
|
key: string;
|
||||||
value: string;
|
value: string;
|
||||||
target: string[];
|
target: string[];
|
||||||
|
gitBranch?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -621,46 +622,7 @@ const syncSecretsVercel = async ({
|
|||||||
}
|
}
|
||||||
: {}),
|
: {}),
|
||||||
};
|
};
|
||||||
|
|
||||||
// const res = (
|
|
||||||
// await Promise.all(
|
|
||||||
// (
|
|
||||||
// await request.get(
|
|
||||||
// `${INTEGRATION_VERCEL_API_URL}/v9/projects/${integration.app}/env`,
|
|
||||||
// {
|
|
||||||
// params,
|
|
||||||
// headers: {
|
|
||||||
// Authorization: `Bearer ${accessToken}`,
|
|
||||||
// 'Accept-Encoding': 'application/json'
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// ))
|
|
||||||
// .data
|
|
||||||
// .envs
|
|
||||||
// .filter((secret: VercelSecret) => secret.target.includes(integration.targetEnvironment))
|
|
||||||
// .map(async (secret: VercelSecret) => {
|
|
||||||
// if (secret.type === 'encrypted') {
|
|
||||||
// // case: secret is encrypted -> need to decrypt
|
|
||||||
// const decryptedSecret = (await request.get(
|
|
||||||
// `${INTEGRATION_VERCEL_API_URL}/v9/projects/${integration.app}/env/${secret.id}`,
|
|
||||||
// {
|
|
||||||
// params,
|
|
||||||
// headers: {
|
|
||||||
// Authorization: `Bearer ${accessToken}`,
|
|
||||||
// 'Accept-Encoding': 'application/json'
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// )).data;
|
|
||||||
|
|
||||||
// return decryptedSecret;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// return secret;
|
|
||||||
// }))).reduce((obj: any, secret: any) => ({
|
|
||||||
// ...obj,
|
|
||||||
// [secret.key]: secret
|
|
||||||
// }), {});
|
|
||||||
|
|
||||||
const vercelSecrets: VercelSecret[] = (await request.get(
|
const vercelSecrets: VercelSecret[] = (await request.get(
|
||||||
`${INTEGRATION_VERCEL_API_URL}/v9/projects/${integration.app}/env`,
|
`${INTEGRATION_VERCEL_API_URL}/v9/projects/${integration.app}/env`,
|
||||||
{
|
{
|
||||||
@@ -673,7 +635,21 @@ const syncSecretsVercel = async ({
|
|||||||
))
|
))
|
||||||
.data
|
.data
|
||||||
.envs
|
.envs
|
||||||
.filter((secret: VercelSecret) => secret.target.includes(integration.targetEnvironment));
|
.filter((secret: VercelSecret) => {
|
||||||
|
if (!secret.target.includes(integration.targetEnvironment)) {
|
||||||
|
// case: secret does not have the same target environment
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (integration.targetEnvironment === 'preview' && integration.path && integration.path !== secret.gitBranch) {
|
||||||
|
// case: secret on preview environment does not have same target git branch
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
// return secret.target.includes(integration.targetEnvironment);
|
||||||
|
|
||||||
const res: { [key: string]: VercelSecret } = {};
|
const res: { [key: string]: VercelSecret } = {};
|
||||||
|
|
||||||
@@ -696,7 +672,7 @@ const syncSecretsVercel = async ({
|
|||||||
res[vercelSecret.key] = vercelSecret;
|
res[vercelSecret.key] = vercelSecret;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const updateSecrets: VercelSecret[] = [];
|
const updateSecrets: VercelSecret[] = [];
|
||||||
const deleteSecrets: VercelSecret[] = [];
|
const deleteSecrets: VercelSecret[] = [];
|
||||||
const newSecrets: VercelSecret[] = [];
|
const newSecrets: VercelSecret[] = [];
|
||||||
@@ -710,6 +686,9 @@ const syncSecretsVercel = async ({
|
|||||||
value: secrets[key],
|
value: secrets[key],
|
||||||
type: "encrypted",
|
type: "encrypted",
|
||||||
target: [integration.targetEnvironment],
|
target: [integration.targetEnvironment],
|
||||||
|
...(integration.path ? {
|
||||||
|
gitBranch: integration.path
|
||||||
|
} : {})
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -726,7 +705,10 @@ const syncSecretsVercel = async ({
|
|||||||
type: res[key].type,
|
type: res[key].type,
|
||||||
target: res[key].target.includes(integration.targetEnvironment)
|
target: res[key].target.includes(integration.targetEnvironment)
|
||||||
? [...res[key].target]
|
? [...res[key].target]
|
||||||
: [...res[key].target, integration.targetEnvironment]
|
: [...res[key].target, integration.targetEnvironment],
|
||||||
|
...(integration.path ? {
|
||||||
|
gitBranch: integration.path
|
||||||
|
} : {})
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -737,6 +719,9 @@ const syncSecretsVercel = async ({
|
|||||||
value: res[key].value,
|
value: res[key].value,
|
||||||
type: "encrypted", // value doesn't matter
|
type: "encrypted", // value doesn't matter
|
||||||
target: [integration.targetEnvironment],
|
target: [integration.targetEnvironment],
|
||||||
|
...(integration.path ? {
|
||||||
|
gitBranch: integration.path
|
||||||
|
} : {})
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -1060,7 +1045,7 @@ const syncSecretsGitHub = async ({
|
|||||||
"GET /repos/{owner}/{repo}/actions/secrets/public-key",
|
"GET /repos/{owner}/{repo}/actions/secrets/public-key",
|
||||||
{
|
{
|
||||||
owner: integration.owner,
|
owner: integration.owner,
|
||||||
repo: integration.app,
|
repo: integration.app
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
).data;
|
).data;
|
||||||
|
|||||||
@@ -80,6 +80,7 @@ const integrationSchema = new Schema<IIntegration>(
|
|||||||
},
|
},
|
||||||
path: {
|
path: {
|
||||||
// aws-parameter-store-specific path
|
// aws-parameter-store-specific path
|
||||||
|
// (also) vercel preview-branch
|
||||||
type: String,
|
type: String,
|
||||||
default: null
|
default: null
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -96,6 +96,21 @@ router.get(
|
|||||||
integrationAuthController.getIntegrationAuthTeams
|
integrationAuthController.getIntegrationAuthTeams
|
||||||
);
|
);
|
||||||
|
|
||||||
|
router.get(
|
||||||
|
'/:integrationAuthId/vercel/branches',
|
||||||
|
requireAuth({
|
||||||
|
acceptedAuthModes: ['jwt']
|
||||||
|
}),
|
||||||
|
requireIntegrationAuthorizationAuth({
|
||||||
|
acceptedRoles: [ADMIN, MEMBER]
|
||||||
|
}),
|
||||||
|
param('integrationAuthId').exists().isString(),
|
||||||
|
query('appId').exists().isString(),
|
||||||
|
query('teamId').optional().isString(),
|
||||||
|
validateRequest,
|
||||||
|
integrationAuthController.getIntegrationAuthVercelBranches
|
||||||
|
);
|
||||||
|
|
||||||
router.delete(
|
router.delete(
|
||||||
'/:integrationAuthId',
|
'/:integrationAuthId',
|
||||||
requireAuth({
|
requireAuth({
|
||||||
|
|||||||
@@ -109,15 +109,33 @@ infisical login
|
|||||||
<Accordion title="Optional: point CLI to self-hosted">
|
<Accordion title="Optional: point CLI to self-hosted">
|
||||||
The CLI is set to connect to Infisical Cloud by default, but if you're running your own instance of Infisical, you can direct the CLI to it using one of the methods provided below.
|
The CLI is set to connect to Infisical Cloud by default, but if you're running your own instance of Infisical, you can direct the CLI to it using one of the methods provided below.
|
||||||
|
|
||||||
#### Export environment variable
|
#### Method 1: Export environment variable
|
||||||
You can point the CLI to the self hosted Infisical instance by exporting the environment variable `INFISICAL_API_URL` in your terminal.
|
You can point the CLI to the self hosted Infisical instance by exporting the environment variable `INFISICAL_API_URL` in your terminal.
|
||||||
|
|
||||||
```bash
|
<Tabs>
|
||||||
# Example
|
<Tab title="Linux/MacOs">
|
||||||
export INFISICAL_API_URL="https://your-self-hosted-infisical.com/api"
|
```bash
|
||||||
```
|
# Set backend host
|
||||||
|
export INFISICAL_API_URL="https://your-self-hosted-infisical.com/api"
|
||||||
|
|
||||||
#### Set manually on every command
|
# Remove backend host
|
||||||
|
unset INFISICAL_API_URL
|
||||||
|
```
|
||||||
|
</Tab>
|
||||||
|
<Tab title="Windows Powershell">
|
||||||
|
```bash
|
||||||
|
# Set backend host
|
||||||
|
setx INFISICAL_API_URL "https://your-self-hosted-infisical.com/api"
|
||||||
|
|
||||||
|
# Remove backend host
|
||||||
|
setx INFISICAL_API_URL ""
|
||||||
|
|
||||||
|
# NOTE: Once set or removed, please restart powershell for the change to take effect
|
||||||
|
```
|
||||||
|
</Tab>
|
||||||
|
</Tabs>
|
||||||
|
|
||||||
|
#### Method 2: Set manually on every command
|
||||||
Another option to point the CLI to your self hosted Infisical instance is to set it via a flag on every command you run.
|
Another option to point the CLI to your self hosted Infisical instance is to set it via a flag on every command you run.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
export {
|
export {
|
||||||
useGetIntegrationAuthApps,
|
useGetIntegrationAuthApps,
|
||||||
useGetIntegrationAuthById,
|
useGetIntegrationAuthById,
|
||||||
useGetIntegrationAuthTeams} from './queries';
|
useGetIntegrationAuthTeams,
|
||||||
|
useGetIntegrationAuthVercelBranches
|
||||||
|
} from './queries';
|
||||||
@@ -5,12 +5,20 @@ import { apiRequest } from "@app/config/request";
|
|||||||
import {
|
import {
|
||||||
App,
|
App,
|
||||||
IntegrationAuth,
|
IntegrationAuth,
|
||||||
Team} from './types';
|
Team
|
||||||
|
} from './types';
|
||||||
|
|
||||||
const integrationAuthKeys = {
|
const integrationAuthKeys = {
|
||||||
getIntegrationAuthById: (integrationAuthId: string) => [{ integrationAuthId }, 'integrationAuth'] as const,
|
getIntegrationAuthById: (integrationAuthId: string) => [{ integrationAuthId }, 'integrationAuth'] as const,
|
||||||
getIntegrationAuthApps: (integrationAuthId: string, teamId?: string) => [{ integrationAuthId, teamId }, 'integrationAuthApps'] as const,
|
getIntegrationAuthApps: (integrationAuthId: string, teamId?: string) => [{ integrationAuthId, teamId }, 'integrationAuthApps'] as const,
|
||||||
getIntegrationAuthTeams: (integrationAuthId: string) => [{ integrationAuthId }, 'integrationAuthTeams'] as const
|
getIntegrationAuthTeams: (integrationAuthId: string) => [{ integrationAuthId }, 'integrationAuthTeams'] as const,
|
||||||
|
getIntegrationAuthVercelBranches: ({
|
||||||
|
integrationAuthId,
|
||||||
|
appId,
|
||||||
|
}: {
|
||||||
|
integrationAuthId: string;
|
||||||
|
appId: string;
|
||||||
|
}) => [{ integrationAuthId, appId }, 'integrationAuthVercelBranches']
|
||||||
}
|
}
|
||||||
|
|
||||||
const fetchIntegrationAuthById = async (integrationAuthId: string) => {
|
const fetchIntegrationAuthById = async (integrationAuthId: string) => {
|
||||||
@@ -38,6 +46,22 @@ const fetchIntegrationAuthTeams = async (integrationAuthId: string) => {
|
|||||||
return data.teams;
|
return data.teams;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const fetchIntegrationAuthVercelBranches = async ({
|
||||||
|
integrationAuthId,
|
||||||
|
appId
|
||||||
|
}: {
|
||||||
|
integrationAuthId: string;
|
||||||
|
appId: string;
|
||||||
|
}) => {
|
||||||
|
const { data: { branches } } = await apiRequest.get<{ branches: string[] }>(`/api/v1/integration-auth/${integrationAuthId}/vercel/branches`, {
|
||||||
|
params: {
|
||||||
|
appId
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return branches;
|
||||||
|
};
|
||||||
|
|
||||||
export const useGetIntegrationAuthById = (integrationAuthId: string) => {
|
export const useGetIntegrationAuthById = (integrationAuthId: string) => {
|
||||||
return useQuery({
|
return useQuery({
|
||||||
queryKey: integrationAuthKeys.getIntegrationAuthById(integrationAuthId),
|
queryKey: integrationAuthKeys.getIntegrationAuthById(integrationAuthId),
|
||||||
@@ -46,7 +70,6 @@ export const useGetIntegrationAuthById = (integrationAuthId: string) => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: fix to teamId
|
|
||||||
export const useGetIntegrationAuthApps = ({
|
export const useGetIntegrationAuthApps = ({
|
||||||
integrationAuthId,
|
integrationAuthId,
|
||||||
teamId
|
teamId
|
||||||
@@ -70,4 +93,24 @@ export const useGetIntegrationAuthTeams = (integrationAuthId: string) => {
|
|||||||
queryFn: () => fetchIntegrationAuthTeams(integrationAuthId),
|
queryFn: () => fetchIntegrationAuthTeams(integrationAuthId),
|
||||||
enabled: true
|
enabled: true
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const useGetIntegrationAuthVercelBranches = ({
|
||||||
|
integrationAuthId,
|
||||||
|
appId,
|
||||||
|
}: {
|
||||||
|
integrationAuthId: string;
|
||||||
|
appId: string;
|
||||||
|
}) => {
|
||||||
|
return useQuery({
|
||||||
|
queryKey: integrationAuthKeys.getIntegrationAuthVercelBranches({
|
||||||
|
integrationAuthId,
|
||||||
|
appId,
|
||||||
|
}),
|
||||||
|
queryFn: () => fetchIntegrationAuthVercelBranches({
|
||||||
|
integrationAuthId,
|
||||||
|
appId,
|
||||||
|
}),
|
||||||
|
enabled: true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|||||||
@@ -27,8 +27,7 @@ export default function GitHubCreateIntegrationPage() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const [selectedSourceEnvironment, setSelectedSourceEnvironment] = useState('');
|
const [selectedSourceEnvironment, setSelectedSourceEnvironment] = useState('');
|
||||||
const [owner, setOwner] = useState<string | null>(null);
|
const [targetAppId, setTargetAppId] = useState('');
|
||||||
const [targetApp, setTargetApp] = useState('');
|
|
||||||
|
|
||||||
const [isLoading, setIsLoading] = useState(false);
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
|
|
||||||
@@ -41,10 +40,9 @@ export default function GitHubCreateIntegrationPage() {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (integrationAuthApps) {
|
if (integrationAuthApps) {
|
||||||
if (integrationAuthApps.length > 0) {
|
if (integrationAuthApps.length > 0) {
|
||||||
setTargetApp(integrationAuthApps[0].name);
|
setTargetAppId(integrationAuthApps[0].appId as string);
|
||||||
setOwner(integrationAuthApps[0]?.owner ?? null);
|
|
||||||
} else {
|
} else {
|
||||||
setTargetApp('none');
|
setTargetAppId('none');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [integrationAuthApps]);
|
}, [integrationAuthApps]);
|
||||||
@@ -55,14 +53,18 @@ export default function GitHubCreateIntegrationPage() {
|
|||||||
|
|
||||||
if (!integrationAuth?._id) return;
|
if (!integrationAuth?._id) return;
|
||||||
|
|
||||||
|
const targetApp = integrationAuthApps?.find((integrationAuthApp) => integrationAuthApp.appId === targetAppId);
|
||||||
|
|
||||||
|
if (!targetApp || !targetApp.owner) return;
|
||||||
|
|
||||||
await createIntegration({
|
await createIntegration({
|
||||||
integrationAuthId: integrationAuth?._id,
|
integrationAuthId: integrationAuth?._id,
|
||||||
isActive: true,
|
isActive: true,
|
||||||
app: targetApp,
|
app: targetApp.name,
|
||||||
appId: null,
|
appId: null,
|
||||||
sourceEnvironment: selectedSourceEnvironment,
|
sourceEnvironment: selectedSourceEnvironment,
|
||||||
targetEnvironment: null,
|
targetEnvironment: null,
|
||||||
owner,
|
owner: targetApp.owner,
|
||||||
path: null,
|
path: null,
|
||||||
region: null
|
region: null
|
||||||
});
|
});
|
||||||
@@ -76,7 +78,7 @@ export default function GitHubCreateIntegrationPage() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (integrationAuth && workspace && selectedSourceEnvironment && integrationAuthApps && targetApp) ? (
|
return (integrationAuth && workspace && selectedSourceEnvironment && integrationAuthApps && targetAppId) ? (
|
||||||
<div className="h-full w-full flex justify-center items-center">
|
<div className="h-full w-full flex justify-center items-center">
|
||||||
<Card className="max-w-md p-8 rounded-md">
|
<Card className="max-w-md p-8 rounded-md">
|
||||||
<CardTitle className='text-center'>GitHub Integration</CardTitle>
|
<CardTitle className='text-center'>GitHub Integration</CardTitle>
|
||||||
@@ -101,14 +103,14 @@ export default function GitHubCreateIntegrationPage() {
|
|||||||
className='mt-4'
|
className='mt-4'
|
||||||
>
|
>
|
||||||
<Select
|
<Select
|
||||||
value={targetApp}
|
value={targetAppId}
|
||||||
onValueChange={(val) => setTargetApp(val)}
|
onValueChange={(val) => setTargetAppId(val)}
|
||||||
className='w-full border border-mineshaft-500'
|
className='w-full border border-mineshaft-500'
|
||||||
isDisabled={integrationAuthApps.length === 0}
|
isDisabled={integrationAuthApps.length === 0}
|
||||||
>
|
>
|
||||||
{integrationAuthApps.length > 0 ? (
|
{integrationAuthApps.length > 0 ? (
|
||||||
integrationAuthApps.map((integrationAuthApp) => (
|
integrationAuthApps.map((integrationAuthApp) => (
|
||||||
<SelectItem value={integrationAuthApp.name} key={`github-environment-${integrationAuthApp.name}`}>
|
<SelectItem value={integrationAuthApp.appId as string} key={`github-repo-${integrationAuthApp.appId}`}>
|
||||||
{integrationAuthApp.name}
|
{integrationAuthApp.name}
|
||||||
</SelectItem>
|
</SelectItem>
|
||||||
))
|
))
|
||||||
|
|||||||
@@ -109,7 +109,6 @@ export default function GitLabCreateIntegrationPage() {
|
|||||||
<CardTitle className='text-center'>GitLab Integration</CardTitle>
|
<CardTitle className='text-center'>GitLab Integration</CardTitle>
|
||||||
<FormControl
|
<FormControl
|
||||||
label="Project Environment"
|
label="Project Environment"
|
||||||
className='mt-4'
|
|
||||||
>
|
>
|
||||||
<Select
|
<Select
|
||||||
value={selectedSourceEnvironment}
|
value={selectedSourceEnvironment}
|
||||||
@@ -125,7 +124,6 @@ export default function GitLabCreateIntegrationPage() {
|
|||||||
</FormControl>
|
</FormControl>
|
||||||
<FormControl
|
<FormControl
|
||||||
label="GitLab Integration Type"
|
label="GitLab Integration Type"
|
||||||
className='mt-4'
|
|
||||||
>
|
>
|
||||||
<Select
|
<Select
|
||||||
value={targetEntity}
|
value={targetEntity}
|
||||||
@@ -144,7 +142,6 @@ export default function GitLabCreateIntegrationPage() {
|
|||||||
{targetEntity === 'group' && targetTeamId && (
|
{targetEntity === 'group' && targetTeamId && (
|
||||||
<FormControl
|
<FormControl
|
||||||
label="GitLab Group"
|
label="GitLab Group"
|
||||||
className='mt-4'
|
|
||||||
>
|
>
|
||||||
<Select
|
<Select
|
||||||
value={targetTeamId}
|
value={targetTeamId}
|
||||||
@@ -167,7 +164,6 @@ export default function GitLabCreateIntegrationPage() {
|
|||||||
)}
|
)}
|
||||||
<FormControl
|
<FormControl
|
||||||
label="GitLab Project"
|
label="GitLab Project"
|
||||||
className='mt-4'
|
|
||||||
>
|
>
|
||||||
<Select
|
<Select
|
||||||
value={targetAppId}
|
value={targetAppId}
|
||||||
|
|||||||
@@ -4,14 +4,18 @@ import queryString from 'query-string';
|
|||||||
|
|
||||||
import { getTranslatedServerSideProps } from '../../../components/utilities/withTranslateProps';
|
import { getTranslatedServerSideProps } from '../../../components/utilities/withTranslateProps';
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
Card,
|
Card,
|
||||||
CardTitle,
|
CardTitle,
|
||||||
FormControl,
|
FormControl,
|
||||||
Select,
|
Select,
|
||||||
SelectItem
|
SelectItem
|
||||||
} from '../../../components/v2';
|
} from '../../../components/v2';
|
||||||
import { useGetIntegrationAuthApps,useGetIntegrationAuthById } from '../../../hooks/api/integrationAuth';
|
import {
|
||||||
|
useGetIntegrationAuthApps,
|
||||||
|
useGetIntegrationAuthById,
|
||||||
|
useGetIntegrationAuthVercelBranches
|
||||||
|
} from '../../../hooks/api/integrationAuth';
|
||||||
import { useGetWorkspaceById } from '../../../hooks/api/workspace';
|
import { useGetWorkspaceById } from '../../../hooks/api/workspace';
|
||||||
import createIntegration from "../../api/integrations/createIntegration";
|
import createIntegration from "../../api/integrations/createIntegration";
|
||||||
|
|
||||||
@@ -24,20 +28,28 @@ const vercelEnvironments = [
|
|||||||
export default function VercelCreateIntegrationPage() {
|
export default function VercelCreateIntegrationPage() {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
const { integrationAuthId } = queryString.parse(router.asPath.split('?')[1]);
|
const [selectedSourceEnvironment, setSelectedSourceEnvironment] = useState('');
|
||||||
|
const [targetAppId, setTargetAppId] = useState('');
|
||||||
|
const [targetEnvironment, setTargetEnvironment] = useState('');
|
||||||
|
const [targetBranch, setTargetBranch] = useState('');
|
||||||
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
|
|
||||||
|
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 { data: branches } = useGetIntegrationAuthVercelBranches({
|
||||||
const [targetApp, setTargetApp] = useState('');
|
integrationAuthId: integrationAuthId as string,
|
||||||
const [targetEnvironment, setTargetEnvironment] = useState('');
|
appId: targetAppId,
|
||||||
|
});
|
||||||
const [isLoading, setIsLoading] = useState(false);
|
|
||||||
|
|
||||||
|
const filteredBranches = branches
|
||||||
|
?.filter((branchName) => branchName !== 'main')
|
||||||
|
.concat('');
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (workspace) {
|
if (workspace) {
|
||||||
setSelectedSourceEnvironment(workspace.environments[0].slug);
|
setSelectedSourceEnvironment(workspace.environments[0].slug);
|
||||||
@@ -45,15 +57,15 @@ export default function VercelCreateIntegrationPage() {
|
|||||||
}, [workspace]);
|
}, [workspace]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (integrationAuthApps) {
|
if (integrationAuthApps) {
|
||||||
if (integrationAuthApps.length > 0) {
|
if (integrationAuthApps.length > 0) {
|
||||||
setTargetApp(integrationAuthApps[0].name);
|
setTargetAppId(integrationAuthApps[0].appId as string);
|
||||||
setTargetEnvironment(vercelEnvironments[0].slug);
|
setTargetEnvironment(vercelEnvironments[0].slug);
|
||||||
} else {
|
} else {
|
||||||
setTargetApp('none');
|
setTargetAppId('none');
|
||||||
setTargetEnvironment(vercelEnvironments[0].slug);
|
setTargetEnvironment(vercelEnvironments[0].slug);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}, [integrationAuthApps]);
|
}, [integrationAuthApps]);
|
||||||
|
|
||||||
const handleButtonClick = async () => {
|
const handleButtonClick = async () => {
|
||||||
@@ -61,15 +73,22 @@ export default function VercelCreateIntegrationPage() {
|
|||||||
if (!integrationAuth?._id) return;
|
if (!integrationAuth?._id) return;
|
||||||
|
|
||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
|
|
||||||
|
const targetApp = integrationAuthApps?.find((integrationAuthApp) => integrationAuthApp.appId === targetAppId);
|
||||||
|
|
||||||
|
if (!targetApp || !targetApp.appId) return;
|
||||||
|
|
||||||
|
const path = (targetEnvironment === 'preview' && targetBranch !== '') ? targetBranch : null;
|
||||||
|
|
||||||
await createIntegration({
|
await createIntegration({
|
||||||
integrationAuthId: integrationAuth?._id,
|
integrationAuthId: integrationAuth?._id,
|
||||||
isActive: true,
|
isActive: true,
|
||||||
app: targetApp,
|
app: targetApp.name,
|
||||||
appId: null,
|
appId: targetApp.appId,
|
||||||
sourceEnvironment: selectedSourceEnvironment,
|
sourceEnvironment: selectedSourceEnvironment,
|
||||||
targetEnvironment,
|
targetEnvironment,
|
||||||
owner: null,
|
owner: null,
|
||||||
path: null,
|
path,
|
||||||
region: null
|
region: null
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -82,7 +101,7 @@ export default function VercelCreateIntegrationPage() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (integrationAuth && workspace && selectedSourceEnvironment && integrationAuthApps && targetApp && targetEnvironment) ? (
|
return (integrationAuth && workspace && selectedSourceEnvironment && integrationAuthApps && targetAppId && targetEnvironment) ? (
|
||||||
<div className="h-full w-full flex justify-center items-center">
|
<div className="h-full w-full flex justify-center items-center">
|
||||||
<Card className="max-w-md p-8 rounded-md">
|
<Card className="max-w-md p-8 rounded-md">
|
||||||
<CardTitle className='text-center'>Vercel Integration</CardTitle>
|
<CardTitle className='text-center'>Vercel Integration</CardTitle>
|
||||||
@@ -106,14 +125,14 @@ export default function VercelCreateIntegrationPage() {
|
|||||||
label="Vercel App"
|
label="Vercel App"
|
||||||
>
|
>
|
||||||
<Select
|
<Select
|
||||||
value={targetApp}
|
value={targetAppId}
|
||||||
onValueChange={(val) => setTargetApp(val)}
|
onValueChange={(val) => setTargetAppId(val)}
|
||||||
className='w-full border border-mineshaft-500'
|
className='w-full border border-mineshaft-500'
|
||||||
isDisabled={integrationAuthApps.length === 0}
|
isDisabled={integrationAuthApps.length === 0}
|
||||||
>
|
>
|
||||||
{integrationAuthApps.length > 0 ? (
|
{integrationAuthApps.length > 0 ? (
|
||||||
integrationAuthApps.map((integrationAuthApp) => (
|
integrationAuthApps.map((integrationAuthApp) => (
|
||||||
<SelectItem value={integrationAuthApp.name} key={`target-app-${integrationAuthApp.name}`}>
|
<SelectItem value={integrationAuthApp.appId as string} key={`target-app-${integrationAuthApp.appId as string}`}>
|
||||||
{integrationAuthApp.name}
|
{integrationAuthApp.name}
|
||||||
</SelectItem>
|
</SelectItem>
|
||||||
))
|
))
|
||||||
@@ -139,6 +158,23 @@ export default function VercelCreateIntegrationPage() {
|
|||||||
))}
|
))}
|
||||||
</Select>
|
</Select>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
{targetEnvironment === 'preview' && filteredBranches && (
|
||||||
|
<FormControl
|
||||||
|
label="Vercel Preview Branch (Optional)"
|
||||||
|
>
|
||||||
|
<Select
|
||||||
|
value={targetBranch}
|
||||||
|
onValueChange={(val) => setTargetBranch(val)}
|
||||||
|
className='w-full border border-mineshaft-500'
|
||||||
|
>
|
||||||
|
{filteredBranches.map((branchName) => (
|
||||||
|
<SelectItem value={branchName} key={`target-branch-${branchName}`}>
|
||||||
|
{branchName}
|
||||||
|
</SelectItem>
|
||||||
|
))}
|
||||||
|
</Select>
|
||||||
|
</FormControl>
|
||||||
|
)}
|
||||||
<Button
|
<Button
|
||||||
onClick={handleButtonClick}
|
onClick={handleButtonClick}
|
||||||
color="mineshaft"
|
color="mineshaft"
|
||||||
|
|||||||
Reference in New Issue
Block a user