Fix: Don't allow users to request access to the same resource with same permissions multiple times

This commit is contained in:
Daniel Hougaard
2024-05-07 17:30:35 +02:00
parent 890c8b89be
commit e6c086ab09
@@ -1,8 +1,10 @@
import { ForbiddenError } from "@casl/ability"; import { ForbiddenError } from "@casl/ability";
import slugify from "@sindresorhus/slugify";
import ms from "ms"; import ms from "ms";
import { ProjectMembershipRole } from "@app/db/schemas"; import { ProjectMembershipRole } from "@app/db/schemas";
import { BadRequestError, UnauthorizedError } from "@app/lib/errors"; import { BadRequestError, UnauthorizedError } from "@app/lib/errors";
import { alphaNumericNanoId } from "@app/lib/nanoid";
import { TProjectDALFactory } from "@app/services/project/project-dal"; import { TProjectDALFactory } from "@app/services/project/project-dal";
import { TProjectEnvDALFactory } from "@app/services/project-env/project-env-dal"; import { TProjectEnvDALFactory } from "@app/services/project-env/project-env-dal";
import { TProjectMembershipDALFactory } from "@app/services/project-membership/project-membership-dal"; import { TProjectMembershipDALFactory } from "@app/services/project-membership/project-membership-dal";
@@ -64,9 +66,15 @@ export const accessApprovalRequestServiceFactory = ({
if (!project) throw new UnauthorizedError({ message: "Project not found" }); if (!project) throw new UnauthorizedError({ message: "Project not found" });
// Anyone can create an access approval request. // Anyone can create an access approval request.
const p = await permissionService.getProjectPermission(actor, actorId, project.id, actorAuthMethod, actorOrgId); const { membership } = await permissionService.getProjectPermission(
actor,
actorId,
project.id,
actorAuthMethod,
actorOrgId
);
if (!p.membership) throw new UnauthorizedError({ message: "You are not a member of this project" }); if (!membership) throw new UnauthorizedError({ message: "You are not a member of this project" });
await projectDAL.checkProjectUpgradeStatus(project.id); await projectDAL.checkProjectUpgradeStatus(project.id);
@@ -81,9 +89,27 @@ export const accessApprovalRequestServiceFactory = ({
}); });
if (!policy) throw new UnauthorizedError({ message: "No policy matching criteria was found." }); if (!policy) throw new UnauthorizedError({ message: "No policy matching criteria was found." });
const duplicateRequest = await accessApprovalRequestDAL.findOne({
policyId: policy.id,
requestedBy: membership.id,
permissions: JSON.stringify(permissions),
temporaryRange: temporaryRange || null,
isTemporary
});
if (duplicateRequest.privilegeId) {
const privilege = await additionalPrivilegeDAL.findById(duplicateRequest.privilegeId);
const isExpired = new Date() > new Date(privilege.temporaryAccessEndTime || ("" as string));
if (!isExpired) {
throw new BadRequestError({ message: "You have already requested access with the same permissions" });
}
}
const approvalRequest = await accessApprovalRequestDAL.create({ const approvalRequest = await accessApprovalRequestDAL.create({
policyId: policy.id, policyId: policy.id,
requestedBy: p.membership.id, requestedBy: membership.id,
temporaryRange: temporaryRange || null, temporaryRange: temporaryRange || null,
permissions: JSON.stringify(permissions), permissions: JSON.stringify(permissions),
isTemporary isTemporary
@@ -209,7 +235,7 @@ export const accessApprovalRequestServiceFactory = ({
// Permanent access // Permanent access
const privilege = await additionalPrivilegeDAL.create({ const privilege = await additionalPrivilegeDAL.create({
projectMembershipId: accessApprovalRequest.requestedBy, projectMembershipId: accessApprovalRequest.requestedBy,
slug: "", slug: `requested-privilege-${slugify(alphaNumericNanoId(12))}`,
permissions: JSON.stringify(accessApprovalRequest.permissions) permissions: JSON.stringify(accessApprovalRequest.permissions)
}); });
privilegeId = privilege.id; privilegeId = privilege.id;
@@ -220,7 +246,7 @@ export const accessApprovalRequestServiceFactory = ({
const privilege = await additionalPrivilegeDAL.create({ const privilege = await additionalPrivilegeDAL.create({
projectMembershipId: accessApprovalRequest.requestedBy, projectMembershipId: accessApprovalRequest.requestedBy,
slug: "", slug: `requested-privilege-${slugify(alphaNumericNanoId(12))}`,
permissions: JSON.stringify(accessApprovalRequest.permissions), permissions: JSON.stringify(accessApprovalRequest.permissions),
isTemporary: true, isTemporary: true,
temporaryMode: ProjectUserAdditionalPrivilegeTemporaryMode.Relative, temporaryMode: ProjectUserAdditionalPrivilegeTemporaryMode.Relative,