misc: added privilege version checks

This commit is contained in:
Sheen Capadngan
2025-03-14 01:59:07 +08:00
parent fc651f6645
commit dc2358bbaa
20 changed files with 119 additions and 46 deletions
+10 -4
View File
@@ -67,7 +67,7 @@ export const groupServiceFactory = ({
const createGroup = async ({ name, slug, role, actor, actorId, actorAuthMethod, actorOrgId }: TCreateGroupDTO) => { const createGroup = async ({ name, slug, role, actor, actorId, actorAuthMethod, actorOrgId }: TCreateGroupDTO) => {
if (!actorOrgId) throw new UnauthorizedError({ message: "No organization ID provided in request" }); if (!actorOrgId) throw new UnauthorizedError({ message: "No organization ID provided in request" });
const { permission } = await permissionService.getOrgPermission( const { permission, membership } = await permissionService.getOrgPermission(
actor, actor,
actorId, actorId,
actorOrgId, actorOrgId,
@@ -89,6 +89,7 @@ export const groupServiceFactory = ({
const isCustomRole = Boolean(customRole); const isCustomRole = Boolean(customRole);
const permissionBoundary = validatePrivilegeChangeOperation( const permissionBoundary = validatePrivilegeChangeOperation(
membership.shouldUseNewPrivilegeSystem,
OrgPermissionGroupActions.ManagePrivileges, OrgPermissionGroupActions.ManagePrivileges,
OrgPermissionSubjects.Groups, OrgPermissionSubjects.Groups,
permission, permission,
@@ -138,13 +139,14 @@ export const groupServiceFactory = ({
}: TUpdateGroupDTO) => { }: TUpdateGroupDTO) => {
if (!actorOrgId) throw new UnauthorizedError({ message: "No organization ID provided in request" }); if (!actorOrgId) throw new UnauthorizedError({ message: "No organization ID provided in request" });
const { permission } = await permissionService.getOrgPermission( const { permission, membership } = await permissionService.getOrgPermission(
actor, actor,
actorId, actorId,
actorOrgId, actorOrgId,
actorAuthMethod, actorAuthMethod,
actorOrgId actorOrgId
); );
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionGroupActions.Edit, OrgPermissionSubjects.Groups); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionGroupActions.Edit, OrgPermissionSubjects.Groups);
const plan = await licenseService.getPlan(actorOrgId); const plan = await licenseService.getPlan(actorOrgId);
@@ -167,6 +169,7 @@ export const groupServiceFactory = ({
const isCustomRole = Boolean(customOrgRole); const isCustomRole = Boolean(customOrgRole);
const permissionBoundary = validatePrivilegeChangeOperation( const permissionBoundary = validatePrivilegeChangeOperation(
membership.shouldUseNewPrivilegeSystem,
OrgPermissionGroupActions.ManagePrivileges, OrgPermissionGroupActions.ManagePrivileges,
OrgPermissionSubjects.Groups, OrgPermissionSubjects.Groups,
permission, permission,
@@ -313,7 +316,7 @@ export const groupServiceFactory = ({
const addUserToGroup = async ({ id, username, actor, actorId, actorAuthMethod, actorOrgId }: TAddUserToGroupDTO) => { const addUserToGroup = async ({ id, username, actor, actorId, actorAuthMethod, actorOrgId }: TAddUserToGroupDTO) => {
if (!actorOrgId) throw new UnauthorizedError({ message: "No organization ID provided in request" }); if (!actorOrgId) throw new UnauthorizedError({ message: "No organization ID provided in request" });
const { permission } = await permissionService.getOrgPermission( const { permission, membership } = await permissionService.getOrgPermission(
actor, actor,
actorId, actorId,
actorOrgId, actorOrgId,
@@ -349,11 +352,13 @@ export const groupServiceFactory = ({
// check if user has broader or equal to privileges than group // check if user has broader or equal to privileges than group
const permissionBoundary = validatePrivilegeChangeOperation( const permissionBoundary = validatePrivilegeChangeOperation(
membership.shouldUseNewPrivilegeSystem,
OrgPermissionGroupActions.AddMembers, OrgPermissionGroupActions.AddMembers,
OrgPermissionSubjects.Groups, OrgPermissionSubjects.Groups,
permission, permission,
groupRolePermission groupRolePermission
); );
if (!permissionBoundary.isValid) if (!permissionBoundary.isValid)
throw new ForbiddenRequestError({ throw new ForbiddenRequestError({
name: "PermissionBoundaryError", name: "PermissionBoundaryError",
@@ -389,7 +394,7 @@ export const groupServiceFactory = ({
}: TRemoveUserFromGroupDTO) => { }: TRemoveUserFromGroupDTO) => {
if (!actorOrgId) throw new UnauthorizedError({ message: "No organization ID provided in request" }); if (!actorOrgId) throw new UnauthorizedError({ message: "No organization ID provided in request" });
const { permission } = await permissionService.getOrgPermission( const { permission, membership } = await permissionService.getOrgPermission(
actor, actor,
actorId, actorId,
actorOrgId, actorOrgId,
@@ -425,6 +430,7 @@ export const groupServiceFactory = ({
// check if user has broader or equal to privileges than group // check if user has broader or equal to privileges than group
const permissionBoundary = validatePrivilegeChangeOperation( const permissionBoundary = validatePrivilegeChangeOperation(
membership.shouldUseNewPrivilegeSystem,
OrgPermissionGroupActions.RemoveMembers, OrgPermissionGroupActions.RemoveMembers,
OrgPermissionSubjects.Groups, OrgPermissionSubjects.Groups,
permission, permission,
@@ -67,7 +67,7 @@ export const identityProjectAdditionalPrivilegeV2ServiceFactory = ({
ProjectPermissionIdentityActions.Edit, ProjectPermissionIdentityActions.Edit,
subject(ProjectPermissionSub.Identity, { identityId }) subject(ProjectPermissionSub.Identity, { identityId })
); );
const { permission: targetIdentityPermission } = await permissionService.getProjectPermission({ const { permission: targetIdentityPermission, membership } = await permissionService.getProjectPermission({
actor: ActorType.IDENTITY, actor: ActorType.IDENTITY,
actorId: identityId, actorId: identityId,
projectId: identityProjectMembership.projectId, projectId: identityProjectMembership.projectId,
@@ -80,6 +80,7 @@ export const identityProjectAdditionalPrivilegeV2ServiceFactory = ({
// @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 permissionBoundary = validatePrivilegeChangeOperation( const permissionBoundary = validatePrivilegeChangeOperation(
membership.shouldUseNewPrivilegeSystem,
ProjectPermissionIdentityActions.ManagePrivileges, ProjectPermissionIdentityActions.ManagePrivileges,
ProjectPermissionSub.Identity, ProjectPermissionSub.Identity,
permission, permission,
@@ -158,7 +159,7 @@ export const identityProjectAdditionalPrivilegeV2ServiceFactory = ({
ProjectPermissionIdentityActions.Edit, ProjectPermissionIdentityActions.Edit,
subject(ProjectPermissionSub.Identity, { identityId: identityProjectMembership.identityId }) subject(ProjectPermissionSub.Identity, { identityId: identityProjectMembership.identityId })
); );
const { permission: targetIdentityPermission } = await permissionService.getProjectPermission({ const { permission: targetIdentityPermission, membership } = await permissionService.getProjectPermission({
actor: ActorType.IDENTITY, actor: ActorType.IDENTITY,
actorId: identityProjectMembership.identityId, actorId: identityProjectMembership.identityId,
projectId: identityProjectMembership.projectId, projectId: identityProjectMembership.projectId,
@@ -171,6 +172,7 @@ export const identityProjectAdditionalPrivilegeV2ServiceFactory = ({
// @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 permissionBoundary = validatePrivilegeChangeOperation( const permissionBoundary = validatePrivilegeChangeOperation(
membership.shouldUseNewPrivilegeSystem,
ProjectPermissionIdentityActions.ManagePrivileges, ProjectPermissionIdentityActions.ManagePrivileges,
ProjectPermissionSub.Identity, ProjectPermissionSub.Identity,
permission, permission,
@@ -237,7 +239,7 @@ export const identityProjectAdditionalPrivilegeV2ServiceFactory = ({
message: `Failed to find identity with membership ${identityPrivilege.projectMembershipId}` message: `Failed to find identity with membership ${identityPrivilege.projectMembershipId}`
}); });
const { permission } = await permissionService.getProjectPermission({ const { permission, membership } = await permissionService.getProjectPermission({
actor, actor,
actorId, actorId,
projectId: identityProjectMembership.projectId, projectId: identityProjectMembership.projectId,
@@ -258,6 +260,7 @@ export const identityProjectAdditionalPrivilegeV2ServiceFactory = ({
actionProjectType: ActionProjectType.Any actionProjectType: ActionProjectType.Any
}); });
const permissionBoundary = validatePrivilegeChangeOperation( const permissionBoundary = validatePrivilegeChangeOperation(
membership.shouldUseNewPrivilegeSystem,
ProjectPermissionIdentityActions.ManagePrivileges, ProjectPermissionIdentityActions.ManagePrivileges,
ProjectPermissionSub.Identity, ProjectPermissionSub.Identity,
permission, permission,
@@ -67,7 +67,7 @@ export const identityProjectAdditionalPrivilegeServiceFactory = ({
if (!identityProjectMembership) if (!identityProjectMembership)
throw new NotFoundError({ message: `Failed to find identity with id ${identityId}` }); throw new NotFoundError({ message: `Failed to find identity with id ${identityId}` });
const { permission } = await permissionService.getProjectPermission({ const { permission, membership } = await permissionService.getProjectPermission({
actor, actor,
actorId, actorId,
projectId: identityProjectMembership.projectId, projectId: identityProjectMembership.projectId,
@@ -94,6 +94,7 @@ export const identityProjectAdditionalPrivilegeServiceFactory = ({
// @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 permissionBoundary = validatePrivilegeChangeOperation( const permissionBoundary = validatePrivilegeChangeOperation(
membership.shouldUseNewPrivilegeSystem,
ProjectPermissionIdentityActions.ManagePrivileges, ProjectPermissionIdentityActions.ManagePrivileges,
ProjectPermissionSub.Identity, ProjectPermissionSub.Identity,
permission, permission,
@@ -160,7 +161,7 @@ export const identityProjectAdditionalPrivilegeServiceFactory = ({
if (!identityProjectMembership) if (!identityProjectMembership)
throw new NotFoundError({ message: `Failed to find identity with id ${identityId}` }); throw new NotFoundError({ message: `Failed to find identity with id ${identityId}` });
const { permission } = await permissionService.getProjectPermission({ const { permission, membership } = await permissionService.getProjectPermission({
actor, actor,
actorId, actorId,
projectId: identityProjectMembership.projectId, projectId: identityProjectMembership.projectId,
@@ -187,6 +188,7 @@ export const identityProjectAdditionalPrivilegeServiceFactory = ({
// @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 permissionBoundary = validatePrivilegeChangeOperation( const permissionBoundary = validatePrivilegeChangeOperation(
membership.shouldUseNewPrivilegeSystem,
ProjectPermissionIdentityActions.ManagePrivileges, ProjectPermissionIdentityActions.ManagePrivileges,
ProjectPermissionSub.Identity, ProjectPermissionSub.Identity,
permission, permission,
@@ -270,7 +272,7 @@ export const identityProjectAdditionalPrivilegeServiceFactory = ({
if (!identityProjectMembership) if (!identityProjectMembership)
throw new NotFoundError({ message: `Failed to find identity with id ${identityId}` }); throw new NotFoundError({ message: `Failed to find identity with id ${identityId}` });
const { permission } = await permissionService.getProjectPermission({ const { permission, membership } = await permissionService.getProjectPermission({
actor, actor,
actorId, actorId,
projectId: identityProjectMembership.projectId, projectId: identityProjectMembership.projectId,
@@ -292,6 +294,7 @@ export const identityProjectAdditionalPrivilegeServiceFactory = ({
actionProjectType: ActionProjectType.Any actionProjectType: ActionProjectType.Any
}); });
const permissionBoundary = validatePrivilegeChangeOperation( const permissionBoundary = validatePrivilegeChangeOperation(
membership.shouldUseNewPrivilegeSystem,
ProjectPermissionIdentityActions.ManagePrivileges, ProjectPermissionIdentityActions.ManagePrivileges,
ProjectPermissionSub.Identity, ProjectPermissionSub.Identity,
permission, permission,
@@ -49,6 +49,7 @@ export const permissionDALFactory = (db: TDbClient) => {
.join(TableName.Organization, `${TableName.Organization}.id`, `${TableName.OrgMembership}.orgId`) .join(TableName.Organization, `${TableName.Organization}.id`, `${TableName.OrgMembership}.orgId`)
.select( .select(
selectAllTableCols(TableName.OrgMembership), selectAllTableCols(TableName.OrgMembership),
db.ref("shouldUseNewPrivilegeSystem").withSchema(TableName.Organization),
db.ref("slug").withSchema(TableName.OrgRoles).withSchema(TableName.OrgRoles).as("customRoleSlug"), db.ref("slug").withSchema(TableName.OrgRoles).withSchema(TableName.OrgRoles).as("customRoleSlug"),
db.ref("permissions").withSchema(TableName.OrgRoles), db.ref("permissions").withSchema(TableName.OrgRoles),
db.ref("authEnforced").withSchema(TableName.Organization).as("orgAuthEnforced"), db.ref("authEnforced").withSchema(TableName.Organization).as("orgAuthEnforced"),
@@ -70,7 +71,8 @@ export const permissionDALFactory = (db: TDbClient) => {
OrgMembershipsSchema.extend({ OrgMembershipsSchema.extend({
permissions: z.unknown(), permissions: z.unknown(),
orgAuthEnforced: z.boolean().optional().nullable(), orgAuthEnforced: z.boolean().optional().nullable(),
customRoleSlug: z.string().optional().nullable() customRoleSlug: z.string().optional().nullable(),
shouldUseNewPrivilegeSystem: z.boolean()
}).parse(el), }).parse(el),
childrenMapper: [ childrenMapper: [
{ {
@@ -118,7 +120,9 @@ export const permissionDALFactory = (db: TDbClient) => {
.select(selectAllTableCols(TableName.IdentityOrgMembership)) .select(selectAllTableCols(TableName.IdentityOrgMembership))
.select(db.ref("authEnforced").withSchema(TableName.Organization).as("orgAuthEnforced")) .select(db.ref("authEnforced").withSchema(TableName.Organization).as("orgAuthEnforced"))
.select("permissions") .select("permissions")
.select(db.ref("shouldUseNewPrivilegeSystem").withSchema(TableName.Organization))
.first(); .first();
return membership; return membership;
} catch (error) { } catch (error) {
throw new DatabaseError({ error, name: "GetOrgIdentityPermission" }); throw new DatabaseError({ error, name: "GetOrgIdentityPermission" });
@@ -668,7 +672,8 @@ export const permissionDALFactory = (db: TDbClient) => {
db.ref("authEnforced").withSchema(TableName.Organization).as("orgAuthEnforced"), db.ref("authEnforced").withSchema(TableName.Organization).as("orgAuthEnforced"),
db.ref("orgId").withSchema(TableName.Project), db.ref("orgId").withSchema(TableName.Project),
db.ref("type").withSchema(TableName.Project).as("projectType"), db.ref("type").withSchema(TableName.Project).as("projectType"),
db.ref("id").withSchema(TableName.Project).as("projectId") db.ref("id").withSchema(TableName.Project).as("projectId"),
db.ref("shouldUseNewPrivilegeSystem").withSchema(TableName.Organization)
); );
const [userPermission] = sqlNestRelationships({ const [userPermission] = sqlNestRelationships({
@@ -684,7 +689,8 @@ export const permissionDALFactory = (db: TDbClient) => {
groupMembershipCreatedAt, groupMembershipCreatedAt,
groupMembershipUpdatedAt, groupMembershipUpdatedAt,
membershipUpdatedAt, membershipUpdatedAt,
projectType projectType,
shouldUseNewPrivilegeSystem
}) => ({ }) => ({
orgId, orgId,
orgAuthEnforced, orgAuthEnforced,
@@ -694,7 +700,8 @@ export const permissionDALFactory = (db: TDbClient) => {
projectType, projectType,
id: membershipId || groupMembershipId, id: membershipId || groupMembershipId,
createdAt: membershipCreatedAt || groupMembershipCreatedAt, createdAt: membershipCreatedAt || groupMembershipCreatedAt,
updatedAt: membershipUpdatedAt || groupMembershipUpdatedAt updatedAt: membershipUpdatedAt || groupMembershipUpdatedAt,
shouldUseNewPrivilegeSystem
}), }),
childrenMapper: [ childrenMapper: [
{ {
@@ -995,6 +1002,7 @@ export const permissionDALFactory = (db: TDbClient) => {
`${TableName.IdentityProjectMembership}.projectId`, `${TableName.IdentityProjectMembership}.projectId`,
`${TableName.Project}.id` `${TableName.Project}.id`
) )
.join(TableName.Organization, `${TableName.Project}.orgId`, `${TableName.Organization}.id`)
.leftJoin(TableName.IdentityMetadata, (queryBuilder) => { .leftJoin(TableName.IdentityMetadata, (queryBuilder) => {
void queryBuilder void queryBuilder
.on(`${TableName.Identity}.id`, `${TableName.IdentityMetadata}.identityId`) .on(`${TableName.Identity}.id`, `${TableName.IdentityMetadata}.identityId`)
@@ -1012,6 +1020,7 @@ export const permissionDALFactory = (db: TDbClient) => {
db.ref("updatedAt").withSchema(TableName.IdentityProjectMembership).as("membershipUpdatedAt"), db.ref("updatedAt").withSchema(TableName.IdentityProjectMembership).as("membershipUpdatedAt"),
db.ref("slug").withSchema(TableName.ProjectRoles).as("customRoleSlug"), db.ref("slug").withSchema(TableName.ProjectRoles).as("customRoleSlug"),
db.ref("permissions").withSchema(TableName.ProjectRoles), db.ref("permissions").withSchema(TableName.ProjectRoles),
db.ref("shouldUseNewPrivilegeSystem").withSchema(TableName.Organization),
db.ref("id").withSchema(TableName.IdentityProjectAdditionalPrivilege).as("identityApId"), db.ref("id").withSchema(TableName.IdentityProjectAdditionalPrivilege).as("identityApId"),
db.ref("permissions").withSchema(TableName.IdentityProjectAdditionalPrivilege).as("identityApPermissions"), db.ref("permissions").withSchema(TableName.IdentityProjectAdditionalPrivilege).as("identityApPermissions"),
db db
@@ -1045,7 +1054,8 @@ export const permissionDALFactory = (db: TDbClient) => {
membershipUpdatedAt, membershipUpdatedAt,
orgId, orgId,
identityName, identityName,
projectType projectType,
shouldUseNewPrivilegeSystem
}) => ({ }) => ({
id: membershipId, id: membershipId,
identityId, identityId,
@@ -1055,6 +1065,7 @@ export const permissionDALFactory = (db: TDbClient) => {
updatedAt: membershipUpdatedAt, updatedAt: membershipUpdatedAt,
orgId, orgId,
projectType, projectType,
shouldUseNewPrivilegeSystem,
// just a prefilled value // just a prefilled value
orgAuthEnforced: false orgAuthEnforced: false
}), }),
@@ -152,16 +152,28 @@ const escapeHandlebarsMissingMetadata = (obj: Record<string, string>) => {
// the new privilege management system is based on the actor having the appropriate permission to perform the privilege change, // the new privilege management system is based on the actor having the appropriate permission to perform the privilege change,
// regardless of the actor's privilege level. // regardless of the actor's privilege level.
const validatePrivilegeChangeOperation = ( const validatePrivilegeChangeOperation = (
shouldUseNewPrivilegeSystem: boolean,
opAction: OrgPermissionSet[0] | ProjectPermissionSet[0], opAction: OrgPermissionSet[0] | ProjectPermissionSet[0],
opSubject: OrgPermissionSet[1] | ProjectPermissionSet[1], opSubject: OrgPermissionSet[1] | ProjectPermissionSet[1],
actorPermission: MongoAbility, actorPermission: MongoAbility,
managedPermission: MongoAbility managedPermission: MongoAbility
) => { ) => {
// first we ensure if the actor has the permission to manage the privilege if (shouldUseNewPrivilegeSystem) {
if (actorPermission.can(opAction, opSubject)) { if (actorPermission.can(opAction, opSubject)) {
return {
isValid: true,
missingPermissions: []
};
}
return { return {
isValid: true, isValid: false,
missingPermissions: [] missingPermissions: [
{
action: opAction,
subject: opSubject
}
]
}; };
} }
@@ -390,14 +390,18 @@ export const permissionServiceFactory = ({
const scopes = ServiceTokenScopes.parse(serviceToken.scopes || []); const scopes = ServiceTokenScopes.parse(serviceToken.scopes || []);
return { return {
permission: buildServiceTokenProjectPermission(scopes, serviceToken.permissions), permission: buildServiceTokenProjectPermission(scopes, serviceToken.permissions),
membership: undefined membership: {
shouldUseNewPrivilegeSystem: true
}
}; };
}; };
type TProjectPermissionRT<T extends ActorType> = T extends ActorType.SERVICE type TProjectPermissionRT<T extends ActorType> = T extends ActorType.SERVICE
? { ? {
permission: MongoAbility<ProjectPermissionSet, MongoQuery>; permission: MongoAbility<ProjectPermissionSet, MongoQuery>;
membership: undefined; membership: {
shouldUseNewPrivilegeSystem: boolean;
};
hasRole: (arg: string) => boolean; hasRole: (arg: string) => boolean;
} // service token doesn't have both membership and roles } // service token doesn't have both membership and roles
: { : {
@@ -406,6 +410,7 @@ export const permissionServiceFactory = ({
orgAuthEnforced: boolean | null | undefined; orgAuthEnforced: boolean | null | undefined;
orgId: string; orgId: string;
roles: Array<{ role: string }>; roles: Array<{ role: string }>;
shouldUseNewPrivilegeSystem: boolean;
}; };
hasRole: (role: string) => boolean; hasRole: (role: string) => boolean;
}; };
@@ -68,7 +68,7 @@ export const projectUserAdditionalPrivilegeServiceFactory = ({
actionProjectType: ActionProjectType.Any actionProjectType: ActionProjectType.Any
}); });
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionMemberActions.Edit, ProjectPermissionSub.Member); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionMemberActions.Edit, ProjectPermissionSub.Member);
const { permission: targetUserPermission } = await permissionService.getProjectPermission({ const { permission: targetUserPermission, membership } = await permissionService.getProjectPermission({
actor: ActorType.USER, actor: ActorType.USER,
actorId: projectMembership.userId, actorId: projectMembership.userId,
projectId: projectMembership.projectId, projectId: projectMembership.projectId,
@@ -81,6 +81,7 @@ export const projectUserAdditionalPrivilegeServiceFactory = ({
// @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 permissionBoundary = validatePrivilegeChangeOperation( const permissionBoundary = validatePrivilegeChangeOperation(
membership.shouldUseNewPrivilegeSystem,
ProjectPermissionMemberActions.ManagePrivileges, ProjectPermissionMemberActions.ManagePrivileges,
ProjectPermissionSub.Member, ProjectPermissionSub.Member,
permission, permission,
@@ -155,7 +156,7 @@ export const projectUserAdditionalPrivilegeServiceFactory = ({
message: `Project membership for user with ID '${userPrivilege.userId}' not found in project with ID '${userPrivilege.projectId}'` message: `Project membership for user with ID '${userPrivilege.userId}' not found in project with ID '${userPrivilege.projectId}'`
}); });
const { permission } = await permissionService.getProjectPermission({ const { permission, membership } = await permissionService.getProjectPermission({
actor, actor,
actorId, actorId,
projectId: projectMembership.projectId, projectId: projectMembership.projectId,
@@ -177,6 +178,7 @@ export const projectUserAdditionalPrivilegeServiceFactory = ({
// @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 permissionBoundary = validatePrivilegeChangeOperation( const permissionBoundary = validatePrivilegeChangeOperation(
membership.shouldUseNewPrivilegeSystem,
ProjectPermissionMemberActions.ManagePrivileges, ProjectPermissionMemberActions.ManagePrivileges,
ProjectPermissionSub.Member, ProjectPermissionSub.Member,
permission, permission,
@@ -70,7 +70,7 @@ export const groupProjectServiceFactory = ({
if (!project) throw new NotFoundError({ message: `Failed to find project with ID ${projectId}` }); if (!project) throw new NotFoundError({ message: `Failed to find project with ID ${projectId}` });
if (project.version < 2) throw new BadRequestError({ message: `Failed to add group to E2EE project` }); if (project.version < 2) throw new BadRequestError({ message: `Failed to add group to E2EE project` });
const { permission } = await permissionService.getProjectPermission({ const { permission, membership } = await permissionService.getProjectPermission({
actor, actor,
actorId, actorId,
projectId, projectId,
@@ -103,6 +103,7 @@ export const groupProjectServiceFactory = ({
); );
const permissionBoundary = validatePrivilegeChangeOperation( const permissionBoundary = validatePrivilegeChangeOperation(
membership.shouldUseNewPrivilegeSystem,
ProjectPermissionGroupActions.ManagePrivileges, ProjectPermissionGroupActions.ManagePrivileges,
ProjectPermissionSub.Groups, ProjectPermissionSub.Groups,
permission, permission,
@@ -253,7 +254,7 @@ export const groupProjectServiceFactory = ({
if (!project) throw new NotFoundError({ message: `Failed to find project with ID ${projectId}` }); if (!project) throw new NotFoundError({ message: `Failed to find project with ID ${projectId}` });
const { permission } = await permissionService.getProjectPermission({ const { permission, membership } = await permissionService.getProjectPermission({
actor, actor,
actorId, actorId,
projectId, projectId,
@@ -275,6 +276,7 @@ export const groupProjectServiceFactory = ({
project.id project.id
); );
const permissionBoundary = validatePrivilegeChangeOperation( const permissionBoundary = validatePrivilegeChangeOperation(
membership.shouldUseNewPrivilegeSystem,
ProjectPermissionGroupActions.ManagePrivileges, ProjectPermissionGroupActions.ManagePrivileges,
ProjectPermissionSub.Groups, ProjectPermissionSub.Groups,
permission, permission,
@@ -322,7 +322,7 @@ export const identityAwsAuthServiceFactory = ({
message: "The identity does not have aws auth" message: "The identity does not have aws auth"
}); });
} }
const { permission } = await permissionService.getOrgPermission( const { permission, membership } = await permissionService.getOrgPermission(
actor, actor,
actorId, actorId,
identityMembershipOrg.orgId, identityMembershipOrg.orgId,
@@ -340,11 +340,13 @@ export const identityAwsAuthServiceFactory = ({
); );
const permissionBoundary = validatePrivilegeChangeOperation( const permissionBoundary = validatePrivilegeChangeOperation(
membership.shouldUseNewPrivilegeSystem,
OrgPermissionIdentityActions.RevokeAuth, OrgPermissionIdentityActions.RevokeAuth,
OrgPermissionSubjects.Identity, OrgPermissionSubjects.Identity,
permission, permission,
rolePermission rolePermission
); );
if (!permissionBoundary.isValid) if (!permissionBoundary.isValid)
throw new ForbiddenRequestError({ throw new ForbiddenRequestError({
name: "PermissionBoundaryError", name: "PermissionBoundaryError",
@@ -296,7 +296,7 @@ export const identityAzureAuthServiceFactory = ({
message: "The identity does not have azure auth" message: "The identity does not have azure auth"
}); });
} }
const { permission } = await permissionService.getOrgPermission( const { permission, membership } = await permissionService.getOrgPermission(
actor, actor,
actorId, actorId,
identityMembershipOrg.orgId, identityMembershipOrg.orgId,
@@ -313,6 +313,7 @@ export const identityAzureAuthServiceFactory = ({
actorOrgId actorOrgId
); );
const permissionBoundary = validatePrivilegeChangeOperation( const permissionBoundary = validatePrivilegeChangeOperation(
membership.shouldUseNewPrivilegeSystem,
OrgPermissionIdentityActions.RevokeAuth, OrgPermissionIdentityActions.RevokeAuth,
OrgPermissionSubjects.Identity, OrgPermissionSubjects.Identity,
permission, permission,
@@ -342,7 +342,7 @@ export const identityGcpAuthServiceFactory = ({
message: "The identity does not have gcp auth" message: "The identity does not have gcp auth"
}); });
} }
const { permission } = await permissionService.getOrgPermission( const { permission, membership } = await permissionService.getOrgPermission(
actor, actor,
actorId, actorId,
identityMembershipOrg.orgId, identityMembershipOrg.orgId,
@@ -359,6 +359,7 @@ export const identityGcpAuthServiceFactory = ({
actorOrgId actorOrgId
); );
const permissionBoundary = validatePrivilegeChangeOperation( const permissionBoundary = validatePrivilegeChangeOperation(
membership.shouldUseNewPrivilegeSystem,
OrgPermissionIdentityActions.RevokeAuth, OrgPermissionIdentityActions.RevokeAuth,
OrgPermissionSubjects.Identity, OrgPermissionSubjects.Identity,
permission, permission,
@@ -498,7 +498,7 @@ export const identityJwtAuthServiceFactory = ({
}); });
} }
const { permission } = await permissionService.getOrgPermission( const { permission, membership } = await permissionService.getOrgPermission(
actor, actor,
actorId, actorId,
identityMembershipOrg.orgId, identityMembershipOrg.orgId,
@@ -517,6 +517,7 @@ export const identityJwtAuthServiceFactory = ({
); );
const permissionBoundary = validatePrivilegeChangeOperation( const permissionBoundary = validatePrivilegeChangeOperation(
membership.shouldUseNewPrivilegeSystem,
OrgPermissionIdentityActions.RevokeAuth, OrgPermissionIdentityActions.RevokeAuth,
OrgPermissionSubjects.Identity, OrgPermissionSubjects.Identity,
permission, permission,
@@ -471,7 +471,7 @@ export const identityKubernetesAuthServiceFactory = ({
message: "The identity does not have kubernetes auth" message: "The identity does not have kubernetes auth"
}); });
} }
const { permission } = await permissionService.getOrgPermission( const { permission, membership } = await permissionService.getOrgPermission(
actor, actor,
actorId, actorId,
identityMembershipOrg.orgId, identityMembershipOrg.orgId,
@@ -488,6 +488,7 @@ export const identityKubernetesAuthServiceFactory = ({
actorOrgId actorOrgId
); );
const permissionBoundary = validatePrivilegeChangeOperation( const permissionBoundary = validatePrivilegeChangeOperation(
membership.shouldUseNewPrivilegeSystem,
OrgPermissionIdentityActions.RevokeAuth, OrgPermissionIdentityActions.RevokeAuth,
OrgPermissionSubjects.Identity, OrgPermissionSubjects.Identity,
permission, permission,
@@ -410,7 +410,7 @@ export const identityOidcAuthServiceFactory = ({
}); });
} }
const { permission } = await permissionService.getOrgPermission( const { permission, membership } = await permissionService.getOrgPermission(
actor, actor,
actorId, actorId,
identityMembershipOrg.orgId, identityMembershipOrg.orgId,
@@ -429,11 +429,13 @@ export const identityOidcAuthServiceFactory = ({
); );
const permissionBoundary = validatePrivilegeChangeOperation( const permissionBoundary = validatePrivilegeChangeOperation(
membership.shouldUseNewPrivilegeSystem,
OrgPermissionIdentityActions.RevokeAuth, OrgPermissionIdentityActions.RevokeAuth,
OrgPermissionSubjects.Identity, OrgPermissionSubjects.Identity,
permission, permission,
rolePermission rolePermission
); );
if (!permissionBoundary.isValid) if (!permissionBoundary.isValid)
throw new ForbiddenRequestError({ throw new ForbiddenRequestError({
name: "PermissionBoundaryError", name: "PermissionBoundaryError",
@@ -53,7 +53,7 @@ export const identityProjectServiceFactory = ({
projectId, projectId,
roles roles
}: TCreateProjectIdentityDTO) => { }: TCreateProjectIdentityDTO) => {
const { permission } = await permissionService.getProjectPermission({ const { permission, membership } = await permissionService.getProjectPermission({
actor, actor,
actorId, actorId,
projectId, projectId,
@@ -91,6 +91,7 @@ export const identityProjectServiceFactory = ({
); );
const permissionBoundary = validatePrivilegeChangeOperation( const permissionBoundary = validatePrivilegeChangeOperation(
membership.shouldUseNewPrivilegeSystem,
ProjectPermissionIdentityActions.ManagePrivileges, ProjectPermissionIdentityActions.ManagePrivileges,
ProjectPermissionSub.Identity, ProjectPermissionSub.Identity,
permission, permission,
@@ -166,7 +167,7 @@ export const identityProjectServiceFactory = ({
actorAuthMethod, actorAuthMethod,
actorOrgId actorOrgId
}: TUpdateProjectIdentityDTO) => { }: TUpdateProjectIdentityDTO) => {
const { permission } = await permissionService.getProjectPermission({ const { permission, membership } = await permissionService.getProjectPermission({
actor, actor,
actorId, actorId,
projectId, projectId,
@@ -192,11 +193,13 @@ export const identityProjectServiceFactory = ({
); );
const permissionBoundary = validatePrivilegeChangeOperation( const permissionBoundary = validatePrivilegeChangeOperation(
membership.shouldUseNewPrivilegeSystem,
ProjectPermissionIdentityActions.ManagePrivileges, ProjectPermissionIdentityActions.ManagePrivileges,
ProjectPermissionSub.Identity, ProjectPermissionSub.Identity,
permission, permission,
rolePermission rolePermission
); );
if (!permissionBoundary.isValid) if (!permissionBoundary.isValid)
throw new ForbiddenRequestError({ throw new ForbiddenRequestError({
name: "PermissionBoundaryError", name: "PermissionBoundaryError",
@@ -237,7 +237,7 @@ export const identityTokenAuthServiceFactory = ({
); );
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionIdentityActions.Edit, OrgPermissionSubjects.Identity); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionIdentityActions.Edit, OrgPermissionSubjects.Identity);
const { permission: rolePermission } = await permissionService.getOrgPermission( const { permission: rolePermission, membership } = await permissionService.getOrgPermission(
ActorType.IDENTITY, ActorType.IDENTITY,
identityMembershipOrg.identityId, identityMembershipOrg.identityId,
identityMembershipOrg.orgId, identityMembershipOrg.orgId,
@@ -246,6 +246,7 @@ export const identityTokenAuthServiceFactory = ({
); );
const permissionBoundary = validatePrivilegeChangeOperation( const permissionBoundary = validatePrivilegeChangeOperation(
membership.shouldUseNewPrivilegeSystem,
OrgPermissionIdentityActions.RevokeAuth, OrgPermissionIdentityActions.RevokeAuth,
OrgPermissionSubjects.Identity, OrgPermissionSubjects.Identity,
permission, permission,
@@ -295,7 +296,7 @@ export const identityTokenAuthServiceFactory = ({
); );
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionIdentityActions.Edit, OrgPermissionSubjects.Identity); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionIdentityActions.Edit, OrgPermissionSubjects.Identity);
const { permission: rolePermission } = await permissionService.getOrgPermission( const { permission: rolePermission, membership } = await permissionService.getOrgPermission(
ActorType.IDENTITY, ActorType.IDENTITY,
identityMembershipOrg.identityId, identityMembershipOrg.identityId,
identityMembershipOrg.orgId, identityMembershipOrg.orgId,
@@ -304,6 +305,7 @@ export const identityTokenAuthServiceFactory = ({
); );
const permissionBoundary = validatePrivilegeChangeOperation( const permissionBoundary = validatePrivilegeChangeOperation(
membership.shouldUseNewPrivilegeSystem,
OrgPermissionIdentityActions.CreateToken, OrgPermissionIdentityActions.CreateToken,
OrgPermissionSubjects.Identity, OrgPermissionSubjects.Identity,
permission, permission,
@@ -423,7 +425,7 @@ export const identityTokenAuthServiceFactory = ({
); );
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionIdentityActions.Edit, OrgPermissionSubjects.Identity); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionIdentityActions.Edit, OrgPermissionSubjects.Identity);
const { permission: rolePermission } = await permissionService.getOrgPermission( const { permission: rolePermission, membership } = await permissionService.getOrgPermission(
ActorType.IDENTITY, ActorType.IDENTITY,
identityMembershipOrg.identityId, identityMembershipOrg.identityId,
identityMembershipOrg.orgId, identityMembershipOrg.orgId,
@@ -431,6 +433,7 @@ export const identityTokenAuthServiceFactory = ({
actorOrgId actorOrgId
); );
const permissionBoundary = validatePrivilegeChangeOperation( const permissionBoundary = validatePrivilegeChangeOperation(
membership.shouldUseNewPrivilegeSystem,
OrgPermissionIdentityActions.CreateToken, OrgPermissionIdentityActions.CreateToken,
OrgPermissionSubjects.Identity, OrgPermissionSubjects.Identity,
permission, permission,
@@ -360,7 +360,7 @@ export const identityUaServiceFactory = ({
); );
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionIdentityActions.Edit, OrgPermissionSubjects.Identity); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionIdentityActions.Edit, OrgPermissionSubjects.Identity);
const { permission: rolePermission } = await permissionService.getOrgPermission( const { permission: rolePermission, membership } = await permissionService.getOrgPermission(
ActorType.IDENTITY, ActorType.IDENTITY,
identityMembershipOrg.identityId, identityMembershipOrg.identityId,
identityMembershipOrg.orgId, identityMembershipOrg.orgId,
@@ -368,6 +368,7 @@ export const identityUaServiceFactory = ({
actorOrgId actorOrgId
); );
const permissionBoundary = validatePrivilegeChangeOperation( const permissionBoundary = validatePrivilegeChangeOperation(
membership.shouldUseNewPrivilegeSystem,
OrgPermissionIdentityActions.RevokeAuth, OrgPermissionIdentityActions.RevokeAuth,
OrgPermissionSubjects.Identity, OrgPermissionSubjects.Identity,
permission, permission,
@@ -406,7 +407,7 @@ export const identityUaServiceFactory = ({
}); });
} }
const { permission } = await permissionService.getOrgPermission( const { permission, membership } = await permissionService.getOrgPermission(
actor, actor,
actorId, actorId,
identityMembershipOrg.orgId, identityMembershipOrg.orgId,
@@ -423,6 +424,7 @@ export const identityUaServiceFactory = ({
actorOrgId actorOrgId
); );
const permissionBoundary = validatePrivilegeChangeOperation( const permissionBoundary = validatePrivilegeChangeOperation(
membership.shouldUseNewPrivilegeSystem,
OrgPermissionIdentityActions.CreateToken, OrgPermissionIdentityActions.CreateToken,
OrgPermissionSubjects.Identity, OrgPermissionSubjects.Identity,
permission, permission,
@@ -473,7 +475,7 @@ export const identityUaServiceFactory = ({
message: "The identity does not have universal auth" message: "The identity does not have universal auth"
}); });
} }
const { permission } = await permissionService.getOrgPermission( const { permission, membership } = await permissionService.getOrgPermission(
actor, actor,
actorId, actorId,
identityMembershipOrg.orgId, identityMembershipOrg.orgId,
@@ -491,6 +493,7 @@ export const identityUaServiceFactory = ({
); );
const permissionBoundary = validatePrivilegeChangeOperation( const permissionBoundary = validatePrivilegeChangeOperation(
membership.shouldUseNewPrivilegeSystem,
OrgPermissionIdentityActions.GetToken, OrgPermissionIdentityActions.GetToken,
OrgPermissionSubjects.Identity, OrgPermissionSubjects.Identity,
permission, permission,
@@ -531,7 +534,7 @@ export const identityUaServiceFactory = ({
}); });
} }
const { permission } = await permissionService.getOrgPermission( const { permission, membership } = await permissionService.getOrgPermission(
actor, actor,
actorId, actorId,
identityMembershipOrg.orgId, identityMembershipOrg.orgId,
@@ -548,6 +551,7 @@ export const identityUaServiceFactory = ({
actorOrgId actorOrgId
); );
const permissionBoundary = validatePrivilegeChangeOperation( const permissionBoundary = validatePrivilegeChangeOperation(
membership.shouldUseNewPrivilegeSystem,
OrgPermissionIdentityActions.GetToken, OrgPermissionIdentityActions.GetToken,
OrgPermissionSubjects.Identity, OrgPermissionSubjects.Identity,
permission, permission,
@@ -581,7 +585,7 @@ export const identityUaServiceFactory = ({
}); });
} }
const { permission } = await permissionService.getOrgPermission( const { permission, membership } = await permissionService.getOrgPermission(
actor, actor,
actorId, actorId,
identityMembershipOrg.orgId, identityMembershipOrg.orgId,
@@ -599,6 +603,7 @@ export const identityUaServiceFactory = ({
); );
const permissionBoundary = validatePrivilegeChangeOperation( const permissionBoundary = validatePrivilegeChangeOperation(
membership.shouldUseNewPrivilegeSystem,
OrgPermissionIdentityActions.DeleteToken, OrgPermissionIdentityActions.DeleteToken,
OrgPermissionSubjects.Identity, OrgPermissionSubjects.Identity,
permission, permission,
@@ -49,7 +49,13 @@ export const identityServiceFactory = ({
actorOrgId, actorOrgId,
metadata metadata
}: TCreateIdentityDTO) => { }: TCreateIdentityDTO) => {
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, actorAuthMethod, actorOrgId); const { permission, membership } = await permissionService.getOrgPermission(
actor,
actorId,
orgId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionIdentityActions.Create, OrgPermissionSubjects.Identity); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionIdentityActions.Create, OrgPermissionSubjects.Identity);
const { permission: rolePermission, role: customRole } = await permissionService.getOrgPermissionByRole( const { permission: rolePermission, role: customRole } = await permissionService.getOrgPermissionByRole(
@@ -58,6 +64,7 @@ export const identityServiceFactory = ({
); );
const isCustomRole = Boolean(customRole); const isCustomRole = Boolean(customRole);
const permissionBoundary = validatePrivilegeChangeOperation( const permissionBoundary = validatePrivilegeChangeOperation(
membership.shouldUseNewPrivilegeSystem,
OrgPermissionIdentityActions.ManagePrivileges, OrgPermissionIdentityActions.ManagePrivileges,
OrgPermissionSubjects.Identity, OrgPermissionSubjects.Identity,
permission, permission,
@@ -121,7 +128,7 @@ export const identityServiceFactory = ({
const identityOrgMembership = await identityOrgMembershipDAL.findOne({ identityId: id }); const identityOrgMembership = await identityOrgMembershipDAL.findOne({ identityId: id });
if (!identityOrgMembership) throw new NotFoundError({ message: `Failed to find identity with id ${id}` }); if (!identityOrgMembership) throw new NotFoundError({ message: `Failed to find identity with id ${id}` });
const { permission } = await permissionService.getOrgPermission( const { permission, membership } = await permissionService.getOrgPermission(
actor, actor,
actorId, actorId,
identityOrgMembership.orgId, identityOrgMembership.orgId,
@@ -139,6 +146,7 @@ export const identityServiceFactory = ({
const isCustomRole = Boolean(customOrgRole); const isCustomRole = Boolean(customOrgRole);
const appliedRolePermissionBoundary = validatePrivilegeChangeOperation( const appliedRolePermissionBoundary = validatePrivilegeChangeOperation(
membership.shouldUseNewPrivilegeSystem,
OrgPermissionIdentityActions.ManagePrivileges, OrgPermissionIdentityActions.ManagePrivileges,
OrgPermissionSubjects.Identity, OrgPermissionSubjects.Identity,
permission, permission,
+3 -2
View File
@@ -291,7 +291,7 @@ export const orgServiceFactory = ({
}: TUpgradePrivilegeSystemDTO) => { }: TUpgradePrivilegeSystemDTO) => {
const { membership } = await permissionService.getUserOrgPermission(actorId, orgId, actorAuthMethod, actorOrgId); const { membership } = await permissionService.getUserOrgPermission(actorId, orgId, actorAuthMethod, actorOrgId);
if (membership.role != OrgMembershipRole.Admin) { if (membership.role !== OrgMembershipRole.Admin) {
throw new ForbiddenRequestError({ throw new ForbiddenRequestError({
message: "Insufficient privileges - only the organization admin can upgrade the privilege system." message: "Insufficient privileges - only the organization admin can upgrade the privilege system."
}); });
@@ -881,7 +881,7 @@ export const orgServiceFactory = ({
// if there exist no project membership we set is as given by the request // if there exist no project membership we set is as given by the request
for await (const project of projectsToInvite) { for await (const project of projectsToInvite) {
const projectId = project.id; const projectId = project.id;
const { permission: projectPermission } = await permissionService.getProjectPermission({ const { permission: projectPermission, membership } = await permissionService.getProjectPermission({
actor, actor,
actorId, actorId,
projectId, projectId,
@@ -920,6 +920,7 @@ export const orgServiceFactory = ({
); );
const permissionBoundary = validatePrivilegeChangeOperation( const permissionBoundary = validatePrivilegeChangeOperation(
membership.shouldUseNewPrivilegeSystem,
ProjectPermissionMemberActions.ManagePrivileges, ProjectPermissionMemberActions.ManagePrivileges,
ProjectPermissionSub.Member, ProjectPermissionSub.Member,
projectPermission, projectPermission,
@@ -253,7 +253,7 @@ export const projectMembershipServiceFactory = ({
membershipId, membershipId,
roles roles
}: TUpdateProjectMembershipDTO) => { }: TUpdateProjectMembershipDTO) => {
const { permission } = await permissionService.getProjectPermission({ const { permission, membership } = await permissionService.getProjectPermission({
actor, actor,
actorId, actorId,
projectId, projectId,
@@ -275,6 +275,7 @@ export const projectMembershipServiceFactory = ({
); );
const permissionBoundary = validatePrivilegeChangeOperation( const permissionBoundary = validatePrivilegeChangeOperation(
membership.shouldUseNewPrivilegeSystem,
ProjectPermissionMemberActions.ManagePrivileges, ProjectPermissionMemberActions.ManagePrivileges,
ProjectPermissionSub.Member, ProjectPermissionSub.Member,
permission, permission,