mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-07 09:28:06 +00:00
Merge pull request #2502 from Infisical/daniel/error-fixes
fix(api): error improvements
This commit is contained in:
@@ -1,23 +1,21 @@
|
|||||||
import { ForbiddenError, subject } from "@casl/ability";
|
import { ForbiddenError, subject } from "@casl/ability";
|
||||||
|
|
||||||
import { BadRequestError, ForbiddenRequestError } from "@app/lib/errors";
|
|
||||||
import { ActorType } from "@app/services/auth/auth-type";
|
import { ActorType } from "@app/services/auth/auth-type";
|
||||||
|
|
||||||
import { ProjectPermissionActions, ProjectPermissionSub } from "../permission/project-permission";
|
import { ProjectPermissionActions, ProjectPermissionSub } from "../permission/project-permission";
|
||||||
import { TVerifyApprovers, VerifyApproversError } from "./access-approval-policy-types";
|
import { TIsApproversValid } from "./access-approval-policy-types";
|
||||||
|
|
||||||
export const verifyApprovers = async ({
|
export const isApproversValid = async ({
|
||||||
userIds,
|
userIds,
|
||||||
projectId,
|
projectId,
|
||||||
orgId,
|
orgId,
|
||||||
envSlug,
|
envSlug,
|
||||||
actorAuthMethod,
|
actorAuthMethod,
|
||||||
secretPath,
|
secretPath,
|
||||||
permissionService,
|
permissionService
|
||||||
error
|
}: TIsApproversValid) => {
|
||||||
}: TVerifyApprovers) => {
|
try {
|
||||||
for await (const userId of userIds) {
|
for await (const userId of userIds) {
|
||||||
try {
|
|
||||||
const { permission: approverPermission } = await permissionService.getProjectPermission(
|
const { permission: approverPermission } = await permissionService.getProjectPermission(
|
||||||
ActorType.USER,
|
ActorType.USER,
|
||||||
userId,
|
userId,
|
||||||
@@ -30,17 +28,9 @@ export const verifyApprovers = async ({
|
|||||||
ProjectPermissionActions.Create,
|
ProjectPermissionActions.Create,
|
||||||
subject(ProjectPermissionSub.Secrets, { environment: envSlug, secretPath })
|
subject(ProjectPermissionSub.Secrets, { environment: envSlug, secretPath })
|
||||||
);
|
);
|
||||||
} catch (err) {
|
|
||||||
if (error === VerifyApproversError.BadRequestError) {
|
|
||||||
throw new BadRequestError({
|
|
||||||
message: "One or more approvers doesn't have access to be specified secret path"
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if (error === VerifyApproversError.ForbiddenError) {
|
|
||||||
throw new ForbiddenRequestError({
|
|
||||||
message: "You don't have access to approve this request"
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
} catch {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { ForbiddenError } from "@casl/ability";
|
|||||||
|
|
||||||
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 { ProjectPermissionActions, ProjectPermissionSub } from "@app/ee/services/permission/project-permission";
|
||||||
import { BadRequestError, NotFoundError } from "@app/lib/errors";
|
import { BadRequestError, ForbiddenRequestError, NotFoundError } from "@app/lib/errors";
|
||||||
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";
|
||||||
@@ -11,7 +11,7 @@ import { TUserDALFactory } from "@app/services/user/user-dal";
|
|||||||
import { TGroupDALFactory } from "../group/group-dal";
|
import { TGroupDALFactory } from "../group/group-dal";
|
||||||
import { TAccessApprovalPolicyApproverDALFactory } from "./access-approval-policy-approver-dal";
|
import { TAccessApprovalPolicyApproverDALFactory } from "./access-approval-policy-approver-dal";
|
||||||
import { TAccessApprovalPolicyDALFactory } from "./access-approval-policy-dal";
|
import { TAccessApprovalPolicyDALFactory } from "./access-approval-policy-dal";
|
||||||
import { verifyApprovers } from "./access-approval-policy-fns";
|
import { isApproversValid } from "./access-approval-policy-fns";
|
||||||
import {
|
import {
|
||||||
ApproverType,
|
ApproverType,
|
||||||
TCreateAccessApprovalPolicy,
|
TCreateAccessApprovalPolicy,
|
||||||
@@ -19,8 +19,7 @@ import {
|
|||||||
TGetAccessApprovalPolicyByIdDTO,
|
TGetAccessApprovalPolicyByIdDTO,
|
||||||
TGetAccessPolicyCountByEnvironmentDTO,
|
TGetAccessPolicyCountByEnvironmentDTO,
|
||||||
TListAccessApprovalPoliciesDTO,
|
TListAccessApprovalPoliciesDTO,
|
||||||
TUpdateAccessApprovalPolicy,
|
TUpdateAccessApprovalPolicy
|
||||||
VerifyApproversError
|
|
||||||
} from "./access-approval-policy-types";
|
} from "./access-approval-policy-types";
|
||||||
|
|
||||||
type TSecretApprovalPolicyServiceFactoryDep = {
|
type TSecretApprovalPolicyServiceFactoryDep = {
|
||||||
@@ -133,17 +132,22 @@ export const accessApprovalPolicyServiceFactory = ({
|
|||||||
.map((user) => user.id);
|
.map((user) => user.id);
|
||||||
verifyAllApprovers.push(...verifyGroupApprovers);
|
verifyAllApprovers.push(...verifyGroupApprovers);
|
||||||
|
|
||||||
await verifyApprovers({
|
const approversValid = await isApproversValid({
|
||||||
projectId: project.id,
|
projectId: project.id,
|
||||||
orgId: actorOrgId,
|
orgId: actorOrgId,
|
||||||
envSlug: environment,
|
envSlug: environment,
|
||||||
secretPath,
|
secretPath,
|
||||||
actorAuthMethod,
|
actorAuthMethod,
|
||||||
permissionService,
|
permissionService,
|
||||||
userIds: verifyAllApprovers,
|
userIds: verifyAllApprovers
|
||||||
error: VerifyApproversError.BadRequestError
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (!approversValid) {
|
||||||
|
throw new BadRequestError({
|
||||||
|
message: "One or more approvers doesn't have access to be specified secret path"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const accessApproval = await accessApprovalPolicyDAL.transaction(async (tx) => {
|
const accessApproval = await accessApprovalPolicyDAL.transaction(async (tx) => {
|
||||||
const doc = await accessApprovalPolicyDAL.create(
|
const doc = await accessApprovalPolicyDAL.create(
|
||||||
{
|
{
|
||||||
@@ -285,17 +289,22 @@ export const accessApprovalPolicyServiceFactory = ({
|
|||||||
userApproverIds = userApproverIds.concat(approverUsers.map((user) => user.id));
|
userApproverIds = userApproverIds.concat(approverUsers.map((user) => user.id));
|
||||||
}
|
}
|
||||||
|
|
||||||
await verifyApprovers({
|
const approversValid = await isApproversValid({
|
||||||
projectId: accessApprovalPolicy.projectId,
|
projectId: accessApprovalPolicy.projectId,
|
||||||
orgId: actorOrgId,
|
orgId: actorOrgId,
|
||||||
envSlug: accessApprovalPolicy.environment.slug,
|
envSlug: accessApprovalPolicy.environment.slug,
|
||||||
secretPath: doc.secretPath!,
|
secretPath: doc.secretPath!,
|
||||||
actorAuthMethod,
|
actorAuthMethod,
|
||||||
permissionService,
|
permissionService,
|
||||||
userIds: userApproverIds,
|
userIds: userApproverIds
|
||||||
error: VerifyApproversError.BadRequestError
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (!approversValid) {
|
||||||
|
throw new BadRequestError({
|
||||||
|
message: "One or more approvers doesn't have access to be specified secret path"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
await accessApprovalPolicyApproverDAL.insertMany(
|
await accessApprovalPolicyApproverDAL.insertMany(
|
||||||
userApproverIds.map((userId) => ({
|
userApproverIds.map((userId) => ({
|
||||||
approverUserId: userId,
|
approverUserId: userId,
|
||||||
@@ -325,16 +334,22 @@ export const accessApprovalPolicyServiceFactory = ({
|
|||||||
.filter((user) => user.isPartOfGroup)
|
.filter((user) => user.isPartOfGroup)
|
||||||
.map((user) => user.id);
|
.map((user) => user.id);
|
||||||
|
|
||||||
await verifyApprovers({
|
const approversValid = await isApproversValid({
|
||||||
projectId: accessApprovalPolicy.projectId,
|
projectId: accessApprovalPolicy.projectId,
|
||||||
orgId: actorOrgId,
|
orgId: actorOrgId,
|
||||||
envSlug: accessApprovalPolicy.environment.slug,
|
envSlug: accessApprovalPolicy.environment.slug,
|
||||||
secretPath: doc.secretPath!,
|
secretPath: doc.secretPath!,
|
||||||
actorAuthMethod,
|
actorAuthMethod,
|
||||||
permissionService,
|
permissionService,
|
||||||
userIds: verifyGroupApprovers,
|
userIds: verifyGroupApprovers
|
||||||
error: VerifyApproversError.BadRequestError
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (!approversValid) {
|
||||||
|
throw new BadRequestError({
|
||||||
|
message: "One or more approvers doesn't have access to be specified secret path"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
await accessApprovalPolicyApproverDAL.insertMany(
|
await accessApprovalPolicyApproverDAL.insertMany(
|
||||||
groupApprovers.map((groupId) => ({
|
groupApprovers.map((groupId) => ({
|
||||||
approverGroupId: groupId,
|
approverGroupId: groupId,
|
||||||
@@ -398,7 +413,9 @@ export const accessApprovalPolicyServiceFactory = ({
|
|||||||
actorAuthMethod,
|
actorAuthMethod,
|
||||||
actorOrgId
|
actorOrgId
|
||||||
);
|
);
|
||||||
if (!membership) throw new NotFoundError({ message: "User not found in project" });
|
if (!membership) {
|
||||||
|
throw new ForbiddenRequestError({ message: "You are not a member of this project" });
|
||||||
|
}
|
||||||
|
|
||||||
const environment = await projectEnvDAL.findOne({ projectId: project.id, slug: envSlug });
|
const environment = await projectEnvDAL.findOne({ projectId: project.id, slug: envSlug });
|
||||||
if (!environment) throw new NotFoundError({ message: "Environment not found" });
|
if (!environment) throw new NotFoundError({ message: "Environment not found" });
|
||||||
|
|||||||
@@ -3,12 +3,7 @@ import { ActorAuthMethod } from "@app/services/auth/auth-type";
|
|||||||
|
|
||||||
import { TPermissionServiceFactory } from "../permission/permission-service";
|
import { TPermissionServiceFactory } from "../permission/permission-service";
|
||||||
|
|
||||||
export enum VerifyApproversError {
|
export type TIsApproversValid = {
|
||||||
ForbiddenError = "ForbiddenError",
|
|
||||||
BadRequestError = "BadRequestError"
|
|
||||||
}
|
|
||||||
|
|
||||||
export type TVerifyApprovers = {
|
|
||||||
userIds: string[];
|
userIds: string[];
|
||||||
permissionService: Pick<TPermissionServiceFactory, "getProjectPermission">;
|
permissionService: Pick<TPermissionServiceFactory, "getProjectPermission">;
|
||||||
envSlug: string;
|
envSlug: string;
|
||||||
@@ -16,7 +11,6 @@ export type TVerifyApprovers = {
|
|||||||
secretPath: string;
|
secretPath: string;
|
||||||
projectId: string;
|
projectId: string;
|
||||||
orgId: string;
|
orgId: string;
|
||||||
error: VerifyApproversError;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export enum ApproverType {
|
export enum ApproverType {
|
||||||
|
|||||||
+20
-10
@@ -17,8 +17,7 @@ import { TUserDALFactory } from "@app/services/user/user-dal";
|
|||||||
|
|
||||||
import { TAccessApprovalPolicyApproverDALFactory } from "../access-approval-policy/access-approval-policy-approver-dal";
|
import { TAccessApprovalPolicyApproverDALFactory } from "../access-approval-policy/access-approval-policy-approver-dal";
|
||||||
import { TAccessApprovalPolicyDALFactory } from "../access-approval-policy/access-approval-policy-dal";
|
import { TAccessApprovalPolicyDALFactory } from "../access-approval-policy/access-approval-policy-dal";
|
||||||
import { verifyApprovers } from "../access-approval-policy/access-approval-policy-fns";
|
import { isApproversValid } from "../access-approval-policy/access-approval-policy-fns";
|
||||||
import { VerifyApproversError } from "../access-approval-policy/access-approval-policy-types";
|
|
||||||
import { TGroupDALFactory } from "../group/group-dal";
|
import { TGroupDALFactory } from "../group/group-dal";
|
||||||
import { TPermissionServiceFactory } from "../permission/permission-service";
|
import { TPermissionServiceFactory } from "../permission/permission-service";
|
||||||
import { TProjectUserAdditionalPrivilegeDALFactory } from "../project-user-additional-privilege/project-user-additional-privilege-dal";
|
import { TProjectUserAdditionalPrivilegeDALFactory } from "../project-user-additional-privilege/project-user-additional-privilege-dal";
|
||||||
@@ -100,7 +99,7 @@ export const accessApprovalRequestServiceFactory = ({
|
|||||||
}: TCreateAccessApprovalRequestDTO) => {
|
}: TCreateAccessApprovalRequestDTO) => {
|
||||||
const cfg = getConfig();
|
const cfg = getConfig();
|
||||||
const project = await projectDAL.findProjectBySlug(projectSlug, actorOrgId);
|
const project = await projectDAL.findProjectBySlug(projectSlug, actorOrgId);
|
||||||
if (!project) throw new ForbiddenRequestError({ message: "Project not found" });
|
if (!project) throw new NotFoundError({ message: "Project not found" });
|
||||||
|
|
||||||
// Anyone can create an access approval request.
|
// Anyone can create an access approval request.
|
||||||
const { membership } = await permissionService.getProjectPermission(
|
const { membership } = await permissionService.getProjectPermission(
|
||||||
@@ -110,7 +109,9 @@ export const accessApprovalRequestServiceFactory = ({
|
|||||||
actorAuthMethod,
|
actorAuthMethod,
|
||||||
actorOrgId
|
actorOrgId
|
||||||
);
|
);
|
||||||
if (!membership) throw new ForbiddenRequestError({ message: "You are not a member of this project" });
|
if (!membership) {
|
||||||
|
throw new ForbiddenRequestError({ message: "You are not a member of this project" });
|
||||||
|
}
|
||||||
|
|
||||||
const requestedByUser = await userDAL.findById(actorId);
|
const requestedByUser = await userDAL.findById(actorId);
|
||||||
if (!requestedByUser) throw new ForbiddenRequestError({ message: "User not found" });
|
if (!requestedByUser) throw new ForbiddenRequestError({ message: "User not found" });
|
||||||
@@ -272,7 +273,9 @@ export const accessApprovalRequestServiceFactory = ({
|
|||||||
actorAuthMethod,
|
actorAuthMethod,
|
||||||
actorOrgId
|
actorOrgId
|
||||||
);
|
);
|
||||||
if (!membership) throw new NotFoundError({ message: "You don't have a membership for the specified project" });
|
if (!membership) {
|
||||||
|
throw new ForbiddenRequestError({ message: "You are not a member of this project" });
|
||||||
|
}
|
||||||
|
|
||||||
const policies = await accessApprovalPolicyDAL.find({ projectId: project.id });
|
const policies = await accessApprovalPolicyDAL.find({ projectId: project.id });
|
||||||
let requests = await accessApprovalRequestDAL.findRequestsWithPrivilegeByPolicyIds(policies.map((p) => p.id));
|
let requests = await accessApprovalRequestDAL.findRequestsWithPrivilegeByPolicyIds(policies.map((p) => p.id));
|
||||||
@@ -308,7 +311,9 @@ export const accessApprovalRequestServiceFactory = ({
|
|||||||
actorOrgId
|
actorOrgId
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!membership) throw new ForbiddenRequestError({ message: "You are not a member of this project" });
|
if (!membership) {
|
||||||
|
throw new ForbiddenRequestError({ message: "You are not a member of this project" });
|
||||||
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
!hasRole(ProjectMembershipRole.Admin) &&
|
!hasRole(ProjectMembershipRole.Admin) &&
|
||||||
@@ -320,17 +325,20 @@ export const accessApprovalRequestServiceFactory = ({
|
|||||||
|
|
||||||
const reviewerProjectMembership = await projectMembershipDAL.findById(membership.id);
|
const reviewerProjectMembership = await projectMembershipDAL.findById(membership.id);
|
||||||
|
|
||||||
await verifyApprovers({
|
const approversValid = await isApproversValid({
|
||||||
projectId: accessApprovalRequest.projectId,
|
projectId: accessApprovalRequest.projectId,
|
||||||
orgId: actorOrgId,
|
orgId: actorOrgId,
|
||||||
envSlug: accessApprovalRequest.environment,
|
envSlug: accessApprovalRequest.environment,
|
||||||
secretPath: accessApprovalRequest.policy.secretPath!,
|
secretPath: accessApprovalRequest.policy.secretPath!,
|
||||||
actorAuthMethod,
|
actorAuthMethod,
|
||||||
permissionService,
|
permissionService,
|
||||||
userIds: [reviewerProjectMembership.userId],
|
userIds: [reviewerProjectMembership.userId]
|
||||||
error: VerifyApproversError.ForbiddenError
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (!approversValid) {
|
||||||
|
throw new ForbiddenRequestError({ message: "You don't have access to approve this request" });
|
||||||
|
}
|
||||||
|
|
||||||
const existingReviews = await accessApprovalRequestReviewerDAL.find({ requestId: accessApprovalRequest.id });
|
const existingReviews = await accessApprovalRequestReviewerDAL.find({ requestId: accessApprovalRequest.id });
|
||||||
if (existingReviews.some((review) => review.status === ApprovalStatus.REJECTED)) {
|
if (existingReviews.some((review) => review.status === ApprovalStatus.REJECTED)) {
|
||||||
throw new BadRequestError({ message: "The request has already been rejected by another reviewer" });
|
throw new BadRequestError({ message: "The request has already been rejected by another reviewer" });
|
||||||
@@ -422,7 +430,9 @@ export const accessApprovalRequestServiceFactory = ({
|
|||||||
actorAuthMethod,
|
actorAuthMethod,
|
||||||
actorOrgId
|
actorOrgId
|
||||||
);
|
);
|
||||||
if (!membership) throw new NotFoundError({ message: "You don't have a membership for the specified project" });
|
if (!membership) {
|
||||||
|
throw new ForbiddenRequestError({ message: "You are not a member of this project" });
|
||||||
|
}
|
||||||
|
|
||||||
const count = await accessApprovalRequestDAL.getCount({ projectId: project.id });
|
const count = await accessApprovalRequestDAL.getCount({ projectId: project.id });
|
||||||
|
|
||||||
|
|||||||
@@ -116,7 +116,7 @@ export const permissionServiceFactory = ({
|
|||||||
if (userOrgId && userOrgId !== orgId)
|
if (userOrgId && userOrgId !== orgId)
|
||||||
throw new ForbiddenRequestError({ message: "Invalid user token. Scoped to different organization." });
|
throw new ForbiddenRequestError({ message: "Invalid user token. Scoped to different organization." });
|
||||||
const membership = await permissionDAL.getOrgPermission(userId, orgId);
|
const membership = await permissionDAL.getOrgPermission(userId, orgId);
|
||||||
if (!membership) throw new ForbiddenRequestError({ name: "User is not a part of the specified organization" });
|
if (!membership) throw new ForbiddenRequestError({ name: "You are not apart of this organization" });
|
||||||
if (membership.role === OrgMembershipRole.Custom && !membership.permissions) {
|
if (membership.role === OrgMembershipRole.Custom && !membership.permissions) {
|
||||||
throw new BadRequestError({ name: "Custom organization permission not found" });
|
throw new BadRequestError({ name: "Custom organization permission not found" });
|
||||||
}
|
}
|
||||||
@@ -143,7 +143,7 @@ export const permissionServiceFactory = ({
|
|||||||
|
|
||||||
const getIdentityOrgPermission = async (identityId: string, orgId: string) => {
|
const getIdentityOrgPermission = async (identityId: string, orgId: string) => {
|
||||||
const membership = await permissionDAL.getOrgIdentityPermission(identityId, orgId);
|
const membership = await permissionDAL.getOrgIdentityPermission(identityId, orgId);
|
||||||
if (!membership) throw new ForbiddenRequestError({ name: "Identity is not a part of the specified organization" });
|
if (!membership) throw new ForbiddenRequestError({ name: "Identity is not apart of this organization" });
|
||||||
if (membership.role === OrgMembershipRole.Custom && !membership.permissions) {
|
if (membership.role === OrgMembershipRole.Custom && !membership.permissions) {
|
||||||
throw new NotFoundError({ name: "Custom organization permission not found" });
|
throw new NotFoundError({ name: "Custom organization permission not found" });
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,28 +19,47 @@ enum JWTErrors {
|
|||||||
InvalidAlgorithm = "invalid algorithm"
|
InvalidAlgorithm = "invalid algorithm"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum HttpStatusCodes {
|
||||||
|
BadRequest = 400,
|
||||||
|
NotFound = 404,
|
||||||
|
Unauthorized = 401,
|
||||||
|
Forbidden = 403,
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-shadow
|
||||||
|
InternalServerError = 500
|
||||||
|
}
|
||||||
|
|
||||||
export const fastifyErrHandler = fastifyPlugin(async (server: FastifyZodProvider) => {
|
export const fastifyErrHandler = fastifyPlugin(async (server: FastifyZodProvider) => {
|
||||||
server.setErrorHandler((error, req, res) => {
|
server.setErrorHandler((error, req, res) => {
|
||||||
req.log.error(error);
|
req.log.error(error);
|
||||||
if (error instanceof BadRequestError) {
|
if (error instanceof BadRequestError) {
|
||||||
void res.status(400).send({ statusCode: 400, message: error.message, error: error.name });
|
void res
|
||||||
|
.status(HttpStatusCodes.BadRequest)
|
||||||
|
.send({ statusCode: HttpStatusCodes.BadRequest, message: error.message, error: error.name });
|
||||||
} else if (error instanceof NotFoundError) {
|
} else if (error instanceof NotFoundError) {
|
||||||
void res.status(404).send({ statusCode: 404, message: error.message, error: error.name });
|
void res
|
||||||
|
.status(HttpStatusCodes.NotFound)
|
||||||
|
.send({ statusCode: HttpStatusCodes.NotFound, message: error.message, error: error.name });
|
||||||
} else if (error instanceof UnauthorizedError) {
|
} else if (error instanceof UnauthorizedError) {
|
||||||
void res.status(401).send({ statusCode: 401, message: error.message, error: error.name });
|
void res
|
||||||
|
.status(HttpStatusCodes.Unauthorized)
|
||||||
|
.send({ statusCode: HttpStatusCodes.Unauthorized, message: error.message, error: error.name });
|
||||||
} else if (error instanceof DatabaseError || error instanceof InternalServerError) {
|
} else if (error instanceof DatabaseError || error instanceof InternalServerError) {
|
||||||
void res.status(500).send({ statusCode: 500, message: "Something went wrong", error: error.name });
|
void res
|
||||||
|
.status(HttpStatusCodes.InternalServerError)
|
||||||
|
.send({ statusCode: HttpStatusCodes.InternalServerError, message: "Something went wrong", error: error.name });
|
||||||
} else if (error instanceof ZodError) {
|
} else if (error instanceof ZodError) {
|
||||||
void res.status(401).send({ statusCode: 401, error: "ValidationFailure", message: error.issues });
|
void res
|
||||||
|
.status(HttpStatusCodes.Unauthorized)
|
||||||
|
.send({ statusCode: HttpStatusCodes.Unauthorized, error: "ValidationFailure", message: error.issues });
|
||||||
} else if (error instanceof ForbiddenError) {
|
} else if (error instanceof ForbiddenError) {
|
||||||
void res.status(403).send({
|
void res.status(HttpStatusCodes.Forbidden).send({
|
||||||
statusCode: 403,
|
statusCode: HttpStatusCodes.Forbidden,
|
||||||
error: "PermissionDenied",
|
error: "PermissionDenied",
|
||||||
message: `You are not allowed to ${error.action} on ${error.subjectType}`
|
message: `You are not allowed to ${error.action} on ${error.subjectType}`
|
||||||
});
|
});
|
||||||
} else if (error instanceof ForbiddenRequestError) {
|
} else if (error instanceof ForbiddenRequestError) {
|
||||||
void res.status(403).send({
|
void res.status(HttpStatusCodes.Forbidden).send({
|
||||||
statusCode: 403,
|
statusCode: HttpStatusCodes.Forbidden,
|
||||||
message: error.message,
|
message: error.message,
|
||||||
error: error.name
|
error: error.name
|
||||||
});
|
});
|
||||||
@@ -66,8 +85,8 @@ export const fastifyErrHandler = fastifyPlugin(async (server: FastifyZodProvider
|
|||||||
return error.message;
|
return error.message;
|
||||||
})();
|
})();
|
||||||
|
|
||||||
void res.status(403).send({
|
void res.status(HttpStatusCodes.Forbidden).send({
|
||||||
statusCode: 403,
|
statusCode: HttpStatusCodes.Forbidden,
|
||||||
error: "TokenError",
|
error: "TokenError",
|
||||||
message
|
message
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -40,12 +40,12 @@ export const DefaultResponseErrorsSchema = {
|
|||||||
}),
|
}),
|
||||||
401: z.object({
|
401: z.object({
|
||||||
statusCode: z.literal(401),
|
statusCode: z.literal(401),
|
||||||
message: z.string(),
|
message: z.any(),
|
||||||
error: z.string()
|
error: z.string()
|
||||||
}),
|
}),
|
||||||
403: z.object({
|
403: z.object({
|
||||||
statusCode: z.literal(403),
|
statusCode: z.literal(403),
|
||||||
message: z.any(),
|
message: z.string(),
|
||||||
error: z.string()
|
error: z.string()
|
||||||
}),
|
}),
|
||||||
500: z.object({
|
500: z.object({
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import jwt, { JwtPayload } from "jsonwebtoken";
|
|||||||
|
|
||||||
import { TableName, TIdentityAccessTokens } from "@app/db/schemas";
|
import { TableName, TIdentityAccessTokens } from "@app/db/schemas";
|
||||||
import { getConfig } from "@app/lib/config/env";
|
import { getConfig } from "@app/lib/config/env";
|
||||||
import { BadRequestError, ForbiddenRequestError, UnauthorizedError } from "@app/lib/errors";
|
import { BadRequestError, UnauthorizedError } from "@app/lib/errors";
|
||||||
import { checkIPAgainstBlocklist, TIp } from "@app/lib/ip";
|
import { checkIPAgainstBlocklist, TIp } from "@app/lib/ip";
|
||||||
|
|
||||||
import { TAccessTokenQueueServiceFactory } from "../access-token-queue/access-token-queue";
|
import { TAccessTokenQueueServiceFactory } from "../access-token-queue/access-token-queue";
|
||||||
@@ -39,7 +39,7 @@ export const identityAccessTokenServiceFactory = ({
|
|||||||
|
|
||||||
if (accessTokenNumUsesLimit > 0 && accessTokenNumUses > 0 && accessTokenNumUses >= accessTokenNumUsesLimit) {
|
if (accessTokenNumUsesLimit > 0 && accessTokenNumUses > 0 && accessTokenNumUses >= accessTokenNumUsesLimit) {
|
||||||
await identityAccessTokenDAL.deleteById(tokenId);
|
await identityAccessTokenDAL.deleteById(tokenId);
|
||||||
throw new ForbiddenRequestError({
|
throw new UnauthorizedError({
|
||||||
message: "Unable to renew because access token number of uses limit reached"
|
message: "Unable to renew because access token number of uses limit reached"
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -55,7 +55,7 @@ export const identityAccessTokenServiceFactory = ({
|
|||||||
|
|
||||||
if (currentDate > expirationDate) {
|
if (currentDate > expirationDate) {
|
||||||
await identityAccessTokenDAL.deleteById(tokenId);
|
await identityAccessTokenDAL.deleteById(tokenId);
|
||||||
throw new ForbiddenRequestError({
|
throw new UnauthorizedError({
|
||||||
message: "Failed to renew MI access token due to TTL expiration"
|
message: "Failed to renew MI access token due to TTL expiration"
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -67,7 +67,7 @@ export const identityAccessTokenServiceFactory = ({
|
|||||||
|
|
||||||
if (currentDate > expirationDate) {
|
if (currentDate > expirationDate) {
|
||||||
await identityAccessTokenDAL.deleteById(tokenId);
|
await identityAccessTokenDAL.deleteById(tokenId);
|
||||||
throw new ForbiddenRequestError({
|
throw new UnauthorizedError({
|
||||||
message: "Failed to renew MI access token due to TTL expiration"
|
message: "Failed to renew MI access token due to TTL expiration"
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -82,7 +82,7 @@ export const identityAccessTokenServiceFactory = ({
|
|||||||
identityAccessTokenId: string;
|
identityAccessTokenId: string;
|
||||||
};
|
};
|
||||||
if (decodedToken.authTokenType !== AuthTokenType.IDENTITY_ACCESS_TOKEN) {
|
if (decodedToken.authTokenType !== AuthTokenType.IDENTITY_ACCESS_TOKEN) {
|
||||||
throw new ForbiddenRequestError({ message: "Only identity access tokens can be renewed" });
|
throw new BadRequestError({ message: "Only identity access tokens can be renewed" });
|
||||||
}
|
}
|
||||||
|
|
||||||
const identityAccessToken = await identityAccessTokenDAL.findOne({
|
const identityAccessToken = await identityAccessTokenDAL.findOne({
|
||||||
@@ -109,7 +109,7 @@ export const identityAccessTokenServiceFactory = ({
|
|||||||
|
|
||||||
if (currentDate > expirationDate) {
|
if (currentDate > expirationDate) {
|
||||||
await identityAccessTokenDAL.deleteById(identityAccessToken.id);
|
await identityAccessTokenDAL.deleteById(identityAccessToken.id);
|
||||||
throw new ForbiddenRequestError({
|
throw new UnauthorizedError({
|
||||||
message: "Failed to renew MI access token due to Max TTL expiration"
|
message: "Failed to renew MI access token due to Max TTL expiration"
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -117,7 +117,7 @@ export const identityAccessTokenServiceFactory = ({
|
|||||||
const extendToDate = new Date(currentDate.getTime() + Number(accessTokenTTL * 1000));
|
const extendToDate = new Date(currentDate.getTime() + Number(accessTokenTTL * 1000));
|
||||||
if (extendToDate > expirationDate) {
|
if (extendToDate > expirationDate) {
|
||||||
await identityAccessTokenDAL.deleteById(identityAccessToken.id);
|
await identityAccessTokenDAL.deleteById(identityAccessToken.id);
|
||||||
throw new ForbiddenRequestError({
|
throw new UnauthorizedError({
|
||||||
message: "Failed to renew MI access token past its Max TTL expiration"
|
message: "Failed to renew MI access token past its Max TTL expiration"
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -137,7 +137,7 @@ export const identityAccessTokenServiceFactory = ({
|
|||||||
identityAccessTokenId: string;
|
identityAccessTokenId: string;
|
||||||
};
|
};
|
||||||
if (decodedToken.authTokenType !== AuthTokenType.IDENTITY_ACCESS_TOKEN) {
|
if (decodedToken.authTokenType !== AuthTokenType.IDENTITY_ACCESS_TOKEN) {
|
||||||
throw new ForbiddenRequestError({ message: "Only identity access tokens can be revoked" });
|
throw new UnauthorizedError({ message: "Only identity access tokens can be revoked" });
|
||||||
}
|
}
|
||||||
|
|
||||||
const identityAccessToken = await identityAccessTokenDAL.findOne({
|
const identityAccessToken = await identityAccessTokenDAL.findOne({
|
||||||
@@ -160,7 +160,7 @@ export const identityAccessTokenServiceFactory = ({
|
|||||||
});
|
});
|
||||||
if (!identityAccessToken) throw new UnauthorizedError({ message: "No identity access token found" });
|
if (!identityAccessToken) throw new UnauthorizedError({ message: "No identity access token found" });
|
||||||
if (identityAccessToken.isAccessTokenRevoked)
|
if (identityAccessToken.isAccessTokenRevoked)
|
||||||
throw new ForbiddenRequestError({
|
throw new UnauthorizedError({
|
||||||
message: "Failed to authorize revoked access token, access token is revoked"
|
message: "Failed to authorize revoked access token, access token is revoked"
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import { OrgPermissionActions, OrgPermissionSubjects } from "@app/ee/services/pe
|
|||||||
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service";
|
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service";
|
||||||
import { isAtLeastAsPrivileged } from "@app/lib/casl";
|
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, UnauthorizedError } from "@app/lib/errors";
|
||||||
import { extractIPDetails, isValidIpOrCidr } from "@app/lib/ip";
|
import { extractIPDetails, isValidIpOrCidr } from "@app/lib/ip";
|
||||||
|
|
||||||
import { ActorType, AuthTokenType } from "../auth/auth-type";
|
import { ActorType, AuthTokenType } from "../auth/auth-type";
|
||||||
@@ -81,7 +81,7 @@ export const identityAwsAuthServiceFactory = ({
|
|||||||
.some((accountId) => accountId === Account);
|
.some((accountId) => accountId === Account);
|
||||||
|
|
||||||
if (!isAccountAllowed)
|
if (!isAccountAllowed)
|
||||||
throw new ForbiddenRequestError({
|
throw new UnauthorizedError({
|
||||||
message: "Access denied: AWS account ID not allowed."
|
message: "Access denied: AWS account ID not allowed."
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -100,7 +100,7 @@ export const identityAwsAuthServiceFactory = ({
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (!isArnAllowed)
|
if (!isArnAllowed)
|
||||||
throw new ForbiddenRequestError({
|
throw new UnauthorizedError({
|
||||||
message: "Access denied: AWS principal ARN not allowed."
|
message: "Access denied: AWS principal ARN not allowed."
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ export const identityAzureAuthServiceFactory = ({
|
|||||||
.map((servicePrincipalId) => servicePrincipalId.trim())
|
.map((servicePrincipalId) => servicePrincipalId.trim())
|
||||||
.some((servicePrincipalId) => servicePrincipalId === azureIdentity.oid);
|
.some((servicePrincipalId) => servicePrincipalId === azureIdentity.oid);
|
||||||
|
|
||||||
if (!isServicePrincipalAllowed) throw new ForbiddenRequestError({ message: "Service principal not allowed" });
|
if (!isServicePrincipalAllowed) throw new UnauthorizedError({ message: "Service principal not allowed" });
|
||||||
}
|
}
|
||||||
|
|
||||||
const identityAccessToken = await identityAzureAuthDAL.transaction(async (tx) => {
|
const identityAccessToken = await identityAzureAuthDAL.transaction(async (tx) => {
|
||||||
@@ -314,8 +314,7 @@ export const identityAzureAuthServiceFactory = ({
|
|||||||
actorAuthMethod,
|
actorAuthMethod,
|
||||||
actorOrgId
|
actorOrgId
|
||||||
);
|
);
|
||||||
const hasPriviledge = isAtLeastAsPrivileged(permission, rolePermission);
|
if (!isAtLeastAsPrivileged(permission, rolePermission))
|
||||||
if (!hasPriviledge)
|
|
||||||
throw new ForbiddenRequestError({
|
throw new ForbiddenRequestError({
|
||||||
message: "Failed to revoke azure auth of identity with more privileged role"
|
message: "Failed to revoke azure auth of identity with more privileged role"
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -86,7 +86,7 @@ export const identityGcpAuthServiceFactory = ({
|
|||||||
.some((serviceAccount) => serviceAccount === gcpIdentityDetails.email);
|
.some((serviceAccount) => serviceAccount === gcpIdentityDetails.email);
|
||||||
|
|
||||||
if (!isServiceAccountAllowed)
|
if (!isServiceAccountAllowed)
|
||||||
throw new ForbiddenRequestError({
|
throw new UnauthorizedError({
|
||||||
message: "Access denied: GCP service account not allowed."
|
message: "Access denied: GCP service account not allowed."
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -100,7 +100,7 @@ export const identityGcpAuthServiceFactory = ({
|
|||||||
.some((project) => project === gcpIdentityDetails.computeEngineDetails?.project_id);
|
.some((project) => project === gcpIdentityDetails.computeEngineDetails?.project_id);
|
||||||
|
|
||||||
if (!isProjectAllowed)
|
if (!isProjectAllowed)
|
||||||
throw new ForbiddenRequestError({
|
throw new UnauthorizedError({
|
||||||
message: "Access denied: GCP project not allowed."
|
message: "Access denied: GCP project not allowed."
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -112,7 +112,7 @@ export const identityGcpAuthServiceFactory = ({
|
|||||||
.some((zone) => zone === gcpIdentityDetails.computeEngineDetails?.zone);
|
.some((zone) => zone === gcpIdentityDetails.computeEngineDetails?.zone);
|
||||||
|
|
||||||
if (!isZoneAllowed)
|
if (!isZoneAllowed)
|
||||||
throw new ForbiddenRequestError({
|
throw new UnauthorizedError({
|
||||||
message: "Access denied: GCP zone not allowed."
|
message: "Access denied: GCP zone not allowed."
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -359,8 +359,7 @@ export const identityGcpAuthServiceFactory = ({
|
|||||||
actorAuthMethod,
|
actorAuthMethod,
|
||||||
actorOrgId
|
actorOrgId
|
||||||
);
|
);
|
||||||
const hasPriviledge = isAtLeastAsPrivileged(permission, rolePermission);
|
if (!isAtLeastAsPrivileged(permission, rolePermission))
|
||||||
if (!hasPriviledge)
|
|
||||||
throw new ForbiddenRequestError({
|
throw new ForbiddenRequestError({
|
||||||
message: "Failed to revoke gcp auth of identity with more privileged role"
|
message: "Failed to revoke gcp auth of identity with more privileged role"
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -132,7 +132,7 @@ export const identityKubernetesAuthServiceFactory = ({
|
|||||||
|
|
||||||
// check the response to determine if the token is valid
|
// check the response to determine if the token is valid
|
||||||
if (!(data.status && data.status.authenticated))
|
if (!(data.status && data.status.authenticated))
|
||||||
throw new ForbiddenRequestError({ message: "Kubernetes token not authenticated" });
|
throw new UnauthorizedError({ message: "Kubernetes token not authenticated" });
|
||||||
|
|
||||||
const { namespace: targetNamespace, name: targetName } = extractK8sUsername(data.status.user.username);
|
const { namespace: targetNamespace, name: targetName } = extractK8sUsername(data.status.user.username);
|
||||||
|
|
||||||
@@ -145,7 +145,7 @@ export const identityKubernetesAuthServiceFactory = ({
|
|||||||
.some((namespace) => namespace === targetNamespace);
|
.some((namespace) => namespace === targetNamespace);
|
||||||
|
|
||||||
if (!isNamespaceAllowed)
|
if (!isNamespaceAllowed)
|
||||||
throw new ForbiddenRequestError({
|
throw new UnauthorizedError({
|
||||||
message: "Access denied: K8s namespace not allowed."
|
message: "Access denied: K8s namespace not allowed."
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -159,7 +159,7 @@ export const identityKubernetesAuthServiceFactory = ({
|
|||||||
.some((name) => name === targetName);
|
.some((name) => name === targetName);
|
||||||
|
|
||||||
if (!isNameAllowed)
|
if (!isNameAllowed)
|
||||||
throw new ForbiddenRequestError({
|
throw new UnauthorizedError({
|
||||||
message: "Access denied: K8s name not allowed."
|
message: "Access denied: K8s name not allowed."
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -171,7 +171,7 @@ export const identityKubernetesAuthServiceFactory = ({
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (!isAudienceAllowed)
|
if (!isAudienceAllowed)
|
||||||
throw new ForbiddenRequestError({
|
throw new UnauthorizedError({
|
||||||
message: "Access denied: K8s audience not allowed."
|
message: "Access denied: K8s audience not allowed."
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -148,7 +148,7 @@ export const identityOidcAuthServiceFactory = ({
|
|||||||
.split(", ")
|
.split(", ")
|
||||||
.some((policyValue) => doesFieldValueMatchOidcPolicy(tokenData.aud, policyValue))
|
.some((policyValue) => doesFieldValueMatchOidcPolicy(tokenData.aud, policyValue))
|
||||||
) {
|
) {
|
||||||
throw new ForbiddenRequestError({
|
throw new UnauthorizedError({
|
||||||
message: "Access denied: OIDC audience not allowed."
|
message: "Access denied: OIDC audience not allowed."
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -161,7 +161,7 @@ export const identityOidcAuthServiceFactory = ({
|
|||||||
if (
|
if (
|
||||||
!claimValue.split(", ").some((claimEntry) => doesFieldValueMatchOidcPolicy(tokenData[claimKey], claimEntry))
|
!claimValue.split(", ").some((claimEntry) => doesFieldValueMatchOidcPolicy(tokenData[claimKey], claimEntry))
|
||||||
) {
|
) {
|
||||||
throw new ForbiddenRequestError({
|
throw new UnauthorizedError({
|
||||||
message: "Access denied: OIDC claim not allowed."
|
message: "Access denied: OIDC claim not allowed."
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -532,8 +532,7 @@ export const identityOidcAuthServiceFactory = ({
|
|||||||
actorOrgId
|
actorOrgId
|
||||||
);
|
);
|
||||||
|
|
||||||
const hasPriviledge = isAtLeastAsPrivileged(permission, rolePermission);
|
if (!isAtLeastAsPrivileged(permission, rolePermission)) {
|
||||||
if (!hasPriviledge) {
|
|
||||||
throw new ForbiddenRequestError({
|
throw new ForbiddenRequestError({
|
||||||
message: "Failed to revoke OIDC auth of identity with more privileged role"
|
message: "Failed to revoke OIDC auth of identity with more privileged role"
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -88,7 +88,7 @@ export const identityUaServiceFactory = ({
|
|||||||
isClientSecretRevoked: true
|
isClientSecretRevoked: true
|
||||||
});
|
});
|
||||||
|
|
||||||
throw new ForbiddenRequestError({
|
throw new UnauthorizedError({
|
||||||
message: "Access denied due to expired client secret"
|
message: "Access denied due to expired client secret"
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -100,7 +100,7 @@ export const identityUaServiceFactory = ({
|
|||||||
await identityUaClientSecretDAL.updateById(validClientSecretInfo.id, {
|
await identityUaClientSecretDAL.updateById(validClientSecretInfo.id, {
|
||||||
isClientSecretRevoked: true
|
isClientSecretRevoked: true
|
||||||
});
|
});
|
||||||
throw new ForbiddenRequestError({
|
throw new UnauthorizedError({
|
||||||
message: "Access denied due to client secret usage limit reached"
|
message: "Access denied due to client secret usage limit reached"
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -368,8 +368,7 @@ export const identityUaServiceFactory = ({
|
|||||||
actorAuthMethod,
|
actorAuthMethod,
|
||||||
actorOrgId
|
actorOrgId
|
||||||
);
|
);
|
||||||
const hasPriviledge = isAtLeastAsPrivileged(permission, rolePermission);
|
if (!isAtLeastAsPrivileged(permission, rolePermission))
|
||||||
if (!hasPriviledge)
|
|
||||||
throw new ForbiddenRequestError({
|
throw new ForbiddenRequestError({
|
||||||
message: "Failed to revoke universal auth of identity with more privileged role"
|
message: "Failed to revoke universal auth of identity with more privileged role"
|
||||||
});
|
});
|
||||||
@@ -474,8 +473,8 @@ export const identityUaServiceFactory = ({
|
|||||||
actorAuthMethod,
|
actorAuthMethod,
|
||||||
actorOrgId
|
actorOrgId
|
||||||
);
|
);
|
||||||
const hasPriviledge = isAtLeastAsPrivileged(permission, rolePermission);
|
|
||||||
if (!hasPriviledge)
|
if (!isAtLeastAsPrivileged(permission, rolePermission))
|
||||||
throw new ForbiddenRequestError({
|
throw new ForbiddenRequestError({
|
||||||
message: "Failed to add identity to project with more privileged role"
|
message: "Failed to add identity to project with more privileged role"
|
||||||
});
|
});
|
||||||
@@ -521,8 +520,7 @@ export const identityUaServiceFactory = ({
|
|||||||
actorAuthMethod,
|
actorAuthMethod,
|
||||||
actorOrgId
|
actorOrgId
|
||||||
);
|
);
|
||||||
const hasPriviledge = isAtLeastAsPrivileged(permission, rolePermission);
|
if (!isAtLeastAsPrivileged(permission, rolePermission))
|
||||||
if (!hasPriviledge)
|
|
||||||
throw new ForbiddenRequestError({
|
throw new ForbiddenRequestError({
|
||||||
message: "Failed to read identity client secret of project with more privileged role"
|
message: "Failed to read identity client secret of project with more privileged role"
|
||||||
});
|
});
|
||||||
@@ -561,8 +559,8 @@ export const identityUaServiceFactory = ({
|
|||||||
actorAuthMethod,
|
actorAuthMethod,
|
||||||
actorOrgId
|
actorOrgId
|
||||||
);
|
);
|
||||||
const hasPriviledge = isAtLeastAsPrivileged(permission, rolePermission);
|
|
||||||
if (!hasPriviledge)
|
if (!isAtLeastAsPrivileged(permission, rolePermission))
|
||||||
throw new ForbiddenRequestError({
|
throw new ForbiddenRequestError({
|
||||||
message: "Failed to revoke identity client secret with more privileged role"
|
message: "Failed to revoke identity client secret with more privileged role"
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -892,7 +892,7 @@ export const orgServiceFactory = ({
|
|||||||
|
|
||||||
const membership = await orgMembershipDAL.findOrgMembershipById(membershipId);
|
const membership = await orgMembershipDAL.findOrgMembershipById(membershipId);
|
||||||
if (!membership) {
|
if (!membership) {
|
||||||
throw new NotFoundError({ message: "Failed to find organization membership" });
|
throw new NotFoundError({ message: "Organization membership not found" });
|
||||||
}
|
}
|
||||||
if (membership.orgId !== orgId) {
|
if (membership.orgId !== orgId) {
|
||||||
throw new ForbiddenRequestError({ message: "Membership does not belong to organization" });
|
throw new ForbiddenRequestError({ message: "Membership does not belong to organization" });
|
||||||
@@ -937,7 +937,9 @@ export const orgServiceFactory = ({
|
|||||||
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Member);
|
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Member);
|
||||||
|
|
||||||
const membership = await orgMembershipDAL.findOrgMembershipById(orgMembershipId);
|
const membership = await orgMembershipDAL.findOrgMembershipById(orgMembershipId);
|
||||||
if (!membership) throw new NotFoundError({ message: "Failed to find organization membership" });
|
if (!membership) {
|
||||||
|
throw new NotFoundError({ message: "Organization membership not found" });
|
||||||
|
}
|
||||||
if (membership.orgId !== orgId) throw new NotFoundError({ message: "Failed to find organization membership" });
|
if (membership.orgId !== orgId) throw new NotFoundError({ message: "Failed to find organization membership" });
|
||||||
|
|
||||||
const projectMemberships = await projectMembershipDAL.findProjectMembershipsByUserId(orgId, membership.user.id);
|
const projectMemberships = await projectMembershipDAL.findProjectMembershipsByUserId(orgId, membership.user.id);
|
||||||
|
|||||||
@@ -909,9 +909,7 @@ export const projectServiceFactory = ({
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (!membership) {
|
if (!membership) {
|
||||||
throw new ForbiddenRequestError({
|
throw new ForbiddenRequestError({ message: "You are not a member of this project" });
|
||||||
message: "User is not a member of the project"
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const kmsKeyId = await kmsService.getProjectSecretManagerKmsKeyId(projectId);
|
const kmsKeyId = await kmsService.getProjectSecretManagerKmsKeyId(projectId);
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import bcrypt from "bcrypt";
|
|||||||
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 { ProjectPermissionActions, ProjectPermissionSub } from "@app/ee/services/permission/project-permission";
|
||||||
import { getConfig } from "@app/lib/config/env";
|
import { getConfig } from "@app/lib/config/env";
|
||||||
import { ForbiddenRequestError, NotFoundError } from "@app/lib/errors";
|
import { ForbiddenRequestError, NotFoundError, UnauthorizedError } from "@app/lib/errors";
|
||||||
|
|
||||||
import { TAccessTokenQueueServiceFactory } from "../access-token-queue/access-token-queue";
|
import { TAccessTokenQueueServiceFactory } from "../access-token-queue/access-token-queue";
|
||||||
import { ActorType } from "../auth/auth-type";
|
import { ActorType } from "../auth/auth-type";
|
||||||
@@ -168,7 +168,7 @@ export const serviceTokenServiceFactory = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
const isMatch = await bcrypt.compare(tokenSecret, serviceToken.secretHash);
|
const isMatch = await bcrypt.compare(tokenSecret, serviceToken.secretHash);
|
||||||
if (!isMatch) throw new ForbiddenRequestError();
|
if (!isMatch) throw new UnauthorizedError({ message: "Invalid service token" });
|
||||||
await accessTokenQueue.updateServiceTokenStatus(serviceToken.id);
|
await accessTokenQueue.updateServiceTokenStatus(serviceToken.id);
|
||||||
|
|
||||||
return { ...serviceToken, lastUsed: new Date(), orgId: project.orgId };
|
return { ...serviceToken, lastUsed: new Date(), orgId: project.orgId };
|
||||||
|
|||||||
Reference in New Issue
Block a user