diff --git a/backend/src/ee/services/permission/permission-types.ts b/backend/src/ee/services/permission/permission-types.ts index 8df85054d..1ad0b205b 100644 --- a/backend/src/ee/services/permission/permission-types.ts +++ b/backend/src/ee/services/permission/permission-types.ts @@ -1,14 +1,7 @@ import picomatch from "picomatch"; import { z } from "zod"; -export enum PermissionConditionOperators { - $IN = "$in", - $ALL = "$all", - $REGEX = "$regex", - $EQ = "$eq", - $NEQ = "$ne", - $GLOB = "$glob" -} +import { PermissionConditionOperators } from "@app/lib/casl"; export const PermissionConditionSchema = { [PermissionConditionOperators.$IN]: z.string().trim().min(1).array(), diff --git a/backend/src/ee/services/permission/project-permission.ts b/backend/src/ee/services/permission/project-permission.ts index 591cdd343..c6e574fb1 100644 --- a/backend/src/ee/services/permission/project-permission.ts +++ b/backend/src/ee/services/permission/project-permission.ts @@ -1,10 +1,10 @@ import { AbilityBuilder, createMongoAbility, ForcedSubject, MongoAbility } from "@casl/ability"; import { z } from "zod"; -import { conditionsMatcher } from "@app/lib/casl"; +import { conditionsMatcher, PermissionConditionOperators } from "@app/lib/casl"; import { UnpackedPermissionSchema } from "@app/server/routes/santizedSchemas/permission"; -import { PermissionConditionOperators, PermissionConditionSchema } from "./permission-types"; +import { PermissionConditionSchema } from "./permission-types"; export enum ProjectPermissionActions { Read = "read", diff --git a/backend/src/lib/casl/index.ts b/backend/src/lib/casl/index.ts index 71625e181..ad4bf028f 100644 --- a/backend/src/lib/casl/index.ts +++ b/backend/src/lib/casl/index.ts @@ -54,3 +54,12 @@ export const isAtLeastAsPrivileged = (permissions1: MongoAbility, permissions2: return set1.size >= set2.size; }; + +export enum PermissionConditionOperators { + $IN = "$in", + $ALL = "$all", + $REGEX = "$regex", + $EQ = "$eq", + $NEQ = "$ne", + $GLOB = "$glob" +} diff --git a/backend/src/server/plugins/error-handler.ts b/backend/src/server/plugins/error-handler.ts index 007902a17..2c456aafc 100644 --- a/backend/src/server/plugins/error-handler.ts +++ b/backend/src/server/plugins/error-handler.ts @@ -1,4 +1,4 @@ -import { ForbiddenError } from "@casl/ability"; +import { ForbiddenError, PureAbility } from "@casl/ability"; import fastifyPlugin from "fastify-plugin"; import jwt from "jsonwebtoken"; import { ZodError } from "zod"; @@ -63,7 +63,13 @@ export const fastifyErrHandler = fastifyPlugin(async (server: FastifyZodProvider void res.status(HttpStatusCodes.Forbidden).send({ statusCode: HttpStatusCodes.Forbidden, error: "PermissionDenied", - message: `You are not allowed to ${error.action} on ${error.subjectType} - ${JSON.stringify(error.subject)}` + message: `You are not allowed to ${error.action} on ${error.subjectType}`, + details: (error.ability as PureAbility).rulesFor(error.action as string, error.subjectType).map((el) => ({ + action: el.action, + inverted: el.inverted, + subject: el.subject, + conditions: el.conditions + })) }); } else if (error instanceof ForbiddenRequestError) { void res.status(HttpStatusCodes.Forbidden).send({ diff --git a/backend/src/server/routes/sanitizedSchemas.ts b/backend/src/server/routes/sanitizedSchemas.ts index 87fa2b120..78575e35d 100644 --- a/backend/src/server/routes/sanitizedSchemas.ts +++ b/backend/src/server/routes/sanitizedSchemas.ts @@ -47,6 +47,7 @@ export const DefaultResponseErrorsSchema = { 403: z.object({ statusCode: z.literal(403), message: z.string(), + details: z.any().optional(), error: z.string() }), 500: z.object({