mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-08 02:27:37 +00:00
Feat: Request access (new routes)
This commit is contained in:
@@ -0,0 +1,176 @@
|
|||||||
|
import slugify from "@sindresorhus/slugify";
|
||||||
|
import { z } from "zod";
|
||||||
|
|
||||||
|
import { AccessApprovalRequestsReviewersSchema, AccessApprovalRequestsSchema } from "@app/db/schemas";
|
||||||
|
import { ApprovalStatus } from "@app/ee/services/access-approval-request/access-approval-request-types";
|
||||||
|
import { alphaNumericNanoId } from "@app/lib/nanoid";
|
||||||
|
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||||
|
import { AuthMode } from "@app/services/auth/auth-type";
|
||||||
|
|
||||||
|
export const registerAccessApprovalRequestRouter = async (server: FastifyZodProvider) => {
|
||||||
|
server.route({
|
||||||
|
url: "/",
|
||||||
|
method: "POST",
|
||||||
|
schema: {
|
||||||
|
body: z.object({
|
||||||
|
slug: z
|
||||||
|
.string()
|
||||||
|
.min(1)
|
||||||
|
.max(60)
|
||||||
|
.trim()
|
||||||
|
.default(`requested-privilege-${slugify(alphaNumericNanoId(12))}`)
|
||||||
|
.refine((v) => v.toLowerCase() === v, "Slug must be lowercase")
|
||||||
|
.refine((v) => slugify(v) === v, {
|
||||||
|
message: "Slug must be a valid slug"
|
||||||
|
}),
|
||||||
|
permissions: z.any().array(),
|
||||||
|
isTemporary: z.boolean(),
|
||||||
|
temporaryRange: z.string().optional()
|
||||||
|
}),
|
||||||
|
querystring: z.object({
|
||||||
|
projectSlug: z.string().trim(),
|
||||||
|
secretPath: z.string().trim(),
|
||||||
|
envSlug: z.string().trim()
|
||||||
|
}),
|
||||||
|
response: {
|
||||||
|
200: z.object({
|
||||||
|
approval: AccessApprovalRequestsSchema
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onRequest: verifyAuth([AuthMode.JWT]),
|
||||||
|
handler: async (req) => {
|
||||||
|
const { request } = await server.services.accessApprovalRequest.createAccessApprovalRequest({
|
||||||
|
actor: req.permission.type,
|
||||||
|
actorId: req.permission.id,
|
||||||
|
actorAuthMethod: req.permission.authMethod,
|
||||||
|
permissions: req.body.permissions,
|
||||||
|
envSlug: req.query.envSlug,
|
||||||
|
actorOrgId: req.permission.orgId,
|
||||||
|
secretPath: req.query.secretPath,
|
||||||
|
projectSlug: req.query.projectSlug,
|
||||||
|
temporaryRange: req.body.temporaryRange,
|
||||||
|
isTemporary: req.body.isTemporary
|
||||||
|
});
|
||||||
|
return { approval: request };
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
server.route({
|
||||||
|
url: "/count",
|
||||||
|
method: "GET",
|
||||||
|
schema: {
|
||||||
|
querystring: z.object({
|
||||||
|
projectSlug: z.string().trim()
|
||||||
|
}),
|
||||||
|
response: {
|
||||||
|
200: z.object({
|
||||||
|
pendingCount: z.number(),
|
||||||
|
finalizedCount: z.number()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onRequest: verifyAuth([AuthMode.JWT]),
|
||||||
|
handler: async (req) => {
|
||||||
|
const { count } = await server.services.accessApprovalRequest.getCount({
|
||||||
|
projectSlug: req.query.projectSlug,
|
||||||
|
actor: req.permission.type,
|
||||||
|
actorId: req.permission.id,
|
||||||
|
actorOrgId: req.permission.orgId,
|
||||||
|
actorAuthMethod: req.permission.authMethod
|
||||||
|
});
|
||||||
|
|
||||||
|
return { ...count };
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
server.route({
|
||||||
|
url: "/",
|
||||||
|
method: "GET",
|
||||||
|
schema: {
|
||||||
|
querystring: z.object({
|
||||||
|
projectSlug: z.string().trim(),
|
||||||
|
authorProjectMembershipId: z.string().trim().optional(),
|
||||||
|
envSlug: z.string().trim().optional()
|
||||||
|
}),
|
||||||
|
response: {
|
||||||
|
200: z.object({
|
||||||
|
requests: AccessApprovalRequestsSchema.extend({
|
||||||
|
environmentName: z.string(),
|
||||||
|
isApproved: z.boolean(),
|
||||||
|
privilege: z
|
||||||
|
.object({
|
||||||
|
membershipId: z.string(),
|
||||||
|
isTemporary: z.boolean(),
|
||||||
|
temporaryMode: z.string().nullish(),
|
||||||
|
temporaryRange: z.string().nullish(),
|
||||||
|
temporaryAccessStartTime: z.date().nullish(),
|
||||||
|
temporaryAccessEndTime: z.date().nullish(),
|
||||||
|
permissions: z.unknown()
|
||||||
|
})
|
||||||
|
.nullable(),
|
||||||
|
policy: z.object({
|
||||||
|
id: z.string(),
|
||||||
|
name: z.string(),
|
||||||
|
approvals: z.number(),
|
||||||
|
approvers: z.string().array(),
|
||||||
|
secretPath: z.string().nullish(),
|
||||||
|
envId: z.string()
|
||||||
|
}),
|
||||||
|
reviewers: z
|
||||||
|
.object({
|
||||||
|
member: z.string(),
|
||||||
|
status: z.string()
|
||||||
|
})
|
||||||
|
.array()
|
||||||
|
}).array()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onRequest: verifyAuth([AuthMode.JWT]),
|
||||||
|
handler: async (req) => {
|
||||||
|
const { requests } = await server.services.accessApprovalRequest.listApprovalRequests({
|
||||||
|
projectSlug: req.query.projectSlug,
|
||||||
|
authorProjectMembershipId: req.query.authorProjectMembershipId,
|
||||||
|
envSlug: req.query.envSlug,
|
||||||
|
actor: req.permission.type,
|
||||||
|
actorId: req.permission.id,
|
||||||
|
actorOrgId: req.permission.orgId,
|
||||||
|
actorAuthMethod: req.permission.authMethod
|
||||||
|
});
|
||||||
|
|
||||||
|
return { requests };
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
server.route({
|
||||||
|
url: "/:requestId/review",
|
||||||
|
method: "POST",
|
||||||
|
schema: {
|
||||||
|
params: z.object({
|
||||||
|
requestId: z.string().trim()
|
||||||
|
}),
|
||||||
|
body: z.object({
|
||||||
|
status: z.enum([ApprovalStatus.APPROVED, ApprovalStatus.REJECTED])
|
||||||
|
}),
|
||||||
|
response: {
|
||||||
|
200: z.object({
|
||||||
|
review: AccessApprovalRequestsReviewersSchema
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onRequest: verifyAuth([AuthMode.JWT]),
|
||||||
|
handler: async (req) => {
|
||||||
|
const review = await server.services.accessApprovalRequest.reviewAccessRequest({
|
||||||
|
actor: req.permission.type,
|
||||||
|
actorId: req.permission.id,
|
||||||
|
actorOrgId: req.permission.orgId,
|
||||||
|
actorAuthMethod: req.permission.authMethod,
|
||||||
|
requestId: req.params.requestId,
|
||||||
|
status: req.body.status
|
||||||
|
});
|
||||||
|
|
||||||
|
return { review };
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
import { registerAuditLogStreamRouter } from "./audit-log-stream-router";
|
import { registerAuditLogStreamRouter } from "./audit-log-stream-router";
|
||||||
import { registerAccessApprovalPolicyRouter } from "./access-approval-policy-router";
|
import { registerAccessApprovalPolicyRouter } from "./access-approval-policy-router";
|
||||||
|
import { registerAccessApprovalRequestRouter } from "./access-approval-request-router";
|
||||||
import { registerDynamicSecretLeaseRouter } from "./dynamic-secret-lease-router";
|
import { registerDynamicSecretLeaseRouter } from "./dynamic-secret-lease-router";
|
||||||
import { registerDynamicSecretRouter } from "./dynamic-secret-router";
|
import { registerDynamicSecretRouter } from "./dynamic-secret-router";
|
||||||
import { registerGroupRouter } from "./group-router";
|
import { registerGroupRouter } from "./group-router";
|
||||||
@@ -43,6 +44,7 @@ export const registerV1EERoutes = async (server: FastifyZodProvider) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
await server.register(registerAccessApprovalPolicyRouter, { prefix: "/access-approvals" });
|
await server.register(registerAccessApprovalPolicyRouter, { prefix: "/access-approvals" });
|
||||||
|
await server.register(registerAccessApprovalRequestRouter, { prefix: "/access-approval-requests" });
|
||||||
|
|
||||||
await server.register(
|
await server.register(
|
||||||
async (dynamicSecretRouter) => {
|
async (dynamicSecretRouter) => {
|
||||||
|
|||||||
Reference in New Issue
Block a user