mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-16 15:31:19 +00:00
feat: changed backend-pg to backend
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,10 @@
|
||||
import { TDbClient } from "@app/db";
|
||||
import { TableName } from "@app/db/schemas";
|
||||
import { ormify } from "@app/lib/knex";
|
||||
|
||||
export type TIntegrationAuthDALFactory = ReturnType<typeof integrationAuthDALFactory>;
|
||||
|
||||
export const integrationAuthDALFactory = (db: TDbClient) => {
|
||||
const integrationAuthOrm = ormify(db, TableName.IntegrationAuth);
|
||||
return integrationAuthOrm;
|
||||
};
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,139 @@
|
||||
import { TProjectPermission } from "@app/lib/types";
|
||||
|
||||
export type TGetIntegrationAuthDTO = {
|
||||
id: string;
|
||||
} & Omit<TProjectPermission, "projectId">;
|
||||
|
||||
export type TOauthExchangeDTO = {
|
||||
integration: string;
|
||||
code: string;
|
||||
url?: string;
|
||||
} & TProjectPermission;
|
||||
|
||||
export type TSaveIntegrationAccessTokenDTO = {
|
||||
integration: string;
|
||||
accessId?: string;
|
||||
accessToken?: string;
|
||||
url?: string;
|
||||
namespace?: string;
|
||||
refreshToken?: string;
|
||||
} & TProjectPermission;
|
||||
|
||||
export type TDeleteIntegrationAuthsDTO = TProjectPermission & {
|
||||
integration: string;
|
||||
projectId: string;
|
||||
};
|
||||
|
||||
export type TIntegrationAuthAppsDTO = {
|
||||
id: string;
|
||||
teamId?: string;
|
||||
workspaceSlug?: string;
|
||||
} & Omit<TProjectPermission, "projectId">;
|
||||
|
||||
export type TIntegrationAuthTeamsDTO = {
|
||||
id: string;
|
||||
} & Omit<TProjectPermission, "projectId">;
|
||||
|
||||
export type TIntegrationAuthVercelBranchesDTO = {
|
||||
id: string;
|
||||
appId: string;
|
||||
} & Omit<TProjectPermission, "projectId">;
|
||||
|
||||
export type TIntegrationAuthChecklyGroupsDTO = {
|
||||
id: string;
|
||||
accountId: string;
|
||||
} & Omit<TProjectPermission, "projectId">;
|
||||
|
||||
export type TIntegrationAuthQoveryOrgsDTO = {
|
||||
id: string;
|
||||
} & Omit<TProjectPermission, "projectId">;
|
||||
|
||||
export type TIntegrationAuthQoveryProjectDTO = {
|
||||
id: string;
|
||||
orgId: string;
|
||||
} & Omit<TProjectPermission, "projectId">;
|
||||
|
||||
export type TIntegrationAuthQoveryEnvironmentsDTO = {
|
||||
id: string;
|
||||
} & TProjectPermission;
|
||||
|
||||
export type TIntegrationAuthQoveryScopesDTO = {
|
||||
id: string;
|
||||
environmentId: string;
|
||||
} & Omit<TProjectPermission, "projectId">;
|
||||
|
||||
export type TIntegrationAuthRailwayEnvDTO = {
|
||||
id: string;
|
||||
appId: string;
|
||||
} & Omit<TProjectPermission, "projectId">;
|
||||
|
||||
export type TIntegrationAuthRailwayServicesDTO = {
|
||||
id: string;
|
||||
appId: string;
|
||||
} & Omit<TProjectPermission, "projectId">;
|
||||
|
||||
export type TIntegrationAuthBitbucketWorkspaceDTO = {
|
||||
id: string;
|
||||
} & Omit<TProjectPermission, "projectId">;
|
||||
|
||||
export type TIntegrationAuthNorthflankSecretGroupDTO = {
|
||||
id: string;
|
||||
appId: string;
|
||||
} & Omit<TProjectPermission, "projectId">;
|
||||
|
||||
export type TDeleteIntegrationAuthByIdDTO = {
|
||||
id: string;
|
||||
} & Omit<TProjectPermission, "projectId">;
|
||||
|
||||
export type TGetIntegrationAuthTeamCityBuildConfigDTO = {
|
||||
id: string;
|
||||
appId: string;
|
||||
} & Omit<TProjectPermission, "projectId">;
|
||||
|
||||
export type TVercelBranches = {
|
||||
ref: string;
|
||||
lastCommit: string;
|
||||
isProtected: boolean;
|
||||
};
|
||||
|
||||
export type TChecklyGroups = {
|
||||
id: number;
|
||||
name: string;
|
||||
};
|
||||
|
||||
export type TQoveryProjects = {
|
||||
id: string;
|
||||
name: string;
|
||||
};
|
||||
|
||||
export type TQoveryEnvironments = {
|
||||
id: string;
|
||||
name: string;
|
||||
};
|
||||
|
||||
export type TBitbucketWorkspace = {
|
||||
type: string;
|
||||
uuid: string;
|
||||
name: string;
|
||||
slug: string;
|
||||
is_private: boolean;
|
||||
created_on: string;
|
||||
updated_on: string;
|
||||
};
|
||||
|
||||
export type TNorthflankSecretGroup = {
|
||||
id: string;
|
||||
name: string;
|
||||
description: string;
|
||||
priority: number;
|
||||
projectId: string;
|
||||
};
|
||||
|
||||
export type TTeamCityBuildConfig = {
|
||||
id: string;
|
||||
name: string;
|
||||
projectName: string;
|
||||
projectId: string;
|
||||
href: string;
|
||||
webUrl: string;
|
||||
};
|
||||
@@ -0,0 +1,363 @@
|
||||
import { getConfig } from "@app/lib/config/env";
|
||||
|
||||
export enum Integrations {
|
||||
AZURE_KEY_VAULT = "azure-key-vault",
|
||||
AWS_PARAMETER_STORE = "aws-parameter-store",
|
||||
AWS_SECRET_MANAGER = "aws-secret-manager",
|
||||
GCP_SECRET_MANAGER = "gcp-secret-manager",
|
||||
HEROKU = "heroku",
|
||||
VERCEL = "vercel",
|
||||
NETLIFY = "netlify",
|
||||
GITHUB = "github",
|
||||
GITLAB = "gitlab",
|
||||
RENDER = "render",
|
||||
RAILWAY = "railway",
|
||||
FLYIO = "flyio",
|
||||
LARAVELFORGE = "laravel-forge",
|
||||
CIRCLECI = "circleci",
|
||||
TRAVISCI = "travisci",
|
||||
TEAMCITY = "teamcity",
|
||||
SUPABASE = "supabase",
|
||||
CHECKLY = "checkly",
|
||||
QOVERY = "qovery",
|
||||
TERRAFORM_CLOUD = "terraform-cloud",
|
||||
HASHICORP_VAULT = "hashicorp-vault",
|
||||
CLOUDFLARE_PAGES = "cloudflare-pages",
|
||||
CLOUDFLARE_WORKERS = "cloudflare-workers",
|
||||
BITBUCKET = "bitbucket",
|
||||
CODEFRESH = "codefresh",
|
||||
WINDMILL = "windmill",
|
||||
DIGITAL_OCEAN_APP_PLATFORM = "digital-ocean-app-platform",
|
||||
CLOUD_66 = "cloud-66",
|
||||
NORTHFLANK = "northflank",
|
||||
HASURA_CLOUD = "hasura-cloud"
|
||||
}
|
||||
|
||||
export enum IntegrationType {
|
||||
OAUTH2 = "oauth2"
|
||||
}
|
||||
|
||||
export enum IntegrationUrls {
|
||||
// integration oauth endpoints
|
||||
GCP_TOKEN_URL = "https://oauth2.googleapis.com/token",
|
||||
AZURE_TOKEN_URL = "https://login.microsoftonline.com/common/oauth2/v2.0/token",
|
||||
HEROKU_TOKEN_URL = "https://id.heroku.com/oauth/token",
|
||||
VERCEL_TOKEN_URL = "https://api.vercel.com/v2/oauth/access_token",
|
||||
NETLIFY_TOKEN_URL = "https://api.netlify.com/oauth/token",
|
||||
GITHUB_TOKEN_URL = "https://github.com/login/oauth/access_token",
|
||||
GITLAB_TOKEN_URL = "https://gitlab.com/oauth/token",
|
||||
BITBUCKET_TOKEN_URL = "https://bitbucket.org/site/oauth2/access_token",
|
||||
|
||||
// integration apps endpoints
|
||||
GCP_API_URL = "https://cloudresourcemanager.googleapis.com",
|
||||
HEROKU_API_URL = "https://api.heroku.com",
|
||||
GITLAB_URL = "https://gitlab.com",
|
||||
GITLAB_API_URL = `${GITLAB_URL}/api`,
|
||||
GITHUB_API_URL = "https://api.github.com",
|
||||
VERCEL_API_URL = "https://api.vercel.com",
|
||||
NETLIFY_API_URL = "https://api.netlify.com",
|
||||
RENDER_API_URL = "https://api.render.com",
|
||||
RAILWAY_API_URL = "https://backboard.railway.app/graphql/v2",
|
||||
FLYIO_API_URL = "https://api.fly.io/graphql",
|
||||
CIRCLECI_API_URL = "https://circleci.com/api",
|
||||
TRAVISCI_API_URL = "https://api.travis-ci.com",
|
||||
SUPABASE_API_URL = "https://api.supabase.com",
|
||||
LARAVELFORGE_API_URL = "https://forge.laravel.com",
|
||||
CHECKLY_API_URL = "https://api.checklyhq.com",
|
||||
QOVERY_API_URL = "https://api.qovery.com",
|
||||
TERRAFORM_CLOUD_API_URL = "https://app.terraform.io",
|
||||
CLOUDFLARE_PAGES_API_URL = "https://api.cloudflare.com",
|
||||
CLOUDFLARE_WORKERS_API_URL = "https://api.cloudflare.com",
|
||||
BITBUCKET_API_URL = "https://api.bitbucket.org",
|
||||
CODEFRESH_API_URL = "https://g.codefresh.io/api",
|
||||
WINDMILL_API_URL = "https://app.windmill.dev/api",
|
||||
DIGITAL_OCEAN_API_URL = "https://api.digitalocean.com",
|
||||
CLOUD_66_API_URL = "https://app.cloud66.com/api",
|
||||
NORTHFLANK_API_URL = "https://api.northflank.com",
|
||||
HASURA_CLOUD_API_URL = "https://data.pro.hasura.io/v1/graphql",
|
||||
|
||||
GCP_SECRET_MANAGER_SERVICE_NAME = "secretmanager.googleapis.com",
|
||||
GCP_SECRET_MANAGER_URL = `https://${GCP_SECRET_MANAGER_SERVICE_NAME}`,
|
||||
GCP_SERVICE_USAGE_URL = "https://serviceusage.googleapis.com",
|
||||
GCP_CLOUD_PLATFORM_SCOPE = "https://www.googleapis.com/auth/cloud-platform"
|
||||
}
|
||||
|
||||
export const getIntegrationOptions = async () => {
|
||||
const appCfg = getConfig();
|
||||
|
||||
const INTEGRATION_OPTIONS = [
|
||||
{
|
||||
name: "Heroku",
|
||||
slug: "heroku",
|
||||
image: "Heroku.png",
|
||||
isAvailable: true,
|
||||
type: "oauth",
|
||||
clientId: appCfg.CLIENT_ID_HEROKU,
|
||||
docsLink: ""
|
||||
},
|
||||
{
|
||||
name: "Vercel",
|
||||
slug: "vercel",
|
||||
image: "Vercel.png",
|
||||
isAvailable: true,
|
||||
type: "oauth",
|
||||
clientId: "",
|
||||
clientSlug: appCfg.CLIENT_SLUG_VERCEL,
|
||||
docsLink: ""
|
||||
},
|
||||
{
|
||||
name: "Netlify",
|
||||
slug: "netlify",
|
||||
image: "Netlify.png",
|
||||
isAvailable: true,
|
||||
type: "oauth",
|
||||
clientId: appCfg.CLIENT_ID_NETLIFY,
|
||||
docsLink: ""
|
||||
},
|
||||
{
|
||||
name: "GitHub",
|
||||
slug: "github",
|
||||
image: "GitHub.png",
|
||||
isAvailable: true,
|
||||
type: "oauth",
|
||||
clientId: appCfg.CLIENT_ID_GITHUB,
|
||||
docsLink: ""
|
||||
},
|
||||
{
|
||||
name: "Render",
|
||||
slug: "render",
|
||||
image: "Render.png",
|
||||
isAvailable: true,
|
||||
type: "pat",
|
||||
clientId: "",
|
||||
docsLink: ""
|
||||
},
|
||||
{
|
||||
name: "Railway",
|
||||
slug: "railway",
|
||||
image: "Railway.png",
|
||||
isAvailable: true,
|
||||
type: "pat",
|
||||
clientId: "",
|
||||
docsLink: ""
|
||||
},
|
||||
{
|
||||
name: "Fly.io",
|
||||
slug: "flyio",
|
||||
image: "Flyio.svg",
|
||||
isAvailable: true,
|
||||
type: "pat",
|
||||
clientId: "",
|
||||
docsLink: ""
|
||||
},
|
||||
{
|
||||
name: "AWS Parameter Store",
|
||||
slug: "aws-parameter-store",
|
||||
image: "Amazon Web Services.png",
|
||||
isAvailable: true,
|
||||
type: "custom",
|
||||
clientId: "",
|
||||
docsLink: ""
|
||||
},
|
||||
{
|
||||
name: "Laravel Forge",
|
||||
slug: "laravel-forge",
|
||||
image: "Laravel Forge.png",
|
||||
isAvailable: true,
|
||||
type: "pat",
|
||||
clientId: "",
|
||||
docsLink: ""
|
||||
},
|
||||
{
|
||||
name: "AWS Secrets Manager",
|
||||
slug: "aws-secret-manager",
|
||||
image: "Amazon Web Services.png",
|
||||
isAvailable: true,
|
||||
type: "custom",
|
||||
clientId: "",
|
||||
docsLink: ""
|
||||
},
|
||||
{
|
||||
name: "Azure Key Vault",
|
||||
slug: "azure-key-vault",
|
||||
image: "Microsoft Azure.png",
|
||||
isAvailable: true,
|
||||
type: "oauth",
|
||||
clientId: appCfg.CLIENT_ID_AZURE,
|
||||
docsLink: ""
|
||||
},
|
||||
{
|
||||
name: "Circle CI",
|
||||
slug: "circleci",
|
||||
image: "Circle CI.png",
|
||||
isAvailable: true,
|
||||
type: "pat",
|
||||
clientId: "",
|
||||
docsLink: ""
|
||||
},
|
||||
{
|
||||
name: "GitLab",
|
||||
slug: "gitlab",
|
||||
image: "GitLab.png",
|
||||
isAvailable: true,
|
||||
type: "custom",
|
||||
clientId: appCfg.CLIENT_ID_GITLAB,
|
||||
docsLink: ""
|
||||
},
|
||||
{
|
||||
name: "Terraform Cloud",
|
||||
slug: "terraform-cloud",
|
||||
image: "Terraform Cloud.png",
|
||||
isAvailable: true,
|
||||
type: "pat",
|
||||
cliendId: "",
|
||||
docsLink: ""
|
||||
},
|
||||
{
|
||||
name: "Travis CI",
|
||||
slug: "travisci",
|
||||
image: "Travis CI.png",
|
||||
isAvailable: true,
|
||||
type: "pat",
|
||||
clientId: "",
|
||||
docsLink: ""
|
||||
},
|
||||
{
|
||||
name: "TeamCity",
|
||||
slug: "teamcity",
|
||||
image: "TeamCity.png",
|
||||
isAvailable: true,
|
||||
type: "pat",
|
||||
clientId: "",
|
||||
docsLink: ""
|
||||
},
|
||||
{
|
||||
name: "Supabase",
|
||||
slug: "supabase",
|
||||
image: "Supabase.png",
|
||||
isAvailable: true,
|
||||
type: "pat",
|
||||
clientId: "",
|
||||
docsLink: ""
|
||||
},
|
||||
{
|
||||
name: "Checkly",
|
||||
slug: "checkly",
|
||||
image: "Checkly.png",
|
||||
isAvailable: true,
|
||||
type: "pat",
|
||||
clientId: "",
|
||||
docsLink: ""
|
||||
},
|
||||
{
|
||||
name: "Qovery",
|
||||
slug: "qovery",
|
||||
image: "Qovery.png",
|
||||
isAvailable: true,
|
||||
type: "pat",
|
||||
clientId: "",
|
||||
docsLink: ""
|
||||
},
|
||||
{
|
||||
name: "HashiCorp Vault",
|
||||
slug: "hashicorp-vault",
|
||||
image: "Vault.png",
|
||||
isAvailable: true,
|
||||
type: "pat",
|
||||
clientId: "",
|
||||
docsLink: ""
|
||||
},
|
||||
{
|
||||
name: "GCP Secret Manager",
|
||||
slug: "gcp-secret-manager",
|
||||
image: "Google Cloud Platform.png",
|
||||
isAvailable: true,
|
||||
type: "oauth",
|
||||
clientId: appCfg.CLIENT_ID_GCP_SECRET_MANAGER,
|
||||
docsLink: ""
|
||||
},
|
||||
{
|
||||
name: "Cloudflare Pages",
|
||||
slug: "cloudflare-pages",
|
||||
image: "Cloudflare.png",
|
||||
isAvailable: true,
|
||||
type: "pat",
|
||||
clientId: "",
|
||||
docsLink: ""
|
||||
},
|
||||
{
|
||||
name: "Cloudflare Workers",
|
||||
slug: "cloudflare-workers",
|
||||
image: "Cloudflare.png",
|
||||
isAvailable: true,
|
||||
type: "pat",
|
||||
clientId: "",
|
||||
docsLink: ""
|
||||
},
|
||||
{
|
||||
name: "BitBucket",
|
||||
slug: "bitbucket",
|
||||
image: "BitBucket.png",
|
||||
isAvailable: true,
|
||||
type: "oauth",
|
||||
clientId: appCfg.CLIENT_ID_BITBUCKET,
|
||||
docsLink: ""
|
||||
},
|
||||
{
|
||||
name: "Codefresh",
|
||||
slug: "codefresh",
|
||||
image: "Codefresh.png",
|
||||
isAvailable: true,
|
||||
type: "pat",
|
||||
clientId: "",
|
||||
docsLink: ""
|
||||
},
|
||||
{
|
||||
name: "Windmill",
|
||||
slug: "windmill",
|
||||
image: "Windmill.png",
|
||||
isAvailable: true,
|
||||
type: "pat",
|
||||
clientId: "",
|
||||
docsLink: ""
|
||||
},
|
||||
{
|
||||
name: "Digital Ocean App Platform",
|
||||
slug: "digital-ocean-app-platform",
|
||||
image: "Digital Ocean.png",
|
||||
isAvailable: true,
|
||||
type: "pat",
|
||||
clientId: "",
|
||||
docsLink: ""
|
||||
},
|
||||
{
|
||||
name: "Cloud 66",
|
||||
slug: "cloud-66",
|
||||
image: "Cloud 66.png",
|
||||
isAvailable: true,
|
||||
type: "pat",
|
||||
clientId: "",
|
||||
docsLink: ""
|
||||
},
|
||||
{
|
||||
name: "Northflank",
|
||||
slug: "northflank",
|
||||
image: "Northflank.png",
|
||||
isAvailable: true,
|
||||
type: "pat",
|
||||
clientId: "",
|
||||
docsLink: ""
|
||||
},
|
||||
{
|
||||
name: "Hasura Cloud",
|
||||
slug: "hasura-cloud",
|
||||
image: "Hasura.svg",
|
||||
isAvailable: true,
|
||||
type: "pat",
|
||||
clientId: "",
|
||||
docsLink: ""
|
||||
}
|
||||
];
|
||||
|
||||
return INTEGRATION_OPTIONS;
|
||||
};
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,49 @@
|
||||
import { request } from "@app/lib/config/request";
|
||||
import { BadRequestError } from "@app/lib/errors";
|
||||
|
||||
import { Integrations,IntegrationUrls } from "./integration-list";
|
||||
|
||||
type Team = {
|
||||
name: string;
|
||||
teamId: string;
|
||||
};
|
||||
const getTeamsGitLab = async ({ url, accessToken }: { url: string; accessToken: string }) => {
|
||||
const gitLabApiUrl = url ? `${url}/api` : IntegrationUrls.GITLAB_API_URL;
|
||||
|
||||
let teams: Team[] = [];
|
||||
const res = (
|
||||
await request.get(`${gitLabApiUrl}/v4/groups`, {
|
||||
headers: {
|
||||
Authorization: `Bearer ${accessToken}`,
|
||||
"Accept-Encoding": "application/json"
|
||||
}
|
||||
})
|
||||
).data;
|
||||
|
||||
teams = res.map((t: any) => ({
|
||||
name: t.name,
|
||||
teamId: t.id
|
||||
}));
|
||||
|
||||
return teams;
|
||||
};
|
||||
|
||||
export const getTeams = async ({
|
||||
accessToken,
|
||||
url,
|
||||
integration
|
||||
}: {
|
||||
accessToken: string;
|
||||
url?: string;
|
||||
integration: string;
|
||||
}) => {
|
||||
switch (integration) {
|
||||
case Integrations.GITLAB:
|
||||
return getTeamsGitLab({
|
||||
url: url as string,
|
||||
accessToken
|
||||
});
|
||||
default:
|
||||
throw new BadRequestError({ message: "Integration doesn't have team support" });
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,724 @@
|
||||
import jwt from "jsonwebtoken";
|
||||
|
||||
import { getConfig } from "@app/lib/config/env";
|
||||
import { request } from "@app/lib/config/request";
|
||||
import { BadRequestError } from "@app/lib/errors";
|
||||
|
||||
import { Integrations, IntegrationUrls } from "./integration-list";
|
||||
|
||||
type ExchangeCodeAzureResponse = {
|
||||
token_type: string;
|
||||
scope: string;
|
||||
expires_in: number;
|
||||
ext_expires_in: number;
|
||||
access_token: string;
|
||||
refresh_token: string;
|
||||
id_token: string;
|
||||
};
|
||||
|
||||
type ExchangeCodeGCPResponse = {
|
||||
access_token: string;
|
||||
expires_in: number;
|
||||
refresh_token: string;
|
||||
scope: string;
|
||||
token_type: string;
|
||||
};
|
||||
|
||||
type ExchangeCodeHerokuResponse = {
|
||||
token_type: string;
|
||||
access_token: string;
|
||||
expires_in: number;
|
||||
refresh_token: string;
|
||||
user_id: string;
|
||||
session_nonce?: string;
|
||||
};
|
||||
|
||||
type ExchangeCodeVercelResponse = {
|
||||
token_type: string;
|
||||
access_token: string;
|
||||
installation_id: string;
|
||||
user_id: string;
|
||||
team_id?: string;
|
||||
};
|
||||
|
||||
type ExchangeCodeNetlifyResponse = {
|
||||
access_token: string;
|
||||
token_type: string;
|
||||
refresh_token: string;
|
||||
scope: string;
|
||||
created_at: number;
|
||||
};
|
||||
|
||||
type ExchangeCodeGithubResponse = {
|
||||
access_token: string;
|
||||
scope: string;
|
||||
token_type: string;
|
||||
};
|
||||
|
||||
type ExchangeCodeGitlabResponse = {
|
||||
access_token: string;
|
||||
token_type: string;
|
||||
expires_in: number;
|
||||
refresh_token: string;
|
||||
scope: string;
|
||||
created_at: number;
|
||||
};
|
||||
|
||||
type ExchangeCodeBitBucketResponse = {
|
||||
access_token: string;
|
||||
token_type: string;
|
||||
expires_in: number;
|
||||
refresh_token: string;
|
||||
scopes: string;
|
||||
state: string;
|
||||
};
|
||||
|
||||
const exchangeCodeGCP = async ({ code }: { code: string }) => {
|
||||
const accessExpiresAt = new Date();
|
||||
const appCfg = getConfig();
|
||||
if (!appCfg.CLIENT_SECRET_GCP_SECRET_MANAGER || !appCfg.CLIENT_ID_GCP_SECRET_MANAGER) {
|
||||
throw new BadRequestError({ message: "Missing client id and client secret" });
|
||||
}
|
||||
|
||||
const res: ExchangeCodeGCPResponse = (
|
||||
await request.post(
|
||||
IntegrationUrls.GCP_TOKEN_URL,
|
||||
new URLSearchParams({
|
||||
grant_type: "authorization_code",
|
||||
code,
|
||||
client_id: appCfg.CLIENT_ID_GCP_SECRET_MANAGER,
|
||||
client_secret: appCfg.CLIENT_SECRET_GCP_SECRET_MANAGER,
|
||||
redirect_uri: `${appCfg.SITE_URL}/integrations/gcp-secret-manager/oauth2/callback`
|
||||
})
|
||||
)
|
||||
).data;
|
||||
|
||||
accessExpiresAt.setSeconds(accessExpiresAt.getSeconds() + res.expires_in);
|
||||
|
||||
return {
|
||||
accessToken: res.access_token,
|
||||
refreshToken: res.refresh_token,
|
||||
accessExpiresAt
|
||||
};
|
||||
};
|
||||
|
||||
const exchangeCodeAzure = async ({ code }: { code: string }) => {
|
||||
const accessExpiresAt = new Date();
|
||||
const appCfg = getConfig();
|
||||
if (!appCfg.CLIENT_ID_AZURE || !appCfg.CLIENT_SECRET_AZURE) {
|
||||
throw new BadRequestError({ message: "Missing client id and client secret" });
|
||||
}
|
||||
const res: ExchangeCodeAzureResponse = (
|
||||
await request.post(
|
||||
IntegrationUrls.AZURE_TOKEN_URL,
|
||||
new URLSearchParams({
|
||||
grant_type: "authorization_code",
|
||||
code,
|
||||
scope: "https://vault.azure.net/.default openid offline_access",
|
||||
client_id: appCfg.CLIENT_ID_AZURE,
|
||||
client_secret: appCfg.CLIENT_SECRET_AZURE,
|
||||
redirect_uri: `${appCfg.SITE_URL}/integrations/azure-key-vault/oauth2/callback`
|
||||
} as any)
|
||||
)
|
||||
).data;
|
||||
|
||||
accessExpiresAt.setSeconds(accessExpiresAt.getSeconds() + res.expires_in);
|
||||
|
||||
return {
|
||||
accessToken: res.access_token,
|
||||
refreshToken: res.refresh_token,
|
||||
accessExpiresAt
|
||||
};
|
||||
};
|
||||
|
||||
const exchangeCodeHeroku = async ({ code }: { code: string }) => {
|
||||
const accessExpiresAt = new Date();
|
||||
const appCfg = getConfig();
|
||||
if (!appCfg.CLIENT_SECRET_HEROKU) {
|
||||
throw new BadRequestError({ message: "Missing client id and client secret" });
|
||||
}
|
||||
|
||||
const res: ExchangeCodeHerokuResponse = (
|
||||
await request.post(
|
||||
IntegrationUrls.HEROKU_TOKEN_URL,
|
||||
new URLSearchParams({
|
||||
grant_type: "authorization_code",
|
||||
code,
|
||||
client_secret: appCfg.CLIENT_SECRET_HEROKU
|
||||
})
|
||||
)
|
||||
).data;
|
||||
accessExpiresAt.setSeconds(accessExpiresAt.getSeconds() + res.expires_in);
|
||||
|
||||
return {
|
||||
accessToken: res.access_token,
|
||||
refreshToken: res.refresh_token,
|
||||
accessExpiresAt
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Return [accessToken], [accessExpiresAt], and [refreshToken] for Vercel
|
||||
* code-token exchange
|
||||
* @param {Object} obj1
|
||||
* @param {Object} obj1.code - code for code-token exchange
|
||||
* @returns {Object} obj2
|
||||
* @returns {String} obj2.accessToken - access token for Heroku API
|
||||
* @returns {String} obj2.refreshToken - refresh token for Heroku API
|
||||
* @returns {Date} obj2.accessExpiresAt - date of expiration for access token
|
||||
*/
|
||||
const exchangeCodeVercel = async ({ code }: { code: string }) => {
|
||||
const appCfg = getConfig();
|
||||
if (!appCfg.CLIENT_ID_VERCEL || !appCfg.CLIENT_SECRET_VERCEL) {
|
||||
throw new BadRequestError({ message: "Missing client id and client secret" });
|
||||
}
|
||||
|
||||
const res: ExchangeCodeVercelResponse = (
|
||||
await request.post(
|
||||
IntegrationUrls.VERCEL_TOKEN_URL,
|
||||
new URLSearchParams({
|
||||
code,
|
||||
client_id: appCfg.CLIENT_ID_VERCEL,
|
||||
client_secret: appCfg.CLIENT_SECRET_VERCEL,
|
||||
redirect_uri: `${appCfg.SITE_URL}/integrations/vercel/oauth2/callback`
|
||||
} as any)
|
||||
)
|
||||
).data;
|
||||
|
||||
return {
|
||||
accessToken: res.access_token,
|
||||
refreshToken: null,
|
||||
accessExpiresAt: null,
|
||||
teamId: res.team_id
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Return [accessToken], [accessExpiresAt], and [refreshToken] for Vercel
|
||||
* code-token exchange
|
||||
* @param {Object} obj1
|
||||
* @param {Object} obj1.code - code for code-token exchange
|
||||
* @returns {Object} obj2
|
||||
* @returns {String} obj2.accessToken - access token for Heroku API
|
||||
* @returns {String} obj2.refreshToken - refresh token for Heroku API
|
||||
* @returns {Date} obj2.accessExpiresAt - date of expiration for access token
|
||||
*/
|
||||
const exchangeCodeNetlify = async ({ code }: { code: string }) => {
|
||||
const appCfg = getConfig();
|
||||
if (!appCfg.CLIENT_ID_NETLIFY || !appCfg.CLIENT_SECRET_NETLIFY) {
|
||||
throw new BadRequestError({ message: "Missing client id and client secret" });
|
||||
}
|
||||
|
||||
const res: ExchangeCodeNetlifyResponse = (
|
||||
await request.post(
|
||||
IntegrationUrls.NETLIFY_TOKEN_URL,
|
||||
new URLSearchParams({
|
||||
grant_type: "authorization_code",
|
||||
code,
|
||||
client_id: appCfg.CLIENT_ID_NETLIFY,
|
||||
client_secret: appCfg.CLIENT_SECRET_NETLIFY,
|
||||
redirect_uri: `${appCfg.SITE_URL}/integrations/netlify/oauth2/callback`
|
||||
} as any)
|
||||
)
|
||||
).data;
|
||||
|
||||
// akhilmhdh: commented out by me. Not sure why its being called but never used in prev codebase
|
||||
// const res2 = await request.get("https://api.netlify.com/api/v1/sites", {
|
||||
// headers: {
|
||||
// Authorization: `Bearer ${res.access_token}`
|
||||
// }
|
||||
// });
|
||||
|
||||
const res3 = (
|
||||
await request.get("https://api.netlify.com/api/v1/accounts", {
|
||||
headers: {
|
||||
Authorization: `Bearer ${res.access_token}`
|
||||
}
|
||||
})
|
||||
).data;
|
||||
|
||||
const accountId = res3[0].id;
|
||||
|
||||
return {
|
||||
accessToken: res.access_token,
|
||||
refreshToken: res.refresh_token,
|
||||
accountId
|
||||
};
|
||||
};
|
||||
|
||||
const exchangeCodeGithub = async ({ code }: { code: string }) => {
|
||||
const appCfg = getConfig();
|
||||
if (!appCfg.CLIENT_ID_GITHUB || !appCfg.CLIENT_SECRET_GITHUB) {
|
||||
throw new BadRequestError({ message: "Missing client id and client secret" });
|
||||
}
|
||||
|
||||
const res: ExchangeCodeGithubResponse = (
|
||||
await request.get(IntegrationUrls.GITHUB_TOKEN_URL, {
|
||||
params: {
|
||||
client_id: appCfg.CLIENT_ID_GITHUB,
|
||||
client_secret: appCfg.CLIENT_SECRET_GITHUB,
|
||||
code,
|
||||
redirect_uri: `${appCfg.SITE_URL}/integrations/github/oauth2/callback`
|
||||
},
|
||||
headers: {
|
||||
Accept: "application/json",
|
||||
"Accept-Encoding": "application/json"
|
||||
}
|
||||
})
|
||||
).data;
|
||||
|
||||
return {
|
||||
accessToken: res.access_token,
|
||||
refreshToken: null,
|
||||
accessExpiresAt: null
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Return [accessToken], [accessExpiresAt], and [refreshToken] for Gitlab
|
||||
* code-token exchange
|
||||
*/
|
||||
const exchangeCodeGitlab = async ({ code, url }: { code: string; url?: string }) => {
|
||||
const accessExpiresAt = new Date();
|
||||
const appCfg = getConfig();
|
||||
if (!appCfg.CLIENT_ID_GITLAB || !appCfg.CLIENT_SECRET_GITLAB) {
|
||||
throw new BadRequestError({ message: "Missing client id and client secret" });
|
||||
}
|
||||
|
||||
const res: ExchangeCodeGitlabResponse = (
|
||||
await request.post(
|
||||
url ? `${url}/oauth/token` : IntegrationUrls.GITLAB_TOKEN_URL,
|
||||
new URLSearchParams({
|
||||
grant_type: "authorization_code",
|
||||
code,
|
||||
client_id: appCfg.CLIENT_ID_GITLAB,
|
||||
client_secret: appCfg.CLIENT_SECRET_GITLAB,
|
||||
redirect_uri: `${appCfg.SITE_URL}/integrations/gitlab/oauth2/callback`
|
||||
} as any),
|
||||
{
|
||||
headers: {
|
||||
"Accept-Encoding": "application/json"
|
||||
}
|
||||
}
|
||||
)
|
||||
).data;
|
||||
|
||||
accessExpiresAt.setSeconds(accessExpiresAt.getSeconds() + res.expires_in);
|
||||
|
||||
return {
|
||||
accessToken: res.access_token,
|
||||
refreshToken: res.refresh_token,
|
||||
accessExpiresAt,
|
||||
url
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Return [accessToken], [accessExpiresAt], and [refreshToken] for BitBucket
|
||||
* code-token exchange
|
||||
*/
|
||||
const exchangeCodeBitBucket = async ({ code }: { code: string }) => {
|
||||
const accessExpiresAt = new Date();
|
||||
const appCfg = getConfig();
|
||||
if (!appCfg.CLIENT_SECRET_BITBUCKET || !appCfg.CLIENT_ID_BITBUCKET) {
|
||||
throw new BadRequestError({ message: "Missing client id and client secret" });
|
||||
}
|
||||
|
||||
const res: ExchangeCodeBitBucketResponse = (
|
||||
await request.post(
|
||||
IntegrationUrls.BITBUCKET_TOKEN_URL,
|
||||
new URLSearchParams({
|
||||
grant_type: "authorization_code",
|
||||
code,
|
||||
client_id: appCfg.CLIENT_ID_BITBUCKET,
|
||||
client_secret: appCfg.CLIENT_SECRET_BITBUCKET,
|
||||
redirect_uri: `${appCfg.SITE_URL}/integrations/bitbucket/oauth2/callback`
|
||||
} as any),
|
||||
{
|
||||
headers: {
|
||||
"Accept-Encoding": "application/json"
|
||||
}
|
||||
}
|
||||
)
|
||||
).data;
|
||||
|
||||
accessExpiresAt.setSeconds(accessExpiresAt.getSeconds() + res.expires_in);
|
||||
|
||||
return {
|
||||
accessToken: res.access_token,
|
||||
refreshToken: res.refresh_token,
|
||||
accessExpiresAt
|
||||
};
|
||||
};
|
||||
|
||||
type TExchangeReturn = {
|
||||
accessToken: string;
|
||||
refreshToken?: string | null;
|
||||
accessExpiresAt?: Date | null;
|
||||
url?: string;
|
||||
teamId?: string;
|
||||
accountId?: string;
|
||||
};
|
||||
|
||||
/**
|
||||
* Return [accessToken], [accessExpiresAt], and [refreshToken] for OAuth2
|
||||
* code-token exchange for integration named [integration]
|
||||
*/
|
||||
export const exchangeCode = async ({
|
||||
integration,
|
||||
code,
|
||||
url
|
||||
}: {
|
||||
integration: string;
|
||||
code: string;
|
||||
url?: string;
|
||||
}): Promise<TExchangeReturn> => {
|
||||
switch (integration) {
|
||||
case Integrations.GCP_SECRET_MANAGER:
|
||||
return exchangeCodeGCP({
|
||||
code
|
||||
});
|
||||
case Integrations.AZURE_KEY_VAULT:
|
||||
return exchangeCodeAzure({
|
||||
code
|
||||
});
|
||||
case Integrations.HEROKU:
|
||||
return exchangeCodeHeroku({
|
||||
code
|
||||
});
|
||||
case Integrations.VERCEL:
|
||||
return exchangeCodeVercel({
|
||||
code
|
||||
});
|
||||
case Integrations.NETLIFY:
|
||||
return exchangeCodeNetlify({
|
||||
code
|
||||
});
|
||||
case Integrations.GITHUB:
|
||||
return exchangeCodeGithub({
|
||||
code
|
||||
});
|
||||
case Integrations.GITLAB:
|
||||
return exchangeCodeGitlab({
|
||||
code,
|
||||
url
|
||||
});
|
||||
case Integrations.BITBUCKET:
|
||||
return exchangeCodeBitBucket({
|
||||
code
|
||||
});
|
||||
default:
|
||||
throw new BadRequestError({ message: "Unknown integration" });
|
||||
}
|
||||
};
|
||||
|
||||
type RefreshTokenAzureResponse = {
|
||||
token_type: string;
|
||||
scope: string;
|
||||
expires_in: number;
|
||||
ext_expires_in: 4871;
|
||||
access_token: string;
|
||||
refresh_token: string;
|
||||
};
|
||||
|
||||
type RefreshTokenHerokuResponse = {
|
||||
access_token: string;
|
||||
expires_in: number;
|
||||
refresh_token: string;
|
||||
token_type: string;
|
||||
user_id: string;
|
||||
};
|
||||
|
||||
type RefreshTokenGitLabResponse = {
|
||||
token_type: string;
|
||||
scope: string;
|
||||
expires_in: number;
|
||||
access_token: string;
|
||||
refresh_token: string;
|
||||
created_at: number;
|
||||
};
|
||||
|
||||
type RefreshTokenBitBucketResponse = {
|
||||
access_token: string;
|
||||
token_type: string;
|
||||
expires_in: number;
|
||||
refresh_token: string;
|
||||
scopes: string;
|
||||
state: string;
|
||||
};
|
||||
|
||||
type ServiceAccountAccessTokenGCPSecretManagerResponse = {
|
||||
access_token: string;
|
||||
expires_in: number;
|
||||
token_type: string;
|
||||
};
|
||||
|
||||
type RefreshTokenGCPSecretManagerResponse = {
|
||||
access_token: string;
|
||||
expires_in: number;
|
||||
scope: string;
|
||||
token_type: string;
|
||||
};
|
||||
|
||||
/**
|
||||
* Return new access token by exchanging refresh token [refreshToken] for the
|
||||
* Azure integration
|
||||
*/
|
||||
const exchangeRefreshAzure = async ({ refreshToken }: { refreshToken: string }) => {
|
||||
const accessExpiresAt = new Date();
|
||||
const appCfg = getConfig();
|
||||
if (!appCfg.CLIENT_ID_AZURE || !appCfg.CLIENT_SECRET_AZURE) {
|
||||
throw new BadRequestError({ message: "Missing client id and client secret" });
|
||||
}
|
||||
|
||||
const { data }: { data: RefreshTokenAzureResponse } = await request.post(
|
||||
IntegrationUrls.AZURE_TOKEN_URL,
|
||||
new URLSearchParams({
|
||||
client_id: appCfg.CLIENT_ID_AZURE,
|
||||
scope: "openid offline_access",
|
||||
refresh_token: refreshToken,
|
||||
grant_type: "refresh_token",
|
||||
client_secret: appCfg.CLIENT_SECRET_AZURE
|
||||
})
|
||||
);
|
||||
|
||||
accessExpiresAt.setSeconds(accessExpiresAt.getSeconds() + data.expires_in);
|
||||
|
||||
return {
|
||||
accessToken: data.access_token,
|
||||
refreshToken: data.refresh_token,
|
||||
accessExpiresAt
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Return new access token by exchanging refresh token [refreshToken] for the
|
||||
* Heroku integration
|
||||
*/
|
||||
const exchangeRefreshHeroku = async ({ refreshToken }: { refreshToken: string }) => {
|
||||
const accessExpiresAt = new Date();
|
||||
const appCfg = getConfig();
|
||||
if (!appCfg.CLIENT_SECRET_HEROKU) {
|
||||
throw new BadRequestError({ message: "Missing client id and client secret" });
|
||||
}
|
||||
const {
|
||||
data
|
||||
}: {
|
||||
data: RefreshTokenHerokuResponse;
|
||||
} = await request.post(
|
||||
IntegrationUrls.HEROKU_TOKEN_URL,
|
||||
new URLSearchParams({
|
||||
grant_type: "refresh_token",
|
||||
refresh_token: refreshToken,
|
||||
client_secret: appCfg.CLIENT_SECRET_HEROKU
|
||||
})
|
||||
);
|
||||
|
||||
accessExpiresAt.setSeconds(accessExpiresAt.getSeconds() + data.expires_in);
|
||||
|
||||
return {
|
||||
accessToken: data.access_token,
|
||||
refreshToken: data.refresh_token,
|
||||
accessExpiresAt
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Return new access token by exchanging refresh token [refreshToken] for the
|
||||
* GitLab integration
|
||||
* @param {Object} obj
|
||||
* @param {String} obj.refreshToken - refresh token to use to get new access token for GitLab
|
||||
* @returns
|
||||
*/
|
||||
const exchangeRefreshGitLab = async ({
|
||||
refreshToken,
|
||||
url
|
||||
}: {
|
||||
url?: string | null;
|
||||
refreshToken: string;
|
||||
}) => {
|
||||
const accessExpiresAt = new Date();
|
||||
const appCfg = getConfig();
|
||||
if (!appCfg.CLIENT_ID_GITLAB || !appCfg.CLIENT_SECRET_GITLAB) {
|
||||
throw new BadRequestError({ message: "Missing client id and client secret" });
|
||||
}
|
||||
const {
|
||||
data
|
||||
}: {
|
||||
data: RefreshTokenGitLabResponse;
|
||||
} = await request.post(
|
||||
url ? `${url}/oauth/token` : IntegrationUrls.GITLAB_TOKEN_URL,
|
||||
new URLSearchParams({
|
||||
grant_type: "refresh_token",
|
||||
refresh_token: refreshToken,
|
||||
client_id: appCfg.CLIENT_ID_GITLAB,
|
||||
client_secret: appCfg.CLIENT_SECRET_GITLAB,
|
||||
redirect_uri: `${appCfg.SITE_URL}/integrations/gitlab/oauth2/callback`
|
||||
}),
|
||||
{
|
||||
headers: {
|
||||
"Accept-Encoding": "application/json"
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
accessExpiresAt.setSeconds(accessExpiresAt.getSeconds() + data.expires_in);
|
||||
|
||||
return {
|
||||
accessToken: data.access_token,
|
||||
refreshToken: data.refresh_token,
|
||||
accessExpiresAt
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Return new access token by exchanging refresh token [refreshToken] for the
|
||||
* BitBucket integration
|
||||
*/
|
||||
const exchangeRefreshBitBucket = async ({ refreshToken }: { refreshToken: string }) => {
|
||||
const accessExpiresAt = new Date();
|
||||
const appCfg = getConfig();
|
||||
if (!appCfg.CLIENT_SECRET_BITBUCKET || !appCfg.CLIENT_ID_BITBUCKET) {
|
||||
throw new BadRequestError({ message: "Missing client id and client secret" });
|
||||
}
|
||||
const {
|
||||
data
|
||||
}: {
|
||||
data: RefreshTokenBitBucketResponse;
|
||||
} = await request.post(
|
||||
IntegrationUrls.BITBUCKET_TOKEN_URL,
|
||||
new URLSearchParams({
|
||||
grant_type: "refresh_token",
|
||||
refresh_token: refreshToken,
|
||||
client_id: appCfg.CLIENT_ID_BITBUCKET,
|
||||
client_secret: appCfg.CLIENT_SECRET_BITBUCKET,
|
||||
redirect_uri: `${appCfg.SITE_URL}/integrations/bitbucket/oauth2/callback`
|
||||
} as any),
|
||||
{
|
||||
headers: {
|
||||
"Accept-Encoding": "application/json"
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
accessExpiresAt.setSeconds(accessExpiresAt.getSeconds() + data.expires_in);
|
||||
|
||||
return {
|
||||
accessToken: data.access_token,
|
||||
refreshToken: data.refresh_token,
|
||||
accessExpiresAt
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Return new access token by exchanging refresh token [refreshToken] for the
|
||||
* GCP Secret Manager integration
|
||||
*/
|
||||
const exchangeRefreshGCPSecretManager = async ({
|
||||
refreshToken,
|
||||
metadata = {}
|
||||
}: {
|
||||
metadata?: Record<string, string>;
|
||||
refreshToken: string;
|
||||
}) => {
|
||||
const accessExpiresAt = new Date();
|
||||
|
||||
if (metadata?.authMethod === "serviceAccount") {
|
||||
const serviceAccount = JSON.parse(refreshToken);
|
||||
|
||||
const payload = {
|
||||
iss: serviceAccount.client_email,
|
||||
aud: serviceAccount.token_uri,
|
||||
scope: IntegrationUrls.GCP_CLOUD_PLATFORM_SCOPE,
|
||||
iat: Math.floor(Date.now() / 1000),
|
||||
exp: Math.floor(Date.now() / 1000) + 3600
|
||||
};
|
||||
|
||||
const token = jwt.sign(payload, serviceAccount.private_key, { algorithm: "RS256" });
|
||||
|
||||
const { data }: { data: ServiceAccountAccessTokenGCPSecretManagerResponse } =
|
||||
await request.post(
|
||||
IntegrationUrls.GCP_TOKEN_URL,
|
||||
new URLSearchParams({
|
||||
grant_type: "urn:ietf:params:oauth:grant-type:jwt-bearer",
|
||||
assertion: token
|
||||
}).toString(),
|
||||
{
|
||||
headers: {
|
||||
"Content-Type": "application/x-www-form-urlencoded"
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
accessExpiresAt.setSeconds(accessExpiresAt.getSeconds() + data.expires_in);
|
||||
|
||||
return {
|
||||
accessToken: data.access_token,
|
||||
refreshToken,
|
||||
accessExpiresAt
|
||||
};
|
||||
}
|
||||
|
||||
const appCfg = getConfig();
|
||||
if (!appCfg.CLIENT_SECRET_GCP_SECRET_MANAGER || !appCfg.CLIENT_ID_GCP_SECRET_MANAGER) {
|
||||
throw new BadRequestError({ message: "Missing client id and client secret" });
|
||||
}
|
||||
const { data }: { data: RefreshTokenGCPSecretManagerResponse } = await request.post(
|
||||
IntegrationUrls.GCP_TOKEN_URL,
|
||||
new URLSearchParams({
|
||||
client_id: appCfg.CLIENT_ID_GCP_SECRET_MANAGER,
|
||||
client_secret: appCfg.CLIENT_SECRET_GCP_SECRET_MANAGER,
|
||||
refresh_token: refreshToken,
|
||||
grant_type: "refresh_token"
|
||||
} as any)
|
||||
);
|
||||
|
||||
accessExpiresAt.setSeconds(accessExpiresAt.getSeconds() + data.expires_in);
|
||||
|
||||
return {
|
||||
accessToken: data.access_token,
|
||||
refreshToken,
|
||||
accessExpiresAt
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Return new access token by exchanging refresh token [refreshToken] for integration
|
||||
*/
|
||||
export const exchangeRefresh = async (
|
||||
integration: string,
|
||||
refreshToken: string,
|
||||
url?: string | null,
|
||||
metadata?: Record<string, string>
|
||||
): Promise<{
|
||||
accessToken: string;
|
||||
refreshToken: string;
|
||||
accessExpiresAt: Date;
|
||||
}> => {
|
||||
switch (integration) {
|
||||
case Integrations.AZURE_KEY_VAULT:
|
||||
return exchangeRefreshAzure({
|
||||
refreshToken
|
||||
});
|
||||
case Integrations.HEROKU:
|
||||
return exchangeRefreshHeroku({
|
||||
refreshToken
|
||||
});
|
||||
case Integrations.GITLAB:
|
||||
return exchangeRefreshGitLab({
|
||||
refreshToken,
|
||||
url
|
||||
});
|
||||
case Integrations.BITBUCKET:
|
||||
return exchangeRefreshBitBucket({
|
||||
refreshToken
|
||||
});
|
||||
case Integrations.GCP_SECRET_MANAGER:
|
||||
return exchangeRefreshGCPSecretManager({
|
||||
refreshToken,
|
||||
metadata
|
||||
});
|
||||
default:
|
||||
throw new Error("Failed to exchange token for incompatible integration");
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user