mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-07 08:27:36 +00:00
misc: project permission transition
This commit is contained in:
+28
-13
@@ -3,15 +3,15 @@ import { packRules } from "@casl/ability/extra";
|
|||||||
import ms from "ms";
|
import ms from "ms";
|
||||||
|
|
||||||
import { ActionProjectType, TableName } from "@app/db/schemas";
|
import { ActionProjectType, TableName } from "@app/db/schemas";
|
||||||
import { isAtLeastAsPrivileged } from "@app/lib/casl";
|
|
||||||
import { BadRequestError, ForbiddenRequestError, NotFoundError } from "@app/lib/errors";
|
import { BadRequestError, ForbiddenRequestError, NotFoundError } from "@app/lib/errors";
|
||||||
import { unpackPermissions } from "@app/server/routes/sanitizedSchema/permission";
|
import { unpackPermissions } from "@app/server/routes/sanitizedSchema/permission";
|
||||||
import { ActorType } from "@app/services/auth/auth-type";
|
import { ActorType } from "@app/services/auth/auth-type";
|
||||||
import { TIdentityProjectDALFactory } from "@app/services/identity-project/identity-project-dal";
|
import { TIdentityProjectDALFactory } from "@app/services/identity-project/identity-project-dal";
|
||||||
import { TProjectDALFactory } from "@app/services/project/project-dal";
|
import { TProjectDALFactory } from "@app/services/project/project-dal";
|
||||||
|
|
||||||
|
import { validatePrivilegeChangeOperation } from "../permission/permission-fns";
|
||||||
import { TPermissionServiceFactory } from "../permission/permission-service";
|
import { TPermissionServiceFactory } from "../permission/permission-service";
|
||||||
import { ProjectPermissionActions, ProjectPermissionSub } from "../permission/project-permission";
|
import { ProjectPermissionIdentityActions, ProjectPermissionSub } from "../permission/project-permission";
|
||||||
import { TIdentityProjectAdditionalPrivilegeV2DALFactory } from "./identity-project-additional-privilege-v2-dal";
|
import { TIdentityProjectAdditionalPrivilegeV2DALFactory } from "./identity-project-additional-privilege-v2-dal";
|
||||||
import {
|
import {
|
||||||
IdentityProjectAdditionalPrivilegeTemporaryMode,
|
IdentityProjectAdditionalPrivilegeTemporaryMode,
|
||||||
@@ -64,7 +64,7 @@ export const identityProjectAdditionalPrivilegeV2ServiceFactory = ({
|
|||||||
actionProjectType: ActionProjectType.Any
|
actionProjectType: ActionProjectType.Any
|
||||||
});
|
});
|
||||||
ForbiddenError.from(permission).throwUnlessCan(
|
ForbiddenError.from(permission).throwUnlessCan(
|
||||||
ProjectPermissionActions.Edit,
|
ProjectPermissionIdentityActions.Edit,
|
||||||
subject(ProjectPermissionSub.Identity, { identityId })
|
subject(ProjectPermissionSub.Identity, { identityId })
|
||||||
);
|
);
|
||||||
const { permission: targetIdentityPermission } = await permissionService.getProjectPermission({
|
const { permission: targetIdentityPermission } = await permissionService.getProjectPermission({
|
||||||
@@ -79,8 +79,13 @@ export const identityProjectAdditionalPrivilegeV2ServiceFactory = ({
|
|||||||
// we need to validate that the privilege given is not higher than the assigning users permission
|
// we need to validate that the privilege given is not higher than the assigning users permission
|
||||||
// @ts-expect-error this is expected error because of one being really accurate rule definition other being a bit more broader. Both are valid casl rules
|
// @ts-expect-error this is expected error because of one being really accurate rule definition other being a bit more broader. Both are valid casl rules
|
||||||
targetIdentityPermission.update(targetIdentityPermission.rules.concat(customPermission));
|
targetIdentityPermission.update(targetIdentityPermission.rules.concat(customPermission));
|
||||||
const hasRequiredPriviledges = isAtLeastAsPrivileged(permission, targetIdentityPermission);
|
const hasRequiredPrivileges = validatePrivilegeChangeOperation(
|
||||||
if (!hasRequiredPriviledges)
|
ProjectPermissionIdentityActions.ManagePrivileges,
|
||||||
|
ProjectPermissionSub.Identity,
|
||||||
|
permission,
|
||||||
|
targetIdentityPermission
|
||||||
|
);
|
||||||
|
if (!hasRequiredPrivileges)
|
||||||
throw new ForbiddenRequestError({ message: "Failed to update more privileged identity" });
|
throw new ForbiddenRequestError({ message: "Failed to update more privileged identity" });
|
||||||
|
|
||||||
const existingSlug = await identityProjectAdditionalPrivilegeDAL.findOne({
|
const existingSlug = await identityProjectAdditionalPrivilegeDAL.findOne({
|
||||||
@@ -146,7 +151,7 @@ export const identityProjectAdditionalPrivilegeV2ServiceFactory = ({
|
|||||||
actionProjectType: ActionProjectType.Any
|
actionProjectType: ActionProjectType.Any
|
||||||
});
|
});
|
||||||
ForbiddenError.from(permission).throwUnlessCan(
|
ForbiddenError.from(permission).throwUnlessCan(
|
||||||
ProjectPermissionActions.Edit,
|
ProjectPermissionIdentityActions.Edit,
|
||||||
subject(ProjectPermissionSub.Identity, { identityId: identityProjectMembership.identityId })
|
subject(ProjectPermissionSub.Identity, { identityId: identityProjectMembership.identityId })
|
||||||
);
|
);
|
||||||
const { permission: targetIdentityPermission } = await permissionService.getProjectPermission({
|
const { permission: targetIdentityPermission } = await permissionService.getProjectPermission({
|
||||||
@@ -161,8 +166,13 @@ export const identityProjectAdditionalPrivilegeV2ServiceFactory = ({
|
|||||||
// we need to validate that the privilege given is not higher than the assigning users permission
|
// we need to validate that the privilege given is not higher than the assigning users permission
|
||||||
// @ts-expect-error this is expected error because of one being really accurate rule definition other being a bit more broader. Both are valid casl rules
|
// @ts-expect-error this is expected error because of one being really accurate rule definition other being a bit more broader. Both are valid casl rules
|
||||||
targetIdentityPermission.update(targetIdentityPermission.rules.concat(data.permissions || []));
|
targetIdentityPermission.update(targetIdentityPermission.rules.concat(data.permissions || []));
|
||||||
const hasRequiredPriviledges = isAtLeastAsPrivileged(permission, targetIdentityPermission);
|
const hasRequiredPrivileges = validatePrivilegeChangeOperation(
|
||||||
if (!hasRequiredPriviledges)
|
ProjectPermissionIdentityActions.ManagePrivileges,
|
||||||
|
ProjectPermissionSub.Identity,
|
||||||
|
permission,
|
||||||
|
targetIdentityPermission
|
||||||
|
);
|
||||||
|
if (!hasRequiredPrivileges)
|
||||||
throw new ForbiddenRequestError({ message: "Failed to update more privileged identity" });
|
throw new ForbiddenRequestError({ message: "Failed to update more privileged identity" });
|
||||||
|
|
||||||
if (data?.slug) {
|
if (data?.slug) {
|
||||||
@@ -228,7 +238,7 @@ export const identityProjectAdditionalPrivilegeV2ServiceFactory = ({
|
|||||||
actionProjectType: ActionProjectType.Any
|
actionProjectType: ActionProjectType.Any
|
||||||
});
|
});
|
||||||
ForbiddenError.from(permission).throwUnlessCan(
|
ForbiddenError.from(permission).throwUnlessCan(
|
||||||
ProjectPermissionActions.Edit,
|
ProjectPermissionIdentityActions.Edit,
|
||||||
subject(ProjectPermissionSub.Identity, { identityId: identityProjectMembership.identityId })
|
subject(ProjectPermissionSub.Identity, { identityId: identityProjectMembership.identityId })
|
||||||
);
|
);
|
||||||
const { permission: identityRolePermission } = await permissionService.getProjectPermission({
|
const { permission: identityRolePermission } = await permissionService.getProjectPermission({
|
||||||
@@ -239,7 +249,12 @@ export const identityProjectAdditionalPrivilegeV2ServiceFactory = ({
|
|||||||
actorOrgId,
|
actorOrgId,
|
||||||
actionProjectType: ActionProjectType.Any
|
actionProjectType: ActionProjectType.Any
|
||||||
});
|
});
|
||||||
const hasRequiredPriviledges = isAtLeastAsPrivileged(permission, identityRolePermission);
|
const hasRequiredPriviledges = validatePrivilegeChangeOperation(
|
||||||
|
ProjectPermissionIdentityActions.ManagePrivileges,
|
||||||
|
ProjectPermissionSub.Identity,
|
||||||
|
permission,
|
||||||
|
identityRolePermission
|
||||||
|
);
|
||||||
if (!hasRequiredPriviledges)
|
if (!hasRequiredPriviledges)
|
||||||
throw new ForbiddenRequestError({ message: "Failed to update more privileged identity" });
|
throw new ForbiddenRequestError({ message: "Failed to update more privileged identity" });
|
||||||
|
|
||||||
@@ -275,7 +290,7 @@ export const identityProjectAdditionalPrivilegeV2ServiceFactory = ({
|
|||||||
actionProjectType: ActionProjectType.Any
|
actionProjectType: ActionProjectType.Any
|
||||||
});
|
});
|
||||||
ForbiddenError.from(permission).throwUnlessCan(
|
ForbiddenError.from(permission).throwUnlessCan(
|
||||||
ProjectPermissionActions.Read,
|
ProjectPermissionIdentityActions.Read,
|
||||||
subject(ProjectPermissionSub.Identity, { identityId: identityProjectMembership.identityId })
|
subject(ProjectPermissionSub.Identity, { identityId: identityProjectMembership.identityId })
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -310,7 +325,7 @@ export const identityProjectAdditionalPrivilegeV2ServiceFactory = ({
|
|||||||
actionProjectType: ActionProjectType.Any
|
actionProjectType: ActionProjectType.Any
|
||||||
});
|
});
|
||||||
ForbiddenError.from(permission).throwUnlessCan(
|
ForbiddenError.from(permission).throwUnlessCan(
|
||||||
ProjectPermissionActions.Read,
|
ProjectPermissionIdentityActions.Read,
|
||||||
subject(ProjectPermissionSub.Identity, { identityId: identityProjectMembership.identityId })
|
subject(ProjectPermissionSub.Identity, { identityId: identityProjectMembership.identityId })
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -346,7 +361,7 @@ export const identityProjectAdditionalPrivilegeV2ServiceFactory = ({
|
|||||||
actionProjectType: ActionProjectType.Any
|
actionProjectType: ActionProjectType.Any
|
||||||
});
|
});
|
||||||
ForbiddenError.from(permission).throwUnlessCan(
|
ForbiddenError.from(permission).throwUnlessCan(
|
||||||
ProjectPermissionActions.Read,
|
ProjectPermissionIdentityActions.Read,
|
||||||
subject(ProjectPermissionSub.Identity, { identityId: identityProjectMembership.identityId })
|
subject(ProjectPermissionSub.Identity, { identityId: identityProjectMembership.identityId })
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
+34
-14
@@ -3,15 +3,19 @@ import { PackRule, packRules, unpackRules } from "@casl/ability/extra";
|
|||||||
import ms from "ms";
|
import ms from "ms";
|
||||||
|
|
||||||
import { ActionProjectType } from "@app/db/schemas";
|
import { ActionProjectType } from "@app/db/schemas";
|
||||||
import { isAtLeastAsPrivileged } from "@app/lib/casl";
|
|
||||||
import { BadRequestError, ForbiddenRequestError, NotFoundError } from "@app/lib/errors";
|
import { BadRequestError, ForbiddenRequestError, NotFoundError } from "@app/lib/errors";
|
||||||
import { UnpackedPermissionSchema } from "@app/server/routes/sanitizedSchema/permission";
|
import { UnpackedPermissionSchema } from "@app/server/routes/sanitizedSchema/permission";
|
||||||
import { ActorType } from "@app/services/auth/auth-type";
|
import { ActorType } from "@app/services/auth/auth-type";
|
||||||
import { TIdentityProjectDALFactory } from "@app/services/identity-project/identity-project-dal";
|
import { TIdentityProjectDALFactory } from "@app/services/identity-project/identity-project-dal";
|
||||||
import { TProjectDALFactory } from "@app/services/project/project-dal";
|
import { TProjectDALFactory } from "@app/services/project/project-dal";
|
||||||
|
|
||||||
|
import { validatePrivilegeChangeOperation } from "../permission/permission-fns";
|
||||||
import { TPermissionServiceFactory } from "../permission/permission-service";
|
import { TPermissionServiceFactory } from "../permission/permission-service";
|
||||||
import { ProjectPermissionActions, ProjectPermissionSet, ProjectPermissionSub } from "../permission/project-permission";
|
import {
|
||||||
|
ProjectPermissionIdentityActions,
|
||||||
|
ProjectPermissionSet,
|
||||||
|
ProjectPermissionSub
|
||||||
|
} from "../permission/project-permission";
|
||||||
import { TIdentityProjectAdditionalPrivilegeDALFactory } from "./identity-project-additional-privilege-dal";
|
import { TIdentityProjectAdditionalPrivilegeDALFactory } from "./identity-project-additional-privilege-dal";
|
||||||
import {
|
import {
|
||||||
IdentityProjectAdditionalPrivilegeTemporaryMode,
|
IdentityProjectAdditionalPrivilegeTemporaryMode,
|
||||||
@@ -71,8 +75,9 @@ export const identityProjectAdditionalPrivilegeServiceFactory = ({
|
|||||||
actorOrgId,
|
actorOrgId,
|
||||||
actionProjectType: ActionProjectType.Any
|
actionProjectType: ActionProjectType.Any
|
||||||
});
|
});
|
||||||
|
|
||||||
ForbiddenError.from(permission).throwUnlessCan(
|
ForbiddenError.from(permission).throwUnlessCan(
|
||||||
ProjectPermissionActions.Edit,
|
ProjectPermissionIdentityActions.Edit,
|
||||||
subject(ProjectPermissionSub.Identity, { identityId })
|
subject(ProjectPermissionSub.Identity, { identityId })
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -88,8 +93,13 @@ export const identityProjectAdditionalPrivilegeServiceFactory = ({
|
|||||||
// we need to validate that the privilege given is not higher than the assigning users permission
|
// we need to validate that the privilege given is not higher than the assigning users permission
|
||||||
// @ts-expect-error this is expected error because of one being really accurate rule definition other being a bit more broader. Both are valid casl rules
|
// @ts-expect-error this is expected error because of one being really accurate rule definition other being a bit more broader. Both are valid casl rules
|
||||||
targetIdentityPermission.update(targetIdentityPermission.rules.concat(customPermission));
|
targetIdentityPermission.update(targetIdentityPermission.rules.concat(customPermission));
|
||||||
const hasRequiredPriviledges = isAtLeastAsPrivileged(permission, targetIdentityPermission);
|
const hasRequiredPrivileges = validatePrivilegeChangeOperation(
|
||||||
if (!hasRequiredPriviledges)
|
ProjectPermissionIdentityActions.ManagePrivileges,
|
||||||
|
ProjectPermissionSub.Identity,
|
||||||
|
permission,
|
||||||
|
targetIdentityPermission
|
||||||
|
);
|
||||||
|
if (!hasRequiredPrivileges)
|
||||||
throw new ForbiddenRequestError({ message: "Failed to update more privileged identity" });
|
throw new ForbiddenRequestError({ message: "Failed to update more privileged identity" });
|
||||||
|
|
||||||
const existingSlug = await identityProjectAdditionalPrivilegeDAL.findOne({
|
const existingSlug = await identityProjectAdditionalPrivilegeDAL.findOne({
|
||||||
@@ -156,7 +166,7 @@ export const identityProjectAdditionalPrivilegeServiceFactory = ({
|
|||||||
});
|
});
|
||||||
|
|
||||||
ForbiddenError.from(permission).throwUnlessCan(
|
ForbiddenError.from(permission).throwUnlessCan(
|
||||||
ProjectPermissionActions.Edit,
|
ProjectPermissionIdentityActions.Edit,
|
||||||
subject(ProjectPermissionSub.Identity, { identityId })
|
subject(ProjectPermissionSub.Identity, { identityId })
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -172,8 +182,13 @@ export const identityProjectAdditionalPrivilegeServiceFactory = ({
|
|||||||
// we need to validate that the privilege given is not higher than the assigning users permission
|
// we need to validate that the privilege given is not higher than the assigning users permission
|
||||||
// @ts-expect-error this is expected error because of one being really accurate rule definition other being a bit more broader. Both are valid casl rules
|
// @ts-expect-error this is expected error because of one being really accurate rule definition other being a bit more broader. Both are valid casl rules
|
||||||
targetIdentityPermission.update(targetIdentityPermission.rules.concat(data.permissions || []));
|
targetIdentityPermission.update(targetIdentityPermission.rules.concat(data.permissions || []));
|
||||||
const hasRequiredPriviledges = isAtLeastAsPrivileged(permission, targetIdentityPermission);
|
const hasRequiredPrivileges = validatePrivilegeChangeOperation(
|
||||||
if (!hasRequiredPriviledges)
|
ProjectPermissionIdentityActions.ManagePrivileges,
|
||||||
|
ProjectPermissionSub.Identity,
|
||||||
|
permission,
|
||||||
|
targetIdentityPermission
|
||||||
|
);
|
||||||
|
if (!hasRequiredPrivileges)
|
||||||
throw new ForbiddenRequestError({ message: "Failed to update more privileged identity" });
|
throw new ForbiddenRequestError({ message: "Failed to update more privileged identity" });
|
||||||
|
|
||||||
const identityPrivilege = await identityProjectAdditionalPrivilegeDAL.findOne({
|
const identityPrivilege = await identityProjectAdditionalPrivilegeDAL.findOne({
|
||||||
@@ -256,7 +271,7 @@ export const identityProjectAdditionalPrivilegeServiceFactory = ({
|
|||||||
actionProjectType: ActionProjectType.Any
|
actionProjectType: ActionProjectType.Any
|
||||||
});
|
});
|
||||||
ForbiddenError.from(permission).throwUnlessCan(
|
ForbiddenError.from(permission).throwUnlessCan(
|
||||||
ProjectPermissionActions.Edit,
|
ProjectPermissionIdentityActions.Edit,
|
||||||
subject(ProjectPermissionSub.Identity, { identityId })
|
subject(ProjectPermissionSub.Identity, { identityId })
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -268,9 +283,14 @@ export const identityProjectAdditionalPrivilegeServiceFactory = ({
|
|||||||
actorOrgId,
|
actorOrgId,
|
||||||
actionProjectType: ActionProjectType.Any
|
actionProjectType: ActionProjectType.Any
|
||||||
});
|
});
|
||||||
const hasRequiredPriviledges = isAtLeastAsPrivileged(permission, identityRolePermission);
|
|
||||||
if (!hasRequiredPriviledges)
|
const hasRequiredPrivileges = validatePrivilegeChangeOperation(
|
||||||
throw new ForbiddenRequestError({ message: "Failed to edit more privileged identity" });
|
ProjectPermissionIdentityActions.ManagePrivileges,
|
||||||
|
ProjectPermissionSub.Identity,
|
||||||
|
permission,
|
||||||
|
identityRolePermission
|
||||||
|
);
|
||||||
|
if (!hasRequiredPrivileges) throw new ForbiddenRequestError({ message: "Failed to edit more privileged identity" });
|
||||||
|
|
||||||
const identityPrivilege = await identityProjectAdditionalPrivilegeDAL.findOne({
|
const identityPrivilege = await identityProjectAdditionalPrivilegeDAL.findOne({
|
||||||
slug,
|
slug,
|
||||||
@@ -315,7 +335,7 @@ export const identityProjectAdditionalPrivilegeServiceFactory = ({
|
|||||||
actionProjectType: ActionProjectType.Any
|
actionProjectType: ActionProjectType.Any
|
||||||
});
|
});
|
||||||
ForbiddenError.from(permission).throwUnlessCan(
|
ForbiddenError.from(permission).throwUnlessCan(
|
||||||
ProjectPermissionActions.Read,
|
ProjectPermissionIdentityActions.Read,
|
||||||
subject(ProjectPermissionSub.Identity, { identityId })
|
subject(ProjectPermissionSub.Identity, { identityId })
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -359,7 +379,7 @@ export const identityProjectAdditionalPrivilegeServiceFactory = ({
|
|||||||
});
|
});
|
||||||
|
|
||||||
ForbiddenError.from(permission).throwUnlessCan(
|
ForbiddenError.from(permission).throwUnlessCan(
|
||||||
ProjectPermissionActions.Read,
|
ProjectPermissionIdentityActions.Read,
|
||||||
subject(ProjectPermissionSub.Identity, { identityId })
|
subject(ProjectPermissionSub.Identity, { identityId })
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -34,6 +34,30 @@ export enum ProjectPermissionDynamicSecretActions {
|
|||||||
Lease = "lease"
|
Lease = "lease"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum ProjectPermissionIdentityActions {
|
||||||
|
Read = "read",
|
||||||
|
Create = "create",
|
||||||
|
Edit = "edit",
|
||||||
|
Delete = "delete",
|
||||||
|
ManagePrivileges = "manage-privileges"
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum ProjectPermissionMemberActions {
|
||||||
|
Read = "read",
|
||||||
|
Create = "create",
|
||||||
|
Edit = "edit",
|
||||||
|
Delete = "delete",
|
||||||
|
ManagePrivileges = "manage-privileges"
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum ProjectPermissionGroupActions {
|
||||||
|
Read = "read",
|
||||||
|
Create = "create",
|
||||||
|
Edit = "edit",
|
||||||
|
Delete = "delete",
|
||||||
|
ManagePrivileges = "manage-privileges"
|
||||||
|
}
|
||||||
|
|
||||||
export enum ProjectPermissionSecretSyncActions {
|
export enum ProjectPermissionSecretSyncActions {
|
||||||
Read = "read",
|
Read = "read",
|
||||||
Create = "create",
|
Create = "create",
|
||||||
@@ -141,8 +165,8 @@ export type ProjectPermissionSet =
|
|||||||
]
|
]
|
||||||
| [ProjectPermissionActions, ProjectPermissionSub.Role]
|
| [ProjectPermissionActions, ProjectPermissionSub.Role]
|
||||||
| [ProjectPermissionActions, ProjectPermissionSub.Tags]
|
| [ProjectPermissionActions, ProjectPermissionSub.Tags]
|
||||||
| [ProjectPermissionActions, ProjectPermissionSub.Member]
|
| [ProjectPermissionMemberActions, ProjectPermissionSub.Member]
|
||||||
| [ProjectPermissionActions, ProjectPermissionSub.Groups]
|
| [ProjectPermissionGroupActions, ProjectPermissionSub.Groups]
|
||||||
| [ProjectPermissionActions, ProjectPermissionSub.Integrations]
|
| [ProjectPermissionActions, ProjectPermissionSub.Integrations]
|
||||||
| [ProjectPermissionActions, ProjectPermissionSub.Webhooks]
|
| [ProjectPermissionActions, ProjectPermissionSub.Webhooks]
|
||||||
| [ProjectPermissionActions, ProjectPermissionSub.AuditLogs]
|
| [ProjectPermissionActions, ProjectPermissionSub.AuditLogs]
|
||||||
@@ -153,7 +177,7 @@ export type ProjectPermissionSet =
|
|||||||
| [ProjectPermissionActions, ProjectPermissionSub.SecretApproval]
|
| [ProjectPermissionActions, ProjectPermissionSub.SecretApproval]
|
||||||
| [ProjectPermissionActions, ProjectPermissionSub.SecretRotation]
|
| [ProjectPermissionActions, ProjectPermissionSub.SecretRotation]
|
||||||
| [
|
| [
|
||||||
ProjectPermissionActions,
|
ProjectPermissionIdentityActions,
|
||||||
ProjectPermissionSub.Identity | (ForcedSubject<ProjectPermissionSub.Identity> & IdentityManagementSubjectFields)
|
ProjectPermissionSub.Identity | (ForcedSubject<ProjectPermissionSub.Identity> & IdentityManagementSubjectFields)
|
||||||
]
|
]
|
||||||
| [ProjectPermissionActions, ProjectPermissionSub.CertificateAuthorities]
|
| [ProjectPermissionActions, ProjectPermissionSub.CertificateAuthorities]
|
||||||
@@ -281,13 +305,13 @@ const GeneralPermissionSchema = [
|
|||||||
}),
|
}),
|
||||||
z.object({
|
z.object({
|
||||||
subject: z.literal(ProjectPermissionSub.Member).describe("The entity this permission pertains to."),
|
subject: z.literal(ProjectPermissionSub.Member).describe("The entity this permission pertains to."),
|
||||||
action: CASL_ACTION_SCHEMA_NATIVE_ENUM(ProjectPermissionActions).describe(
|
action: CASL_ACTION_SCHEMA_NATIVE_ENUM(ProjectPermissionMemberActions).describe(
|
||||||
"Describe what action an entity can take."
|
"Describe what action an entity can take."
|
||||||
)
|
)
|
||||||
}),
|
}),
|
||||||
z.object({
|
z.object({
|
||||||
subject: z.literal(ProjectPermissionSub.Groups).describe("The entity this permission pertains to."),
|
subject: z.literal(ProjectPermissionSub.Groups).describe("The entity this permission pertains to."),
|
||||||
action: CASL_ACTION_SCHEMA_NATIVE_ENUM(ProjectPermissionActions).describe(
|
action: CASL_ACTION_SCHEMA_NATIVE_ENUM(ProjectPermissionGroupActions).describe(
|
||||||
"Describe what action an entity can take."
|
"Describe what action an entity can take."
|
||||||
)
|
)
|
||||||
}),
|
}),
|
||||||
@@ -449,7 +473,7 @@ export const ProjectPermissionV1Schema = z.discriminatedUnion("subject", [
|
|||||||
}),
|
}),
|
||||||
z.object({
|
z.object({
|
||||||
subject: z.literal(ProjectPermissionSub.Identity).describe("The entity this permission pertains to."),
|
subject: z.literal(ProjectPermissionSub.Identity).describe("The entity this permission pertains to."),
|
||||||
action: CASL_ACTION_SCHEMA_NATIVE_ENUM(ProjectPermissionActions).describe(
|
action: CASL_ACTION_SCHEMA_NATIVE_ENUM(ProjectPermissionIdentityActions).describe(
|
||||||
"Describe what action an entity can take."
|
"Describe what action an entity can take."
|
||||||
)
|
)
|
||||||
}),
|
}),
|
||||||
@@ -522,12 +546,9 @@ const buildAdminPermissionRules = () => {
|
|||||||
ProjectPermissionSub.SecretImports,
|
ProjectPermissionSub.SecretImports,
|
||||||
ProjectPermissionSub.SecretApproval,
|
ProjectPermissionSub.SecretApproval,
|
||||||
ProjectPermissionSub.SecretRotation,
|
ProjectPermissionSub.SecretRotation,
|
||||||
ProjectPermissionSub.Member,
|
|
||||||
ProjectPermissionSub.Groups,
|
|
||||||
ProjectPermissionSub.Role,
|
ProjectPermissionSub.Role,
|
||||||
ProjectPermissionSub.Integrations,
|
ProjectPermissionSub.Integrations,
|
||||||
ProjectPermissionSub.Webhooks,
|
ProjectPermissionSub.Webhooks,
|
||||||
ProjectPermissionSub.Identity,
|
|
||||||
ProjectPermissionSub.ServiceTokens,
|
ProjectPermissionSub.ServiceTokens,
|
||||||
ProjectPermissionSub.Settings,
|
ProjectPermissionSub.Settings,
|
||||||
ProjectPermissionSub.Environments,
|
ProjectPermissionSub.Environments,
|
||||||
@@ -554,6 +575,39 @@ const buildAdminPermissionRules = () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
can(
|
||||||
|
[
|
||||||
|
ProjectPermissionMemberActions.Create,
|
||||||
|
ProjectPermissionMemberActions.Edit,
|
||||||
|
ProjectPermissionMemberActions.Delete,
|
||||||
|
ProjectPermissionMemberActions.Read,
|
||||||
|
ProjectPermissionMemberActions.ManagePrivileges
|
||||||
|
],
|
||||||
|
ProjectPermissionSub.Member
|
||||||
|
);
|
||||||
|
|
||||||
|
can(
|
||||||
|
[
|
||||||
|
ProjectPermissionGroupActions.Create,
|
||||||
|
ProjectPermissionGroupActions.Edit,
|
||||||
|
ProjectPermissionGroupActions.Delete,
|
||||||
|
ProjectPermissionGroupActions.Read,
|
||||||
|
ProjectPermissionGroupActions.ManagePrivileges
|
||||||
|
],
|
||||||
|
ProjectPermissionSub.Groups
|
||||||
|
);
|
||||||
|
|
||||||
|
can(
|
||||||
|
[
|
||||||
|
ProjectPermissionIdentityActions.Create,
|
||||||
|
ProjectPermissionIdentityActions.Edit,
|
||||||
|
ProjectPermissionIdentityActions.Delete,
|
||||||
|
ProjectPermissionIdentityActions.Read,
|
||||||
|
ProjectPermissionIdentityActions.ManagePrivileges
|
||||||
|
],
|
||||||
|
ProjectPermissionSub.Identity
|
||||||
|
);
|
||||||
|
|
||||||
can(
|
can(
|
||||||
[
|
[
|
||||||
ProjectPermissionDynamicSecretActions.ReadRootCredential,
|
ProjectPermissionDynamicSecretActions.ReadRootCredential,
|
||||||
@@ -654,9 +708,9 @@ const buildMemberPermissionRules = () => {
|
|||||||
|
|
||||||
can([ProjectPermissionActions.Read, ProjectPermissionActions.Create], ProjectPermissionSub.SecretRollback);
|
can([ProjectPermissionActions.Read, ProjectPermissionActions.Create], ProjectPermissionSub.SecretRollback);
|
||||||
|
|
||||||
can([ProjectPermissionActions.Read, ProjectPermissionActions.Create], ProjectPermissionSub.Member);
|
can([ProjectPermissionMemberActions.Read, ProjectPermissionMemberActions.Create], ProjectPermissionSub.Member);
|
||||||
|
|
||||||
can([ProjectPermissionActions.Read], ProjectPermissionSub.Groups);
|
can([ProjectPermissionGroupActions.Read], ProjectPermissionSub.Groups);
|
||||||
|
|
||||||
can(
|
can(
|
||||||
[
|
[
|
||||||
@@ -680,10 +734,10 @@ const buildMemberPermissionRules = () => {
|
|||||||
|
|
||||||
can(
|
can(
|
||||||
[
|
[
|
||||||
ProjectPermissionActions.Read,
|
ProjectPermissionIdentityActions.Read,
|
||||||
ProjectPermissionActions.Edit,
|
ProjectPermissionIdentityActions.Edit,
|
||||||
ProjectPermissionActions.Create,
|
ProjectPermissionIdentityActions.Create,
|
||||||
ProjectPermissionActions.Delete
|
ProjectPermissionIdentityActions.Delete
|
||||||
],
|
],
|
||||||
ProjectPermissionSub.Identity
|
ProjectPermissionSub.Identity
|
||||||
);
|
);
|
||||||
@@ -795,12 +849,12 @@ const buildViewerPermissionRules = () => {
|
|||||||
can(ProjectPermissionActions.Read, ProjectPermissionSub.SecretApproval);
|
can(ProjectPermissionActions.Read, ProjectPermissionSub.SecretApproval);
|
||||||
can(ProjectPermissionActions.Read, ProjectPermissionSub.SecretRollback);
|
can(ProjectPermissionActions.Read, ProjectPermissionSub.SecretRollback);
|
||||||
can(ProjectPermissionActions.Read, ProjectPermissionSub.SecretRotation);
|
can(ProjectPermissionActions.Read, ProjectPermissionSub.SecretRotation);
|
||||||
can(ProjectPermissionActions.Read, ProjectPermissionSub.Member);
|
can(ProjectPermissionMemberActions.Read, ProjectPermissionSub.Member);
|
||||||
can(ProjectPermissionActions.Read, ProjectPermissionSub.Groups);
|
can(ProjectPermissionGroupActions.Read, ProjectPermissionSub.Groups);
|
||||||
can(ProjectPermissionActions.Read, ProjectPermissionSub.Role);
|
can(ProjectPermissionActions.Read, ProjectPermissionSub.Role);
|
||||||
can(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations);
|
can(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations);
|
||||||
can(ProjectPermissionActions.Read, ProjectPermissionSub.Webhooks);
|
can(ProjectPermissionActions.Read, ProjectPermissionSub.Webhooks);
|
||||||
can(ProjectPermissionActions.Read, ProjectPermissionSub.Identity);
|
can(ProjectPermissionIdentityActions.Read, ProjectPermissionSub.Identity);
|
||||||
can(ProjectPermissionActions.Read, ProjectPermissionSub.ServiceTokens);
|
can(ProjectPermissionActions.Read, ProjectPermissionSub.ServiceTokens);
|
||||||
can(ProjectPermissionActions.Read, ProjectPermissionSub.Settings);
|
can(ProjectPermissionActions.Read, ProjectPermissionSub.Settings);
|
||||||
can(ProjectPermissionActions.Read, ProjectPermissionSub.Environments);
|
can(ProjectPermissionActions.Read, ProjectPermissionSub.Environments);
|
||||||
|
|||||||
+26
-10
@@ -3,14 +3,18 @@ import { PackRule, packRules, unpackRules } from "@casl/ability/extra";
|
|||||||
import ms from "ms";
|
import ms from "ms";
|
||||||
|
|
||||||
import { ActionProjectType, TableName } from "@app/db/schemas";
|
import { ActionProjectType, TableName } from "@app/db/schemas";
|
||||||
import { isAtLeastAsPrivileged } from "@app/lib/casl";
|
|
||||||
import { BadRequestError, ForbiddenRequestError, NotFoundError } from "@app/lib/errors";
|
import { BadRequestError, ForbiddenRequestError, NotFoundError } from "@app/lib/errors";
|
||||||
import { UnpackedPermissionSchema } from "@app/server/routes/sanitizedSchema/permission";
|
import { UnpackedPermissionSchema } from "@app/server/routes/sanitizedSchema/permission";
|
||||||
import { ActorType } from "@app/services/auth/auth-type";
|
import { ActorType } from "@app/services/auth/auth-type";
|
||||||
import { TProjectMembershipDALFactory } from "@app/services/project-membership/project-membership-dal";
|
import { TProjectMembershipDALFactory } from "@app/services/project-membership/project-membership-dal";
|
||||||
|
|
||||||
|
import { validatePrivilegeChangeOperation } from "../permission/permission-fns";
|
||||||
import { TPermissionServiceFactory } from "../permission/permission-service";
|
import { TPermissionServiceFactory } from "../permission/permission-service";
|
||||||
import { ProjectPermissionActions, ProjectPermissionSet, ProjectPermissionSub } from "../permission/project-permission";
|
import {
|
||||||
|
ProjectPermissionMemberActions,
|
||||||
|
ProjectPermissionSet,
|
||||||
|
ProjectPermissionSub
|
||||||
|
} from "../permission/project-permission";
|
||||||
import { TProjectUserAdditionalPrivilegeDALFactory } from "./project-user-additional-privilege-dal";
|
import { TProjectUserAdditionalPrivilegeDALFactory } from "./project-user-additional-privilege-dal";
|
||||||
import {
|
import {
|
||||||
ProjectUserAdditionalPrivilegeTemporaryMode,
|
ProjectUserAdditionalPrivilegeTemporaryMode,
|
||||||
@@ -63,7 +67,7 @@ export const projectUserAdditionalPrivilegeServiceFactory = ({
|
|||||||
actorOrgId,
|
actorOrgId,
|
||||||
actionProjectType: ActionProjectType.Any
|
actionProjectType: ActionProjectType.Any
|
||||||
});
|
});
|
||||||
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.Member);
|
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionMemberActions.Edit, ProjectPermissionSub.Member);
|
||||||
const { permission: targetUserPermission } = await permissionService.getProjectPermission({
|
const { permission: targetUserPermission } = await permissionService.getProjectPermission({
|
||||||
actor: ActorType.USER,
|
actor: ActorType.USER,
|
||||||
actorId: projectMembership.userId,
|
actorId: projectMembership.userId,
|
||||||
@@ -76,7 +80,14 @@ export const projectUserAdditionalPrivilegeServiceFactory = ({
|
|||||||
// we need to validate that the privilege given is not higher than the assigning users permission
|
// we need to validate that the privilege given is not higher than the assigning users permission
|
||||||
// @ts-expect-error this is expected error because of one being really accurate rule definition other being a bit more broader. Both are valid casl rules
|
// @ts-expect-error this is expected error because of one being really accurate rule definition other being a bit more broader. Both are valid casl rules
|
||||||
targetUserPermission.update(targetUserPermission.rules.concat(customPermission));
|
targetUserPermission.update(targetUserPermission.rules.concat(customPermission));
|
||||||
const hasRequiredPriviledges = isAtLeastAsPrivileged(permission, targetUserPermission);
|
|
||||||
|
const hasRequiredPriviledges = validatePrivilegeChangeOperation(
|
||||||
|
ProjectPermissionMemberActions.ManagePrivileges,
|
||||||
|
ProjectPermissionSub.Member,
|
||||||
|
permission,
|
||||||
|
targetUserPermission
|
||||||
|
);
|
||||||
|
|
||||||
if (!hasRequiredPriviledges)
|
if (!hasRequiredPriviledges)
|
||||||
throw new ForbiddenRequestError({ message: "Failed to update more privileged identity" });
|
throw new ForbiddenRequestError({ message: "Failed to update more privileged identity" });
|
||||||
|
|
||||||
@@ -150,7 +161,7 @@ export const projectUserAdditionalPrivilegeServiceFactory = ({
|
|||||||
actorOrgId,
|
actorOrgId,
|
||||||
actionProjectType: ActionProjectType.Any
|
actionProjectType: ActionProjectType.Any
|
||||||
});
|
});
|
||||||
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.Member);
|
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionMemberActions.Edit, ProjectPermissionSub.Member);
|
||||||
const { permission: targetUserPermission } = await permissionService.getProjectPermission({
|
const { permission: targetUserPermission } = await permissionService.getProjectPermission({
|
||||||
actor: ActorType.USER,
|
actor: ActorType.USER,
|
||||||
actorId: projectMembership.userId,
|
actorId: projectMembership.userId,
|
||||||
@@ -163,8 +174,13 @@ export const projectUserAdditionalPrivilegeServiceFactory = ({
|
|||||||
// we need to validate that the privilege given is not higher than the assigning users permission
|
// we need to validate that the privilege given is not higher than the assigning users permission
|
||||||
// @ts-expect-error this is expected error because of one being really accurate rule definition other being a bit more broader. Both are valid casl rules
|
// @ts-expect-error this is expected error because of one being really accurate rule definition other being a bit more broader. Both are valid casl rules
|
||||||
targetUserPermission.update(targetUserPermission.rules.concat(dto.permissions || []));
|
targetUserPermission.update(targetUserPermission.rules.concat(dto.permissions || []));
|
||||||
const hasRequiredPriviledges = isAtLeastAsPrivileged(permission, targetUserPermission);
|
const hasRequiredPrivileges = validatePrivilegeChangeOperation(
|
||||||
if (!hasRequiredPriviledges)
|
ProjectPermissionMemberActions.ManagePrivileges,
|
||||||
|
ProjectPermissionSub.Member,
|
||||||
|
permission,
|
||||||
|
targetUserPermission
|
||||||
|
);
|
||||||
|
if (!hasRequiredPrivileges)
|
||||||
throw new ForbiddenRequestError({ message: "Failed to update more privileged identity" });
|
throw new ForbiddenRequestError({ message: "Failed to update more privileged identity" });
|
||||||
|
|
||||||
if (dto?.slug) {
|
if (dto?.slug) {
|
||||||
@@ -236,7 +252,7 @@ export const projectUserAdditionalPrivilegeServiceFactory = ({
|
|||||||
actorOrgId,
|
actorOrgId,
|
||||||
actionProjectType: ActionProjectType.Any
|
actionProjectType: ActionProjectType.Any
|
||||||
});
|
});
|
||||||
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.Member);
|
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionMemberActions.Edit, ProjectPermissionSub.Member);
|
||||||
|
|
||||||
const deletedPrivilege = await projectUserAdditionalPrivilegeDAL.deleteById(userPrivilege.id);
|
const deletedPrivilege = await projectUserAdditionalPrivilegeDAL.deleteById(userPrivilege.id);
|
||||||
return {
|
return {
|
||||||
@@ -273,7 +289,7 @@ export const projectUserAdditionalPrivilegeServiceFactory = ({
|
|||||||
actorOrgId,
|
actorOrgId,
|
||||||
actionProjectType: ActionProjectType.Any
|
actionProjectType: ActionProjectType.Any
|
||||||
});
|
});
|
||||||
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Member);
|
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionMemberActions.Read, ProjectPermissionSub.Member);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...userPrivilege,
|
...userPrivilege,
|
||||||
@@ -300,7 +316,7 @@ export const projectUserAdditionalPrivilegeServiceFactory = ({
|
|||||||
actorOrgId,
|
actorOrgId,
|
||||||
actionProjectType: ActionProjectType.Any
|
actionProjectType: ActionProjectType.Any
|
||||||
});
|
});
|
||||||
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Member);
|
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionMemberActions.Read, ProjectPermissionSub.Member);
|
||||||
|
|
||||||
const userPrivileges = await projectUserAdditionalPrivilegeDAL.find(
|
const userPrivileges = await projectUserAdditionalPrivilegeDAL.find(
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -2,9 +2,9 @@ import { ForbiddenError } from "@casl/ability";
|
|||||||
import ms from "ms";
|
import ms from "ms";
|
||||||
|
|
||||||
import { ActionProjectType, ProjectMembershipRole, SecretKeyEncoding, TGroups } from "@app/db/schemas";
|
import { ActionProjectType, ProjectMembershipRole, SecretKeyEncoding, TGroups } from "@app/db/schemas";
|
||||||
|
import { validatePrivilegeChangeOperation } from "@app/ee/services/permission/permission-fns";
|
||||||
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service";
|
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service";
|
||||||
import { ProjectPermissionActions, ProjectPermissionSub } from "@app/ee/services/permission/project-permission";
|
import { ProjectPermissionGroupActions, ProjectPermissionSub } from "@app/ee/services/permission/project-permission";
|
||||||
import { isAtLeastAsPrivileged } from "@app/lib/casl";
|
|
||||||
import { decryptAsymmetric, encryptAsymmetric } from "@app/lib/crypto";
|
import { decryptAsymmetric, encryptAsymmetric } from "@app/lib/crypto";
|
||||||
import { infisicalSymmetricDecrypt } from "@app/lib/crypto/encryption";
|
import { infisicalSymmetricDecrypt } from "@app/lib/crypto/encryption";
|
||||||
import { BadRequestError, ForbiddenRequestError, NotFoundError } from "@app/lib/errors";
|
import { BadRequestError, ForbiddenRequestError, NotFoundError } from "@app/lib/errors";
|
||||||
@@ -78,7 +78,7 @@ export const groupProjectServiceFactory = ({
|
|||||||
actorOrgId,
|
actorOrgId,
|
||||||
actionProjectType: ActionProjectType.Any
|
actionProjectType: ActionProjectType.Any
|
||||||
});
|
});
|
||||||
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Create, ProjectPermissionSub.Groups);
|
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionGroupActions.Create, ProjectPermissionSub.Groups);
|
||||||
|
|
||||||
let group: TGroups | null = null;
|
let group: TGroups | null = null;
|
||||||
if (isUuidV4(groupIdOrName)) {
|
if (isUuidV4(groupIdOrName)) {
|
||||||
@@ -102,7 +102,12 @@ export const groupProjectServiceFactory = ({
|
|||||||
project.id
|
project.id
|
||||||
);
|
);
|
||||||
|
|
||||||
const hasRequiredPrivileges = isAtLeastAsPrivileged(permission, rolePermission);
|
const hasRequiredPrivileges = validatePrivilegeChangeOperation(
|
||||||
|
ProjectPermissionGroupActions.ManagePrivileges,
|
||||||
|
ProjectPermissionSub.Groups,
|
||||||
|
permission,
|
||||||
|
rolePermission
|
||||||
|
);
|
||||||
|
|
||||||
if (!hasRequiredPrivileges) {
|
if (!hasRequiredPrivileges) {
|
||||||
throw new ForbiddenRequestError({ message: "Failed to assign group to a more privileged role" });
|
throw new ForbiddenRequestError({ message: "Failed to assign group to a more privileged role" });
|
||||||
@@ -254,7 +259,7 @@ export const groupProjectServiceFactory = ({
|
|||||||
actorOrgId,
|
actorOrgId,
|
||||||
actionProjectType: ActionProjectType.Any
|
actionProjectType: ActionProjectType.Any
|
||||||
});
|
});
|
||||||
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.Groups);
|
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionGroupActions.Edit, ProjectPermissionSub.Groups);
|
||||||
|
|
||||||
const group = await groupDAL.findOne({ orgId: actorOrgId, id: groupId });
|
const group = await groupDAL.findOne({ orgId: actorOrgId, id: groupId });
|
||||||
if (!group) throw new NotFoundError({ message: `Failed to find group with ID ${groupId}` });
|
if (!group) throw new NotFoundError({ message: `Failed to find group with ID ${groupId}` });
|
||||||
@@ -268,7 +273,12 @@ export const groupProjectServiceFactory = ({
|
|||||||
project.id
|
project.id
|
||||||
);
|
);
|
||||||
|
|
||||||
const hasRequiredPrivileges = isAtLeastAsPrivileged(permission, rolePermission);
|
const hasRequiredPrivileges = validatePrivilegeChangeOperation(
|
||||||
|
ProjectPermissionGroupActions.ManagePrivileges,
|
||||||
|
ProjectPermissionSub.Groups,
|
||||||
|
permission,
|
||||||
|
rolePermission
|
||||||
|
);
|
||||||
|
|
||||||
if (!hasRequiredPrivileges) {
|
if (!hasRequiredPrivileges) {
|
||||||
throw new ForbiddenRequestError({ message: "Failed to assign group to a more privileged role" });
|
throw new ForbiddenRequestError({ message: "Failed to assign group to a more privileged role" });
|
||||||
@@ -357,7 +367,7 @@ export const groupProjectServiceFactory = ({
|
|||||||
actorOrgId,
|
actorOrgId,
|
||||||
actionProjectType: ActionProjectType.Any
|
actionProjectType: ActionProjectType.Any
|
||||||
});
|
});
|
||||||
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Delete, ProjectPermissionSub.Groups);
|
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionGroupActions.Delete, ProjectPermissionSub.Groups);
|
||||||
|
|
||||||
const deletedProjectGroup = await groupProjectDAL.transaction(async (tx) => {
|
const deletedProjectGroup = await groupProjectDAL.transaction(async (tx) => {
|
||||||
const groupMembers = await userGroupMembershipDAL.findGroupMembersNotInProject(group.id, project.id, tx);
|
const groupMembers = await userGroupMembershipDAL.findGroupMembersNotInProject(group.id, project.id, tx);
|
||||||
@@ -402,7 +412,7 @@ export const groupProjectServiceFactory = ({
|
|||||||
actorOrgId,
|
actorOrgId,
|
||||||
actionProjectType: ActionProjectType.Any
|
actionProjectType: ActionProjectType.Any
|
||||||
});
|
});
|
||||||
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Groups);
|
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionGroupActions.Read, ProjectPermissionSub.Groups);
|
||||||
|
|
||||||
const groupMemberships = await groupProjectDAL.findByProjectId(project.id);
|
const groupMemberships = await groupProjectDAL.findByProjectId(project.id);
|
||||||
return groupMemberships;
|
return groupMemberships;
|
||||||
@@ -430,7 +440,7 @@ export const groupProjectServiceFactory = ({
|
|||||||
actorOrgId,
|
actorOrgId,
|
||||||
actionProjectType: ActionProjectType.Any
|
actionProjectType: ActionProjectType.Any
|
||||||
});
|
});
|
||||||
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Groups);
|
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionGroupActions.Read, ProjectPermissionSub.Groups);
|
||||||
|
|
||||||
const [groupMembership] = await groupProjectDAL.findByProjectId(project.id, {
|
const [groupMembership] = await groupProjectDAL.findByProjectId(project.id, {
|
||||||
groupId
|
groupId
|
||||||
|
|||||||
@@ -2,13 +2,12 @@ import { ForbiddenError, subject } from "@casl/ability";
|
|||||||
import ms from "ms";
|
import ms from "ms";
|
||||||
|
|
||||||
import { ActionProjectType, ProjectMembershipRole } from "@app/db/schemas";
|
import { ActionProjectType, ProjectMembershipRole } from "@app/db/schemas";
|
||||||
|
import { validatePrivilegeChangeOperation } from "@app/ee/services/permission/permission-fns";
|
||||||
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service";
|
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service";
|
||||||
import { ProjectPermissionActions, ProjectPermissionSub } from "@app/ee/services/permission/project-permission";
|
import { ProjectPermissionIdentityActions, ProjectPermissionSub } from "@app/ee/services/permission/project-permission";
|
||||||
import { isAtLeastAsPrivileged } from "@app/lib/casl";
|
|
||||||
import { BadRequestError, ForbiddenRequestError, NotFoundError } from "@app/lib/errors";
|
import { BadRequestError, ForbiddenRequestError, NotFoundError } from "@app/lib/errors";
|
||||||
import { groupBy } from "@app/lib/fn";
|
import { groupBy } from "@app/lib/fn";
|
||||||
|
|
||||||
import { ActorType } from "../auth/auth-type";
|
|
||||||
import { TIdentityOrgDALFactory } from "../identity/identity-org-dal";
|
import { TIdentityOrgDALFactory } from "../identity/identity-org-dal";
|
||||||
import { TProjectDALFactory } from "../project/project-dal";
|
import { TProjectDALFactory } from "../project/project-dal";
|
||||||
import { ProjectUserMembershipTemporaryMode } from "../project-membership/project-membership-types";
|
import { ProjectUserMembershipTemporaryMode } from "../project-membership/project-membership-types";
|
||||||
@@ -63,7 +62,7 @@ export const identityProjectServiceFactory = ({
|
|||||||
actionProjectType: ActionProjectType.Any
|
actionProjectType: ActionProjectType.Any
|
||||||
});
|
});
|
||||||
ForbiddenError.from(permission).throwUnlessCan(
|
ForbiddenError.from(permission).throwUnlessCan(
|
||||||
ProjectPermissionActions.Create,
|
ProjectPermissionIdentityActions.Create,
|
||||||
subject(ProjectPermissionSub.Identity, {
|
subject(ProjectPermissionSub.Identity, {
|
||||||
identityId
|
identityId
|
||||||
})
|
})
|
||||||
@@ -91,7 +90,12 @@ export const identityProjectServiceFactory = ({
|
|||||||
projectId
|
projectId
|
||||||
);
|
);
|
||||||
|
|
||||||
const hasRequiredPriviledges = isAtLeastAsPrivileged(permission, rolePermission);
|
const hasRequiredPriviledges = validatePrivilegeChangeOperation(
|
||||||
|
ProjectPermissionIdentityActions.ManagePrivileges,
|
||||||
|
ProjectPermissionSub.Identity,
|
||||||
|
permission,
|
||||||
|
rolePermission
|
||||||
|
);
|
||||||
|
|
||||||
if (!hasRequiredPriviledges) {
|
if (!hasRequiredPriviledges) {
|
||||||
throw new ForbiddenRequestError({ message: "Failed to change to a more privileged role" });
|
throw new ForbiddenRequestError({ message: "Failed to change to a more privileged role" });
|
||||||
@@ -169,7 +173,7 @@ export const identityProjectServiceFactory = ({
|
|||||||
actionProjectType: ActionProjectType.Any
|
actionProjectType: ActionProjectType.Any
|
||||||
});
|
});
|
||||||
ForbiddenError.from(permission).throwUnlessCan(
|
ForbiddenError.from(permission).throwUnlessCan(
|
||||||
ProjectPermissionActions.Edit,
|
ProjectPermissionIdentityActions.Edit,
|
||||||
subject(ProjectPermissionSub.Identity, { identityId })
|
subject(ProjectPermissionSub.Identity, { identityId })
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -185,7 +189,13 @@ export const identityProjectServiceFactory = ({
|
|||||||
projectId
|
projectId
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!isAtLeastAsPrivileged(permission, rolePermission)) {
|
const hasRequiredPriviledges = validatePrivilegeChangeOperation(
|
||||||
|
ProjectPermissionIdentityActions.ManagePrivileges,
|
||||||
|
ProjectPermissionSub.Identity,
|
||||||
|
permission,
|
||||||
|
rolePermission
|
||||||
|
);
|
||||||
|
if (!hasRequiredPriviledges) {
|
||||||
throw new ForbiddenRequestError({ message: "Failed to change to a more privileged role" });
|
throw new ForbiddenRequestError({ message: "Failed to change to a more privileged role" });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -265,21 +275,10 @@ export const identityProjectServiceFactory = ({
|
|||||||
actionProjectType: ActionProjectType.Any
|
actionProjectType: ActionProjectType.Any
|
||||||
});
|
});
|
||||||
ForbiddenError.from(permission).throwUnlessCan(
|
ForbiddenError.from(permission).throwUnlessCan(
|
||||||
ProjectPermissionActions.Delete,
|
ProjectPermissionIdentityActions.Delete,
|
||||||
subject(ProjectPermissionSub.Identity, { identityId })
|
subject(ProjectPermissionSub.Identity, { identityId })
|
||||||
);
|
);
|
||||||
|
|
||||||
const { permission: identityRolePermission } = await permissionService.getProjectPermission({
|
|
||||||
actor: ActorType.IDENTITY,
|
|
||||||
actorId: identityId,
|
|
||||||
projectId: identityProjectMembership.projectId,
|
|
||||||
actorAuthMethod,
|
|
||||||
actorOrgId,
|
|
||||||
actionProjectType: ActionProjectType.Any
|
|
||||||
});
|
|
||||||
if (!isAtLeastAsPrivileged(permission, identityRolePermission))
|
|
||||||
throw new ForbiddenRequestError({ message: "Failed to delete more privileged identity" });
|
|
||||||
|
|
||||||
const [deletedIdentity] = await identityProjectDAL.delete({ identityId, projectId });
|
const [deletedIdentity] = await identityProjectDAL.delete({ identityId, projectId });
|
||||||
return deletedIdentity;
|
return deletedIdentity;
|
||||||
};
|
};
|
||||||
@@ -304,7 +303,10 @@ export const identityProjectServiceFactory = ({
|
|||||||
actorOrgId,
|
actorOrgId,
|
||||||
actionProjectType: ActionProjectType.Any
|
actionProjectType: ActionProjectType.Any
|
||||||
});
|
});
|
||||||
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Identity);
|
ForbiddenError.from(permission).throwUnlessCan(
|
||||||
|
ProjectPermissionIdentityActions.Read,
|
||||||
|
ProjectPermissionSub.Identity
|
||||||
|
);
|
||||||
|
|
||||||
const identityMemberships = await identityProjectDAL.findByProjectId(projectId, {
|
const identityMemberships = await identityProjectDAL.findByProjectId(projectId, {
|
||||||
limit,
|
limit,
|
||||||
@@ -337,7 +339,7 @@ export const identityProjectServiceFactory = ({
|
|||||||
});
|
});
|
||||||
|
|
||||||
ForbiddenError.from(permission).throwUnlessCan(
|
ForbiddenError.from(permission).throwUnlessCan(
|
||||||
ProjectPermissionActions.Read,
|
ProjectPermissionIdentityActions.Read,
|
||||||
subject(ProjectPermissionSub.Identity, { identityId })
|
subject(ProjectPermissionSub.Identity, { identityId })
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -4,10 +4,10 @@ import ms from "ms";
|
|||||||
|
|
||||||
import { ActionProjectType, ProjectMembershipRole, ProjectVersion, TableName } from "@app/db/schemas";
|
import { ActionProjectType, ProjectMembershipRole, ProjectVersion, TableName } from "@app/db/schemas";
|
||||||
import { TLicenseServiceFactory } from "@app/ee/services/license/license-service";
|
import { TLicenseServiceFactory } from "@app/ee/services/license/license-service";
|
||||||
|
import { validatePrivilegeChangeOperation } from "@app/ee/services/permission/permission-fns";
|
||||||
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service";
|
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service";
|
||||||
import { ProjectPermissionActions, ProjectPermissionSub } from "@app/ee/services/permission/project-permission";
|
import { ProjectPermissionMemberActions, ProjectPermissionSub } from "@app/ee/services/permission/project-permission";
|
||||||
import { TProjectUserAdditionalPrivilegeDALFactory } from "@app/ee/services/project-user-additional-privilege/project-user-additional-privilege-dal";
|
import { TProjectUserAdditionalPrivilegeDALFactory } from "@app/ee/services/project-user-additional-privilege/project-user-additional-privilege-dal";
|
||||||
import { isAtLeastAsPrivileged } from "@app/lib/casl";
|
|
||||||
import { getConfig } from "@app/lib/config/env";
|
import { getConfig } from "@app/lib/config/env";
|
||||||
import { BadRequestError, ForbiddenRequestError, NotFoundError } from "@app/lib/errors";
|
import { BadRequestError, ForbiddenRequestError, NotFoundError } from "@app/lib/errors";
|
||||||
import { groupBy } from "@app/lib/fn";
|
import { groupBy } from "@app/lib/fn";
|
||||||
@@ -86,7 +86,7 @@ export const projectMembershipServiceFactory = ({
|
|||||||
actorOrgId,
|
actorOrgId,
|
||||||
actionProjectType: ActionProjectType.Any
|
actionProjectType: ActionProjectType.Any
|
||||||
});
|
});
|
||||||
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Member);
|
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionMemberActions.Read, ProjectPermissionSub.Member);
|
||||||
|
|
||||||
const projectMembers = await projectMembershipDAL.findAllProjectMembers(projectId);
|
const projectMembers = await projectMembershipDAL.findAllProjectMembers(projectId);
|
||||||
|
|
||||||
@@ -130,7 +130,7 @@ export const projectMembershipServiceFactory = ({
|
|||||||
actorOrgId,
|
actorOrgId,
|
||||||
actionProjectType: ActionProjectType.Any
|
actionProjectType: ActionProjectType.Any
|
||||||
});
|
});
|
||||||
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Member);
|
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionMemberActions.Read, ProjectPermissionSub.Member);
|
||||||
|
|
||||||
const [membership] = await projectMembershipDAL.findAllProjectMembers(projectId, { username });
|
const [membership] = await projectMembershipDAL.findAllProjectMembers(projectId, { username });
|
||||||
if (!membership) throw new NotFoundError({ message: `Project membership not found for user '${username}'` });
|
if (!membership) throw new NotFoundError({ message: `Project membership not found for user '${username}'` });
|
||||||
@@ -153,7 +153,7 @@ export const projectMembershipServiceFactory = ({
|
|||||||
actorOrgId,
|
actorOrgId,
|
||||||
actionProjectType: ActionProjectType.Any
|
actionProjectType: ActionProjectType.Any
|
||||||
});
|
});
|
||||||
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Member);
|
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionMemberActions.Read, ProjectPermissionSub.Member);
|
||||||
|
|
||||||
const [membership] = await projectMembershipDAL.findAllProjectMembers(projectId, { id });
|
const [membership] = await projectMembershipDAL.findAllProjectMembers(projectId, { id });
|
||||||
if (!membership) throw new NotFoundError({ message: `Project membership not found for user ${id}` });
|
if (!membership) throw new NotFoundError({ message: `Project membership not found for user ${id}` });
|
||||||
@@ -180,7 +180,7 @@ export const projectMembershipServiceFactory = ({
|
|||||||
actorOrgId,
|
actorOrgId,
|
||||||
actionProjectType: ActionProjectType.Any
|
actionProjectType: ActionProjectType.Any
|
||||||
});
|
});
|
||||||
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Create, ProjectPermissionSub.Member);
|
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionMemberActions.Create, ProjectPermissionSub.Member);
|
||||||
const orgMembers = await orgDAL.findMembership({
|
const orgMembers = await orgDAL.findMembership({
|
||||||
[`${TableName.OrgMembership}.orgId` as "orgId"]: project.orgId,
|
[`${TableName.OrgMembership}.orgId` as "orgId"]: project.orgId,
|
||||||
$in: {
|
$in: {
|
||||||
@@ -261,7 +261,7 @@ export const projectMembershipServiceFactory = ({
|
|||||||
actorOrgId,
|
actorOrgId,
|
||||||
actionProjectType: ActionProjectType.Any
|
actionProjectType: ActionProjectType.Any
|
||||||
});
|
});
|
||||||
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.Member);
|
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionMemberActions.Edit, ProjectPermissionSub.Member);
|
||||||
|
|
||||||
const membershipUser = await userDAL.findUserByProjectMembershipId(membershipId);
|
const membershipUser = await userDAL.findUserByProjectMembershipId(membershipId);
|
||||||
if (membershipUser?.isGhost || membershipUser?.projectId !== projectId) {
|
if (membershipUser?.isGhost || membershipUser?.projectId !== projectId) {
|
||||||
@@ -274,7 +274,12 @@ export const projectMembershipServiceFactory = ({
|
|||||||
projectId
|
projectId
|
||||||
);
|
);
|
||||||
|
|
||||||
const hasRequiredPriviledges = isAtLeastAsPrivileged(permission, rolePermission);
|
const hasRequiredPriviledges = validatePrivilegeChangeOperation(
|
||||||
|
ProjectPermissionMemberActions.ManagePrivileges,
|
||||||
|
ProjectPermissionSub.Member,
|
||||||
|
permission,
|
||||||
|
rolePermission
|
||||||
|
);
|
||||||
|
|
||||||
if (!hasRequiredPriviledges) {
|
if (!hasRequiredPriviledges) {
|
||||||
throw new ForbiddenRequestError({
|
throw new ForbiddenRequestError({
|
||||||
@@ -361,7 +366,7 @@ export const projectMembershipServiceFactory = ({
|
|||||||
actorOrgId,
|
actorOrgId,
|
||||||
actionProjectType: ActionProjectType.Any
|
actionProjectType: ActionProjectType.Any
|
||||||
});
|
});
|
||||||
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Delete, ProjectPermissionSub.Member);
|
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionMemberActions.Delete, ProjectPermissionSub.Member);
|
||||||
|
|
||||||
const member = await userDAL.findUserByProjectMembershipId(membershipId);
|
const member = await userDAL.findUserByProjectMembershipId(membershipId);
|
||||||
|
|
||||||
@@ -397,7 +402,7 @@ export const projectMembershipServiceFactory = ({
|
|||||||
actorOrgId,
|
actorOrgId,
|
||||||
actionProjectType: ActionProjectType.Any
|
actionProjectType: ActionProjectType.Any
|
||||||
});
|
});
|
||||||
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Delete, ProjectPermissionSub.Member);
|
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionMemberActions.Delete, ProjectPermissionSub.Member);
|
||||||
|
|
||||||
const project = await projectDAL.findById(projectId);
|
const project = await projectDAL.findById(projectId);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user