mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-09-22 13:39:35 +00:00
734 lines
22 KiB
TypeScript
734 lines
22 KiB
TypeScript
import { z } from "zod";
|
|
|
|
import {
|
|
CertificateAuthoritiesSchema,
|
|
CertificatesSchema,
|
|
PkiAlertsSchema,
|
|
PkiCollectionsSchema,
|
|
ProjectKeysSchema,
|
|
ProjectType
|
|
} from "@app/db/schemas";
|
|
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
|
|
import { InfisicalProjectTemplate } from "@app/ee/services/project-template/project-template-types";
|
|
import { sanitizedSshCa } from "@app/ee/services/ssh/ssh-certificate-authority-schema";
|
|
import { sanitizedSshCertificate } from "@app/ee/services/ssh-certificate/ssh-certificate-schema";
|
|
import { sanitizedSshCertificateTemplate } from "@app/ee/services/ssh-certificate-template/ssh-certificate-template-schema";
|
|
import { loginMappingSchema, sanitizedSshHost } from "@app/ee/services/ssh-host/ssh-host-schema";
|
|
import { LoginMappingSource } from "@app/ee/services/ssh-host/ssh-host-types";
|
|
import { sanitizedSshHostGroup } from "@app/ee/services/ssh-host-group/ssh-host-group-schema";
|
|
import { ApiDocsTags, PROJECTS } from "@app/lib/api-docs";
|
|
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
|
import { slugSchema } from "@app/server/lib/schemas";
|
|
import { getTelemetryDistinctId } from "@app/server/lib/telemetry";
|
|
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
|
import { AuthMode } from "@app/services/auth/auth-type";
|
|
import { CaStatus } from "@app/services/certificate-authority/certificate-authority-types";
|
|
import { sanitizedCertificateTemplate } from "@app/services/certificate-template/certificate-template-schema";
|
|
import { sanitizedPkiSubscriber } from "@app/services/pki-subscriber/pki-subscriber-schema";
|
|
import { ProjectFilterType } from "@app/services/project/project-types";
|
|
import { PostHogEventTypes } from "@app/services/telemetry/telemetry-types";
|
|
|
|
import { SanitizedProjectSchema } from "../sanitizedSchemas";
|
|
|
|
const projectWithEnv = SanitizedProjectSchema.extend({
|
|
_id: z.string(),
|
|
environments: z.object({ name: z.string(), slug: z.string(), id: z.string() }).array(),
|
|
kmsSecretManagerKeyId: z.string().nullable().optional()
|
|
});
|
|
|
|
export const registerProjectRouter = async (server: FastifyZodProvider) => {
|
|
/* Get project key */
|
|
server.route({
|
|
method: "GET",
|
|
url: "/:workspaceId/encrypted-key",
|
|
config: {
|
|
rateLimit: readLimit
|
|
},
|
|
schema: {
|
|
description: "Return encrypted project key",
|
|
params: z.object({
|
|
workspaceId: z.string().trim().describe(PROJECTS.GET_KEY.workspaceId)
|
|
}),
|
|
response: {
|
|
200: ProjectKeysSchema.merge(
|
|
z.object({
|
|
sender: z.object({
|
|
publicKey: z.string()
|
|
})
|
|
})
|
|
)
|
|
}
|
|
},
|
|
onResponse: verifyAuth([AuthMode.JWT, AuthMode.API_KEY]),
|
|
handler: async (req) => {
|
|
const key = await server.services.projectKey.getLatestProjectKey({
|
|
actor: req.permission.type,
|
|
actorId: req.permission.id,
|
|
actorAuthMethod: req.permission.authMethod,
|
|
actorOrgId: req.permission.orgId,
|
|
projectId: req.params.workspaceId
|
|
});
|
|
|
|
await server.services.auditLog.createAuditLog({
|
|
...req.auditLogInfo,
|
|
projectId: req.params.workspaceId,
|
|
event: {
|
|
type: EventType.GET_WORKSPACE_KEY,
|
|
metadata: {
|
|
keyId: key?.id as string
|
|
}
|
|
}
|
|
});
|
|
|
|
return key;
|
|
}
|
|
});
|
|
|
|
/* Start upgrade of a project */
|
|
server.route({
|
|
method: "POST",
|
|
url: "/:projectId/upgrade",
|
|
config: {
|
|
rateLimit: writeLimit
|
|
},
|
|
schema: {
|
|
params: z.object({
|
|
projectId: z.string().trim()
|
|
}),
|
|
body: z.object({
|
|
userPrivateKey: z.string().trim()
|
|
}),
|
|
response: {
|
|
200: z.void()
|
|
}
|
|
},
|
|
onRequest: verifyAuth([AuthMode.JWT]),
|
|
handler: async (req) => {
|
|
await server.services.project.upgradeProject({
|
|
actorId: req.permission.id,
|
|
actorOrgId: req.permission.orgId,
|
|
actor: req.permission.type,
|
|
actorAuthMethod: req.permission.authMethod,
|
|
projectId: req.params.projectId,
|
|
userPrivateKey: req.body.userPrivateKey
|
|
});
|
|
}
|
|
});
|
|
|
|
/* Get upgrade status of project */
|
|
server.route({
|
|
url: "/:projectId/upgrade/status",
|
|
method: "GET",
|
|
config: {
|
|
rateLimit: readLimit
|
|
},
|
|
schema: {
|
|
params: z.object({
|
|
projectId: z.string().trim()
|
|
}),
|
|
response: {
|
|
200: z.object({
|
|
status: z.string().nullable()
|
|
})
|
|
}
|
|
},
|
|
onRequest: verifyAuth([AuthMode.JWT]),
|
|
handler: async (req) => {
|
|
const status = await server.services.project.getProjectUpgradeStatus({
|
|
actorAuthMethod: req.permission.authMethod,
|
|
actorOrgId: req.permission.orgId,
|
|
projectId: req.params.projectId,
|
|
actor: req.permission.type,
|
|
actorId: req.permission.id
|
|
});
|
|
|
|
return { status };
|
|
}
|
|
});
|
|
|
|
/* Create new project */
|
|
server.route({
|
|
method: "POST",
|
|
url: "/",
|
|
config: {
|
|
rateLimit: writeLimit
|
|
},
|
|
schema: {
|
|
hide: false,
|
|
tags: [ApiDocsTags.Projects],
|
|
description: "Create a new project",
|
|
security: [
|
|
{
|
|
bearerAuth: []
|
|
}
|
|
],
|
|
body: z.object({
|
|
projectName: z.string().trim().describe(PROJECTS.CREATE.projectName),
|
|
projectDescription: z.string().trim().optional().describe(PROJECTS.CREATE.projectDescription),
|
|
slug: slugSchema({ min: 5, max: 36 }).optional().describe(PROJECTS.CREATE.slug),
|
|
kmsKeyId: z.string().optional(),
|
|
template: slugSchema({ field: "Template Name", max: 64 })
|
|
.optional()
|
|
.default(InfisicalProjectTemplate.Default)
|
|
.describe(PROJECTS.CREATE.template),
|
|
type: z.nativeEnum(ProjectType).default(ProjectType.SecretManager),
|
|
shouldCreateDefaultEnvs: z.boolean().optional().default(true)
|
|
}),
|
|
response: {
|
|
200: z.object({
|
|
project: projectWithEnv
|
|
})
|
|
}
|
|
},
|
|
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
|
handler: async (req) => {
|
|
const project = await server.services.project.createProject({
|
|
actorId: req.permission.id,
|
|
actor: req.permission.type,
|
|
actorOrgId: req.permission.orgId,
|
|
actorAuthMethod: req.permission.authMethod,
|
|
workspaceName: req.body.projectName,
|
|
workspaceDescription: req.body.projectDescription,
|
|
slug: req.body.slug,
|
|
kmsKeyId: req.body.kmsKeyId,
|
|
template: req.body.template,
|
|
type: req.body.type,
|
|
createDefaultEnvs: req.body.shouldCreateDefaultEnvs
|
|
});
|
|
|
|
await server.services.telemetry.sendPostHogEvents({
|
|
event: PostHogEventTypes.ProjectCreated,
|
|
distinctId: getTelemetryDistinctId(req),
|
|
properties: {
|
|
orgId: project.orgId,
|
|
name: project.name,
|
|
...req.auditLogInfo
|
|
}
|
|
});
|
|
|
|
if (req.body.template) {
|
|
await server.services.auditLog.createAuditLog({
|
|
...req.auditLogInfo,
|
|
orgId: req.permission.orgId,
|
|
event: {
|
|
type: EventType.APPLY_PROJECT_TEMPLATE,
|
|
metadata: {
|
|
template: req.body.template,
|
|
projectId: project.id
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
return { project };
|
|
}
|
|
});
|
|
|
|
/* Delete a project by slug */
|
|
server.route({
|
|
method: "DELETE",
|
|
url: "/:slug",
|
|
config: {
|
|
rateLimit: writeLimit
|
|
},
|
|
schema: {
|
|
hide: false,
|
|
tags: [ApiDocsTags.Projects],
|
|
description: "Delete project",
|
|
security: [
|
|
{
|
|
bearerAuth: []
|
|
}
|
|
],
|
|
params: z.object({
|
|
slug: slugSchema({ min: 5, max: 36 }).describe("The slug of the project to delete.")
|
|
}),
|
|
response: {
|
|
200: SanitizedProjectSchema
|
|
}
|
|
},
|
|
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
|
|
|
handler: async (req) => {
|
|
const project = await server.services.project.deleteProject({
|
|
filter: {
|
|
type: ProjectFilterType.SLUG,
|
|
slug: req.params.slug,
|
|
orgId: req.permission.orgId
|
|
},
|
|
actorId: req.permission.id,
|
|
actorAuthMethod: req.permission.authMethod,
|
|
actorOrgId: req.permission.orgId,
|
|
actor: req.permission.type
|
|
});
|
|
|
|
return project;
|
|
}
|
|
});
|
|
|
|
/* Get a project by slug */
|
|
server.route({
|
|
method: "GET",
|
|
url: "/:slug",
|
|
config: {
|
|
rateLimit: readLimit
|
|
},
|
|
schema: {
|
|
params: z.object({
|
|
slug: slugSchema({ max: 36 }).describe("The slug of the project to get.")
|
|
}),
|
|
response: {
|
|
200: projectWithEnv
|
|
}
|
|
},
|
|
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
|
handler: async (req) => {
|
|
const project = await server.services.project.getAProject({
|
|
filter: {
|
|
slug: req.params.slug,
|
|
orgId: req.permission.orgId,
|
|
type: ProjectFilterType.SLUG
|
|
},
|
|
actorId: req.permission.id,
|
|
actorOrgId: req.permission.orgId,
|
|
actorAuthMethod: req.permission.authMethod,
|
|
actor: req.permission.type
|
|
});
|
|
|
|
return project;
|
|
}
|
|
});
|
|
|
|
/* Update a project by slug */
|
|
server.route({
|
|
method: "PATCH",
|
|
url: "/:slug",
|
|
config: {
|
|
rateLimit: writeLimit
|
|
},
|
|
schema: {
|
|
params: z.object({
|
|
slug: slugSchema({ min: 5, max: 36 }).describe("The slug of the project to update.")
|
|
}),
|
|
body: z.object({
|
|
name: z.string().trim().optional().describe(PROJECTS.UPDATE.name),
|
|
description: z.string().trim().optional().describe(PROJECTS.UPDATE.projectDescription),
|
|
autoCapitalization: z.boolean().optional().describe(PROJECTS.UPDATE.autoCapitalization),
|
|
hasDeleteProtection: z.boolean().optional().describe(PROJECTS.UPDATE.hasDeleteProtection)
|
|
}),
|
|
response: {
|
|
200: SanitizedProjectSchema
|
|
}
|
|
},
|
|
|
|
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
|
handler: async (req) => {
|
|
const project = await server.services.project.updateProject({
|
|
filter: {
|
|
type: ProjectFilterType.SLUG,
|
|
slug: req.params.slug,
|
|
orgId: req.permission.orgId
|
|
},
|
|
update: {
|
|
name: req.body.name,
|
|
description: req.body.description,
|
|
autoCapitalization: req.body.autoCapitalization,
|
|
hasDeleteProtection: req.body.hasDeleteProtection
|
|
},
|
|
actorId: req.permission.id,
|
|
actorAuthMethod: req.permission.authMethod,
|
|
actor: req.permission.type,
|
|
actorOrgId: req.permission.orgId
|
|
});
|
|
|
|
return project;
|
|
}
|
|
});
|
|
|
|
server.route({
|
|
method: "GET",
|
|
url: "/:slug/cas",
|
|
config: {
|
|
rateLimit: readLimit
|
|
},
|
|
schema: {
|
|
hide: false,
|
|
tags: [ApiDocsTags.PkiCertificateAuthorities],
|
|
params: z.object({
|
|
slug: slugSchema({ min: 5, max: 36 }).describe(PROJECTS.LIST_CAS.slug)
|
|
}),
|
|
querystring: z.object({
|
|
status: z.enum([CaStatus.ACTIVE, CaStatus.PENDING_CERTIFICATE]).optional().describe(PROJECTS.LIST_CAS.status),
|
|
friendlyName: z.string().optional().describe(PROJECTS.LIST_CAS.friendlyName),
|
|
commonName: z.string().optional().describe(PROJECTS.LIST_CAS.commonName),
|
|
offset: z.coerce.number().min(0).max(100).default(0).describe(PROJECTS.LIST_CAS.offset),
|
|
limit: z.coerce.number().min(1).max(100).default(25).describe(PROJECTS.LIST_CAS.limit)
|
|
}),
|
|
response: {
|
|
200: z.object({
|
|
cas: z.array(CertificateAuthoritiesSchema)
|
|
})
|
|
}
|
|
},
|
|
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
|
handler: async (req) => {
|
|
const cas = await server.services.project.listProjectCas({
|
|
filter: {
|
|
slug: req.params.slug,
|
|
orgId: req.permission.orgId,
|
|
type: ProjectFilterType.SLUG
|
|
},
|
|
actorId: req.permission.id,
|
|
actorOrgId: req.permission.orgId,
|
|
actorAuthMethod: req.permission.authMethod,
|
|
actor: req.permission.type,
|
|
...req.query
|
|
});
|
|
return { cas };
|
|
}
|
|
});
|
|
|
|
server.route({
|
|
method: "GET",
|
|
url: "/:slug/certificates",
|
|
config: {
|
|
rateLimit: readLimit
|
|
},
|
|
schema: {
|
|
hide: false,
|
|
tags: [ApiDocsTags.PkiCertificates],
|
|
params: z.object({
|
|
slug: slugSchema({ min: 5, max: 36 }).describe(PROJECTS.LIST_CERTIFICATES.slug)
|
|
}),
|
|
querystring: z.object({
|
|
friendlyName: z.string().optional().describe(PROJECTS.LIST_CERTIFICATES.friendlyName),
|
|
commonName: z.string().optional().describe(PROJECTS.LIST_CERTIFICATES.commonName),
|
|
offset: z.coerce.number().min(0).max(100).default(0).describe(PROJECTS.LIST_CERTIFICATES.offset),
|
|
limit: z.coerce.number().min(1).max(100).default(25).describe(PROJECTS.LIST_CERTIFICATES.limit)
|
|
}),
|
|
response: {
|
|
200: z.object({
|
|
certificates: z.array(CertificatesSchema),
|
|
totalCount: z.number()
|
|
})
|
|
}
|
|
},
|
|
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
|
handler: async (req) => {
|
|
const { certificates, totalCount } = await server.services.project.listProjectCertificates({
|
|
filter: {
|
|
slug: req.params.slug,
|
|
orgId: req.permission.orgId,
|
|
type: ProjectFilterType.SLUG
|
|
},
|
|
actorId: req.permission.id,
|
|
actorOrgId: req.permission.orgId,
|
|
actorAuthMethod: req.permission.authMethod,
|
|
actor: req.permission.type,
|
|
...req.query
|
|
});
|
|
return { certificates, totalCount };
|
|
}
|
|
});
|
|
|
|
server.route({
|
|
method: "GET",
|
|
url: "/:projectId/pki-alerts",
|
|
config: {
|
|
rateLimit: readLimit
|
|
},
|
|
schema: {
|
|
params: z.object({
|
|
projectId: z.string().trim()
|
|
}),
|
|
response: {
|
|
200: z.object({
|
|
alerts: z.array(PkiAlertsSchema)
|
|
})
|
|
}
|
|
},
|
|
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
|
handler: async (req) => {
|
|
const { alerts } = await server.services.project.listProjectAlerts({
|
|
projectId: req.params.projectId,
|
|
actorId: req.permission.id,
|
|
actorOrgId: req.permission.orgId,
|
|
actorAuthMethod: req.permission.authMethod,
|
|
actor: req.permission.type
|
|
});
|
|
|
|
return { alerts };
|
|
}
|
|
});
|
|
|
|
server.route({
|
|
method: "GET",
|
|
url: "/:projectId/pki-collections",
|
|
config: {
|
|
rateLimit: readLimit
|
|
},
|
|
schema: {
|
|
params: z.object({
|
|
projectId: z.string().trim()
|
|
}),
|
|
response: {
|
|
200: z.object({
|
|
collections: z.array(PkiCollectionsSchema)
|
|
})
|
|
}
|
|
},
|
|
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
|
handler: async (req) => {
|
|
const { pkiCollections } = await server.services.project.listProjectPkiCollections({
|
|
projectId: req.params.projectId,
|
|
actorId: req.permission.id,
|
|
actorOrgId: req.permission.orgId,
|
|
actorAuthMethod: req.permission.authMethod,
|
|
actor: req.permission.type
|
|
});
|
|
|
|
return { collections: pkiCollections };
|
|
}
|
|
});
|
|
|
|
server.route({
|
|
method: "GET",
|
|
url: "/:projectId/pki-subscribers",
|
|
config: {
|
|
rateLimit: readLimit
|
|
},
|
|
schema: {
|
|
hide: false,
|
|
tags: [ApiDocsTags.PkiSubscribers],
|
|
params: z.object({
|
|
projectId: z.string().trim().describe(PROJECTS.LIST_PKI_SUBSCRIBERS.projectId)
|
|
}),
|
|
response: {
|
|
200: z.object({
|
|
subscribers: z.array(sanitizedPkiSubscriber)
|
|
})
|
|
}
|
|
},
|
|
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
|
handler: async (req) => {
|
|
const subscribers = await server.services.project.listProjectPkiSubscribers({
|
|
actorId: req.permission.id,
|
|
actorOrgId: req.permission.orgId,
|
|
actorAuthMethod: req.permission.authMethod,
|
|
actor: req.permission.type,
|
|
projectId: req.params.projectId
|
|
});
|
|
|
|
return { subscribers };
|
|
}
|
|
});
|
|
|
|
server.route({
|
|
method: "GET",
|
|
url: "/:projectId/certificate-templates",
|
|
config: {
|
|
rateLimit: readLimit
|
|
},
|
|
schema: {
|
|
params: z.object({
|
|
projectId: z.string().trim()
|
|
}),
|
|
response: {
|
|
200: z.object({
|
|
certificateTemplates: sanitizedCertificateTemplate.array()
|
|
})
|
|
}
|
|
},
|
|
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
|
handler: async (req) => {
|
|
const { certificateTemplates } = await server.services.project.listProjectCertificateTemplates({
|
|
projectId: req.params.projectId,
|
|
actorId: req.permission.id,
|
|
actorOrgId: req.permission.orgId,
|
|
actorAuthMethod: req.permission.authMethod,
|
|
actor: req.permission.type
|
|
});
|
|
|
|
return { certificateTemplates };
|
|
}
|
|
});
|
|
|
|
server.route({
|
|
method: "GET",
|
|
url: "/:projectId/ssh-certificates",
|
|
config: {
|
|
rateLimit: readLimit
|
|
},
|
|
schema: {
|
|
params: z.object({
|
|
projectId: z.string().trim().describe(PROJECTS.LIST_SSH_CAS.projectId)
|
|
}),
|
|
querystring: z.object({
|
|
offset: z.coerce.number().default(0).describe(PROJECTS.LIST_SSH_CERTIFICATES.offset),
|
|
limit: z.coerce.number().default(25).describe(PROJECTS.LIST_SSH_CERTIFICATES.limit)
|
|
}),
|
|
response: {
|
|
200: z.object({
|
|
certificates: z.array(sanitizedSshCertificate),
|
|
totalCount: z.number()
|
|
})
|
|
}
|
|
},
|
|
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
|
handler: async (req) => {
|
|
const { certificates, totalCount } = await server.services.project.listProjectSshCertificates({
|
|
actorId: req.permission.id,
|
|
actorOrgId: req.permission.orgId,
|
|
actorAuthMethod: req.permission.authMethod,
|
|
actor: req.permission.type,
|
|
projectId: req.params.projectId,
|
|
offset: req.query.offset,
|
|
limit: req.query.limit
|
|
});
|
|
|
|
return { certificates, totalCount };
|
|
}
|
|
});
|
|
|
|
server.route({
|
|
method: "GET",
|
|
url: "/:projectId/ssh-certificate-templates",
|
|
config: {
|
|
rateLimit: readLimit
|
|
},
|
|
schema: {
|
|
hide: false,
|
|
tags: [ApiDocsTags.SshCertificateTemplates],
|
|
params: z.object({
|
|
projectId: z.string().trim().describe(PROJECTS.LIST_SSH_CERTIFICATE_TEMPLATES.projectId)
|
|
}),
|
|
response: {
|
|
200: z.object({
|
|
certificateTemplates: z.array(sanitizedSshCertificateTemplate)
|
|
})
|
|
}
|
|
},
|
|
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
|
handler: async (req) => {
|
|
const { certificateTemplates } = await server.services.project.listProjectSshCertificateTemplates({
|
|
actorId: req.permission.id,
|
|
actorOrgId: req.permission.orgId,
|
|
actorAuthMethod: req.permission.authMethod,
|
|
actor: req.permission.type,
|
|
projectId: req.params.projectId
|
|
});
|
|
|
|
return { certificateTemplates };
|
|
}
|
|
});
|
|
|
|
server.route({
|
|
method: "GET",
|
|
url: "/:projectId/ssh-cas",
|
|
config: {
|
|
rateLimit: readLimit
|
|
},
|
|
schema: {
|
|
hide: false,
|
|
tags: [ApiDocsTags.SshCertificateAuthorities],
|
|
params: z.object({
|
|
projectId: z.string().trim().describe(PROJECTS.LIST_SSH_CAS.projectId)
|
|
}),
|
|
response: {
|
|
200: z.object({
|
|
cas: z.array(sanitizedSshCa)
|
|
})
|
|
}
|
|
},
|
|
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
|
handler: async (req) => {
|
|
const cas = await server.services.project.listProjectSshCas({
|
|
actorId: req.permission.id,
|
|
actorOrgId: req.permission.orgId,
|
|
actorAuthMethod: req.permission.authMethod,
|
|
actor: req.permission.type,
|
|
projectId: req.params.projectId
|
|
});
|
|
|
|
return { cas };
|
|
}
|
|
});
|
|
|
|
server.route({
|
|
method: "GET",
|
|
url: "/:projectId/ssh-hosts",
|
|
config: {
|
|
rateLimit: readLimit
|
|
},
|
|
schema: {
|
|
hide: false,
|
|
tags: [ApiDocsTags.SshHosts],
|
|
params: z.object({
|
|
projectId: z.string().trim().describe(PROJECTS.LIST_SSH_HOSTS.projectId)
|
|
}),
|
|
response: {
|
|
200: z.object({
|
|
hosts: z.array(
|
|
sanitizedSshHost.extend({
|
|
loginMappings: loginMappingSchema
|
|
.extend({
|
|
source: z.nativeEnum(LoginMappingSource)
|
|
})
|
|
.array()
|
|
})
|
|
)
|
|
})
|
|
}
|
|
},
|
|
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
|
handler: async (req) => {
|
|
const hosts = await server.services.project.listProjectSshHosts({
|
|
actorId: req.permission.id,
|
|
actorOrgId: req.permission.orgId,
|
|
actorAuthMethod: req.permission.authMethod,
|
|
actor: req.permission.type,
|
|
projectId: req.params.projectId
|
|
});
|
|
|
|
return { hosts };
|
|
}
|
|
});
|
|
|
|
server.route({
|
|
method: "GET",
|
|
url: "/:projectId/ssh-host-groups",
|
|
config: {
|
|
rateLimit: readLimit
|
|
},
|
|
schema: {
|
|
hide: false,
|
|
tags: [ApiDocsTags.SshHostGroups],
|
|
params: z.object({
|
|
projectId: z.string().trim().describe(PROJECTS.LIST_SSH_HOST_GROUPS.projectId)
|
|
}),
|
|
response: {
|
|
200: z.object({
|
|
groups: z.array(
|
|
sanitizedSshHostGroup.extend({
|
|
loginMappings: loginMappingSchema.array(),
|
|
hostCount: z.number()
|
|
})
|
|
)
|
|
})
|
|
}
|
|
},
|
|
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
|
handler: async (req) => {
|
|
const groups = await server.services.project.listProjectSshHostGroups({
|
|
actorId: req.permission.id,
|
|
actorOrgId: req.permission.orgId,
|
|
actorAuthMethod: req.permission.authMethod,
|
|
actor: req.permission.type,
|
|
projectId: req.params.projectId
|
|
});
|
|
|
|
return { groups };
|
|
}
|
|
});
|
|
};
|