feat(infisical-pg): completed integration, integration auth and project bot api migration

This commit is contained in:
Akhil Mohan
2024-01-27 12:38:23 +05:30
parent 010963a80c
commit 771bec6d6d
36 changed files with 5245 additions and 9 deletions
+28 -1
View File
@@ -13,6 +13,10 @@ import { authPaswordServiceFactory } from "@app/services/auth/auth-password-serv
import { authSignupServiceFactory } from "@app/services/auth/auth-signup-service";
import { tokenDalFactory } from "@app/services/auth-token/auth-token-dal";
import { tokenServiceFactory } from "@app/services/auth-token/auth-token-service";
import { integrationDalFactory } from "@app/services/integration/integration-dal";
import { integrationServiceFactory } from "@app/services/integration/integration-service";
import { integrationAuthDalFactory } from "@app/services/integration-auth/integration-auth-dal";
import { integrationAuthServiceFactory } from "@app/services/integration-auth/integration-auth-service";
import { incidentContactDalFactory } from "@app/services/org/incident-contacts-dal";
import { orgDalFactory } from "@app/services/org/org-dal";
import { orgRoleDalFactory } from "@app/services/org/org-role-dal";
@@ -20,6 +24,8 @@ import { orgRoleServiceFactory } from "@app/services/org/org-role-service";
import { orgServiceFactory } from "@app/services/org/org-service";
import { projectDalFactory } from "@app/services/project/project-dal";
import { projectServiceFactory } from "@app/services/project/project-service";
import { projectBotDalFactory } from "@app/services/project-bot/project-bot-dal";
import { projectBotServiceFactory } from "@app/services/project-bot/project-bot-service";
import { projectEnvDalFactory } from "@app/services/project-env/project-env-dal";
import { projectEnvServiceFactory } from "@app/services/project-env/project-env-service";
import { projectKeyDalFactory } from "@app/services/project-key/project-key-dal";
@@ -67,6 +73,7 @@ export const registerRoutes = async (
const projectRoleDal = projectRoleDalFactory(db);
const projectEnvDal = projectEnvDalFactory(db);
const projectKeyDal = projectKeyDalFactory(db);
const projectBotDal = projectBotDalFactory(db);
const secretDal = secretDalFactory(db);
const folderDal = secretFolderDalFactory(db);
@@ -74,6 +81,9 @@ export const registerRoutes = async (
const secretVersionDal = secretVersionDalFactory(db);
const secretBlindIndexDal = secretBlindIndexDalFactory(db);
const integrationDal = integrationDalFactory(db);
const integrationAuthDal = integrationAuthDalFactory(db);
// ee db layer ops
const permissionDal = permissionDalFactory(db);
@@ -159,6 +169,20 @@ export const registerRoutes = async (
permissionService,
secretImportDal
});
const projectBotService = projectBotServiceFactory({ permissionService, projectBotDal });
const integrationService = integrationServiceFactory({
permissionService,
folderDal,
integrationDal,
integrationAuthDal
});
const integrationAuthService = integrationAuthServiceFactory({
integrationAuthDal,
integrationDal,
permissionService,
projectBotDal,
projectBotService
});
await superAdminService.initServerCfg();
// inject all services
@@ -180,7 +204,10 @@ export const registerRoutes = async (
projectRole: projectRoleService,
secret: secretService,
folder: folderService,
secretImport: secretImportService
secretImport: secretImportService,
projectBot: projectBotService,
integration: integrationService,
integrationAuth: integrationAuthService
});
server.decorate<FastifyZodProvider["store"]>("store", {
@@ -0,0 +1,80 @@
import { z } from "zod";
import { ProjectBotsSchema } from "@app/db/schemas";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
import { AuthMode } from "@app/services/auth/auth-type";
export const registerProjectBotRouter = async (server: FastifyZodProvider) => {
server.route({
url: "/:projectId",
method: "GET",
schema: {
params: z.object({
workspaceId: z.string().trim()
}),
response: {
200: z.object({
bot: ProjectBotsSchema.pick({
name: true,
projectId: true,
isActive: true,
publicKey: true,
createdAt: true,
updatedAt: true
})
})
}
},
onRequest: verifyAuth([AuthMode.JWT]),
handler: async (req) => {
const bot = await server.services.projectBot.findBotByProjectId({
actor: req.permission.type,
actorId: req.permission.id,
projectId: req.params.workspaceId
});
return { bot };
}
});
server.route({
url: "/:botId/active",
method: "PATCH",
schema: {
body: z.object({
isActive: z.boolean(),
botKey: z
.object({
nonce: z.string().trim().optional(),
encryptedKey: z.string().trim().optional()
})
.optional()
}),
params: z.object({
botId: z.string().trim()
}),
response: {
200: z.object({
bot: ProjectBotsSchema.pick({
name: true,
projectId: true,
isActive: true,
publicKey: true,
createdAt: true,
updatedAt: true
})
})
}
},
onRequest: verifyAuth([AuthMode.JWT]),
handler: async (req) => {
const bot = await server.services.projectBot.setBotActiveState({
actor: req.permission.type,
actorId: req.permission.id,
botId: req.params.botId,
botKey: req.body.botKey,
isActive: req.body.isActive
});
return { bot };
}
});
};
+7
View File
@@ -1,5 +1,8 @@
import { registerAdminRouter } from "./admin-router";
import { registerAuthRoutes } from "./auth-router";
import { registerProjectBotRouter } from "./bot-router";
import { registerIntegrationAuthRouter } from "./integration-auth-router";
import { registerIntegrationRouter } from "./integration-router";
import { registerInviteOrgRouter } from "./invite-org-router";
import { registerOrgRouter } from "./organization-router";
import { registerPasswordRouter } from "./password-router";
@@ -34,4 +37,8 @@ export const registerV1Routes = async (server: FastifyZodProvider) => {
},
{ prefix: "/workspace" }
);
await server.register(registerProjectBotRouter, { prefix: "/bot" });
await server.register(registerIntegrationRouter, { prefix: "/integration" });
await server.register(registerIntegrationAuthRouter, { prefix: "/integration-auth" });
};
@@ -0,0 +1,565 @@
import { z } from "zod";
import { IntegrationAuthsSchema } from "@app/db/schemas";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
import { AuthMode } from "@app/services/auth/auth-type";
export const registerIntegrationAuthRouter = async (server: FastifyZodProvider) => {
server.route({
url: "/integration-options",
method: "GET",
onRequest: verifyAuth([AuthMode.JWT]),
schema: {
response: {
200: z.object({
integrationOptions: z
.object({
name: z.string(),
slug: z.string(),
image: z.string(),
isAvailable: z.boolean().optional(),
type: z.string(),
clientId: z.string().optional(),
docsLink: z.string().optional()
})
.array()
})
}
},
handler: async () => {
const integrationOptions = await server.services.integrationAuth.getIntegrationOptions();
return { integrationOptions };
}
});
const integrationPublicSchema = IntegrationAuthsSchema.pick({
projectId: true,
integration: true,
teamId: true,
url: true,
namespace: true,
accountId: true,
metadata: true,
createdAt: true,
updatedAt: true
});
server.route({
url: "/:integrationAuthId",
method: "GET",
onRequest: verifyAuth([AuthMode.JWT]),
schema: {
params: z.object({
integrationAuthId: z.string().trim()
}),
response: {
200: z.object({
integrationAuth: integrationPublicSchema
})
}
},
handler: async (req) => {
const integrationAuth = await server.services.integrationAuth.getIntegrationAuth({
actorId: req.permission.id,
actor: req.permission.type,
id: req.params.integrationAuthId
});
return { integrationAuth };
}
});
server.route({
url: "/:integrationAuthId",
method: "DELETE",
onRequest: verifyAuth([AuthMode.JWT]),
schema: {
params: z.object({
integrationAuthId: z.string().trim()
}),
response: {
200: z.object({
integrationAuth: integrationPublicSchema
})
}
},
handler: async (req) => {
const integrationAuth = await server.services.integrationAuth.deleteIntegrationAuth({
actorId: req.permission.id,
actor: req.permission.type,
id: req.params.integrationAuthId
});
return { integrationAuth };
}
});
server.route({
url: "/oauth-token",
method: "POST",
onRequest: verifyAuth([AuthMode.JWT]),
schema: {
body: z.object({
workspaceId: z.string().trim(),
integration: z.string().trim(),
accessId: z.string().trim().optional(),
accessToken: z.string().trim().optional(),
url: z.string().url().trim().optional(),
namespace: z.string().trim().optional(),
refreshToken: z.string().trim().optional()
}),
response: {
200: z.object({
integrationAuth: integrationPublicSchema
})
}
},
handler: async (req) => {
const integrationAuth = await server.services.integrationAuth.saveIntegrationToken({
actorId: req.permission.id,
actor: req.permission.type,
projectId: req.body.workspaceId,
...req.body
});
return { integrationAuth };
}
});
server.route({
url: "/:integrationAuthId/apps",
method: "GET",
onRequest: verifyAuth([AuthMode.JWT]),
schema: {
params: z.object({
integrationAuthId: z.string().trim()
}),
querystring: z.object({
teamId: z.string().trim().optional(),
workspaceSlug: z.string().trim().optional()
}),
response: {
200: z.object({
apps: z
.object({
name: z.string(),
appId: z.string().optional(),
owner: z.string().optional()
})
.array()
})
}
},
handler: async (req) => {
const apps = await server.services.integrationAuth.getIntegrationApps({
actorId: req.permission.id,
actor: req.permission.type,
id: req.params.integrationAuthId,
...req.query
});
return { apps };
}
});
server.route({
url: "/:integrationAuthId/teams",
method: "GET",
onRequest: verifyAuth([AuthMode.JWT]),
schema: {
params: z.object({
integrationAuthId: z.string().trim()
}),
response: {
200: z.object({
teams: z
.object({
name: z.string(),
id: z.string().optional()
})
.array()
})
}
},
handler: async (req) => {
const teams = await server.services.integrationAuth.getIntegrationAuthTeams({
actorId: req.permission.id,
actor: req.permission.type,
id: req.params.integrationAuthId
});
return { teams };
}
});
server.route({
url: "/:integrationAuthId/vercel/branches",
method: "GET",
onRequest: verifyAuth([AuthMode.JWT]),
schema: {
params: z.object({
integrationAuthId: z.string().trim()
}),
querystring: z.object({
appId: z.string().trim()
}),
response: {
200: z.object({
branches: z.string().array()
})
}
},
handler: async (req) => {
const branches = await server.services.integrationAuth.getVercelBranches({
actorId: req.permission.id,
actor: req.permission.type,
id: req.params.integrationAuthId,
appId: req.query.appId
});
return { branches };
}
});
server.route({
url: "/:integrationAuthId/checkly/groups",
method: "GET",
onRequest: verifyAuth([AuthMode.JWT]),
schema: {
params: z.object({
integrationAuthId: z.string().trim()
}),
querystring: z.object({
accountId: z.string().trim()
}),
response: {
200: z.object({
groups: z.object({ name: z.string(), groupId: z.number() }).array()
})
}
},
handler: async (req) => {
const groups = await server.services.integrationAuth.getChecklyGroups({
actorId: req.permission.id,
actor: req.permission.type,
id: req.params.integrationAuthId,
accountId: req.query.accountId
});
return { groups };
}
});
server.route({
url: "/:integrationAuthId/qovery/orgs",
method: "GET",
onRequest: verifyAuth([AuthMode.JWT]),
schema: {
params: z.object({
integrationAuthId: z.string().trim()
}),
response: {
200: z.object({
orgs: z.object({ name: z.string(), orgId: z.string() }).array()
})
}
},
handler: async (req) => {
const orgs = await server.services.integrationAuth.getQoveryOrgs({
actorId: req.permission.id,
actor: req.permission.type,
id: req.params.integrationAuthId
});
return { orgs };
}
});
server.route({
url: "/:integrationAuthId/qovery/projects",
method: "GET",
onRequest: verifyAuth([AuthMode.JWT]),
schema: {
params: z.object({
integrationAuthId: z.string().trim()
}),
querystring: z.object({
orgId: z.string().trim()
}),
response: {
200: z.object({
projects: z.object({ name: z.string(), projectId: z.string() }).array()
})
}
},
handler: async (req) => {
const projects = await server.services.integrationAuth.getQoveryProjects({
actorId: req.permission.id,
actor: req.permission.type,
id: req.params.integrationAuthId,
orgId: req.query.orgId
});
return { projects };
}
});
server.route({
url: "/:integrationAuthId/qovery/environments",
method: "GET",
onRequest: verifyAuth([AuthMode.JWT]),
schema: {
params: z.object({
integrationAuthId: z.string().trim()
}),
querystring: z.object({
projectId: z.string().trim()
}),
response: {
200: z.object({
environments: z.object({ name: z.string(), environmentId: z.string() }).array()
})
}
},
handler: async (req) => {
const environments = await server.services.integrationAuth.getQoveryEnvs({
actorId: req.permission.id,
actor: req.permission.type,
id: req.params.integrationAuthId,
projectId: req.query.projectId
});
return { environments };
}
});
server.route({
url: "/:integrationAuthId/qovery/apps",
method: "GET",
onRequest: verifyAuth([AuthMode.JWT]),
schema: {
params: z.object({
integrationAuthId: z.string().trim()
}),
querystring: z.object({
environmentId: z.string().trim()
}),
response: {
200: z.object({
apps: z.object({ name: z.string(), appId: z.string() }).array()
})
}
},
handler: async (req) => {
const apps = await server.services.integrationAuth.getQoveryApps({
actorId: req.permission.id,
actor: req.permission.type,
id: req.params.integrationAuthId,
environmentId: req.query.environmentId
});
return { apps };
}
});
server.route({
url: "/:integrationAuthId/qovery/containers",
method: "GET",
onRequest: verifyAuth([AuthMode.JWT]),
schema: {
params: z.object({
integrationAuthId: z.string().trim()
}),
querystring: z.object({
environmentId: z.string().trim()
}),
response: {
200: z.object({
containers: z.object({ name: z.string(), appId: z.string() }).array()
})
}
},
handler: async (req) => {
const containers = await server.services.integrationAuth.getQoveryContainers({
actorId: req.permission.id,
actor: req.permission.type,
id: req.params.integrationAuthId,
environmentId: req.query.environmentId
});
return { containers };
}
});
server.route({
url: "/:integrationAuthId/qovery/jobs",
method: "GET",
onRequest: verifyAuth([AuthMode.JWT]),
schema: {
params: z.object({
integrationAuthId: z.string().trim()
}),
querystring: z.object({
environmentId: z.string().trim()
}),
response: {
200: z.object({
jobs: z.object({ name: z.string(), appId: z.string() }).array()
})
}
},
handler: async (req) => {
const jobs = await server.services.integrationAuth.getQoveryJobs({
actorId: req.permission.id,
actor: req.permission.type,
id: req.params.integrationAuthId,
environmentId: req.query.environmentId
});
return { jobs };
}
});
server.route({
url: "/:integrationAuthId/railway/environments",
method: "GET",
onRequest: verifyAuth([AuthMode.JWT]),
schema: {
params: z.object({
integrationAuthId: z.string().trim()
}),
querystring: z.object({
appId: z.string().trim()
}),
response: {
200: z.object({
environments: z.object({ name: z.string(), environmentId: z.string() }).array()
})
}
},
handler: async (req) => {
const environments = await server.services.integrationAuth.getRailwayEnvironments({
actorId: req.permission.id,
actor: req.permission.type,
id: req.params.integrationAuthId,
appId: req.query.appId
});
return { environments };
}
});
server.route({
url: "/:integrationAuthId/railway/services",
method: "GET",
onRequest: verifyAuth([AuthMode.JWT]),
schema: {
params: z.object({
integrationAuthId: z.string().trim()
}),
querystring: z.object({
appId: z.string().trim()
}),
response: {
200: z.object({
services: z.object({ name: z.string(), serviceId: z.string() }).array()
})
}
},
handler: async (req) => {
const services = await server.services.integrationAuth.getRailwayServices({
actorId: req.permission.id,
actor: req.permission.type,
id: req.params.integrationAuthId,
appId: req.query.appId
});
return { services };
}
});
server.route({
url: "/:integrationAuthId/bitbucket/workspaces",
method: "GET",
onRequest: verifyAuth([AuthMode.JWT]),
schema: {
params: z.object({
integrationAuthId: z.string().trim()
}),
response: {
200: z.object({
workspaces: z
.object({
name: z.string(),
slug: z.string(),
uuid: z.string(),
type: z.string(),
is_private: z.boolean(),
created_on: z.string(),
updated_on: z.string()
})
.array()
})
}
},
handler: async (req) => {
const workspaces = await server.services.integrationAuth.getBitbucketWorkspaces({
actorId: req.permission.id,
actor: req.permission.type,
id: req.params.integrationAuthId
});
return { workspaces };
}
});
server.route({
url: "/:integrationAuthId/northflank/secret-groups",
method: "GET",
onRequest: verifyAuth([AuthMode.JWT]),
schema: {
params: z.object({
integrationAuthId: z.string().trim()
}),
querystring: z.object({
appId: z.string().trim()
}),
response: {
200: z.object({
secretGroups: z
.object({
name: z.string(),
groupId: z.string()
})
.array()
})
}
},
handler: async (req) => {
const secretGroups = await server.services.integrationAuth.getNorthFlankSecretGroups({
actorId: req.permission.id,
actor: req.permission.type,
id: req.params.integrationAuthId,
appId: req.query.appId
});
return { secretGroups };
}
});
server.route({
url: "/:integrationAuthId/teamcity/build-configs",
method: "GET",
onRequest: verifyAuth([AuthMode.JWT]),
schema: {
params: z.object({
integrationAuthId: z.string().trim()
}),
querystring: z.object({
appId: z.string().trim()
}),
response: {
200: z.object({
buildConfigs: z
.object({
name: z.string(),
buildConfigId: z.string()
})
.array()
})
}
},
handler: async (req) => {
const buildConfigs = await server.services.integrationAuth.getTeamcityBuildConfigs({
actorId: req.permission.id,
actor: req.permission.type,
id: req.params.integrationAuthId,
appId: req.query.appId
});
return { buildConfigs };
}
});
};
@@ -0,0 +1,116 @@
import { z } from "zod";
import { IntegrationsSchema } from "@app/db/schemas";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
import { AuthMode } from "@app/services/auth/auth-type";
export const registerIntegrationRouter = async (server: FastifyZodProvider) => {
server.route({
url: "/",
method: "POST",
schema: {
body: z.object({
integrationAuthId: z.string().trim(),
app: z.string().trim().optional(),
isActive: z.boolean(),
appId: z.string().trim().optional(),
secretPath: z.string().trim().default("/"),
sourceEnvironment: z.string().trim(),
targetEnvironment: z.string().trim().optional(),
targetEnvironmentId: z.string().trim().optional(),
targetService: z.string().trim().optional(),
targetServiceId: z.string().trim().optional(),
owner: z.string().trim().optional(),
path: z.string().trim().optional(),
region: z.string().trim().optional(),
scope: z.string().trim().optional(),
metadata: z
.object({
secretPrefix: z.string().optional(),
secretSuffix: z.string().optional(),
secretGCPLabel: z
.object({
labelName: z.string(),
labelValue: z.string()
})
.optional()
})
.optional()
}),
response: {
200: z.object({
integration: IntegrationsSchema
})
}
},
onRequest: verifyAuth([AuthMode.JWT]),
handler: async (req) => {
const integration = await server.services.integration.createIntegration({
actorId: req.permission.id,
actor: req.permission.type,
...req.body
});
return { integration };
}
});
server.route({
url: "/:integrationId",
method: "PATCH",
schema: {
params: z.object({
integrationId: z.string().trim()
}),
body: z.object({
app: z.string().trim(),
appId: z.string().trim(),
isActive: z.boolean(),
secretPath: z.string().trim().default("/"),
targetEnvironment: z.string().trim(),
owner: z.string().trim(),
environment: z.string().trim()
}),
response: {
200: z.object({
integration: IntegrationsSchema
})
}
},
onRequest: verifyAuth([AuthMode.JWT]),
handler: async (req) => {
const integration = await server.services.integration.updateIntegration({
actorId: req.permission.id,
actor: req.permission.type,
id: req.params.integrationId,
...req.body
});
return { integration };
}
});
server.route({
url: "/:integrationId",
method: "DELETE",
schema: {
params: z.object({
integrationId: z.string().trim()
}),
response: {
200: z.object({
integration: IntegrationsSchema
})
}
},
onRequest: verifyAuth([AuthMode.JWT]),
handler: async (req) => {
const integration = await server.services.integration.deleteIntegration({
actorId: req.permission.id,
actor: req.permission.type,
id: req.params.integrationId
});
return { integration };
}
});
// TODO(akhilmhdh-pg): manual sync
};