mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-06 20:27:12 +00:00
feat: added v1 projects project-role-router
This commit is contained in:
@@ -0,0 +1,287 @@
|
|||||||
|
import { packRules } from "@casl/ability/extra";
|
||||||
|
import { z } from "zod";
|
||||||
|
|
||||||
|
import { ProjectMembershipRole, ProjectRolesSchema } from "@app/db/schemas";
|
||||||
|
import {
|
||||||
|
backfillPermissionV1SchemaToV2Schema,
|
||||||
|
ProjectPermissionV1Schema
|
||||||
|
} from "@app/ee/services/permission/project-permission";
|
||||||
|
import { PROJECT_ROLE } from "@app/lib/api-docs";
|
||||||
|
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
||||||
|
import { slugSchema } from "@app/server/lib/schemas";
|
||||||
|
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||||
|
import { SanitizedRoleSchemaV1 } from "@app/server/routes/sanitizedSchemas";
|
||||||
|
import { AuthMode } from "@app/services/auth/auth-type";
|
||||||
|
import { ProjectRoleServiceIdentifierType } from "@app/services/project-role/project-role-types";
|
||||||
|
|
||||||
|
export const registerDepreciatedProjectRoleRouter = async (server: FastifyZodProvider) => {
|
||||||
|
server.route({
|
||||||
|
method: "POST",
|
||||||
|
url: "/:projectSlug/roles",
|
||||||
|
config: {
|
||||||
|
rateLimit: writeLimit
|
||||||
|
},
|
||||||
|
schema: {
|
||||||
|
description: "Create a project role",
|
||||||
|
security: [
|
||||||
|
{
|
||||||
|
bearerAuth: []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
params: z.object({
|
||||||
|
projectSlug: z.string().trim().describe(PROJECT_ROLE.CREATE.projectSlug)
|
||||||
|
}),
|
||||||
|
body: z.object({
|
||||||
|
slug: slugSchema({ max: 64 })
|
||||||
|
.refine(
|
||||||
|
(val) => !Object.values(ProjectMembershipRole).includes(val as ProjectMembershipRole),
|
||||||
|
"Please choose a different slug, the slug you have entered is reserved"
|
||||||
|
)
|
||||||
|
.describe(PROJECT_ROLE.CREATE.slug),
|
||||||
|
name: z.string().min(1).trim().describe(PROJECT_ROLE.CREATE.name),
|
||||||
|
description: z.string().trim().nullish().describe(PROJECT_ROLE.CREATE.description),
|
||||||
|
permissions: ProjectPermissionV1Schema.array().describe(PROJECT_ROLE.CREATE.permissions)
|
||||||
|
}),
|
||||||
|
response: {
|
||||||
|
200: z.object({
|
||||||
|
role: SanitizedRoleSchemaV1
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||||
|
handler: async (req) => {
|
||||||
|
const role = await server.services.projectRole.createRole({
|
||||||
|
actorAuthMethod: req.permission.authMethod,
|
||||||
|
actorId: req.permission.id,
|
||||||
|
actorOrgId: req.permission.orgId,
|
||||||
|
actor: req.permission.type,
|
||||||
|
filter: {
|
||||||
|
type: ProjectRoleServiceIdentifierType.SLUG,
|
||||||
|
projectSlug: req.params.projectSlug
|
||||||
|
},
|
||||||
|
data: {
|
||||||
|
...req.body,
|
||||||
|
permissions: JSON.stringify(packRules(backfillPermissionV1SchemaToV2Schema(req.body.permissions, true)))
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return { role };
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
server.route({
|
||||||
|
method: "PATCH",
|
||||||
|
url: "/:projectSlug/roles/:roleId",
|
||||||
|
config: {
|
||||||
|
rateLimit: writeLimit
|
||||||
|
},
|
||||||
|
schema: {
|
||||||
|
description: "Update a project role",
|
||||||
|
security: [
|
||||||
|
{
|
||||||
|
bearerAuth: []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
params: z.object({
|
||||||
|
projectSlug: z.string().trim().describe(PROJECT_ROLE.UPDATE.projectSlug),
|
||||||
|
roleId: z.string().trim().describe(PROJECT_ROLE.UPDATE.roleId)
|
||||||
|
}),
|
||||||
|
body: z.object({
|
||||||
|
slug: slugSchema({ max: 64 })
|
||||||
|
.refine(
|
||||||
|
(val) => !Object.values(ProjectMembershipRole).includes(val as ProjectMembershipRole),
|
||||||
|
"Please choose a different slug, the slug you have entered is reserved"
|
||||||
|
)
|
||||||
|
.describe(PROJECT_ROLE.UPDATE.slug)
|
||||||
|
.optional(),
|
||||||
|
name: z.string().trim().optional().describe(PROJECT_ROLE.UPDATE.name),
|
||||||
|
description: z.string().trim().nullish().describe(PROJECT_ROLE.UPDATE.description),
|
||||||
|
permissions: ProjectPermissionV1Schema.array().describe(PROJECT_ROLE.UPDATE.permissions).optional()
|
||||||
|
}),
|
||||||
|
response: {
|
||||||
|
200: z.object({
|
||||||
|
role: SanitizedRoleSchemaV1
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||||
|
handler: async (req) => {
|
||||||
|
const role = await server.services.projectRole.updateRole({
|
||||||
|
actorAuthMethod: req.permission.authMethod,
|
||||||
|
actorId: req.permission.id,
|
||||||
|
actorOrgId: req.permission.orgId,
|
||||||
|
actor: req.permission.type,
|
||||||
|
roleId: req.params.roleId,
|
||||||
|
data: {
|
||||||
|
...req.body,
|
||||||
|
permissions: req.body.permissions
|
||||||
|
? JSON.stringify(packRules(backfillPermissionV1SchemaToV2Schema(req.body.permissions, true)))
|
||||||
|
: undefined
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return { role };
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
server.route({
|
||||||
|
method: "DELETE",
|
||||||
|
url: "/:projectSlug/roles/:roleId",
|
||||||
|
config: {
|
||||||
|
rateLimit: writeLimit
|
||||||
|
},
|
||||||
|
schema: {
|
||||||
|
description: "Delete a project role",
|
||||||
|
security: [
|
||||||
|
{
|
||||||
|
bearerAuth: []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
params: z.object({
|
||||||
|
projectSlug: z.string().trim().describe(PROJECT_ROLE.DELETE.projectSlug),
|
||||||
|
roleId: z.string().trim().describe(PROJECT_ROLE.DELETE.roleId)
|
||||||
|
}),
|
||||||
|
response: {
|
||||||
|
200: z.object({
|
||||||
|
role: SanitizedRoleSchemaV1
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||||
|
handler: async (req) => {
|
||||||
|
const role = await server.services.projectRole.deleteRole({
|
||||||
|
actorAuthMethod: req.permission.authMethod,
|
||||||
|
actorId: req.permission.id,
|
||||||
|
actorOrgId: req.permission.orgId,
|
||||||
|
actor: req.permission.type,
|
||||||
|
roleId: req.params.roleId
|
||||||
|
});
|
||||||
|
return { role };
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
server.route({
|
||||||
|
method: "GET",
|
||||||
|
url: "/:projectSlug/roles",
|
||||||
|
config: {
|
||||||
|
rateLimit: readLimit
|
||||||
|
},
|
||||||
|
schema: {
|
||||||
|
description: "List project role",
|
||||||
|
security: [
|
||||||
|
{
|
||||||
|
bearerAuth: []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
params: z.object({
|
||||||
|
projectSlug: z.string().trim().describe(PROJECT_ROLE.LIST.projectSlug)
|
||||||
|
}),
|
||||||
|
response: {
|
||||||
|
200: z.object({
|
||||||
|
roles: ProjectRolesSchema.omit({ permissions: true, version: true }).array()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||||
|
handler: async (req) => {
|
||||||
|
const roles = await server.services.projectRole.listRoles({
|
||||||
|
actorAuthMethod: req.permission.authMethod,
|
||||||
|
actorId: req.permission.id,
|
||||||
|
actorOrgId: req.permission.orgId,
|
||||||
|
actor: req.permission.type,
|
||||||
|
filter: {
|
||||||
|
type: ProjectRoleServiceIdentifierType.SLUG,
|
||||||
|
projectSlug: req.params.projectSlug
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return { roles };
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
server.route({
|
||||||
|
method: "GET",
|
||||||
|
url: "/:projectSlug/roles/slug/:slug",
|
||||||
|
config: {
|
||||||
|
rateLimit: readLimit
|
||||||
|
},
|
||||||
|
schema: {
|
||||||
|
params: z.object({
|
||||||
|
projectSlug: z.string().trim().describe(PROJECT_ROLE.GET_ROLE_BY_SLUG.projectSlug),
|
||||||
|
slug: z.string().trim().describe(PROJECT_ROLE.GET_ROLE_BY_SLUG.roleSlug)
|
||||||
|
}),
|
||||||
|
response: {
|
||||||
|
200: z.object({
|
||||||
|
role: SanitizedRoleSchemaV1.omit({ version: true })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||||
|
handler: async (req) => {
|
||||||
|
const role = await server.services.projectRole.getRoleBySlug({
|
||||||
|
actorAuthMethod: req.permission.authMethod,
|
||||||
|
actorId: req.permission.id,
|
||||||
|
actorOrgId: req.permission.orgId,
|
||||||
|
actor: req.permission.type,
|
||||||
|
filter: {
|
||||||
|
type: ProjectRoleServiceIdentifierType.SLUG,
|
||||||
|
projectSlug: req.params.projectSlug
|
||||||
|
},
|
||||||
|
roleSlug: req.params.slug
|
||||||
|
});
|
||||||
|
|
||||||
|
return { role };
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
server.route({
|
||||||
|
method: "GET",
|
||||||
|
url: "/:projectId/permissions",
|
||||||
|
config: {
|
||||||
|
rateLimit: readLimit
|
||||||
|
},
|
||||||
|
schema: {
|
||||||
|
params: z.object({
|
||||||
|
projectId: z.string().trim()
|
||||||
|
}),
|
||||||
|
response: {
|
||||||
|
200: z.object({
|
||||||
|
data: z.object({
|
||||||
|
membership: z.object({
|
||||||
|
id: z.string(),
|
||||||
|
roles: z
|
||||||
|
.object({
|
||||||
|
role: z.string()
|
||||||
|
})
|
||||||
|
.array()
|
||||||
|
}),
|
||||||
|
assumedPrivilegeDetails: z
|
||||||
|
.object({
|
||||||
|
actorId: z.string(),
|
||||||
|
actorType: z.string(),
|
||||||
|
actorName: z.string(),
|
||||||
|
actorEmail: z.string().optional()
|
||||||
|
})
|
||||||
|
.optional(),
|
||||||
|
permissions: z.any().array()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onRequest: verifyAuth([AuthMode.JWT]),
|
||||||
|
handler: async (req) => {
|
||||||
|
const { permissions, membership, assumedPrivilegeDetails } = await server.services.projectRole.getUserPermission(
|
||||||
|
req.permission.id,
|
||||||
|
req.params.projectId,
|
||||||
|
req.permission.authMethod,
|
||||||
|
req.permission.orgId
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
data: {
|
||||||
|
permissions,
|
||||||
|
membership,
|
||||||
|
assumedPrivilegeDetails
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
@@ -22,6 +22,7 @@ import { registerOidcRouter } from "./oidc-router";
|
|||||||
import { registerOrgRoleRouter } from "./org-role-router";
|
import { registerOrgRoleRouter } from "./org-role-router";
|
||||||
import { registerPITRouter } from "./pit-router";
|
import { registerPITRouter } from "./pit-router";
|
||||||
import { registerProjectRoleRouter } from "./project-role-router";
|
import { registerProjectRoleRouter } from "./project-role-router";
|
||||||
|
import { registerDepreciatedProjectRoleRouter } from "./depreciated-project-role-router";
|
||||||
import { registerProjectRouter } from "./project-router";
|
import { registerProjectRouter } from "./project-router";
|
||||||
import { registerRateLimitRouter } from "./rate-limit-router";
|
import { registerRateLimitRouter } from "./rate-limit-router";
|
||||||
import { registerRelayRouter } from "./relay-router";
|
import { registerRelayRouter } from "./relay-router";
|
||||||
@@ -49,13 +50,21 @@ export const registerV1EERoutes = async (server: FastifyZodProvider) => {
|
|||||||
await server.register(registerLicenseRouter, { prefix: "/organizations" });
|
await server.register(registerLicenseRouter, { prefix: "/organizations" });
|
||||||
await server.register(
|
await server.register(
|
||||||
async (projectRouter) => {
|
async (projectRouter) => {
|
||||||
await projectRouter.register(registerProjectRoleRouter);
|
await projectRouter.register(registerDepreciatedProjectRoleRouter);
|
||||||
await projectRouter.register(registerProjectRouter);
|
await projectRouter.register(registerProjectRouter);
|
||||||
await projectRouter.register(registerTrustedIpRouter);
|
await projectRouter.register(registerTrustedIpRouter);
|
||||||
await projectRouter.register(registerAssumePrivilegeRouter);
|
await projectRouter.register(registerAssumePrivilegeRouter);
|
||||||
},
|
},
|
||||||
{ prefix: "/workspace" }
|
{ prefix: "/workspace" }
|
||||||
);
|
);
|
||||||
|
|
||||||
|
await server.register(
|
||||||
|
async (projectRouter) => {
|
||||||
|
await projectRouter.register(registerProjectRoleRouter);
|
||||||
|
},
|
||||||
|
{ prefix: "/projects" }
|
||||||
|
);
|
||||||
|
|
||||||
await server.register(registerSnapshotRouter, { prefix: "/secret-snapshot" });
|
await server.register(registerSnapshotRouter, { prefix: "/secret-snapshot" });
|
||||||
await server.register(registerPITRouter, { prefix: "/pit" });
|
await server.register(registerPITRouter, { prefix: "/pit" });
|
||||||
await server.register(registerSecretApprovalPolicyRouter, { prefix: "/secret-approvals" });
|
await server.register(registerSecretApprovalPolicyRouter, { prefix: "/secret-approvals" });
|
||||||
|
|||||||
@@ -2,26 +2,26 @@ import { packRules } from "@casl/ability/extra";
|
|||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
|
|
||||||
import { ProjectMembershipRole, ProjectRolesSchema } from "@app/db/schemas";
|
import { ProjectMembershipRole, ProjectRolesSchema } from "@app/db/schemas";
|
||||||
import {
|
import { checkForInvalidPermissionCombination } from "@app/ee/services/permission/permission-fns";
|
||||||
backfillPermissionV1SchemaToV2Schema,
|
import { ProjectPermissionV2Schema } from "@app/ee/services/permission/project-permission";
|
||||||
ProjectPermissionV1Schema
|
import { ApiDocsTags, PROJECT_ROLE } from "@app/lib/api-docs";
|
||||||
} from "@app/ee/services/permission/project-permission";
|
|
||||||
import { PROJECT_ROLE } from "@app/lib/api-docs";
|
|
||||||
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
||||||
import { slugSchema } from "@app/server/lib/schemas";
|
import { slugSchema } from "@app/server/lib/schemas";
|
||||||
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||||
import { SanitizedRoleSchemaV1 } from "@app/server/routes/sanitizedSchemas";
|
import { SanitizedRoleSchema } from "@app/server/routes/sanitizedSchemas";
|
||||||
import { AuthMode } from "@app/services/auth/auth-type";
|
import { AuthMode } from "@app/services/auth/auth-type";
|
||||||
import { ProjectRoleServiceIdentifierType } from "@app/services/project-role/project-role-types";
|
import { ProjectRoleServiceIdentifierType } from "@app/services/project-role/project-role-types";
|
||||||
|
|
||||||
export const registerProjectRoleRouter = async (server: FastifyZodProvider) => {
|
export const registerProjectRoleRouter = async (server: FastifyZodProvider) => {
|
||||||
server.route({
|
server.route({
|
||||||
method: "POST",
|
method: "POST",
|
||||||
url: "/:projectSlug/roles",
|
url: "/:projectId/roles",
|
||||||
config: {
|
config: {
|
||||||
rateLimit: writeLimit
|
rateLimit: writeLimit
|
||||||
},
|
},
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.ProjectRoles],
|
||||||
description: "Create a project role",
|
description: "Create a project role",
|
||||||
security: [
|
security: [
|
||||||
{
|
{
|
||||||
@@ -29,10 +29,10 @@ export const registerProjectRoleRouter = async (server: FastifyZodProvider) => {
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
params: z.object({
|
params: z.object({
|
||||||
projectSlug: z.string().trim().describe(PROJECT_ROLE.CREATE.projectSlug)
|
projectId: z.string().trim().describe(PROJECT_ROLE.CREATE.projectId)
|
||||||
}),
|
}),
|
||||||
body: z.object({
|
body: z.object({
|
||||||
slug: slugSchema({ max: 64 })
|
slug: slugSchema({ min: 1, max: 64 })
|
||||||
.refine(
|
.refine(
|
||||||
(val) => !Object.values(ProjectMembershipRole).includes(val as ProjectMembershipRole),
|
(val) => !Object.values(ProjectMembershipRole).includes(val as ProjectMembershipRole),
|
||||||
"Please choose a different slug, the slug you have entered is reserved"
|
"Please choose a different slug, the slug you have entered is reserved"
|
||||||
@@ -40,11 +40,13 @@ export const registerProjectRoleRouter = async (server: FastifyZodProvider) => {
|
|||||||
.describe(PROJECT_ROLE.CREATE.slug),
|
.describe(PROJECT_ROLE.CREATE.slug),
|
||||||
name: z.string().min(1).trim().describe(PROJECT_ROLE.CREATE.name),
|
name: z.string().min(1).trim().describe(PROJECT_ROLE.CREATE.name),
|
||||||
description: z.string().trim().nullish().describe(PROJECT_ROLE.CREATE.description),
|
description: z.string().trim().nullish().describe(PROJECT_ROLE.CREATE.description),
|
||||||
permissions: ProjectPermissionV1Schema.array().describe(PROJECT_ROLE.CREATE.permissions)
|
permissions: ProjectPermissionV2Schema.array()
|
||||||
|
.describe(PROJECT_ROLE.CREATE.permissions)
|
||||||
|
.refine(checkForInvalidPermissionCombination)
|
||||||
}),
|
}),
|
||||||
response: {
|
response: {
|
||||||
200: z.object({
|
200: z.object({
|
||||||
role: SanitizedRoleSchemaV1
|
role: SanitizedRoleSchema
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -56,26 +58,27 @@ export const registerProjectRoleRouter = async (server: FastifyZodProvider) => {
|
|||||||
actorOrgId: req.permission.orgId,
|
actorOrgId: req.permission.orgId,
|
||||||
actor: req.permission.type,
|
actor: req.permission.type,
|
||||||
filter: {
|
filter: {
|
||||||
type: ProjectRoleServiceIdentifierType.SLUG,
|
type: ProjectRoleServiceIdentifierType.ID,
|
||||||
projectSlug: req.params.projectSlug
|
projectId: req.params.projectId
|
||||||
},
|
},
|
||||||
data: {
|
data: {
|
||||||
...req.body,
|
...req.body,
|
||||||
permissions: JSON.stringify(packRules(backfillPermissionV1SchemaToV2Schema(req.body.permissions, true)))
|
permissions: JSON.stringify(packRules(req.body.permissions))
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return { role };
|
return { role };
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
server.route({
|
server.route({
|
||||||
method: "PATCH",
|
method: "PATCH",
|
||||||
url: "/:projectSlug/roles/:roleId",
|
url: "/:projectId/roles/:roleId",
|
||||||
config: {
|
config: {
|
||||||
rateLimit: writeLimit
|
rateLimit: writeLimit
|
||||||
},
|
},
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.ProjectRoles],
|
||||||
description: "Update a project role",
|
description: "Update a project role",
|
||||||
security: [
|
security: [
|
||||||
{
|
{
|
||||||
@@ -83,24 +86,27 @@ export const registerProjectRoleRouter = async (server: FastifyZodProvider) => {
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
params: z.object({
|
params: z.object({
|
||||||
projectSlug: z.string().trim().describe(PROJECT_ROLE.UPDATE.projectSlug),
|
projectId: z.string().trim().describe(PROJECT_ROLE.UPDATE.projectId),
|
||||||
roleId: z.string().trim().describe(PROJECT_ROLE.UPDATE.roleId)
|
roleId: z.string().trim().describe(PROJECT_ROLE.UPDATE.roleId)
|
||||||
}),
|
}),
|
||||||
body: z.object({
|
body: z.object({
|
||||||
slug: slugSchema({ max: 64 })
|
slug: slugSchema({ min: 1, max: 64 })
|
||||||
.refine(
|
.refine(
|
||||||
(val) => !Object.values(ProjectMembershipRole).includes(val as ProjectMembershipRole),
|
(val) => !Object.values(ProjectMembershipRole).includes(val as ProjectMembershipRole),
|
||||||
"Please choose a different slug, the slug you have entered is reserved"
|
"Please choose a different slug, the slug you have entered is reserved"
|
||||||
)
|
)
|
||||||
.describe(PROJECT_ROLE.UPDATE.slug)
|
.optional()
|
||||||
.optional(),
|
.describe(PROJECT_ROLE.UPDATE.slug),
|
||||||
name: z.string().trim().optional().describe(PROJECT_ROLE.UPDATE.name),
|
name: z.string().trim().optional().describe(PROJECT_ROLE.UPDATE.name),
|
||||||
description: z.string().trim().nullish().describe(PROJECT_ROLE.UPDATE.description),
|
description: z.string().trim().nullish().describe(PROJECT_ROLE.UPDATE.description),
|
||||||
permissions: ProjectPermissionV1Schema.array().describe(PROJECT_ROLE.UPDATE.permissions).optional()
|
permissions: ProjectPermissionV2Schema.array()
|
||||||
|
.describe(PROJECT_ROLE.UPDATE.permissions)
|
||||||
|
.optional()
|
||||||
|
.superRefine(checkForInvalidPermissionCombination)
|
||||||
}),
|
}),
|
||||||
response: {
|
response: {
|
||||||
200: z.object({
|
200: z.object({
|
||||||
role: SanitizedRoleSchemaV1
|
role: SanitizedRoleSchema
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -114,9 +120,7 @@ export const registerProjectRoleRouter = async (server: FastifyZodProvider) => {
|
|||||||
roleId: req.params.roleId,
|
roleId: req.params.roleId,
|
||||||
data: {
|
data: {
|
||||||
...req.body,
|
...req.body,
|
||||||
permissions: req.body.permissions
|
permissions: req.body.permissions ? JSON.stringify(packRules(req.body.permissions)) : undefined
|
||||||
? JSON.stringify(packRules(backfillPermissionV1SchemaToV2Schema(req.body.permissions, true)))
|
|
||||||
: undefined
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return { role };
|
return { role };
|
||||||
@@ -125,11 +129,13 @@ export const registerProjectRoleRouter = async (server: FastifyZodProvider) => {
|
|||||||
|
|
||||||
server.route({
|
server.route({
|
||||||
method: "DELETE",
|
method: "DELETE",
|
||||||
url: "/:projectSlug/roles/:roleId",
|
url: "/:projectId/roles/:roleId",
|
||||||
config: {
|
config: {
|
||||||
rateLimit: writeLimit
|
rateLimit: writeLimit
|
||||||
},
|
},
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.ProjectRoles],
|
||||||
description: "Delete a project role",
|
description: "Delete a project role",
|
||||||
security: [
|
security: [
|
||||||
{
|
{
|
||||||
@@ -137,12 +143,12 @@ export const registerProjectRoleRouter = async (server: FastifyZodProvider) => {
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
params: z.object({
|
params: z.object({
|
||||||
projectSlug: z.string().trim().describe(PROJECT_ROLE.DELETE.projectSlug),
|
projectId: z.string().trim().describe(PROJECT_ROLE.DELETE.projectId),
|
||||||
roleId: z.string().trim().describe(PROJECT_ROLE.DELETE.roleId)
|
roleId: z.string().trim().describe(PROJECT_ROLE.DELETE.roleId)
|
||||||
}),
|
}),
|
||||||
response: {
|
response: {
|
||||||
200: z.object({
|
200: z.object({
|
||||||
role: SanitizedRoleSchemaV1
|
role: SanitizedRoleSchema
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -161,11 +167,13 @@ export const registerProjectRoleRouter = async (server: FastifyZodProvider) => {
|
|||||||
|
|
||||||
server.route({
|
server.route({
|
||||||
method: "GET",
|
method: "GET",
|
||||||
url: "/:projectSlug/roles",
|
url: "/:projectId/roles",
|
||||||
config: {
|
config: {
|
||||||
rateLimit: readLimit
|
rateLimit: readLimit
|
||||||
},
|
},
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.ProjectRoles],
|
||||||
description: "List project role",
|
description: "List project role",
|
||||||
security: [
|
security: [
|
||||||
{
|
{
|
||||||
@@ -173,7 +181,7 @@ export const registerProjectRoleRouter = async (server: FastifyZodProvider) => {
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
params: z.object({
|
params: z.object({
|
||||||
projectSlug: z.string().trim().describe(PROJECT_ROLE.LIST.projectSlug)
|
projectId: z.string().trim().describe(PROJECT_ROLE.LIST.projectId)
|
||||||
}),
|
}),
|
||||||
response: {
|
response: {
|
||||||
200: z.object({
|
200: z.object({
|
||||||
@@ -189,8 +197,8 @@ export const registerProjectRoleRouter = async (server: FastifyZodProvider) => {
|
|||||||
actorOrgId: req.permission.orgId,
|
actorOrgId: req.permission.orgId,
|
||||||
actor: req.permission.type,
|
actor: req.permission.type,
|
||||||
filter: {
|
filter: {
|
||||||
type: ProjectRoleServiceIdentifierType.SLUG,
|
type: ProjectRoleServiceIdentifierType.ID,
|
||||||
projectSlug: req.params.projectSlug
|
projectId: req.params.projectId
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return { roles };
|
return { roles };
|
||||||
@@ -199,18 +207,20 @@ export const registerProjectRoleRouter = async (server: FastifyZodProvider) => {
|
|||||||
|
|
||||||
server.route({
|
server.route({
|
||||||
method: "GET",
|
method: "GET",
|
||||||
url: "/:projectSlug/roles/slug/:slug",
|
url: "/:projectId/roles/slug/:roleSlug",
|
||||||
config: {
|
config: {
|
||||||
rateLimit: readLimit
|
rateLimit: readLimit
|
||||||
},
|
},
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.ProjectRoles],
|
||||||
params: z.object({
|
params: z.object({
|
||||||
projectSlug: z.string().trim().describe(PROJECT_ROLE.GET_ROLE_BY_SLUG.projectSlug),
|
projectId: z.string().trim().describe(PROJECT_ROLE.GET_ROLE_BY_SLUG.projectId),
|
||||||
slug: z.string().trim().describe(PROJECT_ROLE.GET_ROLE_BY_SLUG.roleSlug)
|
roleSlug: z.string().trim().describe(PROJECT_ROLE.GET_ROLE_BY_SLUG.roleSlug)
|
||||||
}),
|
}),
|
||||||
response: {
|
response: {
|
||||||
200: z.object({
|
200: z.object({
|
||||||
role: SanitizedRoleSchemaV1.omit({ version: true })
|
role: SanitizedRoleSchema.omit({ version: true })
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -222,12 +232,11 @@ export const registerProjectRoleRouter = async (server: FastifyZodProvider) => {
|
|||||||
actorOrgId: req.permission.orgId,
|
actorOrgId: req.permission.orgId,
|
||||||
actor: req.permission.type,
|
actor: req.permission.type,
|
||||||
filter: {
|
filter: {
|
||||||
type: ProjectRoleServiceIdentifierType.SLUG,
|
type: ProjectRoleServiceIdentifierType.ID,
|
||||||
projectSlug: req.params.projectSlug
|
projectId: req.params.projectId
|
||||||
},
|
},
|
||||||
roleSlug: req.params.slug
|
roleSlug: req.params.roleSlug
|
||||||
});
|
});
|
||||||
|
|
||||||
return { role };
|
return { role };
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ export const useCreateProjectRole = () => {
|
|||||||
mutationFn: async ({ projectId, ...dto }: TCreateProjectRoleDTO) => {
|
mutationFn: async ({ projectId, ...dto }: TCreateProjectRoleDTO) => {
|
||||||
const {
|
const {
|
||||||
data: { role }
|
data: { role }
|
||||||
} = await apiRequest.post(`/api/v2/workspace/${projectId}/roles`, dto);
|
} = await apiRequest.post(`/api/v1/projects/${projectId}/roles`, dto);
|
||||||
return role;
|
return role;
|
||||||
},
|
},
|
||||||
onSuccess: (_, { projectId }) => {
|
onSuccess: (_, { projectId }) => {
|
||||||
@@ -38,7 +38,7 @@ export const useUpdateProjectRole = () => {
|
|||||||
mutationFn: async ({ id, projectId, ...dto }: TUpdateProjectRoleDTO) => {
|
mutationFn: async ({ id, projectId, ...dto }: TUpdateProjectRoleDTO) => {
|
||||||
const {
|
const {
|
||||||
data: { role }
|
data: { role }
|
||||||
} = await apiRequest.patch(`/api/v2/workspace/${projectId}/roles/${id}`, dto);
|
} = await apiRequest.patch(`/api/v1/projects/${projectId}/roles/${id}`, dto);
|
||||||
return role;
|
return role;
|
||||||
},
|
},
|
||||||
onSuccess: (_, { projectId, slug }) => {
|
onSuccess: (_, { projectId, slug }) => {
|
||||||
@@ -58,7 +58,7 @@ export const useDeleteProjectRole = () => {
|
|||||||
mutationFn: async ({ projectId, id }: TDeleteProjectRoleDTO) => {
|
mutationFn: async ({ projectId, id }: TDeleteProjectRoleDTO) => {
|
||||||
const {
|
const {
|
||||||
data: { role }
|
data: { role }
|
||||||
} = await apiRequest.delete(`/api/v2/workspace/${projectId}/roles/${id}`);
|
} = await apiRequest.delete(`/api/v1/projects/${projectId}/roles/${id}`);
|
||||||
return role;
|
return role;
|
||||||
},
|
},
|
||||||
onSuccess: (_, { projectId }) => {
|
onSuccess: (_, { projectId }) => {
|
||||||
|
|||||||
@@ -46,13 +46,13 @@ export const roleQueryKeys = {
|
|||||||
getOrgRole: (orgId: string, roleId: string) => [{ orgId, roleId }, "org-role"] as const,
|
getOrgRole: (orgId: string, roleId: string) => [{ orgId, roleId }, "org-role"] as const,
|
||||||
getUserOrgPermissions: ({ orgId }: TGetUserOrgPermissionsDTO) =>
|
getUserOrgPermissions: ({ orgId }: TGetUserOrgPermissionsDTO) =>
|
||||||
["user-permissions", { orgId }] as const,
|
["user-permissions", { orgId }] as const,
|
||||||
getUserProjectPermissions: ({ workspaceId }: TGetUserProjectPermissionDTO) =>
|
getUserProjectPermissions: ({ projectId }: TGetUserProjectPermissionDTO) =>
|
||||||
["user-project-permissions", { workspaceId }] as const
|
["user-project-permissions", { projectId }] as const
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getProjectRoles = async (projectId: string) => {
|
export const getProjectRoles = async (projectId: string) => {
|
||||||
const { data } = await apiRequest.get<{ roles: Array<Omit<TProjectRole, "permissions">> }>(
|
const { data } = await apiRequest.get<{ roles: Array<Omit<TProjectRole, "permissions">> }>(
|
||||||
`/api/v2/workspace/${projectId}/roles`
|
`/api/v1/projects/${projectId}/roles`
|
||||||
);
|
);
|
||||||
return data.roles;
|
return data.roles;
|
||||||
};
|
};
|
||||||
@@ -69,7 +69,7 @@ export const useGetProjectRoleBySlug = (projectId: string, roleSlug: string) =>
|
|||||||
queryKey: roleQueryKeys.getProjectRoleBySlug(projectId, roleSlug),
|
queryKey: roleQueryKeys.getProjectRoleBySlug(projectId, roleSlug),
|
||||||
queryFn: async () => {
|
queryFn: async () => {
|
||||||
const { data } = await apiRequest.get<{ role: TProjectRole }>(
|
const { data } = await apiRequest.get<{ role: TProjectRole }>(
|
||||||
`/api/v2/workspace/${projectId}/roles/slug/${roleSlug}`
|
`/api/v1/projects/${projectId}/roles/slug/${roleSlug}`
|
||||||
);
|
);
|
||||||
return data.role;
|
return data.role;
|
||||||
},
|
},
|
||||||
@@ -131,9 +131,7 @@ export const useGetUserOrgPermissions = ({ orgId }: TGetUserOrgPermissionsDTO) =
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
export const fetchUserProjectPermissions = async ({
|
export const fetchUserProjectPermissions = async ({ projectId }: TGetUserProjectPermissionDTO) => {
|
||||||
workspaceId
|
|
||||||
}: TGetUserProjectPermissionDTO) => {
|
|
||||||
const { data } = await apiRequest.get<{
|
const { data } = await apiRequest.get<{
|
||||||
data: {
|
data: {
|
||||||
permissions: PackRule<RawRuleOf<MongoAbility<OrgPermissionSet>>>[];
|
permissions: PackRule<RawRuleOf<MongoAbility<OrgPermissionSet>>>[];
|
||||||
@@ -145,16 +143,16 @@ export const fetchUserProjectPermissions = async ({
|
|||||||
actorName: string;
|
actorName: string;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}>(`/api/v1/workspace/${workspaceId}/permissions`, {});
|
}>(`/api/v1/projects/${projectId}/permissions`, {});
|
||||||
|
|
||||||
return data.data;
|
return data.data;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const useGetUserProjectPermissions = ({ workspaceId }: TGetUserProjectPermissionDTO) =>
|
export const useGetUserProjectPermissions = ({ projectId }: TGetUserProjectPermissionDTO) =>
|
||||||
useQuery({
|
useQuery({
|
||||||
queryKey: roleQueryKeys.getUserProjectPermissions({ workspaceId }),
|
queryKey: roleQueryKeys.getUserProjectPermissions({ projectId }),
|
||||||
queryFn: () => fetchUserProjectPermissions({ workspaceId }),
|
queryFn: () => fetchUserProjectPermissions({ projectId }),
|
||||||
enabled: Boolean(workspaceId),
|
enabled: Boolean(projectId),
|
||||||
select: (data) => {
|
select: (data) => {
|
||||||
const rule = unpackRules<RawRuleOf<MongoAbility<ProjectPermissionSet>>>(data.permissions);
|
const rule = unpackRules<RawRuleOf<MongoAbility<ProjectPermissionSet>>>(data.permissions);
|
||||||
const negatedRules = groupBy(
|
const negatedRules = groupBy(
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ export enum ProjectMembershipRole {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export type TGetProjectRolesDTO = {
|
export type TGetProjectRolesDTO = {
|
||||||
workspaceId?: string;
|
projectId?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type TProjectRole = {
|
export type TProjectRole = {
|
||||||
@@ -52,7 +52,7 @@ export type TGetUserOrgPermissionsDTO = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export type TGetUserProjectPermissionDTO = {
|
export type TGetUserProjectPermissionDTO = {
|
||||||
workspaceId: string;
|
projectId: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type TCreateOrgRoleDTO = {
|
export type TCreateOrgRoleDTO = {
|
||||||
|
|||||||
Reference in New Issue
Block a user