mirror of
https://github.com/Infisical/infisical.git
synced 2025-03-27 09:40:45 +00:00
Compare commits
45 Commits
daniel/fix
...
daniel/err
Author | SHA1 | Date | |
---|---|---|---|
7885a3b0ff | |||
66485f0464 | |||
032197ee9f | |||
d5a4eb609a | |||
d430293c66 | |||
180d2692cd | |||
433e58655a | |||
5ffb6b7232 | |||
55ca9149d5 | |||
4ea57ca9a0 | |||
7ac4b0b79f | |||
2d51ed317f | |||
02c51b05b6 | |||
441b008709 | |||
4d81a0251e | |||
59da513481 | |||
c17047a193 | |||
f50a881273 | |||
c011d99b8b | |||
adc3542750 | |||
82e3241f1b | |||
2bca46886a | |||
971987c786 | |||
cd71a13bb7 | |||
98290fe31b | |||
9f15fb1474 | |||
301a867f8b | |||
658a044e85 | |||
2c1e29445d | |||
3f4c4f7418 | |||
592cc13b1f | |||
e70c2f3d10 | |||
bac865eab1 | |||
3d8fbc0a58 | |||
a1f2629366 | |||
bf8e1f2bfd | |||
f7d10ceeda | |||
095883a94e | |||
51638b7c71 | |||
adaddad370 | |||
cf6ff58f16 | |||
3e3f42a8f7 | |||
974e21d856 | |||
6733349af0 | |||
14c89c9be5 |
backend
e2e-test/routes
src
ee
routes/v1
access-approval-policy-router.tsgroup-router.tsidentity-project-additional-privilege-router.tsrate-limit-router.tssaml-router.tssecret-approval-policy-router.ts
services
access-approval-policy
access-approval-policy-dal.tsaccess-approval-policy-fns.tsaccess-approval-policy-service.tsaccess-approval-policy-types.ts
access-approval-request
audit-log-stream
certificate-authority-crl
dynamic-secret-lease
dynamic-secret
external-kms
group
identity-project-additional-privilege
ldap-config
license
oidc
permission
project-user-additional-privilege
saml-config
scim
secret-approval-policy
secret-approval-request
secret-replication
secret-rotation
secret-scanning
secret-snapshot
lib
server
services
api-key
auth-token
auth
certificate-authority
group-project
identity-access-token
identity-aws-auth
identity-azure-auth
identity-gcp-auth
identity-kubernetes-auth
identity-oidc-auth
identity-project
identity-token-auth
identity-ua
identity
integration-auth
integration
kms
org-admin
org
pki-alert
project-bot
project-env
project-membership
project-role
project
secret-blind-index
secret-folder
secret-import
secret-sharing
secret-tag
secret-v2-bridge
secret
service-token
super-admin
user
webhook
docs
api-reference/endpoints
groups
add-group-user.mdxcreate.mdxdelete.mdxget-by-id.mdxget.mdxlist-group-users.mdxremove-group-user.mdxupdate.mdx
project-groups
cli/commands
mint.jsonfrontend/src
hooks/api/kms
layouts/AppLayout
pages
views
Org/AuditLogsPage
Project/CertificatesPage/components
CertificatesTab/components
PkiAlertsTab/components
SecretMainPage
SecretOverviewPage
helm-charts/secrets-operator
k8-operator/controllers
@ -510,7 +510,7 @@ describe("Service token fail cases", async () => {
|
||||
authorization: `Bearer ${serviceToken}`
|
||||
}
|
||||
});
|
||||
expect(fetchSecrets.statusCode).toBe(401);
|
||||
expect(fetchSecrets.statusCode).toBe(403);
|
||||
expect(fetchSecrets.json().error).toBe("PermissionDenied");
|
||||
await deleteServiceToken();
|
||||
});
|
||||
@ -532,7 +532,7 @@ describe("Service token fail cases", async () => {
|
||||
authorization: `Bearer ${serviceToken}`
|
||||
}
|
||||
});
|
||||
expect(fetchSecrets.statusCode).toBe(401);
|
||||
expect(fetchSecrets.statusCode).toBe(403);
|
||||
expect(fetchSecrets.json().error).toBe("PermissionDenied");
|
||||
await deleteServiceToken();
|
||||
});
|
||||
@ -557,7 +557,7 @@ describe("Service token fail cases", async () => {
|
||||
authorization: `Bearer ${serviceToken}`
|
||||
}
|
||||
});
|
||||
expect(writeSecrets.statusCode).toBe(401);
|
||||
expect(writeSecrets.statusCode).toBe(403);
|
||||
expect(writeSecrets.json().error).toBe("PermissionDenied");
|
||||
|
||||
// but read access should still work fine
|
||||
|
@ -1075,7 +1075,7 @@ describe("Secret V3 Raw Router Without E2EE enabled", async () => {
|
||||
},
|
||||
body: createSecretReqBody
|
||||
});
|
||||
expect(createSecRes.statusCode).toBe(400);
|
||||
expect(createSecRes.statusCode).toBe(404);
|
||||
});
|
||||
|
||||
test("Update secret raw", async () => {
|
||||
@ -1093,7 +1093,7 @@ describe("Secret V3 Raw Router Without E2EE enabled", async () => {
|
||||
},
|
||||
body: updateSecretReqBody
|
||||
});
|
||||
expect(updateSecRes.statusCode).toBe(400);
|
||||
expect(updateSecRes.statusCode).toBe(404);
|
||||
});
|
||||
|
||||
test("Delete secret raw", async () => {
|
||||
@ -1110,6 +1110,6 @@ describe("Secret V3 Raw Router Without E2EE enabled", async () => {
|
||||
},
|
||||
body: deletedSecretReqBody
|
||||
});
|
||||
expect(deletedSecRes.statusCode).toBe(400);
|
||||
expect(deletedSecRes.statusCode).toBe(404);
|
||||
});
|
||||
});
|
||||
|
@ -3,6 +3,7 @@ import { z } from "zod";
|
||||
|
||||
import { ApproverType } from "@app/ee/services/access-approval-policy/access-approval-policy-types";
|
||||
import { EnforcementLevel } from "@app/lib/types";
|
||||
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
||||
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||
import { sapPubSchema } from "@app/server/routes/sanitizedSchemas";
|
||||
import { AuthMode } from "@app/services/auth/auth-type";
|
||||
@ -11,6 +12,9 @@ export const registerAccessApprovalPolicyRouter = async (server: FastifyZodProvi
|
||||
server.route({
|
||||
url: "/",
|
||||
method: "POST",
|
||||
config: {
|
||||
rateLimit: writeLimit
|
||||
},
|
||||
schema: {
|
||||
body: z.object({
|
||||
projectSlug: z.string().trim(),
|
||||
@ -18,7 +22,10 @@ export const registerAccessApprovalPolicyRouter = async (server: FastifyZodProvi
|
||||
secretPath: z.string().trim().default("/"),
|
||||
environment: z.string(),
|
||||
approvers: z
|
||||
.object({ type: z.nativeEnum(ApproverType), id: z.string() })
|
||||
.discriminatedUnion("type", [
|
||||
z.object({ type: z.literal(ApproverType.Group), id: z.string() }),
|
||||
z.object({ type: z.literal(ApproverType.User), id: z.string().optional(), name: z.string().optional() })
|
||||
])
|
||||
.array()
|
||||
.min(1, { message: "At least one approver should be provided" }),
|
||||
approvals: z.number().min(1).default(1),
|
||||
@ -30,7 +37,7 @@ export const registerAccessApprovalPolicyRouter = async (server: FastifyZodProvi
|
||||
})
|
||||
}
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT]),
|
||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||
handler: async (req) => {
|
||||
const approval = await server.services.accessApprovalPolicy.createAccessApprovalPolicy({
|
||||
actor: req.permission.type,
|
||||
@ -49,6 +56,9 @@ export const registerAccessApprovalPolicyRouter = async (server: FastifyZodProvi
|
||||
server.route({
|
||||
url: "/",
|
||||
method: "GET",
|
||||
config: {
|
||||
rateLimit: readLimit
|
||||
},
|
||||
schema: {
|
||||
querystring: z.object({
|
||||
projectSlug: z.string().trim()
|
||||
@ -115,6 +125,9 @@ export const registerAccessApprovalPolicyRouter = async (server: FastifyZodProvi
|
||||
server.route({
|
||||
url: "/:policyId",
|
||||
method: "PATCH",
|
||||
config: {
|
||||
rateLimit: writeLimit
|
||||
},
|
||||
schema: {
|
||||
params: z.object({
|
||||
policyId: z.string()
|
||||
@ -127,7 +140,10 @@ export const registerAccessApprovalPolicyRouter = async (server: FastifyZodProvi
|
||||
.optional()
|
||||
.transform((val) => (val === "" ? "/" : val)),
|
||||
approvers: z
|
||||
.object({ type: z.nativeEnum(ApproverType), id: z.string() })
|
||||
.discriminatedUnion("type", [
|
||||
z.object({ type: z.literal(ApproverType.Group), id: z.string() }),
|
||||
z.object({ type: z.literal(ApproverType.User), id: z.string().optional(), name: z.string().optional() })
|
||||
])
|
||||
.array()
|
||||
.min(1, { message: "At least one approver should be provided" }),
|
||||
approvals: z.number().min(1).optional(),
|
||||
@ -139,7 +155,7 @@ export const registerAccessApprovalPolicyRouter = async (server: FastifyZodProvi
|
||||
})
|
||||
}
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT]),
|
||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||
handler: async (req) => {
|
||||
await server.services.accessApprovalPolicy.updateAccessApprovalPolicy({
|
||||
policyId: req.params.policyId,
|
||||
@ -155,6 +171,9 @@ export const registerAccessApprovalPolicyRouter = async (server: FastifyZodProvi
|
||||
server.route({
|
||||
url: "/:policyId",
|
||||
method: "DELETE",
|
||||
config: {
|
||||
rateLimit: writeLimit
|
||||
},
|
||||
schema: {
|
||||
params: z.object({
|
||||
policyId: z.string()
|
||||
@ -165,7 +184,7 @@ export const registerAccessApprovalPolicyRouter = async (server: FastifyZodProvi
|
||||
})
|
||||
}
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT]),
|
||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||
handler: async (req) => {
|
||||
const approval = await server.services.accessApprovalPolicy.deleteAccessApprovalPolicy({
|
||||
actor: req.permission.type,
|
||||
@ -177,4 +196,44 @@ export const registerAccessApprovalPolicyRouter = async (server: FastifyZodProvi
|
||||
return { approval };
|
||||
}
|
||||
});
|
||||
|
||||
server.route({
|
||||
url: "/:policyId",
|
||||
method: "GET",
|
||||
config: {
|
||||
rateLimit: readLimit
|
||||
},
|
||||
schema: {
|
||||
params: z.object({
|
||||
policyId: z.string()
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
approval: sapPubSchema.extend({
|
||||
approvers: z
|
||||
.object({
|
||||
type: z.nativeEnum(ApproverType),
|
||||
id: z.string().nullable().optional(),
|
||||
name: z.string().nullable().optional()
|
||||
})
|
||||
.array()
|
||||
.nullable()
|
||||
.optional()
|
||||
})
|
||||
})
|
||||
}
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||
handler: async (req) => {
|
||||
const approval = await server.services.accessApprovalPolicy.getAccessApprovalPolicyById({
|
||||
actor: req.permission.type,
|
||||
actorId: req.permission.id,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
...req.params
|
||||
});
|
||||
|
||||
return { approval };
|
||||
}
|
||||
});
|
||||
};
|
||||
|
@ -48,7 +48,7 @@ export const registerGroupRouter = async (server: FastifyZodProvider) => {
|
||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||
schema: {
|
||||
params: z.object({
|
||||
id: z.string()
|
||||
id: z.string().trim().describe(GROUPS.GET_BY_ID.id)
|
||||
}),
|
||||
response: {
|
||||
200: GroupsSchema
|
||||
|
@ -5,7 +5,7 @@ import { z } from "zod";
|
||||
|
||||
import { IdentityProjectAdditionalPrivilegeTemporaryMode } from "@app/ee/services/identity-project-additional-privilege/identity-project-additional-privilege-types";
|
||||
import { IDENTITY_ADDITIONAL_PRIVILEGE } from "@app/lib/api-docs";
|
||||
import { BadRequestError } from "@app/lib/errors";
|
||||
import { UnauthorizedError } from "@app/lib/errors";
|
||||
import { alphaNumericNanoId } from "@app/lib/nanoid";
|
||||
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
||||
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||
@ -61,7 +61,7 @@ export const registerIdentityProjectAdditionalPrivilegeRouter = async (server: F
|
||||
handler: async (req) => {
|
||||
const { permissions, privilegePermission } = req.body;
|
||||
if (!permissions && !privilegePermission) {
|
||||
throw new BadRequestError({ message: "Permission or privilegePermission must be provided" });
|
||||
throw new UnauthorizedError({ message: "Permission or privilegePermission must be provided" });
|
||||
}
|
||||
|
||||
const permission = privilegePermission
|
||||
@ -140,7 +140,7 @@ export const registerIdentityProjectAdditionalPrivilegeRouter = async (server: F
|
||||
handler: async (req) => {
|
||||
const { permissions, privilegePermission } = req.body;
|
||||
if (!permissions && !privilegePermission) {
|
||||
throw new BadRequestError({ message: "Permission or privilegePermission must be provided" });
|
||||
throw new UnauthorizedError({ message: "Permission or privilegePermission must be provided" });
|
||||
}
|
||||
|
||||
const permission = privilegePermission
|
||||
@ -224,7 +224,7 @@ export const registerIdentityProjectAdditionalPrivilegeRouter = async (server: F
|
||||
handler: async (req) => {
|
||||
const { permissions, privilegePermission, ...updatedInfo } = req.body.privilegeDetails;
|
||||
if (!permissions && !privilegePermission) {
|
||||
throw new BadRequestError({ message: "Permission or privilegePermission must be provided" });
|
||||
throw new UnauthorizedError({ message: "Permission or privilegePermission must be provided" });
|
||||
}
|
||||
|
||||
const permission = privilegePermission
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { z } from "zod";
|
||||
|
||||
import { RateLimitSchema } from "@app/db/schemas";
|
||||
import { BadRequestError } from "@app/lib/errors";
|
||||
import { NotFoundError } from "@app/lib/errors";
|
||||
import { readLimit } from "@app/server/config/rateLimiter";
|
||||
import { verifySuperAdmin } from "@app/server/plugins/auth/superAdmin";
|
||||
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||
@ -29,7 +29,7 @@ export const registerRateLimitRouter = async (server: FastifyZodProvider) => {
|
||||
handler: async () => {
|
||||
const rateLimit = await server.services.rateLimit.getRateLimits();
|
||||
if (!rateLimit) {
|
||||
throw new BadRequestError({
|
||||
throw new NotFoundError({
|
||||
name: "Get Rate Limit Error",
|
||||
message: "Rate limit configuration does not exist."
|
||||
});
|
||||
|
@ -61,7 +61,7 @@ export const registerSamlRouter = async (server: FastifyZodProvider) => {
|
||||
id: samlConfigId
|
||||
};
|
||||
} else {
|
||||
throw new BadRequestError({ message: "Missing sso identitier or org slug" });
|
||||
throw new BadRequestError({ message: "Missing sso identifier or org slug" });
|
||||
}
|
||||
|
||||
const ssoConfig = await server.services.saml.getSaml(ssoLookupDetails);
|
||||
|
@ -28,7 +28,10 @@ export const registerSecretApprovalPolicyRouter = async (server: FastifyZodProvi
|
||||
.default("/")
|
||||
.transform((val) => (val ? removeTrailingSlash(val) : val)),
|
||||
approvers: z
|
||||
.object({ type: z.nativeEnum(ApproverType), id: z.string() })
|
||||
.discriminatedUnion("type", [
|
||||
z.object({ type: z.literal(ApproverType.Group), id: z.string() }),
|
||||
z.object({ type: z.literal(ApproverType.User), id: z.string().optional(), name: z.string().optional() })
|
||||
])
|
||||
.array()
|
||||
.min(1, { message: "At least one approver should be provided" }),
|
||||
approvals: z.number().min(1).default(1),
|
||||
@ -40,7 +43,7 @@ export const registerSecretApprovalPolicyRouter = async (server: FastifyZodProvi
|
||||
})
|
||||
}
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT]),
|
||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||
handler: async (req) => {
|
||||
const approval = await server.services.secretApprovalPolicy.createSecretApprovalPolicy({
|
||||
actor: req.permission.type,
|
||||
@ -69,7 +72,10 @@ export const registerSecretApprovalPolicyRouter = async (server: FastifyZodProvi
|
||||
body: z.object({
|
||||
name: z.string().optional(),
|
||||
approvers: z
|
||||
.object({ type: z.nativeEnum(ApproverType), id: z.string() })
|
||||
.discriminatedUnion("type", [
|
||||
z.object({ type: z.literal(ApproverType.Group), id: z.string() }),
|
||||
z.object({ type: z.literal(ApproverType.User), id: z.string().optional(), name: z.string().optional() })
|
||||
])
|
||||
.array()
|
||||
.min(1, { message: "At least one approver should be provided" }),
|
||||
approvals: z.number().min(1).default(1),
|
||||
@ -87,7 +93,7 @@ export const registerSecretApprovalPolicyRouter = async (server: FastifyZodProvi
|
||||
})
|
||||
}
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT]),
|
||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||
handler: async (req) => {
|
||||
const approval = await server.services.secretApprovalPolicy.updateSecretApprovalPolicy({
|
||||
actor: req.permission.type,
|
||||
@ -117,7 +123,7 @@ export const registerSecretApprovalPolicyRouter = async (server: FastifyZodProvi
|
||||
})
|
||||
}
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT]),
|
||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||
handler: async (req) => {
|
||||
const approval = await server.services.secretApprovalPolicy.deleteSecretApprovalPolicy({
|
||||
actor: req.permission.type,
|
||||
@ -168,6 +174,44 @@ export const registerSecretApprovalPolicyRouter = async (server: FastifyZodProvi
|
||||
}
|
||||
});
|
||||
|
||||
server.route({
|
||||
url: "/:sapId",
|
||||
method: "GET",
|
||||
config: {
|
||||
rateLimit: readLimit
|
||||
},
|
||||
schema: {
|
||||
params: z.object({
|
||||
sapId: z.string()
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
approval: sapPubSchema.extend({
|
||||
approvers: z
|
||||
.object({
|
||||
id: z.string().nullable().optional(),
|
||||
type: z.nativeEnum(ApproverType),
|
||||
name: z.string().nullable().optional()
|
||||
})
|
||||
.array()
|
||||
})
|
||||
})
|
||||
}
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||
handler: async (req) => {
|
||||
const approval = await server.services.secretApprovalPolicy.getSecretApprovalPolicyById({
|
||||
actor: req.permission.type,
|
||||
actorId: req.permission.id,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
...req.params
|
||||
});
|
||||
|
||||
return { approval };
|
||||
}
|
||||
});
|
||||
|
||||
server.route({
|
||||
url: "/board",
|
||||
method: "GET",
|
||||
|
@ -12,16 +12,29 @@ export type TAccessApprovalPolicyDALFactory = ReturnType<typeof accessApprovalPo
|
||||
export const accessApprovalPolicyDALFactory = (db: TDbClient) => {
|
||||
const accessApprovalPolicyOrm = ormify(db, TableName.AccessApprovalPolicy);
|
||||
|
||||
const accessApprovalPolicyFindQuery = async (tx: Knex, filter: TFindFilter<TAccessApprovalPolicies>) => {
|
||||
const accessApprovalPolicyFindQuery = async (
|
||||
tx: Knex,
|
||||
filter: TFindFilter<TAccessApprovalPolicies>,
|
||||
customFilter?: {
|
||||
policyId?: string;
|
||||
}
|
||||
) => {
|
||||
const result = await tx(TableName.AccessApprovalPolicy)
|
||||
// eslint-disable-next-line
|
||||
.where(buildFindFilter(filter))
|
||||
.where((qb) => {
|
||||
if (customFilter?.policyId) {
|
||||
void qb.where(`${TableName.AccessApprovalPolicy}.id`, "=", customFilter.policyId);
|
||||
}
|
||||
})
|
||||
.join(TableName.Environment, `${TableName.AccessApprovalPolicy}.envId`, `${TableName.Environment}.id`)
|
||||
.leftJoin(
|
||||
TableName.AccessApprovalPolicyApprover,
|
||||
`${TableName.AccessApprovalPolicy}.id`,
|
||||
`${TableName.AccessApprovalPolicyApprover}.policyId`
|
||||
)
|
||||
.leftJoin(TableName.Users, `${TableName.AccessApprovalPolicyApprover}.approverUserId`, `${TableName.Users}.id`)
|
||||
.select(tx.ref("username").withSchema(TableName.Users).as("approverUsername"))
|
||||
.select(tx.ref("approverUserId").withSchema(TableName.AccessApprovalPolicyApprover))
|
||||
.select(tx.ref("approverGroupId").withSchema(TableName.AccessApprovalPolicyApprover))
|
||||
.select(tx.ref("name").withSchema(TableName.Environment).as("envName"))
|
||||
@ -76,9 +89,15 @@ export const accessApprovalPolicyDALFactory = (db: TDbClient) => {
|
||||
}
|
||||
};
|
||||
|
||||
const find = async (filter: TFindFilter<TAccessApprovalPolicies & { projectId: string }>, tx?: Knex) => {
|
||||
const find = async (
|
||||
filter: TFindFilter<TAccessApprovalPolicies & { projectId: string }>,
|
||||
customFilter?: {
|
||||
policyId?: string;
|
||||
},
|
||||
tx?: Knex
|
||||
) => {
|
||||
try {
|
||||
const docs = await accessApprovalPolicyFindQuery(tx || db.replicaNode(), filter);
|
||||
const docs = await accessApprovalPolicyFindQuery(tx || db.replicaNode(), filter, customFilter);
|
||||
|
||||
const formattedDocs = sqlNestRelationships({
|
||||
data: docs,
|
||||
@ -97,9 +116,10 @@ export const accessApprovalPolicyDALFactory = (db: TDbClient) => {
|
||||
{
|
||||
key: "approverUserId",
|
||||
label: "approvers" as const,
|
||||
mapper: ({ approverUserId: id }) => ({
|
||||
mapper: ({ approverUserId: id, approverUsername }) => ({
|
||||
id,
|
||||
type: ApproverType.User
|
||||
type: ApproverType.User,
|
||||
name: approverUsername
|
||||
})
|
||||
},
|
||||
{
|
||||
|
@ -1,12 +1,11 @@
|
||||
import { ForbiddenError, subject } from "@casl/ability";
|
||||
|
||||
import { BadRequestError } from "@app/lib/errors";
|
||||
import { ActorType } from "@app/services/auth/auth-type";
|
||||
|
||||
import { ProjectPermissionActions, ProjectPermissionSub } from "../permission/project-permission";
|
||||
import { TVerifyApprovers } from "./access-approval-policy-types";
|
||||
import { TIsApproversValid } from "./access-approval-policy-types";
|
||||
|
||||
export const verifyApprovers = async ({
|
||||
export const isApproversValid = async ({
|
||||
userIds,
|
||||
projectId,
|
||||
orgId,
|
||||
@ -14,9 +13,9 @@ export const verifyApprovers = async ({
|
||||
actorAuthMethod,
|
||||
secretPath,
|
||||
permissionService
|
||||
}: TVerifyApprovers) => {
|
||||
for await (const userId of userIds) {
|
||||
try {
|
||||
}: TIsApproversValid) => {
|
||||
try {
|
||||
for await (const userId of userIds) {
|
||||
const { permission: approverPermission } = await permissionService.getProjectPermission(
|
||||
ActorType.USER,
|
||||
userId,
|
||||
@ -29,8 +28,9 @@ export const verifyApprovers = async ({
|
||||
ProjectPermissionActions.Create,
|
||||
subject(ProjectPermissionSub.Secrets, { environment: envSlug, secretPath })
|
||||
);
|
||||
} catch (err) {
|
||||
throw new BadRequestError({ message: "One or more approvers doesn't have access to be specified secret path" });
|
||||
}
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
@ -2,19 +2,21 @@ import { ForbiddenError } from "@casl/ability";
|
||||
|
||||
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service";
|
||||
import { ProjectPermissionActions, ProjectPermissionSub } from "@app/ee/services/permission/project-permission";
|
||||
import { BadRequestError } from "@app/lib/errors";
|
||||
import { BadRequestError, ForbiddenRequestError, NotFoundError } from "@app/lib/errors";
|
||||
import { TProjectDALFactory } from "@app/services/project/project-dal";
|
||||
import { TProjectEnvDALFactory } from "@app/services/project-env/project-env-dal";
|
||||
import { TProjectMembershipDALFactory } from "@app/services/project-membership/project-membership-dal";
|
||||
import { TUserDALFactory } from "@app/services/user/user-dal";
|
||||
|
||||
import { TGroupDALFactory } from "../group/group-dal";
|
||||
import { TAccessApprovalPolicyApproverDALFactory } from "./access-approval-policy-approver-dal";
|
||||
import { TAccessApprovalPolicyDALFactory } from "./access-approval-policy-dal";
|
||||
import { verifyApprovers } from "./access-approval-policy-fns";
|
||||
import { isApproversValid } from "./access-approval-policy-fns";
|
||||
import {
|
||||
ApproverType,
|
||||
TCreateAccessApprovalPolicy,
|
||||
TDeleteAccessApprovalPolicy,
|
||||
TGetAccessApprovalPolicyByIdDTO,
|
||||
TGetAccessPolicyCountByEnvironmentDTO,
|
||||
TListAccessApprovalPoliciesDTO,
|
||||
TUpdateAccessApprovalPolicy
|
||||
@ -28,6 +30,7 @@ type TSecretApprovalPolicyServiceFactoryDep = {
|
||||
accessApprovalPolicyApproverDAL: TAccessApprovalPolicyApproverDALFactory;
|
||||
projectMembershipDAL: Pick<TProjectMembershipDALFactory, "find">;
|
||||
groupDAL: TGroupDALFactory;
|
||||
userDAL: Pick<TUserDALFactory, "find">;
|
||||
};
|
||||
|
||||
export type TAccessApprovalPolicyServiceFactory = ReturnType<typeof accessApprovalPolicyServiceFactory>;
|
||||
@ -38,7 +41,8 @@ export const accessApprovalPolicyServiceFactory = ({
|
||||
groupDAL,
|
||||
permissionService,
|
||||
projectEnvDAL,
|
||||
projectDAL
|
||||
projectDAL,
|
||||
userDAL
|
||||
}: TSecretApprovalPolicyServiceFactoryDep) => {
|
||||
const createAccessApprovalPolicy = async ({
|
||||
name,
|
||||
@ -54,17 +58,23 @@ export const accessApprovalPolicyServiceFactory = ({
|
||||
enforcementLevel
|
||||
}: TCreateAccessApprovalPolicy) => {
|
||||
const project = await projectDAL.findProjectBySlug(projectSlug, actorOrgId);
|
||||
if (!project) throw new BadRequestError({ message: "Project not found" });
|
||||
if (!project) throw new NotFoundError({ message: "Project not found" });
|
||||
|
||||
// If there is a group approver people might be added to the group later to meet the approvers quota
|
||||
const groupApprovers = approvers
|
||||
.filter((approver) => approver.type === ApproverType.Group)
|
||||
.map((approver) => approver.id);
|
||||
.map((approver) => approver.id) as string[];
|
||||
|
||||
const userApprovers = approvers
|
||||
.filter((approver) => approver.type === ApproverType.User)
|
||||
.map((approver) => approver.id);
|
||||
.map((approver) => approver.id)
|
||||
.filter(Boolean) as string[];
|
||||
|
||||
if (!groupApprovers && approvals > userApprovers.length)
|
||||
const userApproverNames = approvers
|
||||
.map((approver) => (approver.type === ApproverType.User ? approver.name : undefined))
|
||||
.filter(Boolean) as string[];
|
||||
|
||||
if (!groupApprovers && approvals > userApprovers.length + userApproverNames.length)
|
||||
throw new BadRequestError({ message: "Approvals cannot be greater than approvers" });
|
||||
|
||||
const { permission } = await permissionService.getProjectPermission(
|
||||
@ -79,9 +89,28 @@ export const accessApprovalPolicyServiceFactory = ({
|
||||
ProjectPermissionSub.SecretApproval
|
||||
);
|
||||
const env = await projectEnvDAL.findOne({ slug: environment, projectId: project.id });
|
||||
if (!env) throw new BadRequestError({ message: "Environment not found" });
|
||||
if (!env) throw new NotFoundError({ message: "Environment not found" });
|
||||
|
||||
let approverUserIds = userApprovers;
|
||||
if (userApproverNames.length) {
|
||||
const approverUsers = await userDAL.find({
|
||||
$in: {
|
||||
username: userApproverNames
|
||||
}
|
||||
});
|
||||
|
||||
const approverNamesFromDb = approverUsers.map((user) => user.username);
|
||||
const invalidUsernames = userApproverNames.filter((username) => !approverNamesFromDb.includes(username));
|
||||
|
||||
if (invalidUsernames.length) {
|
||||
throw new BadRequestError({
|
||||
message: `Invalid approver user: ${invalidUsernames.join(", ")}`
|
||||
});
|
||||
}
|
||||
|
||||
approverUserIds = approverUserIds.concat(approverUsers.map((user) => user.id));
|
||||
}
|
||||
|
||||
const verifyAllApprovers = userApprovers;
|
||||
const usersPromises: Promise<
|
||||
{
|
||||
id: string;
|
||||
@ -92,14 +121,18 @@ export const accessApprovalPolicyServiceFactory = ({
|
||||
isPartOfGroup: boolean;
|
||||
}[]
|
||||
>[] = [];
|
||||
const verifyAllApprovers = [...approverUserIds];
|
||||
|
||||
for (const groupId of groupApprovers) {
|
||||
usersPromises.push(groupDAL.findAllGroupMembers({ orgId: actorOrgId, groupId, offset: 0 }));
|
||||
usersPromises.push(groupDAL.findAllGroupPossibleMembers({ orgId: actorOrgId, groupId, offset: 0 }));
|
||||
}
|
||||
const verifyGroupApprovers = (await Promise.all(usersPromises)).flat().map((user) => user.id);
|
||||
const verifyGroupApprovers = (await Promise.all(usersPromises))
|
||||
.flat()
|
||||
.filter((user) => user.isPartOfGroup)
|
||||
.map((user) => user.id);
|
||||
verifyAllApprovers.push(...verifyGroupApprovers);
|
||||
|
||||
await verifyApprovers({
|
||||
const approversValid = await isApproversValid({
|
||||
projectId: project.id,
|
||||
orgId: actorOrgId,
|
||||
envSlug: environment,
|
||||
@ -109,6 +142,12 @@ export const accessApprovalPolicyServiceFactory = ({
|
||||
userIds: verifyAllApprovers
|
||||
});
|
||||
|
||||
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 doc = await accessApprovalPolicyDAL.create(
|
||||
{
|
||||
@ -120,9 +159,9 @@ export const accessApprovalPolicyServiceFactory = ({
|
||||
},
|
||||
tx
|
||||
);
|
||||
if (userApprovers) {
|
||||
if (approverUserIds.length) {
|
||||
await accessApprovalPolicyApproverDAL.insertMany(
|
||||
userApprovers.map((userId) => ({
|
||||
approverUserIds.map((userId) => ({
|
||||
approverUserId: userId,
|
||||
policyId: doc.id
|
||||
})),
|
||||
@ -153,7 +192,7 @@ export const accessApprovalPolicyServiceFactory = ({
|
||||
projectSlug
|
||||
}: TListAccessApprovalPoliciesDTO) => {
|
||||
const project = await projectDAL.findProjectBySlug(projectSlug, actorOrgId);
|
||||
if (!project) throw new BadRequestError({ message: "Project not found" });
|
||||
if (!project) throw new NotFoundError({ message: "Project not found" });
|
||||
|
||||
// Anyone in the project should be able to get the policies.
|
||||
/* const { permission } = */ await permissionService.getProjectPermission(
|
||||
@ -182,19 +221,29 @@ export const accessApprovalPolicyServiceFactory = ({
|
||||
enforcementLevel
|
||||
}: TUpdateAccessApprovalPolicy) => {
|
||||
const groupApprovers = approvers
|
||||
?.filter((approver) => approver.type === ApproverType.Group)
|
||||
.map((approver) => approver.id);
|
||||
.filter((approver) => approver.type === ApproverType.Group)
|
||||
.map((approver) => approver.id) as string[];
|
||||
|
||||
const userApprovers = approvers
|
||||
?.filter((approver) => approver.type === ApproverType.User)
|
||||
.map((approver) => approver.id);
|
||||
.filter((approver) => approver.type === ApproverType.User)
|
||||
.map((approver) => approver.id)
|
||||
.filter(Boolean) as string[];
|
||||
|
||||
const userApproverNames = approvers
|
||||
.map((approver) => (approver.type === ApproverType.User ? approver.name : undefined))
|
||||
.filter(Boolean) as string[];
|
||||
|
||||
const accessApprovalPolicy = await accessApprovalPolicyDAL.findById(policyId);
|
||||
const currentAppovals = approvals || accessApprovalPolicy.approvals;
|
||||
if (groupApprovers?.length === 0 && userApprovers && currentAppovals > userApprovers.length) {
|
||||
if (
|
||||
groupApprovers?.length === 0 &&
|
||||
userApprovers &&
|
||||
currentAppovals > userApprovers.length + userApproverNames.length
|
||||
) {
|
||||
throw new BadRequestError({ message: "Approvals cannot be greater than approvers" });
|
||||
}
|
||||
|
||||
if (!accessApprovalPolicy) throw new BadRequestError({ message: "Secret approval policy not found" });
|
||||
if (!accessApprovalPolicy) throw new NotFoundError({ message: "Secret approval policy not found" });
|
||||
const { permission } = await permissionService.getProjectPermission(
|
||||
actor,
|
||||
actorId,
|
||||
@ -219,18 +268,45 @@ export const accessApprovalPolicyServiceFactory = ({
|
||||
|
||||
await accessApprovalPolicyApproverDAL.delete({ policyId: doc.id }, tx);
|
||||
|
||||
if (userApprovers) {
|
||||
await verifyApprovers({
|
||||
if (userApprovers.length || userApproverNames.length) {
|
||||
let userApproverIds = userApprovers;
|
||||
if (userApproverNames.length) {
|
||||
const approverUsers = await userDAL.find({
|
||||
$in: {
|
||||
username: userApproverNames
|
||||
}
|
||||
});
|
||||
|
||||
const approverNamesFromDb = approverUsers.map((user) => user.username);
|
||||
const invalidUsernames = userApproverNames.filter((username) => !approverNamesFromDb.includes(username));
|
||||
|
||||
if (invalidUsernames.length) {
|
||||
throw new BadRequestError({
|
||||
message: `Invalid approver user: ${invalidUsernames.join(", ")}`
|
||||
});
|
||||
}
|
||||
|
||||
userApproverIds = userApproverIds.concat(approverUsers.map((user) => user.id));
|
||||
}
|
||||
|
||||
const approversValid = await isApproversValid({
|
||||
projectId: accessApprovalPolicy.projectId,
|
||||
orgId: actorOrgId,
|
||||
envSlug: accessApprovalPolicy.environment.slug,
|
||||
secretPath: doc.secretPath!,
|
||||
actorAuthMethod,
|
||||
permissionService,
|
||||
userIds: userApprovers
|
||||
userIds: userApproverIds
|
||||
});
|
||||
|
||||
if (!approversValid) {
|
||||
throw new BadRequestError({
|
||||
message: "One or more approvers doesn't have access to be specified secret path"
|
||||
});
|
||||
}
|
||||
|
||||
await accessApprovalPolicyApproverDAL.insertMany(
|
||||
userApprovers.map((userId) => ({
|
||||
userApproverIds.map((userId) => ({
|
||||
approverUserId: userId,
|
||||
policyId: doc.id
|
||||
})),
|
||||
@ -251,11 +327,14 @@ export const accessApprovalPolicyServiceFactory = ({
|
||||
>[] = [];
|
||||
|
||||
for (const groupId of groupApprovers) {
|
||||
usersPromises.push(groupDAL.findAllGroupMembers({ orgId: actorOrgId, groupId, offset: 0 }));
|
||||
usersPromises.push(groupDAL.findAllGroupPossibleMembers({ orgId: actorOrgId, groupId, offset: 0 }));
|
||||
}
|
||||
const verifyGroupApprovers = (await Promise.all(usersPromises)).flat().map((user) => user.id);
|
||||
const verifyGroupApprovers = (await Promise.all(usersPromises))
|
||||
.flat()
|
||||
.filter((user) => user.isPartOfGroup)
|
||||
.map((user) => user.id);
|
||||
|
||||
await verifyApprovers({
|
||||
const approversValid = await isApproversValid({
|
||||
projectId: accessApprovalPolicy.projectId,
|
||||
orgId: actorOrgId,
|
||||
envSlug: accessApprovalPolicy.environment.slug,
|
||||
@ -264,6 +343,13 @@ export const accessApprovalPolicyServiceFactory = ({
|
||||
permissionService,
|
||||
userIds: verifyGroupApprovers
|
||||
});
|
||||
|
||||
if (!approversValid) {
|
||||
throw new BadRequestError({
|
||||
message: "One or more approvers doesn't have access to be specified secret path"
|
||||
});
|
||||
}
|
||||
|
||||
await accessApprovalPolicyApproverDAL.insertMany(
|
||||
groupApprovers.map((groupId) => ({
|
||||
approverGroupId: groupId,
|
||||
@ -290,7 +376,7 @@ export const accessApprovalPolicyServiceFactory = ({
|
||||
actorOrgId
|
||||
}: TDeleteAccessApprovalPolicy) => {
|
||||
const policy = await accessApprovalPolicyDAL.findById(policyId);
|
||||
if (!policy) throw new BadRequestError({ message: "Secret approval policy not found" });
|
||||
if (!policy) throw new NotFoundError({ message: "Secret approval policy not found" });
|
||||
|
||||
const { permission } = await permissionService.getProjectPermission(
|
||||
actor,
|
||||
@ -318,7 +404,7 @@ export const accessApprovalPolicyServiceFactory = ({
|
||||
}: TGetAccessPolicyCountByEnvironmentDTO) => {
|
||||
const project = await projectDAL.findProjectBySlug(projectSlug, actorOrgId);
|
||||
|
||||
if (!project) throw new BadRequestError({ message: "Project not found" });
|
||||
if (!project) throw new NotFoundError({ message: "Project not found" });
|
||||
|
||||
const { membership } = await permissionService.getProjectPermission(
|
||||
actor,
|
||||
@ -327,22 +413,53 @@ export const accessApprovalPolicyServiceFactory = ({
|
||||
actorAuthMethod,
|
||||
actorOrgId
|
||||
);
|
||||
if (!membership) throw new BadRequestError({ 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 });
|
||||
if (!environment) throw new BadRequestError({ message: "Environment not found" });
|
||||
if (!environment) throw new NotFoundError({ message: "Environment not found" });
|
||||
|
||||
const policies = await accessApprovalPolicyDAL.find({ envId: environment.id, projectId: project.id });
|
||||
if (!policies) throw new BadRequestError({ message: "No policies found" });
|
||||
if (!policies) throw new NotFoundError({ message: "No policies found" });
|
||||
|
||||
return { count: policies.length };
|
||||
};
|
||||
|
||||
const getAccessApprovalPolicyById = async ({
|
||||
actorId,
|
||||
actor,
|
||||
actorOrgId,
|
||||
actorAuthMethod,
|
||||
policyId
|
||||
}: TGetAccessApprovalPolicyByIdDTO) => {
|
||||
const [policy] = await accessApprovalPolicyDAL.find({}, { policyId });
|
||||
|
||||
if (!policy) {
|
||||
throw new NotFoundError({
|
||||
message: "Cannot find access approval policy"
|
||||
});
|
||||
}
|
||||
|
||||
const { permission } = await permissionService.getProjectPermission(
|
||||
actor,
|
||||
actorId,
|
||||
policy.projectId,
|
||||
actorAuthMethod,
|
||||
actorOrgId
|
||||
);
|
||||
|
||||
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.SecretApproval);
|
||||
|
||||
return policy;
|
||||
};
|
||||
|
||||
return {
|
||||
getAccessPolicyCountByEnvSlug,
|
||||
createAccessApprovalPolicy,
|
||||
deleteAccessApprovalPolicy,
|
||||
updateAccessApprovalPolicy,
|
||||
getAccessApprovalPolicyByProjectSlug
|
||||
getAccessApprovalPolicyByProjectSlug,
|
||||
getAccessApprovalPolicyById
|
||||
};
|
||||
};
|
||||
|
@ -3,7 +3,7 @@ import { ActorAuthMethod } from "@app/services/auth/auth-type";
|
||||
|
||||
import { TPermissionServiceFactory } from "../permission/permission-service";
|
||||
|
||||
export type TVerifyApprovers = {
|
||||
export type TIsApproversValid = {
|
||||
userIds: string[];
|
||||
permissionService: Pick<TPermissionServiceFactory, "getProjectPermission">;
|
||||
envSlug: string;
|
||||
@ -22,7 +22,7 @@ export type TCreateAccessApprovalPolicy = {
|
||||
approvals: number;
|
||||
secretPath: string;
|
||||
environment: string;
|
||||
approvers: { type: ApproverType; id: string }[];
|
||||
approvers: ({ type: ApproverType.Group; id: string } | { type: ApproverType.User; id?: string; name?: string })[];
|
||||
projectSlug: string;
|
||||
name: string;
|
||||
enforcementLevel: EnforcementLevel;
|
||||
@ -31,7 +31,7 @@ export type TCreateAccessApprovalPolicy = {
|
||||
export type TUpdateAccessApprovalPolicy = {
|
||||
policyId: string;
|
||||
approvals?: number;
|
||||
approvers?: { type: ApproverType; id: string }[];
|
||||
approvers: ({ type: ApproverType.Group; id: string } | { type: ApproverType.User; id?: string; name?: string })[];
|
||||
secretPath?: string;
|
||||
name?: string;
|
||||
enforcementLevel?: EnforcementLevel;
|
||||
@ -46,6 +46,10 @@ export type TGetAccessPolicyCountByEnvironmentDTO = {
|
||||
projectSlug: string;
|
||||
} & Omit<TProjectPermission, "projectId">;
|
||||
|
||||
export type TGetAccessApprovalPolicyByIdDTO = {
|
||||
policyId: string;
|
||||
} & Omit<TProjectPermission, "projectId">;
|
||||
|
||||
export type TListAccessApprovalPoliciesDTO = {
|
||||
projectSlug: string;
|
||||
} & Omit<TProjectPermission, "projectId">;
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { PackRule, unpackRules } from "@casl/ability/extra";
|
||||
|
||||
import { UnauthorizedError } from "@app/lib/errors";
|
||||
import { BadRequestError } from "@app/lib/errors";
|
||||
|
||||
import { TVerifyPermission } from "./access-approval-request-types";
|
||||
|
||||
@ -19,7 +19,7 @@ export const verifyRequestedPermissions = ({ permissions }: TVerifyPermission) =
|
||||
);
|
||||
|
||||
if (!permission || !permission.length) {
|
||||
throw new UnauthorizedError({ message: "No permission provided" });
|
||||
throw new BadRequestError({ message: "No permission provided" });
|
||||
}
|
||||
|
||||
const requestedPermissions: string[] = [];
|
||||
@ -39,10 +39,10 @@ export const verifyRequestedPermissions = ({ permissions }: TVerifyPermission) =
|
||||
const permissionEnv = firstPermission.conditions?.environment;
|
||||
|
||||
if (!permissionEnv || typeof permissionEnv !== "string") {
|
||||
throw new UnauthorizedError({ message: "Permission environment is not a string" });
|
||||
throw new BadRequestError({ message: "Permission environment is not a string" });
|
||||
}
|
||||
if (!permissionSecretPath || typeof permissionSecretPath !== "string") {
|
||||
throw new UnauthorizedError({ message: "Permission path is not a string" });
|
||||
throw new BadRequestError({ message: "Permission path is not a string" });
|
||||
}
|
||||
|
||||
return {
|
||||
|
@ -3,7 +3,7 @@ import ms from "ms";
|
||||
|
||||
import { ProjectMembershipRole } from "@app/db/schemas";
|
||||
import { getConfig } from "@app/lib/config/env";
|
||||
import { BadRequestError, UnauthorizedError } from "@app/lib/errors";
|
||||
import { BadRequestError, ForbiddenRequestError, NotFoundError } from "@app/lib/errors";
|
||||
import { alphaNumericNanoId } from "@app/lib/nanoid";
|
||||
import { TKmsServiceFactory } from "@app/services/kms/kms-service";
|
||||
import { TProjectDALFactory } from "@app/services/project/project-dal";
|
||||
@ -17,7 +17,7 @@ import { TUserDALFactory } from "@app/services/user/user-dal";
|
||||
|
||||
import { TAccessApprovalPolicyApproverDALFactory } from "../access-approval-policy/access-approval-policy-approver-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 { TGroupDALFactory } from "../group/group-dal";
|
||||
import { TPermissionServiceFactory } from "../permission/permission-service";
|
||||
import { TProjectUserAdditionalPrivilegeDALFactory } from "../project-user-additional-privilege/project-user-additional-privilege-dal";
|
||||
@ -58,7 +58,7 @@ type TSecretApprovalRequestServiceFactoryDep = {
|
||||
TAccessApprovalRequestReviewerDALFactory,
|
||||
"create" | "find" | "findOne" | "transaction"
|
||||
>;
|
||||
groupDAL: Pick<TGroupDALFactory, "findAllGroupMembers">;
|
||||
groupDAL: Pick<TGroupDALFactory, "findAllGroupPossibleMembers">;
|
||||
projectMembershipDAL: Pick<TProjectMembershipDALFactory, "findById">;
|
||||
smtpService: Pick<TSmtpService, "sendMail">;
|
||||
userDAL: Pick<
|
||||
@ -99,7 +99,7 @@ export const accessApprovalRequestServiceFactory = ({
|
||||
}: TCreateAccessApprovalRequestDTO) => {
|
||||
const cfg = getConfig();
|
||||
const project = await projectDAL.findProjectBySlug(projectSlug, actorOrgId);
|
||||
if (!project) throw new UnauthorizedError({ message: "Project not found" });
|
||||
if (!project) throw new NotFoundError({ message: "Project not found" });
|
||||
|
||||
// Anyone can create an access approval request.
|
||||
const { membership } = await permissionService.getProjectPermission(
|
||||
@ -109,23 +109,25 @@ export const accessApprovalRequestServiceFactory = ({
|
||||
actorAuthMethod,
|
||||
actorOrgId
|
||||
);
|
||||
if (!membership) throw new UnauthorizedError({ 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);
|
||||
if (!requestedByUser) throw new UnauthorizedError({ message: "User not found" });
|
||||
if (!requestedByUser) throw new ForbiddenRequestError({ message: "User not found" });
|
||||
|
||||
await projectDAL.checkProjectUpgradeStatus(project.id);
|
||||
|
||||
const { envSlug, secretPath, accessTypes } = verifyRequestedPermissions({ permissions: requestedPermissions });
|
||||
const environment = await projectEnvDAL.findOne({ projectId: project.id, slug: envSlug });
|
||||
|
||||
if (!environment) throw new UnauthorizedError({ message: "Environment not found" });
|
||||
if (!environment) throw new NotFoundError({ message: "Environment not found" });
|
||||
|
||||
const policy = await accessApprovalPolicyDAL.findOne({
|
||||
envId: environment.id,
|
||||
secretPath
|
||||
});
|
||||
if (!policy) throw new UnauthorizedError({ message: "No policy matching criteria was found." });
|
||||
if (!policy) throw new NotFoundError({ message: "No policy matching criteria was found." });
|
||||
|
||||
const approverIds: string[] = [];
|
||||
const approverGroupIds: string[] = [];
|
||||
@ -145,14 +147,14 @@ export const accessApprovalRequestServiceFactory = ({
|
||||
const groupUsers = (
|
||||
await Promise.all(
|
||||
approverGroupIds.map((groupApproverId) =>
|
||||
groupDAL.findAllGroupMembers({
|
||||
groupDAL.findAllGroupPossibleMembers({
|
||||
orgId: actorOrgId,
|
||||
groupId: groupApproverId
|
||||
})
|
||||
)
|
||||
)
|
||||
).flat();
|
||||
approverIds.push(...groupUsers.map((user) => user.id));
|
||||
approverIds.push(...groupUsers.filter((user) => user.isPartOfGroup).map((user) => user.id));
|
||||
|
||||
const approverUsers = await userDAL.find({
|
||||
$in: {
|
||||
@ -262,7 +264,7 @@ export const accessApprovalRequestServiceFactory = ({
|
||||
actorAuthMethod
|
||||
}: TListApprovalRequestsDTO) => {
|
||||
const project = await projectDAL.findProjectBySlug(projectSlug, actorOrgId);
|
||||
if (!project) throw new UnauthorizedError({ message: "Project not found" });
|
||||
if (!project) throw new NotFoundError({ message: "Project not found" });
|
||||
|
||||
const { membership } = await permissionService.getProjectPermission(
|
||||
actor,
|
||||
@ -271,7 +273,9 @@ export const accessApprovalRequestServiceFactory = ({
|
||||
actorAuthMethod,
|
||||
actorOrgId
|
||||
);
|
||||
if (!membership) throw new UnauthorizedError({ message: "You are not a member of this project" });
|
||||
if (!membership) {
|
||||
throw new ForbiddenRequestError({ message: "You are not a member of this project" });
|
||||
}
|
||||
|
||||
const policies = await accessApprovalPolicyDAL.find({ projectId: project.id });
|
||||
let requests = await accessApprovalRequestDAL.findRequestsWithPrivilegeByPolicyIds(policies.map((p) => p.id));
|
||||
@ -296,7 +300,7 @@ export const accessApprovalRequestServiceFactory = ({
|
||||
actorOrgId
|
||||
}: TReviewAccessRequestDTO) => {
|
||||
const accessApprovalRequest = await accessApprovalRequestDAL.findById(requestId);
|
||||
if (!accessApprovalRequest) throw new BadRequestError({ message: "Secret approval request not found" });
|
||||
if (!accessApprovalRequest) throw new NotFoundError({ message: "Secret approval request not found" });
|
||||
|
||||
const { policy } = accessApprovalRequest;
|
||||
const { membership, hasRole } = await permissionService.getProjectPermission(
|
||||
@ -307,19 +311,21 @@ export const accessApprovalRequestServiceFactory = ({
|
||||
actorOrgId
|
||||
);
|
||||
|
||||
if (!membership) throw new UnauthorizedError({ message: "You are not a member of this project" });
|
||||
if (!membership) {
|
||||
throw new ForbiddenRequestError({ message: "You are not a member of this project" });
|
||||
}
|
||||
|
||||
if (
|
||||
!hasRole(ProjectMembershipRole.Admin) &&
|
||||
accessApprovalRequest.requestedByUserId !== actorId && // The request wasn't made by the current user
|
||||
!policy.approvers.find((approver) => approver.userId === actorId) // The request isn't performed by an assigned approver
|
||||
) {
|
||||
throw new UnauthorizedError({ message: "You are not authorized to approve this request" });
|
||||
throw new ForbiddenRequestError({ message: "You are not authorized to approve this request" });
|
||||
}
|
||||
|
||||
const reviewerProjectMembership = await projectMembershipDAL.findById(membership.id);
|
||||
|
||||
await verifyApprovers({
|
||||
const approversValid = await isApproversValid({
|
||||
projectId: accessApprovalRequest.projectId,
|
||||
orgId: actorOrgId,
|
||||
envSlug: accessApprovalRequest.environment,
|
||||
@ -329,6 +335,10 @@ export const accessApprovalRequestServiceFactory = ({
|
||||
userIds: [reviewerProjectMembership.userId]
|
||||
});
|
||||
|
||||
if (!approversValid) {
|
||||
throw new ForbiddenRequestError({ message: "You don't have access to approve this request" });
|
||||
}
|
||||
|
||||
const existingReviews = await accessApprovalRequestReviewerDAL.find({ requestId: accessApprovalRequest.id });
|
||||
if (existingReviews.some((review) => review.status === ApprovalStatus.REJECTED)) {
|
||||
throw new BadRequestError({ message: "The request has already been rejected by another reviewer" });
|
||||
@ -411,7 +421,7 @@ export const accessApprovalRequestServiceFactory = ({
|
||||
|
||||
const getCount = async ({ projectSlug, actor, actorAuthMethod, actorId, actorOrgId }: TGetAccessRequestCountDTO) => {
|
||||
const project = await projectDAL.findProjectBySlug(projectSlug, actorOrgId);
|
||||
if (!project) throw new UnauthorizedError({ message: "Project not found" });
|
||||
if (!project) throw new NotFoundError({ message: "Project not found" });
|
||||
|
||||
const { membership } = await permissionService.getProjectPermission(
|
||||
actor,
|
||||
@ -420,7 +430,9 @@ export const accessApprovalRequestServiceFactory = ({
|
||||
actorAuthMethod,
|
||||
actorOrgId
|
||||
);
|
||||
if (!membership) throw new BadRequestError({ message: "User not found in project" });
|
||||
if (!membership) {
|
||||
throw new ForbiddenRequestError({ message: "You are not a member of this project" });
|
||||
}
|
||||
|
||||
const count = await accessApprovalRequestDAL.getCount({ projectId: project.id });
|
||||
|
||||
|
@ -5,7 +5,7 @@ import { SecretKeyEncoding } from "@app/db/schemas";
|
||||
import { getConfig } from "@app/lib/config/env";
|
||||
import { request } from "@app/lib/config/request";
|
||||
import { infisicalSymmetricDecrypt, infisicalSymmetricEncypt } from "@app/lib/crypto/encryption";
|
||||
import { BadRequestError } from "@app/lib/errors";
|
||||
import { BadRequestError, NotFoundError, UnauthorizedError } from "@app/lib/errors";
|
||||
import { blockLocalAndPrivateIpAddresses } from "@app/lib/validator";
|
||||
|
||||
import { AUDIT_LOG_STREAM_TIMEOUT } from "../audit-log/audit-log-queue";
|
||||
@ -43,14 +43,15 @@ export const auditLogStreamServiceFactory = ({
|
||||
actorOrgId,
|
||||
actorAuthMethod
|
||||
}: TCreateAuditLogStreamDTO) => {
|
||||
if (!actorOrgId) throw new BadRequestError({ message: "Missing org id from token" });
|
||||
if (!actorOrgId) throw new UnauthorizedError({ message: "No organization ID attached to authentication token" });
|
||||
|
||||
const appCfg = getConfig();
|
||||
const plan = await licenseService.getPlan(actorOrgId);
|
||||
if (!plan.auditLogStreams)
|
||||
if (!plan.auditLogStreams) {
|
||||
throw new BadRequestError({
|
||||
message: "Failed to create audit log streams due to plan restriction. Upgrade plan to create group."
|
||||
});
|
||||
}
|
||||
|
||||
const { permission } = await permissionService.getOrgPermission(
|
||||
actor,
|
||||
@ -120,7 +121,7 @@ export const auditLogStreamServiceFactory = ({
|
||||
actorOrgId,
|
||||
actorAuthMethod
|
||||
}: TUpdateAuditLogStreamDTO) => {
|
||||
if (!actorOrgId) throw new BadRequestError({ message: "Missing org id from token" });
|
||||
if (!actorOrgId) throw new UnauthorizedError({ message: "No organization ID attached to authentication token" });
|
||||
|
||||
const plan = await licenseService.getPlan(actorOrgId);
|
||||
if (!plan.auditLogStreams)
|
||||
@ -129,7 +130,7 @@ export const auditLogStreamServiceFactory = ({
|
||||
});
|
||||
|
||||
const logStream = await auditLogStreamDAL.findById(id);
|
||||
if (!logStream) throw new BadRequestError({ message: "Audit log stream not found" });
|
||||
if (!logStream) throw new NotFoundError({ message: "Audit log stream not found" });
|
||||
|
||||
const { orgId } = logStream;
|
||||
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, actorAuthMethod, actorOrgId);
|
||||
@ -178,10 +179,10 @@ export const auditLogStreamServiceFactory = ({
|
||||
};
|
||||
|
||||
const deleteById = async ({ id, actor, actorId, actorOrgId, actorAuthMethod }: TDeleteAuditLogStreamDTO) => {
|
||||
if (!actorOrgId) throw new BadRequestError({ message: "Missing org id from token" });
|
||||
if (!actorOrgId) throw new UnauthorizedError({ message: "No organization ID attached to authentication token" });
|
||||
|
||||
const logStream = await auditLogStreamDAL.findById(id);
|
||||
if (!logStream) throw new BadRequestError({ message: "Audit log stream not found" });
|
||||
if (!logStream) throw new NotFoundError({ message: "Audit log stream not found" });
|
||||
|
||||
const { orgId } = logStream;
|
||||
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, actorAuthMethod, actorOrgId);
|
||||
@ -193,7 +194,7 @@ export const auditLogStreamServiceFactory = ({
|
||||
|
||||
const getById = async ({ id, actor, actorId, actorOrgId, actorAuthMethod }: TGetDetailsAuditLogStreamDTO) => {
|
||||
const logStream = await auditLogStreamDAL.findById(id);
|
||||
if (!logStream) throw new BadRequestError({ message: "Audit log stream not found" });
|
||||
if (!logStream) throw new NotFoundError({ message: "Audit log stream not found" });
|
||||
|
||||
const { orgId } = logStream;
|
||||
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, actorAuthMethod, actorOrgId);
|
||||
|
@ -2,10 +2,9 @@ import { ForbiddenError } from "@casl/ability";
|
||||
import * as x509 from "@peculiar/x509";
|
||||
|
||||
import { TCertificateAuthorityCrlDALFactory } from "@app/ee/services/certificate-authority-crl/certificate-authority-crl-dal";
|
||||
// import { TLicenseServiceFactory } from "@app/ee/services/license/license-service";
|
||||
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service";
|
||||
import { ProjectPermissionActions, ProjectPermissionSub } from "@app/ee/services/permission/project-permission";
|
||||
import { BadRequestError, NotFoundError } from "@app/lib/errors";
|
||||
import { NotFoundError } from "@app/lib/errors";
|
||||
import { TCertificateAuthorityDALFactory } from "@app/services/certificate-authority/certificate-authority-dal";
|
||||
import { TKmsServiceFactory } from "@app/services/kms/kms-service";
|
||||
import { TProjectDALFactory } from "@app/services/project/project-dal";
|
||||
@ -19,7 +18,6 @@ type TCertificateAuthorityCrlServiceFactoryDep = {
|
||||
projectDAL: Pick<TProjectDALFactory, "findOne" | "updateById" | "transaction">;
|
||||
kmsService: Pick<TKmsServiceFactory, "decryptWithKmsKey" | "generateKmsKey">;
|
||||
permissionService: Pick<TPermissionServiceFactory, "getProjectPermission">;
|
||||
// licenseService: Pick<TLicenseServiceFactory, "getPlan">;
|
||||
};
|
||||
|
||||
export type TCertificateAuthorityCrlServiceFactory = ReturnType<typeof certificateAuthorityCrlServiceFactory>;
|
||||
@ -66,7 +64,7 @@ export const certificateAuthorityCrlServiceFactory = ({
|
||||
*/
|
||||
const getCaCrls = async ({ caId, actorId, actorAuthMethod, actor, actorOrgId }: TGetCaCrlsDTO) => {
|
||||
const ca = await certificateAuthorityDAL.findById(caId);
|
||||
if (!ca) throw new BadRequestError({ message: "CA not found" });
|
||||
if (!ca) throw new NotFoundError({ message: "CA not found" });
|
||||
|
||||
const { permission } = await permissionService.getProjectPermission(
|
||||
actor,
|
||||
@ -81,13 +79,6 @@ export const certificateAuthorityCrlServiceFactory = ({
|
||||
ProjectPermissionSub.CertificateAuthorities
|
||||
);
|
||||
|
||||
// const plan = await licenseService.getPlan(actorOrgId);
|
||||
// if (!plan.caCrl)
|
||||
// throw new BadRequestError({
|
||||
// message:
|
||||
// "Failed to get CA certificate revocation lists (CRLs) due to plan restriction. Upgrade plan to get the CA CRL."
|
||||
// });
|
||||
|
||||
const caCrls = await certificateAuthorityCrlDAL.find({ caId: ca.id }, { sort: [["createdAt", "desc"]] });
|
||||
|
||||
const keyId = await getProjectKmsCertificateKeyId({
|
||||
|
@ -7,7 +7,7 @@ import { TPermissionServiceFactory } from "@app/ee/services/permission/permissio
|
||||
import { ProjectPermissionActions, ProjectPermissionSub } from "@app/ee/services/permission/project-permission";
|
||||
import { getConfig } from "@app/lib/config/env";
|
||||
import { infisicalSymmetricDecrypt } from "@app/lib/crypto/encryption";
|
||||
import { BadRequestError } from "@app/lib/errors";
|
||||
import { BadRequestError, NotFoundError } from "@app/lib/errors";
|
||||
import { logger } from "@app/lib/logger";
|
||||
import { TProjectDALFactory } from "@app/services/project/project-dal";
|
||||
import { TSecretFolderDALFactory } from "@app/services/secret-folder/secret-folder-dal";
|
||||
@ -61,7 +61,7 @@ export const dynamicSecretLeaseServiceFactory = ({
|
||||
}: TCreateDynamicSecretLeaseDTO) => {
|
||||
const appCfg = getConfig();
|
||||
const project = await projectDAL.findProjectBySlug(projectSlug, actorOrgId);
|
||||
if (!project) throw new BadRequestError({ message: "Project not found" });
|
||||
if (!project) throw new NotFoundError({ message: "Project not found" });
|
||||
|
||||
const projectId = project.id;
|
||||
const { permission } = await permissionService.getProjectPermission(
|
||||
@ -84,10 +84,10 @@ export const dynamicSecretLeaseServiceFactory = ({
|
||||
}
|
||||
|
||||
const folder = await folderDAL.findBySecretPath(projectId, environmentSlug, path);
|
||||
if (!folder) throw new BadRequestError({ message: "Folder not found" });
|
||||
if (!folder) throw new NotFoundError({ message: "Folder not found" });
|
||||
|
||||
const dynamicSecretCfg = await dynamicSecretDAL.findOne({ name, folderId: folder.id });
|
||||
if (!dynamicSecretCfg) throw new BadRequestError({ message: "Dynamic secret not found" });
|
||||
if (!dynamicSecretCfg) throw new NotFoundError({ message: "Dynamic secret not found" });
|
||||
|
||||
const totalLeasesTaken = await dynamicSecretLeaseDAL.countLeasesForDynamicSecret(dynamicSecretCfg.id);
|
||||
if (totalLeasesTaken >= appCfg.MAX_LEASE_LIMIT)
|
||||
@ -134,7 +134,7 @@ export const dynamicSecretLeaseServiceFactory = ({
|
||||
leaseId
|
||||
}: TRenewDynamicSecretLeaseDTO) => {
|
||||
const project = await projectDAL.findProjectBySlug(projectSlug, actorOrgId);
|
||||
if (!project) throw new BadRequestError({ message: "Project not found" });
|
||||
if (!project) throw new NotFoundError({ message: "Project not found" });
|
||||
|
||||
const projectId = project.id;
|
||||
const { permission } = await permissionService.getProjectPermission(
|
||||
@ -157,10 +157,10 @@ export const dynamicSecretLeaseServiceFactory = ({
|
||||
}
|
||||
|
||||
const folder = await folderDAL.findBySecretPath(projectId, environmentSlug, path);
|
||||
if (!folder) throw new BadRequestError({ message: "Folder not found" });
|
||||
if (!folder) throw new NotFoundError({ message: "Folder not found" });
|
||||
|
||||
const dynamicSecretLease = await dynamicSecretLeaseDAL.findById(leaseId);
|
||||
if (!dynamicSecretLease) throw new BadRequestError({ message: "Dynamic secret lease not found" });
|
||||
if (!dynamicSecretLease) throw new NotFoundError({ message: "Dynamic secret lease not found" });
|
||||
|
||||
const dynamicSecretCfg = dynamicSecretLease.dynamicSecret;
|
||||
const selectedProvider = dynamicSecretProviders[dynamicSecretCfg.type as DynamicSecretProviders];
|
||||
@ -208,7 +208,7 @@ export const dynamicSecretLeaseServiceFactory = ({
|
||||
isForced
|
||||
}: TDeleteDynamicSecretLeaseDTO) => {
|
||||
const project = await projectDAL.findProjectBySlug(projectSlug, actorOrgId);
|
||||
if (!project) throw new BadRequestError({ message: "Project not found" });
|
||||
if (!project) throw new NotFoundError({ message: "Project not found" });
|
||||
|
||||
const projectId = project.id;
|
||||
const { permission } = await permissionService.getProjectPermission(
|
||||
@ -224,10 +224,10 @@ export const dynamicSecretLeaseServiceFactory = ({
|
||||
);
|
||||
|
||||
const folder = await folderDAL.findBySecretPath(projectId, environmentSlug, path);
|
||||
if (!folder) throw new BadRequestError({ message: "Folder not found" });
|
||||
if (!folder) throw new NotFoundError({ message: "Folder not found" });
|
||||
|
||||
const dynamicSecretLease = await dynamicSecretLeaseDAL.findById(leaseId);
|
||||
if (!dynamicSecretLease) throw new BadRequestError({ message: "Dynamic secret lease not found" });
|
||||
if (!dynamicSecretLease) throw new NotFoundError({ message: "Dynamic secret lease not found" });
|
||||
|
||||
const dynamicSecretCfg = dynamicSecretLease.dynamicSecret;
|
||||
const selectedProvider = dynamicSecretProviders[dynamicSecretCfg.type as DynamicSecretProviders];
|
||||
@ -273,7 +273,7 @@ export const dynamicSecretLeaseServiceFactory = ({
|
||||
actorAuthMethod
|
||||
}: TListDynamicSecretLeasesDTO) => {
|
||||
const project = await projectDAL.findProjectBySlug(projectSlug, actorOrgId);
|
||||
if (!project) throw new BadRequestError({ message: "Project not found" });
|
||||
if (!project) throw new NotFoundError({ message: "Project not found" });
|
||||
|
||||
const projectId = project.id;
|
||||
const { permission } = await permissionService.getProjectPermission(
|
||||
@ -289,10 +289,10 @@ export const dynamicSecretLeaseServiceFactory = ({
|
||||
);
|
||||
|
||||
const folder = await folderDAL.findBySecretPath(projectId, environmentSlug, path);
|
||||
if (!folder) throw new BadRequestError({ message: "Folder not found" });
|
||||
if (!folder) throw new NotFoundError({ message: "Folder not found" });
|
||||
|
||||
const dynamicSecretCfg = await dynamicSecretDAL.findOne({ name, folderId: folder.id });
|
||||
if (!dynamicSecretCfg) throw new BadRequestError({ message: "Dynamic secret not found" });
|
||||
if (!dynamicSecretCfg) throw new NotFoundError({ message: "Dynamic secret not found" });
|
||||
|
||||
const dynamicSecretLeases = await dynamicSecretLeaseDAL.find({ dynamicSecretId: dynamicSecretCfg.id });
|
||||
return dynamicSecretLeases;
|
||||
@ -309,7 +309,7 @@ export const dynamicSecretLeaseServiceFactory = ({
|
||||
actorAuthMethod
|
||||
}: TDetailsDynamicSecretLeaseDTO) => {
|
||||
const project = await projectDAL.findProjectBySlug(projectSlug, actorOrgId);
|
||||
if (!project) throw new BadRequestError({ message: "Project not found" });
|
||||
if (!project) throw new NotFoundError({ message: "Project not found" });
|
||||
|
||||
const projectId = project.id;
|
||||
const { permission } = await permissionService.getProjectPermission(
|
||||
@ -325,10 +325,10 @@ export const dynamicSecretLeaseServiceFactory = ({
|
||||
);
|
||||
|
||||
const folder = await folderDAL.findBySecretPath(projectId, environmentSlug, path);
|
||||
if (!folder) throw new BadRequestError({ message: "Folder not found" });
|
||||
if (!folder) throw new NotFoundError({ message: "Folder not found" });
|
||||
|
||||
const dynamicSecretLease = await dynamicSecretLeaseDAL.findById(leaseId);
|
||||
if (!dynamicSecretLease) throw new BadRequestError({ message: "Dynamic secret lease not found" });
|
||||
if (!dynamicSecretLease) throw new NotFoundError({ message: "Dynamic secret lease not found" });
|
||||
|
||||
return dynamicSecretLease;
|
||||
};
|
||||
|
@ -5,7 +5,7 @@ import { TLicenseServiceFactory } from "@app/ee/services/license/license-service
|
||||
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service";
|
||||
import { ProjectPermissionActions, ProjectPermissionSub } from "@app/ee/services/permission/project-permission";
|
||||
import { infisicalSymmetricDecrypt, infisicalSymmetricEncypt } from "@app/lib/crypto/encryption";
|
||||
import { BadRequestError } from "@app/lib/errors";
|
||||
import { BadRequestError, NotFoundError } from "@app/lib/errors";
|
||||
import { OrderByDirection } from "@app/lib/types";
|
||||
import { TProjectDALFactory } from "@app/services/project/project-dal";
|
||||
import { TSecretFolderDALFactory } from "@app/services/secret-folder/secret-folder-dal";
|
||||
@ -66,7 +66,7 @@ export const dynamicSecretServiceFactory = ({
|
||||
actorAuthMethod
|
||||
}: TCreateDynamicSecretDTO) => {
|
||||
const project = await projectDAL.findProjectBySlug(projectSlug, actorOrgId);
|
||||
if (!project) throw new BadRequestError({ message: "Project not found" });
|
||||
if (!project) throw new NotFoundError({ message: "Project not found" });
|
||||
|
||||
const projectId = project.id;
|
||||
const { permission } = await permissionService.getProjectPermission(
|
||||
@ -89,7 +89,7 @@ export const dynamicSecretServiceFactory = ({
|
||||
}
|
||||
|
||||
const folder = await folderDAL.findBySecretPath(projectId, environmentSlug, path);
|
||||
if (!folder) throw new BadRequestError({ message: "Folder not found" });
|
||||
if (!folder) throw new NotFoundError({ message: "Folder not found" });
|
||||
|
||||
const existingDynamicSecret = await dynamicSecretDAL.findOne({ name, folderId: folder.id });
|
||||
if (existingDynamicSecret)
|
||||
@ -134,7 +134,7 @@ export const dynamicSecretServiceFactory = ({
|
||||
actorAuthMethod
|
||||
}: TUpdateDynamicSecretDTO) => {
|
||||
const project = await projectDAL.findProjectBySlug(projectSlug, actorOrgId);
|
||||
if (!project) throw new BadRequestError({ message: "Project not found" });
|
||||
if (!project) throw new NotFoundError({ message: "Project not found" });
|
||||
|
||||
const projectId = project.id;
|
||||
|
||||
@ -158,10 +158,10 @@ export const dynamicSecretServiceFactory = ({
|
||||
}
|
||||
|
||||
const folder = await folderDAL.findBySecretPath(projectId, environmentSlug, path);
|
||||
if (!folder) throw new BadRequestError({ message: "Folder not found" });
|
||||
if (!folder) throw new NotFoundError({ message: "Folder not found" });
|
||||
|
||||
const dynamicSecretCfg = await dynamicSecretDAL.findOne({ name, folderId: folder.id });
|
||||
if (!dynamicSecretCfg) throw new BadRequestError({ message: "Dynamic secret not found" });
|
||||
if (!dynamicSecretCfg) throw new NotFoundError({ message: "Dynamic secret not found" });
|
||||
|
||||
if (newName) {
|
||||
const existingDynamicSecret = await dynamicSecretDAL.findOne({ name: newName, folderId: folder.id });
|
||||
@ -213,7 +213,7 @@ export const dynamicSecretServiceFactory = ({
|
||||
isForced
|
||||
}: TDeleteDynamicSecretDTO) => {
|
||||
const project = await projectDAL.findProjectBySlug(projectSlug, actorOrgId);
|
||||
if (!project) throw new BadRequestError({ message: "Project not found" });
|
||||
if (!project) throw new NotFoundError({ message: "Project not found" });
|
||||
|
||||
const projectId = project.id;
|
||||
|
||||
@ -230,7 +230,7 @@ export const dynamicSecretServiceFactory = ({
|
||||
);
|
||||
|
||||
const folder = await folderDAL.findBySecretPath(projectId, environmentSlug, path);
|
||||
if (!folder) throw new BadRequestError({ message: "Folder not found" });
|
||||
if (!folder) throw new NotFoundError({ message: "Folder not found" });
|
||||
|
||||
const dynamicSecretCfg = await dynamicSecretDAL.findOne({ name, folderId: folder.id });
|
||||
if (!dynamicSecretCfg) throw new BadRequestError({ message: "Dynamic secret not found" });
|
||||
@ -271,7 +271,7 @@ export const dynamicSecretServiceFactory = ({
|
||||
actor
|
||||
}: TDetailsDynamicSecretDTO) => {
|
||||
const project = await projectDAL.findProjectBySlug(projectSlug, actorOrgId);
|
||||
if (!project) throw new BadRequestError({ message: "Project not found" });
|
||||
if (!project) throw new NotFoundError({ message: "Project not found" });
|
||||
|
||||
const projectId = project.id;
|
||||
const { permission } = await permissionService.getProjectPermission(
|
||||
@ -287,10 +287,10 @@ export const dynamicSecretServiceFactory = ({
|
||||
);
|
||||
|
||||
const folder = await folderDAL.findBySecretPath(projectId, environmentSlug, path);
|
||||
if (!folder) throw new BadRequestError({ message: "Folder not found" });
|
||||
if (!folder) throw new NotFoundError({ message: "Folder not found" });
|
||||
|
||||
const dynamicSecretCfg = await dynamicSecretDAL.findOne({ name, folderId: folder.id });
|
||||
if (!dynamicSecretCfg) throw new BadRequestError({ message: "Dynamic secret not found" });
|
||||
if (!dynamicSecretCfg) throw new NotFoundError({ message: "Dynamic secret not found" });
|
||||
const decryptedStoredInput = JSON.parse(
|
||||
infisicalSymmetricDecrypt({
|
||||
keyEncoding: dynamicSecretCfg.keyEncoding as SecretKeyEncoding,
|
||||
@ -313,26 +313,29 @@ export const dynamicSecretServiceFactory = ({
|
||||
projectId,
|
||||
path,
|
||||
environmentSlugs,
|
||||
search
|
||||
search,
|
||||
isInternal
|
||||
}: TListDynamicSecretsMultiEnvDTO) => {
|
||||
const { permission } = await permissionService.getProjectPermission(
|
||||
actor,
|
||||
actorId,
|
||||
projectId,
|
||||
actorAuthMethod,
|
||||
actorOrgId
|
||||
);
|
||||
if (!isInternal) {
|
||||
const { permission } = await permissionService.getProjectPermission(
|
||||
actor,
|
||||
actorId,
|
||||
projectId,
|
||||
actorAuthMethod,
|
||||
actorOrgId
|
||||
);
|
||||
|
||||
// verify user has access to each env in request
|
||||
environmentSlugs.forEach((environmentSlug) =>
|
||||
ForbiddenError.from(permission).throwUnlessCan(
|
||||
ProjectPermissionActions.Read,
|
||||
subject(ProjectPermissionSub.Secrets, { environment: environmentSlug, secretPath: path })
|
||||
)
|
||||
);
|
||||
// verify user has access to each env in request
|
||||
environmentSlugs.forEach((environmentSlug) =>
|
||||
ForbiddenError.from(permission).throwUnlessCan(
|
||||
ProjectPermissionActions.Read,
|
||||
subject(ProjectPermissionSub.Secrets, { environment: environmentSlug, secretPath: path })
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
const folders = await folderDAL.findBySecretPathMultiEnv(projectId, environmentSlugs, path);
|
||||
if (!folders.length) throw new BadRequestError({ message: "Folders not found" });
|
||||
if (!folders.length) throw new NotFoundError({ message: "Folders not found" });
|
||||
|
||||
const dynamicSecretCfg = await dynamicSecretDAL.find(
|
||||
{ $in: { folderId: folders.map((folder) => folder.id) }, $search: search ? { name: `%${search}%` } : undefined },
|
||||
@ -366,7 +369,7 @@ export const dynamicSecretServiceFactory = ({
|
||||
);
|
||||
|
||||
const folder = await folderDAL.findBySecretPath(projectId, environmentSlug, path);
|
||||
if (!folder) throw new BadRequestError({ message: "Folder not found" });
|
||||
if (!folder) throw new NotFoundError({ message: "Folder not found" });
|
||||
|
||||
const dynamicSecretCfg = await dynamicSecretDAL.find(
|
||||
{ folderId: folder.id, $search: search ? { name: `%${search}%` } : undefined },
|
||||
@ -395,7 +398,7 @@ export const dynamicSecretServiceFactory = ({
|
||||
if (!projectId) {
|
||||
if (!projectSlug) throw new BadRequestError({ message: "Project ID or slug required" });
|
||||
const project = await projectDAL.findProjectBySlug(projectSlug, actorOrgId);
|
||||
if (!project) throw new BadRequestError({ message: "Project not found" });
|
||||
if (!project) throw new NotFoundError({ message: "Project not found" });
|
||||
projectId = project.id;
|
||||
}
|
||||
|
||||
@ -412,7 +415,7 @@ export const dynamicSecretServiceFactory = ({
|
||||
);
|
||||
|
||||
const folder = await folderDAL.findBySecretPath(projectId, environmentSlug, path);
|
||||
if (!folder) throw new BadRequestError({ message: "Folder not found" });
|
||||
if (!folder) throw new NotFoundError({ message: "Folder not found" });
|
||||
|
||||
const dynamicSecretCfg = await dynamicSecretDAL.find(
|
||||
{ folderId: folder.id, $search: search ? { name: `%${search}%` } : undefined },
|
||||
@ -434,26 +437,29 @@ export const dynamicSecretServiceFactory = ({
|
||||
path,
|
||||
environmentSlugs,
|
||||
projectId,
|
||||
isInternal,
|
||||
...params
|
||||
}: TListDynamicSecretsMultiEnvDTO) => {
|
||||
const { permission } = await permissionService.getProjectPermission(
|
||||
actor,
|
||||
actorId,
|
||||
projectId,
|
||||
actorAuthMethod,
|
||||
actorOrgId
|
||||
);
|
||||
if (!isInternal) {
|
||||
const { permission } = await permissionService.getProjectPermission(
|
||||
actor,
|
||||
actorId,
|
||||
projectId,
|
||||
actorAuthMethod,
|
||||
actorOrgId
|
||||
);
|
||||
|
||||
// verify user has access to each env in request
|
||||
environmentSlugs.forEach((environmentSlug) =>
|
||||
ForbiddenError.from(permission).throwUnlessCan(
|
||||
ProjectPermissionActions.Read,
|
||||
subject(ProjectPermissionSub.Secrets, { environment: environmentSlug, secretPath: path })
|
||||
)
|
||||
);
|
||||
// verify user has access to each env in request
|
||||
environmentSlugs.forEach((environmentSlug) =>
|
||||
ForbiddenError.from(permission).throwUnlessCan(
|
||||
ProjectPermissionActions.Read,
|
||||
subject(ProjectPermissionSub.Secrets, { environment: environmentSlug, secretPath: path })
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
const folders = await folderDAL.findBySecretPathMultiEnv(projectId, environmentSlugs, path);
|
||||
if (!folders.length) throw new BadRequestError({ message: "Folders not found" });
|
||||
if (!folders.length) throw new NotFoundError({ message: "Folders not found" });
|
||||
|
||||
const dynamicSecretCfg = await dynamicSecretDAL.listDynamicSecretsByFolderIds({
|
||||
folderIds: folders.map((folder) => folder.id),
|
||||
|
@ -63,7 +63,7 @@ export type TListDynamicSecretsDTO = {
|
||||
export type TListDynamicSecretsMultiEnvDTO = Omit<
|
||||
TListDynamicSecretsDTO,
|
||||
"projectId" | "environmentSlug" | "projectSlug"
|
||||
> & { projectId: string; environmentSlugs: string[] };
|
||||
> & { projectId: string; environmentSlugs: string[]; isInternal?: boolean };
|
||||
|
||||
export type TGetDynamicSecretsCountDTO = Omit<TListDynamicSecretsDTO, "projectSlug" | "projectId"> & {
|
||||
projectId: string;
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { ForbiddenError } from "@casl/ability";
|
||||
import slugify from "@sindresorhus/slugify";
|
||||
|
||||
import { BadRequestError } from "@app/lib/errors";
|
||||
import { BadRequestError, NotFoundError } from "@app/lib/errors";
|
||||
import { alphaNumericNanoId } from "@app/lib/nanoid";
|
||||
import { TKmsKeyDALFactory } from "@app/services/kms/kms-key-dal";
|
||||
import { TKmsServiceFactory } from "@app/services/kms/kms-service";
|
||||
@ -145,7 +145,7 @@ export const externalKmsServiceFactory = ({
|
||||
const kmsSlug = slug ? slugify(slug) : undefined;
|
||||
|
||||
const externalKmsDoc = await externalKmsDAL.findOne({ kmsKeyId: kmsDoc.id });
|
||||
if (!externalKmsDoc) throw new BadRequestError({ message: "External kms not found" });
|
||||
if (!externalKmsDoc) throw new NotFoundError({ message: "External kms not found" });
|
||||
|
||||
let sanitizedProviderInput = "";
|
||||
const { encryptor: orgDataKeyEncryptor, decryptor: orgDataKeyDecryptor } =
|
||||
@ -220,7 +220,7 @@ export const externalKmsServiceFactory = ({
|
||||
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Delete, OrgPermissionSubjects.Kms);
|
||||
|
||||
const externalKmsDoc = await externalKmsDAL.findOne({ kmsKeyId: kmsDoc.id });
|
||||
if (!externalKmsDoc) throw new BadRequestError({ message: "External kms not found" });
|
||||
if (!externalKmsDoc) throw new NotFoundError({ message: "External kms not found" });
|
||||
|
||||
const externalKms = await externalKmsDAL.transaction(async (tx) => {
|
||||
const kms = await kmsDAL.deleteById(kmsDoc.id, tx);
|
||||
@ -258,7 +258,7 @@ export const externalKmsServiceFactory = ({
|
||||
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Kms);
|
||||
|
||||
const externalKmsDoc = await externalKmsDAL.findOne({ kmsKeyId: kmsDoc.id });
|
||||
if (!externalKmsDoc) throw new BadRequestError({ message: "External kms not found" });
|
||||
if (!externalKmsDoc) throw new NotFoundError({ message: "External kms not found" });
|
||||
|
||||
const { decryptor: orgDataKeyDecryptor } = await kmsService.createCipherPairWithDataKey({
|
||||
type: KmsDataKey.Organization,
|
||||
@ -298,7 +298,7 @@ export const externalKmsServiceFactory = ({
|
||||
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Kms);
|
||||
|
||||
const externalKmsDoc = await externalKmsDAL.findOne({ kmsKeyId: kmsDoc.id });
|
||||
if (!externalKmsDoc) throw new BadRequestError({ message: "External kms not found" });
|
||||
if (!externalKmsDoc) throw new NotFoundError({ message: "External kms not found" });
|
||||
|
||||
const { decryptor: orgDataKeyDecryptor } = await kmsService.createCipherPairWithDataKey({
|
||||
type: KmsDataKey.Organization,
|
||||
|
@ -60,7 +60,7 @@ export const groupDALFactory = (db: TDbClient) => {
|
||||
};
|
||||
|
||||
// special query
|
||||
const findAllGroupMembers = async ({
|
||||
const findAllGroupPossibleMembers = async ({
|
||||
orgId,
|
||||
groupId,
|
||||
offset = 0,
|
||||
@ -125,7 +125,7 @@ export const groupDALFactory = (db: TDbClient) => {
|
||||
return {
|
||||
findGroups,
|
||||
findByOrgId,
|
||||
findAllGroupMembers,
|
||||
findAllGroupPossibleMembers,
|
||||
...groupOrm
|
||||
};
|
||||
};
|
||||
|
@ -2,7 +2,7 @@ import { Knex } from "knex";
|
||||
|
||||
import { SecretKeyEncoding, TableName, TUsers } from "@app/db/schemas";
|
||||
import { decryptAsymmetric, encryptAsymmetric, infisicalSymmetricDecrypt } from "@app/lib/crypto/encryption";
|
||||
import { BadRequestError, ScimRequestError } from "@app/lib/errors";
|
||||
import { BadRequestError, ForbiddenRequestError, NotFoundError, ScimRequestError } from "@app/lib/errors";
|
||||
|
||||
import {
|
||||
TAddUsersToGroup,
|
||||
@ -73,24 +73,24 @@ const addAcceptedUsersToGroup = async ({
|
||||
const ghostUser = await projectDAL.findProjectGhostUser(projectId, tx);
|
||||
|
||||
if (!ghostUser) {
|
||||
throw new BadRequestError({
|
||||
message: "Failed to find sudo user"
|
||||
throw new NotFoundError({
|
||||
message: "Failed to find project owner"
|
||||
});
|
||||
}
|
||||
|
||||
const ghostUserLatestKey = await projectKeyDAL.findLatestProjectKey(ghostUser.id, projectId, tx);
|
||||
|
||||
if (!ghostUserLatestKey) {
|
||||
throw new BadRequestError({
|
||||
message: "Failed to find sudo user latest key"
|
||||
throw new NotFoundError({
|
||||
message: "Failed to find project owner's latest key"
|
||||
});
|
||||
}
|
||||
|
||||
const bot = await projectBotDAL.findOne({ projectId }, tx);
|
||||
|
||||
if (!bot) {
|
||||
throw new BadRequestError({
|
||||
message: "Failed to find bot"
|
||||
throw new NotFoundError({
|
||||
message: "Failed to find project bot"
|
||||
});
|
||||
}
|
||||
|
||||
@ -200,7 +200,7 @@ export const addUsersToGroupByUserIds = async ({
|
||||
|
||||
userIds.forEach((userId) => {
|
||||
if (!existingUserOrgMembershipsUserIdsSet.has(userId))
|
||||
throw new BadRequestError({
|
||||
throw new ForbiddenRequestError({
|
||||
message: `User with id ${userId} is not part of the organization`
|
||||
});
|
||||
});
|
||||
@ -303,7 +303,7 @@ export const removeUsersFromGroupByUserIds = async ({
|
||||
|
||||
userIds.forEach((userId) => {
|
||||
if (!existingUserGroupMembershipsUserIdsSet.has(userId))
|
||||
throw new BadRequestError({
|
||||
throw new ForbiddenRequestError({
|
||||
message: `User(s) are not part of the group ${group.slug}`
|
||||
});
|
||||
});
|
||||
@ -415,7 +415,7 @@ export const convertPendingGroupAdditionsToGroupMemberships = async ({
|
||||
const usersUserIdsSet = new Set(users.map((u) => u.id));
|
||||
userIds.forEach((userId) => {
|
||||
if (!usersUserIdsSet.has(userId)) {
|
||||
throw new BadRequestError({
|
||||
throw new NotFoundError({
|
||||
message: `Failed to find user with id ${userId}`
|
||||
});
|
||||
}
|
||||
|
@ -3,7 +3,7 @@ import slugify from "@sindresorhus/slugify";
|
||||
|
||||
import { OrgMembershipRole, TOrgRoles } from "@app/db/schemas";
|
||||
import { isAtLeastAsPrivileged } from "@app/lib/casl";
|
||||
import { BadRequestError, ForbiddenRequestError, NotFoundError } from "@app/lib/errors";
|
||||
import { BadRequestError, ForbiddenRequestError, NotFoundError, UnauthorizedError } from "@app/lib/errors";
|
||||
import { alphaNumericNanoId } from "@app/lib/nanoid";
|
||||
import { TGroupProjectDALFactory } from "@app/services/group-project/group-project-dal";
|
||||
import { TOrgDALFactory } from "@app/services/org/org-dal";
|
||||
@ -30,7 +30,10 @@ import { TUserGroupMembershipDALFactory } from "./user-group-membership-dal";
|
||||
|
||||
type TGroupServiceFactoryDep = {
|
||||
userDAL: Pick<TUserDALFactory, "find" | "findUserEncKeyByUserIdsBatch" | "transaction" | "findOne">;
|
||||
groupDAL: Pick<TGroupDALFactory, "create" | "findOne" | "update" | "delete" | "findAllGroupMembers" | "findById">;
|
||||
groupDAL: Pick<
|
||||
TGroupDALFactory,
|
||||
"create" | "findOne" | "update" | "delete" | "findAllGroupPossibleMembers" | "findById"
|
||||
>;
|
||||
groupProjectDAL: Pick<TGroupProjectDALFactory, "find">;
|
||||
orgDAL: Pick<TOrgDALFactory, "findMembership" | "countAllOrgMembers">;
|
||||
userGroupMembershipDAL: Pick<
|
||||
@ -59,7 +62,7 @@ export const groupServiceFactory = ({
|
||||
licenseService
|
||||
}: TGroupServiceFactoryDep) => {
|
||||
const createGroup = async ({ name, slug, role, actor, actorId, actorAuthMethod, actorOrgId }: TCreateGroupDTO) => {
|
||||
if (!actorOrgId) throw new BadRequestError({ message: "Failed to create group without organization" });
|
||||
if (!actorOrgId) throw new UnauthorizedError({ message: "No organization ID provided in request" });
|
||||
|
||||
const { permission } = await permissionService.getOrgPermission(
|
||||
actor,
|
||||
@ -82,7 +85,8 @@ export const groupServiceFactory = ({
|
||||
);
|
||||
const isCustomRole = Boolean(customRole);
|
||||
const hasRequiredPriviledges = isAtLeastAsPrivileged(permission, rolePermission);
|
||||
if (!hasRequiredPriviledges) throw new BadRequestError({ message: "Failed to create a more privileged group" });
|
||||
if (!hasRequiredPriviledges)
|
||||
throw new ForbiddenRequestError({ message: "Failed to create a more privileged group" });
|
||||
|
||||
const group = await groupDAL.create({
|
||||
name,
|
||||
@ -105,7 +109,7 @@ export const groupServiceFactory = ({
|
||||
actorAuthMethod,
|
||||
actorOrgId
|
||||
}: TUpdateGroupDTO) => {
|
||||
if (!actorOrgId) throw new BadRequestError({ message: "Failed to create group without organization" });
|
||||
if (!actorOrgId) throw new UnauthorizedError({ message: "No organization ID provided in request" });
|
||||
|
||||
const { permission } = await permissionService.getOrgPermission(
|
||||
actor,
|
||||
@ -124,7 +128,7 @@ export const groupServiceFactory = ({
|
||||
|
||||
const group = await groupDAL.findOne({ orgId: actorOrgId, id });
|
||||
if (!group) {
|
||||
throw new BadRequestError({ message: `Failed to find group with ID ${id}` });
|
||||
throw new NotFoundError({ message: `Failed to find group with ID ${id}` });
|
||||
}
|
||||
|
||||
let customRole: TOrgRoles | undefined;
|
||||
@ -137,7 +141,7 @@ export const groupServiceFactory = ({
|
||||
const isCustomRole = Boolean(customOrgRole);
|
||||
const hasRequiredNewRolePermission = isAtLeastAsPrivileged(permission, rolePermission);
|
||||
if (!hasRequiredNewRolePermission)
|
||||
throw new BadRequestError({ message: "Failed to create a more privileged group" });
|
||||
throw new ForbiddenRequestError({ message: "Failed to create a more privileged group" });
|
||||
if (isCustomRole) customRole = customOrgRole;
|
||||
}
|
||||
|
||||
@ -161,7 +165,7 @@ export const groupServiceFactory = ({
|
||||
};
|
||||
|
||||
const deleteGroup = async ({ id, actor, actorId, actorAuthMethod, actorOrgId }: TDeleteGroupDTO) => {
|
||||
if (!actorOrgId) throw new BadRequestError({ message: "Failed to create group without organization" });
|
||||
if (!actorOrgId) throw new UnauthorizedError({ message: "No organization ID provided in request" });
|
||||
|
||||
const { permission } = await permissionService.getOrgPermission(
|
||||
actor,
|
||||
@ -188,9 +192,7 @@ export const groupServiceFactory = ({
|
||||
};
|
||||
|
||||
const getGroupById = async ({ id, actor, actorId, actorAuthMethod, actorOrgId }: TGetGroupByIdDTO) => {
|
||||
if (!actorOrgId) {
|
||||
throw new BadRequestError({ message: "Failed to read group without organization" });
|
||||
}
|
||||
if (!actorOrgId) throw new UnauthorizedError({ message: "No organization ID provided in request" });
|
||||
|
||||
const { permission } = await permissionService.getOrgPermission(
|
||||
actor,
|
||||
@ -221,7 +223,7 @@ export const groupServiceFactory = ({
|
||||
actorAuthMethod,
|
||||
actorOrgId
|
||||
}: TListGroupUsersDTO) => {
|
||||
if (!actorOrgId) throw new BadRequestError({ message: "Failed to create group without organization" });
|
||||
if (!actorOrgId) throw new UnauthorizedError({ message: "No organization ID provided in request" });
|
||||
|
||||
const { permission } = await permissionService.getOrgPermission(
|
||||
actor,
|
||||
@ -238,11 +240,11 @@ export const groupServiceFactory = ({
|
||||
});
|
||||
|
||||
if (!group)
|
||||
throw new BadRequestError({
|
||||
throw new NotFoundError({
|
||||
message: `Failed to find group with ID ${id}`
|
||||
});
|
||||
|
||||
const users = await groupDAL.findAllGroupMembers({
|
||||
const users = await groupDAL.findAllGroupPossibleMembers({
|
||||
orgId: group.orgId,
|
||||
groupId: group.id,
|
||||
offset,
|
||||
@ -256,7 +258,7 @@ export const groupServiceFactory = ({
|
||||
};
|
||||
|
||||
const addUserToGroup = async ({ id, username, actor, actorId, actorAuthMethod, actorOrgId }: TAddUserToGroupDTO) => {
|
||||
if (!actorOrgId) throw new BadRequestError({ message: "Failed to create group without organization" });
|
||||
if (!actorOrgId) throw new UnauthorizedError({ message: "No organization ID provided in request" });
|
||||
|
||||
const { permission } = await permissionService.getOrgPermission(
|
||||
actor,
|
||||
@ -274,7 +276,7 @@ export const groupServiceFactory = ({
|
||||
});
|
||||
|
||||
if (!group)
|
||||
throw new BadRequestError({
|
||||
throw new NotFoundError({
|
||||
message: `Failed to find group with ID ${id}`
|
||||
});
|
||||
|
||||
@ -286,7 +288,7 @@ export const groupServiceFactory = ({
|
||||
throw new ForbiddenRequestError({ message: "Failed to add user to more privileged group" });
|
||||
|
||||
const user = await userDAL.findOne({ username });
|
||||
if (!user) throw new BadRequestError({ message: `Failed to find user with username ${username}` });
|
||||
if (!user) throw new NotFoundError({ message: `Failed to find user with username ${username}` });
|
||||
|
||||
const users = await addUsersToGroupByUserIds({
|
||||
group,
|
||||
@ -311,7 +313,7 @@ export const groupServiceFactory = ({
|
||||
actorAuthMethod,
|
||||
actorOrgId
|
||||
}: TRemoveUserFromGroupDTO) => {
|
||||
if (!actorOrgId) throw new BadRequestError({ message: "Failed to create group without organization" });
|
||||
if (!actorOrgId) throw new UnauthorizedError({ message: "No organization ID provided in request" });
|
||||
|
||||
const { permission } = await permissionService.getOrgPermission(
|
||||
actor,
|
||||
@ -329,7 +331,7 @@ export const groupServiceFactory = ({
|
||||
});
|
||||
|
||||
if (!group)
|
||||
throw new BadRequestError({
|
||||
throw new NotFoundError({
|
||||
message: `Failed to find group with ID ${id}`
|
||||
});
|
||||
|
||||
@ -341,7 +343,7 @@ export const groupServiceFactory = ({
|
||||
throw new ForbiddenRequestError({ message: "Failed to delete user from more privileged group" });
|
||||
|
||||
const user = await userDAL.findOne({ username });
|
||||
if (!user) throw new BadRequestError({ message: `Failed to find user with username ${username}` });
|
||||
if (!user) throw new NotFoundError({ message: `Failed to find user with username ${username}` });
|
||||
|
||||
const users = await removeUsersFromGroupByUserIds({
|
||||
group,
|
||||
|
@ -4,7 +4,7 @@ import ms from "ms";
|
||||
import { z } from "zod";
|
||||
|
||||
import { isAtLeastAsPrivileged } from "@app/lib/casl";
|
||||
import { BadRequestError, ForbiddenRequestError } from "@app/lib/errors";
|
||||
import { BadRequestError, ForbiddenRequestError, NotFoundError } from "@app/lib/errors";
|
||||
import { ActorType } from "@app/services/auth/auth-type";
|
||||
import { TIdentityProjectDALFactory } from "@app/services/identity-project/identity-project-dal";
|
||||
import { TProjectDALFactory } from "@app/services/project/project-dal";
|
||||
@ -71,12 +71,12 @@ export const identityProjectAdditionalPrivilegeServiceFactory = ({
|
||||
...dto
|
||||
}: TCreateIdentityPrivilegeDTO) => {
|
||||
const project = await projectDAL.findProjectBySlug(projectSlug, actorOrgId);
|
||||
if (!project) throw new BadRequestError({ message: "Project not found" });
|
||||
if (!project) throw new NotFoundError({ message: "Project not found" });
|
||||
const projectId = project.id;
|
||||
|
||||
const identityProjectMembership = await identityProjectDAL.findOne({ identityId, projectId });
|
||||
if (!identityProjectMembership)
|
||||
throw new BadRequestError({ message: `Failed to find identity with id ${identityId}` });
|
||||
throw new NotFoundError({ message: `Failed to find identity with id ${identityId}` });
|
||||
|
||||
const { permission } = await permissionService.getProjectPermission(
|
||||
actor,
|
||||
@ -143,12 +143,12 @@ export const identityProjectAdditionalPrivilegeServiceFactory = ({
|
||||
actorAuthMethod
|
||||
}: TUpdateIdentityPrivilegeDTO) => {
|
||||
const project = await projectDAL.findProjectBySlug(projectSlug, actorOrgId);
|
||||
if (!project) throw new BadRequestError({ message: "Project not found" });
|
||||
if (!project) throw new NotFoundError({ message: "Project not found" });
|
||||
const projectId = project.id;
|
||||
|
||||
const identityProjectMembership = await identityProjectDAL.findOne({ identityId, projectId });
|
||||
if (!identityProjectMembership)
|
||||
throw new BadRequestError({ message: `Failed to find identity with id ${identityId}` });
|
||||
throw new NotFoundError({ message: `Failed to find identity with id ${identityId}` });
|
||||
|
||||
const { permission } = await permissionService.getProjectPermission(
|
||||
actor,
|
||||
@ -173,7 +173,7 @@ export const identityProjectAdditionalPrivilegeServiceFactory = ({
|
||||
slug,
|
||||
projectMembershipId: identityProjectMembership.id
|
||||
});
|
||||
if (!identityPrivilege) throw new BadRequestError({ message: "Identity additional privilege not found" });
|
||||
if (!identityPrivilege) throw new NotFoundError({ message: "Identity additional privilege not found" });
|
||||
if (data?.slug) {
|
||||
const existingSlug = await identityProjectAdditionalPrivilegeDAL.findOne({
|
||||
slug: data.slug,
|
||||
@ -224,12 +224,12 @@ export const identityProjectAdditionalPrivilegeServiceFactory = ({
|
||||
actorAuthMethod
|
||||
}: TDeleteIdentityPrivilegeDTO) => {
|
||||
const project = await projectDAL.findProjectBySlug(projectSlug, actorOrgId);
|
||||
if (!project) throw new BadRequestError({ message: "Project not found" });
|
||||
if (!project) throw new NotFoundError({ message: "Project not found" });
|
||||
const projectId = project.id;
|
||||
|
||||
const identityProjectMembership = await identityProjectDAL.findOne({ identityId, projectId });
|
||||
if (!identityProjectMembership)
|
||||
throw new BadRequestError({ message: `Failed to find identity with id ${identityId}` });
|
||||
throw new NotFoundError({ message: `Failed to find identity with id ${identityId}` });
|
||||
|
||||
const { permission } = await permissionService.getProjectPermission(
|
||||
actor,
|
||||
@ -254,7 +254,7 @@ export const identityProjectAdditionalPrivilegeServiceFactory = ({
|
||||
slug,
|
||||
projectMembershipId: identityProjectMembership.id
|
||||
});
|
||||
if (!identityPrivilege) throw new BadRequestError({ message: "Identity additional privilege not found" });
|
||||
if (!identityPrivilege) throw new NotFoundError({ message: "Identity additional privilege not found" });
|
||||
|
||||
const deletedPrivilege = await identityProjectAdditionalPrivilegeDAL.deleteById(identityPrivilege.id);
|
||||
return {
|
||||
@ -274,12 +274,12 @@ export const identityProjectAdditionalPrivilegeServiceFactory = ({
|
||||
actorAuthMethod
|
||||
}: TGetIdentityPrivilegeDetailsDTO) => {
|
||||
const project = await projectDAL.findProjectBySlug(projectSlug, actorOrgId);
|
||||
if (!project) throw new BadRequestError({ message: "Project not found" });
|
||||
if (!project) throw new NotFoundError({ message: "Project not found" });
|
||||
const projectId = project.id;
|
||||
|
||||
const identityProjectMembership = await identityProjectDAL.findOne({ identityId, projectId });
|
||||
if (!identityProjectMembership)
|
||||
throw new BadRequestError({ message: `Failed to find identity with id ${identityId}` });
|
||||
throw new NotFoundError({ message: `Failed to find identity with id ${identityId}` });
|
||||
const { permission } = await permissionService.getProjectPermission(
|
||||
actor,
|
||||
actorId,
|
||||
@ -293,7 +293,7 @@ export const identityProjectAdditionalPrivilegeServiceFactory = ({
|
||||
slug,
|
||||
projectMembershipId: identityProjectMembership.id
|
||||
});
|
||||
if (!identityPrivilege) throw new BadRequestError({ message: "Identity additional privilege not found" });
|
||||
if (!identityPrivilege) throw new NotFoundError({ message: "Identity additional privilege not found" });
|
||||
|
||||
return {
|
||||
...identityPrivilege,
|
||||
@ -310,12 +310,12 @@ export const identityProjectAdditionalPrivilegeServiceFactory = ({
|
||||
projectSlug
|
||||
}: TListIdentityPrivilegesDTO) => {
|
||||
const project = await projectDAL.findProjectBySlug(projectSlug, actorOrgId);
|
||||
if (!project) throw new BadRequestError({ message: "Project not found" });
|
||||
if (!project) throw new NotFoundError({ message: "Project not found" });
|
||||
const projectId = project.id;
|
||||
|
||||
const identityProjectMembership = await identityProjectDAL.findOne({ identityId, projectId });
|
||||
if (!identityProjectMembership)
|
||||
throw new BadRequestError({ message: `Failed to find identity with id ${identityId}` });
|
||||
throw new NotFoundError({ message: `Failed to find identity with id ${identityId}` });
|
||||
const { permission } = await permissionService.getProjectPermission(
|
||||
actor,
|
||||
actorId,
|
||||
|
@ -21,7 +21,7 @@ import {
|
||||
infisicalSymmetricDecrypt,
|
||||
infisicalSymmetricEncypt
|
||||
} from "@app/lib/crypto/encryption";
|
||||
import { BadRequestError } from "@app/lib/errors";
|
||||
import { BadRequestError, ForbiddenRequestError, NotFoundError } from "@app/lib/errors";
|
||||
import { AuthMethod, AuthTokenType } from "@app/services/auth/auth-type";
|
||||
import { TAuthTokenServiceFactory } from "@app/services/auth-token/auth-token-service";
|
||||
import { TokenType } from "@app/services/auth-token/auth-token-types";
|
||||
@ -253,7 +253,7 @@ export const ldapConfigServiceFactory = ({
|
||||
};
|
||||
|
||||
const orgBot = await orgBotDAL.findOne({ orgId });
|
||||
if (!orgBot) throw new BadRequestError({ message: "Org bot not found", name: "OrgBotNotFound" });
|
||||
if (!orgBot) throw new NotFoundError({ message: "Organization bot not found", name: "OrgBotNotFound" });
|
||||
const key = infisicalSymmetricDecrypt({
|
||||
ciphertext: orgBot.encryptedSymmetricKey,
|
||||
iv: orgBot.symmetricKeyIV,
|
||||
@ -289,10 +289,10 @@ export const ldapConfigServiceFactory = ({
|
||||
|
||||
const getLdapCfg = async (filter: { orgId: string; isActive?: boolean; id?: string }) => {
|
||||
const ldapConfig = await ldapConfigDAL.findOne(filter);
|
||||
if (!ldapConfig) throw new BadRequestError({ message: "Failed to find organization LDAP data" });
|
||||
if (!ldapConfig) throw new NotFoundError({ message: "Failed to find organization LDAP data" });
|
||||
|
||||
const orgBot = await orgBotDAL.findOne({ orgId: ldapConfig.orgId });
|
||||
if (!orgBot) throw new BadRequestError({ message: "Org bot not found", name: "OrgBotNotFound" });
|
||||
if (!orgBot) throw new NotFoundError({ message: "Organization bot not found", name: "OrgBotNotFound" });
|
||||
|
||||
const key = infisicalSymmetricDecrypt({
|
||||
ciphertext: orgBot.encryptedSymmetricKey,
|
||||
@ -375,7 +375,7 @@ export const ldapConfigServiceFactory = ({
|
||||
|
||||
const bootLdap = async (organizationSlug: string) => {
|
||||
const organization = await orgDAL.findOne({ slug: organizationSlug });
|
||||
if (!organization) throw new BadRequestError({ message: "Org not found" });
|
||||
if (!organization) throw new NotFoundError({ message: "Organization not found" });
|
||||
|
||||
const ldapConfig = await getLdapCfg({
|
||||
orgId: organization.id,
|
||||
@ -420,7 +420,7 @@ export const ldapConfigServiceFactory = ({
|
||||
const serverCfg = await getServerCfg();
|
||||
|
||||
if (serverCfg.enabledLoginMethods && !serverCfg.enabledLoginMethods.includes(LoginMethod.LDAP)) {
|
||||
throw new BadRequestError({
|
||||
throw new ForbiddenRequestError({
|
||||
message: "Login with LDAP is disabled by administrator."
|
||||
});
|
||||
}
|
||||
@ -432,7 +432,7 @@ export const ldapConfigServiceFactory = ({
|
||||
});
|
||||
|
||||
const organization = await orgDAL.findOrgById(orgId);
|
||||
if (!organization) throw new BadRequestError({ message: "Org not found" });
|
||||
if (!organization) throw new NotFoundError({ message: "Organization not found" });
|
||||
|
||||
if (userAlias) {
|
||||
await userDAL.transaction(async (tx) => {
|
||||
@ -700,7 +700,7 @@ export const ldapConfigServiceFactory = ({
|
||||
orgId
|
||||
});
|
||||
|
||||
if (!ldapConfig) throw new BadRequestError({ message: "Failed to find organization LDAP data" });
|
||||
if (!ldapConfig) throw new NotFoundError({ message: "Failed to find organization LDAP data" });
|
||||
|
||||
const groupMaps = await ldapGroupMapDAL.findLdapGroupMapsByLdapConfigId(ldapConfigId);
|
||||
|
||||
@ -741,13 +741,13 @@ export const ldapConfigServiceFactory = ({
|
||||
const groups = await searchGroups(ldapConfig, groupSearchFilter, ldapConfig.groupSearchBase);
|
||||
|
||||
if (!groups.some((g) => g.cn === ldapGroupCN)) {
|
||||
throw new BadRequestError({
|
||||
throw new NotFoundError({
|
||||
message: "Failed to find LDAP Group CN"
|
||||
});
|
||||
}
|
||||
|
||||
const group = await groupDAL.findOne({ slug: groupSlug, orgId });
|
||||
if (!group) throw new BadRequestError({ message: "Failed to find group" });
|
||||
if (!group) throw new NotFoundError({ message: "Failed to find group" });
|
||||
|
||||
const groupMap = await ldapGroupMapDAL.create({
|
||||
ldapConfigId,
|
||||
@ -781,7 +781,7 @@ export const ldapConfigServiceFactory = ({
|
||||
orgId
|
||||
});
|
||||
|
||||
if (!ldapConfig) throw new BadRequestError({ message: "Failed to find organization LDAP data" });
|
||||
if (!ldapConfig) throw new NotFoundError({ message: "Failed to find organization LDAP data" });
|
||||
|
||||
const [deletedGroupMap] = await ldapGroupMapDAL.delete({
|
||||
ldapConfigId: ldapConfig.id,
|
||||
|
@ -10,7 +10,7 @@ import { Knex } from "knex";
|
||||
import { TKeyStoreFactory } from "@app/keystore/keystore";
|
||||
import { getConfig } from "@app/lib/config/env";
|
||||
import { verifyOfflineLicense } from "@app/lib/crypto";
|
||||
import { BadRequestError } from "@app/lib/errors";
|
||||
import { NotFoundError } from "@app/lib/errors";
|
||||
import { logger } from "@app/lib/logger";
|
||||
import { TOrgDALFactory } from "@app/services/org/org-dal";
|
||||
|
||||
@ -145,7 +145,7 @@ export const licenseServiceFactory = ({
|
||||
if (cachedPlan) return JSON.parse(cachedPlan) as TFeatureSet;
|
||||
|
||||
const org = await orgDAL.findOrgById(orgId);
|
||||
if (!org) throw new BadRequestError({ message: "Org not found" });
|
||||
if (!org) throw new NotFoundError({ message: "Organization not found" });
|
||||
const {
|
||||
data: { currentPlan }
|
||||
} = await licenseServerCloudApi.request.get<{ currentPlan: TFeatureSet }>(
|
||||
@ -204,7 +204,7 @@ export const licenseServiceFactory = ({
|
||||
const updateSubscriptionOrgMemberCount = async (orgId: string, tx?: Knex) => {
|
||||
if (instanceType === InstanceType.Cloud) {
|
||||
const org = await orgDAL.findOrgById(orgId);
|
||||
if (!org) throw new BadRequestError({ message: "Org not found" });
|
||||
if (!org) throw new NotFoundError({ message: "Organization not found" });
|
||||
|
||||
const quantity = await licenseDAL.countOfOrgMembers(orgId, tx);
|
||||
const quantityIdentities = await licenseDAL.countOrgUsersAndIdentities(orgId, tx);
|
||||
@ -266,8 +266,8 @@ export const licenseServiceFactory = ({
|
||||
|
||||
const organization = await orgDAL.findOrgById(orgId);
|
||||
if (!organization) {
|
||||
throw new BadRequestError({
|
||||
message: "Failed to find organization"
|
||||
throw new NotFoundError({
|
||||
message: "Organization not found"
|
||||
});
|
||||
}
|
||||
|
||||
@ -294,8 +294,8 @@ export const licenseServiceFactory = ({
|
||||
|
||||
const organization = await orgDAL.findOrgById(orgId);
|
||||
if (!organization) {
|
||||
throw new BadRequestError({
|
||||
message: "Failed to find organization"
|
||||
throw new NotFoundError({
|
||||
message: "Organization not found"
|
||||
});
|
||||
}
|
||||
|
||||
@ -340,8 +340,8 @@ export const licenseServiceFactory = ({
|
||||
|
||||
const organization = await orgDAL.findOrgById(orgId);
|
||||
if (!organization) {
|
||||
throw new BadRequestError({
|
||||
message: "Failed to find organization"
|
||||
throw new NotFoundError({
|
||||
message: "Organization not found"
|
||||
});
|
||||
}
|
||||
const { data } = await licenseServerCloudApi.request.get(
|
||||
@ -357,8 +357,8 @@ export const licenseServiceFactory = ({
|
||||
|
||||
const organization = await orgDAL.findOrgById(orgId);
|
||||
if (!organization) {
|
||||
throw new BadRequestError({
|
||||
message: "Failed to find organization"
|
||||
throw new NotFoundError({
|
||||
message: "Organization not found"
|
||||
});
|
||||
}
|
||||
const { data } = await licenseServerCloudApi.request.get(
|
||||
@ -373,8 +373,8 @@ export const licenseServiceFactory = ({
|
||||
|
||||
const organization = await orgDAL.findOrgById(orgId);
|
||||
if (!organization) {
|
||||
throw new BadRequestError({
|
||||
message: "Failed to find organization"
|
||||
throw new NotFoundError({
|
||||
message: "Organization not found"
|
||||
});
|
||||
}
|
||||
|
||||
@ -398,8 +398,8 @@ export const licenseServiceFactory = ({
|
||||
|
||||
const organization = await orgDAL.findOrgById(orgId);
|
||||
if (!organization) {
|
||||
throw new BadRequestError({
|
||||
message: "Failed to find organization"
|
||||
throw new NotFoundError({
|
||||
message: "Organization not found"
|
||||
});
|
||||
}
|
||||
const { data } = await licenseServerCloudApi.request.patch(
|
||||
@ -418,8 +418,8 @@ export const licenseServiceFactory = ({
|
||||
|
||||
const organization = await orgDAL.findOrgById(orgId);
|
||||
if (!organization) {
|
||||
throw new BadRequestError({
|
||||
message: "Failed to find organization"
|
||||
throw new NotFoundError({
|
||||
message: "Organization not found"
|
||||
});
|
||||
}
|
||||
|
||||
@ -445,8 +445,8 @@ export const licenseServiceFactory = ({
|
||||
|
||||
const organization = await orgDAL.findOrgById(orgId);
|
||||
if (!organization) {
|
||||
throw new BadRequestError({
|
||||
message: "Failed to find organization"
|
||||
throw new NotFoundError({
|
||||
message: "Organization not found"
|
||||
});
|
||||
}
|
||||
const {
|
||||
@ -474,8 +474,8 @@ export const licenseServiceFactory = ({
|
||||
|
||||
const organization = await orgDAL.findOrgById(orgId);
|
||||
if (!organization) {
|
||||
throw new BadRequestError({
|
||||
message: "Failed to find organization"
|
||||
throw new NotFoundError({
|
||||
message: "Organization not found"
|
||||
});
|
||||
}
|
||||
|
||||
@ -491,8 +491,8 @@ export const licenseServiceFactory = ({
|
||||
|
||||
const organization = await orgDAL.findOrgById(orgId);
|
||||
if (!organization) {
|
||||
throw new BadRequestError({
|
||||
message: "Failed to find organization"
|
||||
throw new NotFoundError({
|
||||
message: "Organization not found"
|
||||
});
|
||||
}
|
||||
const {
|
||||
@ -509,8 +509,8 @@ export const licenseServiceFactory = ({
|
||||
|
||||
const organization = await orgDAL.findOrgById(orgId);
|
||||
if (!organization) {
|
||||
throw new BadRequestError({
|
||||
message: "Failed to find organization"
|
||||
throw new NotFoundError({
|
||||
message: "Organization not found"
|
||||
});
|
||||
}
|
||||
|
||||
@ -530,8 +530,8 @@ export const licenseServiceFactory = ({
|
||||
|
||||
const organization = await orgDAL.findOrgById(orgId);
|
||||
if (!organization) {
|
||||
throw new BadRequestError({
|
||||
message: "Failed to find organization"
|
||||
throw new NotFoundError({
|
||||
message: "Organization not found"
|
||||
});
|
||||
}
|
||||
|
||||
@ -547,8 +547,8 @@ export const licenseServiceFactory = ({
|
||||
|
||||
const organization = await orgDAL.findOrgById(orgId);
|
||||
if (!organization) {
|
||||
throw new BadRequestError({
|
||||
message: "Failed to find organization"
|
||||
throw new NotFoundError({
|
||||
message: "Organization not found"
|
||||
});
|
||||
}
|
||||
|
||||
@ -564,8 +564,8 @@ export const licenseServiceFactory = ({
|
||||
|
||||
const organization = await orgDAL.findOrgById(orgId);
|
||||
if (!organization) {
|
||||
throw new BadRequestError({
|
||||
message: "Failed to find organization"
|
||||
throw new NotFoundError({
|
||||
message: "Organization not found"
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -17,7 +17,7 @@ import {
|
||||
infisicalSymmetricDecrypt,
|
||||
infisicalSymmetricEncypt
|
||||
} from "@app/lib/crypto/encryption";
|
||||
import { BadRequestError } from "@app/lib/errors";
|
||||
import { BadRequestError, ForbiddenRequestError, NotFoundError } from "@app/lib/errors";
|
||||
import { AuthMethod, AuthTokenType } from "@app/services/auth/auth-type";
|
||||
import { TAuthTokenServiceFactory } from "@app/services/auth-token/auth-token-service";
|
||||
import { TokenType } from "@app/services/auth-token/auth-token-types";
|
||||
@ -77,7 +77,7 @@ export const oidcConfigServiceFactory = ({
|
||||
const getOidc = async (dto: TGetOidcCfgDTO) => {
|
||||
const org = await orgDAL.findOne({ slug: dto.orgSlug });
|
||||
if (!org) {
|
||||
throw new BadRequestError({
|
||||
throw new NotFoundError({
|
||||
message: "Organization not found",
|
||||
name: "OrgNotFound"
|
||||
});
|
||||
@ -98,7 +98,7 @@ export const oidcConfigServiceFactory = ({
|
||||
});
|
||||
|
||||
if (!oidcCfg) {
|
||||
throw new BadRequestError({
|
||||
throw new NotFoundError({
|
||||
message: "Failed to find organization OIDC configuration"
|
||||
});
|
||||
}
|
||||
@ -106,7 +106,7 @@ export const oidcConfigServiceFactory = ({
|
||||
// decrypt and return cfg
|
||||
const orgBot = await orgBotDAL.findOne({ orgId: oidcCfg.orgId });
|
||||
if (!orgBot) {
|
||||
throw new BadRequestError({ message: "Org bot not found", name: "OrgBotNotFound" });
|
||||
throw new NotFoundError({ message: "Organization bot not found", name: "OrgBotNotFound" });
|
||||
}
|
||||
|
||||
const key = infisicalSymmetricDecrypt({
|
||||
@ -160,7 +160,7 @@ export const oidcConfigServiceFactory = ({
|
||||
const serverCfg = await getServerCfg();
|
||||
|
||||
if (serverCfg.enabledLoginMethods && !serverCfg.enabledLoginMethods.includes(LoginMethod.OIDC)) {
|
||||
throw new BadRequestError({
|
||||
throw new ForbiddenRequestError({
|
||||
message: "Login with OIDC is disabled by administrator."
|
||||
});
|
||||
}
|
||||
@ -173,7 +173,7 @@ export const oidcConfigServiceFactory = ({
|
||||
});
|
||||
|
||||
const organization = await orgDAL.findOrgById(orgId);
|
||||
if (!organization) throw new BadRequestError({ message: "Org not found" });
|
||||
if (!organization) throw new NotFoundError({ message: "Organization not found" });
|
||||
|
||||
let user: TUsers;
|
||||
if (userAlias) {
|
||||
@ -356,7 +356,7 @@ export const oidcConfigServiceFactory = ({
|
||||
});
|
||||
|
||||
if (!org) {
|
||||
throw new BadRequestError({
|
||||
throw new NotFoundError({
|
||||
message: "Organization not found"
|
||||
});
|
||||
}
|
||||
@ -378,7 +378,7 @@ export const oidcConfigServiceFactory = ({
|
||||
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Edit, OrgPermissionSubjects.Sso);
|
||||
|
||||
const orgBot = await orgBotDAL.findOne({ orgId: org.id });
|
||||
if (!orgBot) throw new BadRequestError({ message: "Org bot not found", name: "OrgBotNotFound" });
|
||||
if (!orgBot) throw new NotFoundError({ message: "Organization bot not found", name: "OrgBotNotFound" });
|
||||
const key = infisicalSymmetricDecrypt({
|
||||
ciphertext: orgBot.encryptedSymmetricKey,
|
||||
iv: orgBot.symmetricKeyIV,
|
||||
@ -443,7 +443,7 @@ export const oidcConfigServiceFactory = ({
|
||||
slug: orgSlug
|
||||
});
|
||||
if (!org) {
|
||||
throw new BadRequestError({
|
||||
throw new NotFoundError({
|
||||
message: "Organization not found"
|
||||
});
|
||||
}
|
||||
@ -549,7 +549,7 @@ export const oidcConfigServiceFactory = ({
|
||||
});
|
||||
|
||||
if (!org) {
|
||||
throw new BadRequestError({
|
||||
throw new NotFoundError({
|
||||
message: "Organization not found."
|
||||
});
|
||||
}
|
||||
@ -560,7 +560,7 @@ export const oidcConfigServiceFactory = ({
|
||||
});
|
||||
|
||||
if (!oidcCfg || !oidcCfg.isActive) {
|
||||
throw new BadRequestError({
|
||||
throw new ForbiddenRequestError({
|
||||
message: "Failed to authenticate with OIDC SSO"
|
||||
});
|
||||
}
|
||||
@ -617,7 +617,7 @@ export const oidcConfigServiceFactory = ({
|
||||
if (oidcCfg.allowedEmailDomains) {
|
||||
const allowedDomains = oidcCfg.allowedEmailDomains.split(", ");
|
||||
if (!allowedDomains.includes(claims.email.split("@")[1])) {
|
||||
throw new BadRequestError({
|
||||
throw new ForbiddenRequestError({
|
||||
message: "Email not allowed."
|
||||
});
|
||||
}
|
||||
|
@ -50,6 +50,7 @@ export const permissionDALFactory = (db: TDbClient) => {
|
||||
.select(
|
||||
selectAllTableCols(TableName.OrgMembership),
|
||||
db.ref("slug").withSchema(TableName.OrgRoles).withSchema(TableName.OrgRoles).as("customRoleSlug"),
|
||||
db.ref("permissions").withSchema(TableName.OrgRoles),
|
||||
db.ref("authEnforced").withSchema(TableName.Organization).as("orgAuthEnforced"),
|
||||
db.ref("groupId").withSchema("userGroups"),
|
||||
db.ref("groupOrgId").withSchema("userGroups"),
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { TOrganizations } from "@app/db/schemas";
|
||||
import { UnauthorizedError } from "@app/lib/errors";
|
||||
import { ForbiddenRequestError, UnauthorizedError } from "@app/lib/errors";
|
||||
import { ActorAuthMethod, AuthMethod } from "@app/services/auth/auth-type";
|
||||
|
||||
function isAuthMethodSaml(actorAuthMethod: ActorAuthMethod) {
|
||||
@ -20,7 +20,7 @@ function validateOrgSAML(actorAuthMethod: ActorAuthMethod, isSamlEnforced: TOrga
|
||||
}
|
||||
|
||||
if (isSamlEnforced && actorAuthMethod !== null && !isAuthMethodSaml(actorAuthMethod)) {
|
||||
throw new UnauthorizedError({ name: "Cannot access org-scoped resource" });
|
||||
throw new ForbiddenRequestError({ name: "SAML auth enforced, cannot access org-scoped resource" });
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -10,7 +10,7 @@ import {
|
||||
TProjectMemberships
|
||||
} from "@app/db/schemas";
|
||||
import { conditionsMatcher } from "@app/lib/casl";
|
||||
import { BadRequestError, UnauthorizedError } from "@app/lib/errors";
|
||||
import { BadRequestError, ForbiddenRequestError, NotFoundError } from "@app/lib/errors";
|
||||
import { ActorAuthMethod, ActorType } from "@app/services/auth/auth-type";
|
||||
import { TOrgRoleDALFactory } from "@app/services/org/org-role-dal";
|
||||
import { TProjectDALFactory } from "@app/services/project/project-dal";
|
||||
@ -62,7 +62,7 @@ export const permissionServiceFactory = ({
|
||||
permissions as PackRule<RawRuleOf<MongoAbility<OrgPermissionSet>>>[]
|
||||
);
|
||||
default:
|
||||
throw new BadRequestError({ name: "OrgRoleInvalid", message: "Org role not found" });
|
||||
throw new NotFoundError({ name: "OrgRoleInvalid", message: "Organization role not found" });
|
||||
}
|
||||
})
|
||||
.reduce((curr, prev) => prev.concat(curr), []);
|
||||
@ -90,7 +90,7 @@ export const permissionServiceFactory = ({
|
||||
);
|
||||
}
|
||||
default:
|
||||
throw new BadRequestError({
|
||||
throw new NotFoundError({
|
||||
name: "ProjectRoleInvalid",
|
||||
message: "Project role not found"
|
||||
});
|
||||
@ -114,11 +114,11 @@ export const permissionServiceFactory = ({
|
||||
) => {
|
||||
// when token is scoped, ensure the passed org id is same as user org id
|
||||
if (userOrgId && userOrgId !== orgId)
|
||||
throw new BadRequestError({ 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);
|
||||
if (!membership) throw new UnauthorizedError({ name: "User not in org" });
|
||||
if (!membership) throw new ForbiddenRequestError({ name: "You are not apart of this organization" });
|
||||
if (membership.role === OrgMembershipRole.Custom && !membership.permissions) {
|
||||
throw new BadRequestError({ name: "Custom permission not found" });
|
||||
throw new BadRequestError({ name: "Custom organization permission not found" });
|
||||
}
|
||||
|
||||
// If the org ID is API_KEY, the request is being made with an API Key.
|
||||
@ -127,7 +127,7 @@ export const permissionServiceFactory = ({
|
||||
// Extra: This means that when users are using API keys to make requests, they can't use slug-based routes.
|
||||
// Slug-based routes depend on the organization ID being present on the request, since project slugs aren't globally unique, and we need a way to filter by organization.
|
||||
if (userOrgId !== "API_KEY" && membership.orgId !== userOrgId) {
|
||||
throw new UnauthorizedError({ name: "You are not logged into this organization" });
|
||||
throw new ForbiddenRequestError({ name: "You are not logged into this organization" });
|
||||
}
|
||||
|
||||
validateOrgSAML(authMethod, membership.orgAuthEnforced);
|
||||
@ -143,9 +143,9 @@ export const permissionServiceFactory = ({
|
||||
|
||||
const getIdentityOrgPermission = async (identityId: string, orgId: string) => {
|
||||
const membership = await permissionDAL.getOrgIdentityPermission(identityId, orgId);
|
||||
if (!membership) throw new UnauthorizedError({ name: "Identity not in org" });
|
||||
if (!membership) throw new ForbiddenRequestError({ name: "Identity is not apart of this organization" });
|
||||
if (membership.role === OrgMembershipRole.Custom && !membership.permissions) {
|
||||
throw new BadRequestError({ name: "Custom permission not found" });
|
||||
throw new NotFoundError({ name: "Custom organization permission not found" });
|
||||
}
|
||||
return {
|
||||
permission: buildOrgPermission([{ role: membership.role, permissions: membership.permissions }]),
|
||||
@ -166,8 +166,8 @@ export const permissionServiceFactory = ({
|
||||
case ActorType.IDENTITY:
|
||||
return getIdentityOrgPermission(id, orgId);
|
||||
default:
|
||||
throw new UnauthorizedError({
|
||||
message: "Permission not defined",
|
||||
throw new BadRequestError({
|
||||
message: "Invalid actor provided",
|
||||
name: "Get org permission"
|
||||
});
|
||||
}
|
||||
@ -179,7 +179,7 @@ export const permissionServiceFactory = ({
|
||||
const isCustomRole = !Object.values(OrgMembershipRole).includes(role as OrgMembershipRole);
|
||||
if (isCustomRole) {
|
||||
const orgRole = await orgRoleDAL.findOne({ slug: role, orgId });
|
||||
if (!orgRole) throw new BadRequestError({ message: "Role not found" });
|
||||
if (!orgRole) throw new NotFoundError({ message: "Specified role was not found" });
|
||||
return {
|
||||
permission: buildOrgPermission([{ role: OrgMembershipRole.Custom, permissions: orgRole.permissions }]),
|
||||
role: orgRole
|
||||
@ -196,12 +196,12 @@ export const permissionServiceFactory = ({
|
||||
userOrgId?: string
|
||||
): Promise<TProjectPermissionRT<ActorType.USER>> => {
|
||||
const userProjectPermission = await permissionDAL.getProjectPermission(userId, projectId);
|
||||
if (!userProjectPermission) throw new UnauthorizedError({ name: "User not in project" });
|
||||
if (!userProjectPermission) throw new ForbiddenRequestError({ name: "User not a part of the specified project" });
|
||||
|
||||
if (
|
||||
userProjectPermission.roles.some(({ role, permissions }) => role === ProjectMembershipRole.Custom && !permissions)
|
||||
) {
|
||||
throw new BadRequestError({ name: "Custom permission not found" });
|
||||
throw new NotFoundError({ name: "The permission was not found" });
|
||||
}
|
||||
|
||||
// If the org ID is API_KEY, the request is being made with an API Key.
|
||||
@ -210,7 +210,7 @@ export const permissionServiceFactory = ({
|
||||
// Extra: This means that when users are using API keys to make requests, they can't use slug-based routes.
|
||||
// Slug-based routes depend on the organization ID being present on the request, since project slugs aren't globally unique, and we need a way to filter by organization.
|
||||
if (userOrgId !== "API_KEY" && userProjectPermission.orgId !== userOrgId) {
|
||||
throw new UnauthorizedError({ name: "You are not logged into this organization" });
|
||||
throw new ForbiddenRequestError({ name: "You are not logged into this organization" });
|
||||
}
|
||||
|
||||
validateOrgSAML(authMethod, userProjectPermission.orgAuthEnforced);
|
||||
@ -239,18 +239,19 @@ export const permissionServiceFactory = ({
|
||||
identityOrgId: string | undefined
|
||||
): Promise<TProjectPermissionRT<ActorType.IDENTITY>> => {
|
||||
const identityProjectPermission = await permissionDAL.getProjectIdentityPermission(identityId, projectId);
|
||||
if (!identityProjectPermission) throw new UnauthorizedError({ name: "Identity not in project" });
|
||||
if (!identityProjectPermission)
|
||||
throw new ForbiddenRequestError({ name: "Identity is not a member of the specified project" });
|
||||
|
||||
if (
|
||||
identityProjectPermission.roles.some(
|
||||
({ role, permissions }) => role === ProjectMembershipRole.Custom && !permissions
|
||||
)
|
||||
) {
|
||||
throw new BadRequestError({ name: "Custom permission not found" });
|
||||
throw new NotFoundError({ name: "Custom permission not found" });
|
||||
}
|
||||
|
||||
if (identityProjectPermission.orgId !== identityOrgId) {
|
||||
throw new UnauthorizedError({ name: "You are not a member of this organization" });
|
||||
throw new ForbiddenRequestError({ name: "Identity is not a member of the specified organization" });
|
||||
}
|
||||
|
||||
const rolePermissions =
|
||||
@ -277,25 +278,23 @@ export const permissionServiceFactory = ({
|
||||
actorOrgId: string | undefined
|
||||
) => {
|
||||
const serviceToken = await serviceTokenDAL.findById(serviceTokenId);
|
||||
if (!serviceToken) throw new BadRequestError({ message: "Service token not found" });
|
||||
if (!serviceToken) throw new NotFoundError({ message: "Service token not found" });
|
||||
|
||||
const serviceTokenProject = await projectDAL.findById(serviceToken.projectId);
|
||||
|
||||
if (!serviceTokenProject) throw new BadRequestError({ message: "Service token not linked to a project" });
|
||||
|
||||
if (serviceTokenProject.orgId !== actorOrgId) {
|
||||
throw new UnauthorizedError({ message: "Service token not a part of this organization" });
|
||||
throw new ForbiddenRequestError({ message: "Service token not a part of the specified organization" });
|
||||
}
|
||||
|
||||
if (serviceToken.projectId !== projectId)
|
||||
throw new UnauthorizedError({
|
||||
message: "Failed to find service authorization for given project"
|
||||
});
|
||||
if (serviceToken.projectId !== projectId) {
|
||||
throw new ForbiddenRequestError({ name: "Service token not a part of the specified project" });
|
||||
}
|
||||
|
||||
if (serviceTokenProject.orgId !== actorOrgId)
|
||||
throw new UnauthorizedError({
|
||||
message: "Failed to find service authorization for given project"
|
||||
});
|
||||
if (serviceTokenProject.orgId !== actorOrgId) {
|
||||
throw new ForbiddenRequestError({ message: "Service token not a part of the specified organization" });
|
||||
}
|
||||
|
||||
const scopes = ServiceTokenScopes.parse(serviceToken.scopes || []);
|
||||
return {
|
||||
@ -335,8 +334,8 @@ export const permissionServiceFactory = ({
|
||||
case ActorType.IDENTITY:
|
||||
return getIdentityProjectPermission(id, projectId, actorOrgId) as Promise<TProjectPermissionRT<T>>;
|
||||
default:
|
||||
throw new UnauthorizedError({
|
||||
message: "Permission not defined",
|
||||
throw new BadRequestError({
|
||||
message: "Invalid actor provided",
|
||||
name: "Get project permission"
|
||||
});
|
||||
}
|
||||
@ -346,7 +345,7 @@ export const permissionServiceFactory = ({
|
||||
const isCustomRole = !Object.values(ProjectMembershipRole).includes(role as ProjectMembershipRole);
|
||||
if (isCustomRole) {
|
||||
const projectRole = await projectRoleDAL.findOne({ slug: role, projectId });
|
||||
if (!projectRole) throw new BadRequestError({ message: `Role not found: ${role}` });
|
||||
if (!projectRole) throw new NotFoundError({ message: `Specified role was not found: ${role}` });
|
||||
return {
|
||||
permission: buildProjectPermission([
|
||||
{ role: ProjectMembershipRole.Custom, permissions: projectRole.permissions }
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { ForbiddenError } from "@casl/ability";
|
||||
import ms from "ms";
|
||||
|
||||
import { BadRequestError } from "@app/lib/errors";
|
||||
import { BadRequestError, NotFoundError } from "@app/lib/errors";
|
||||
import { TProjectMembershipDALFactory } from "@app/services/project-membership/project-membership-dal";
|
||||
|
||||
import { TPermissionServiceFactory } from "../permission/permission-service";
|
||||
@ -42,7 +42,7 @@ export const projectUserAdditionalPrivilegeServiceFactory = ({
|
||||
...dto
|
||||
}: TCreateUserPrivilegeDTO) => {
|
||||
const projectMembership = await projectMembershipDAL.findById(projectMembershipId);
|
||||
if (!projectMembership) throw new BadRequestError({ message: "Project membership not found" });
|
||||
if (!projectMembership) throw new NotFoundError({ message: "Project membership not found" });
|
||||
|
||||
const { permission } = await permissionService.getProjectPermission(
|
||||
actor,
|
||||
@ -94,14 +94,14 @@ export const projectUserAdditionalPrivilegeServiceFactory = ({
|
||||
...dto
|
||||
}: TUpdateUserPrivilegeDTO) => {
|
||||
const userPrivilege = await projectUserAdditionalPrivilegeDAL.findById(privilegeId);
|
||||
if (!userPrivilege) throw new BadRequestError({ message: "User additional privilege not found" });
|
||||
if (!userPrivilege) throw new NotFoundError({ message: "User additional privilege not found" });
|
||||
|
||||
const projectMembership = await projectMembershipDAL.findOne({
|
||||
userId: userPrivilege.userId,
|
||||
projectId: userPrivilege.projectId
|
||||
});
|
||||
|
||||
if (!projectMembership) throw new BadRequestError({ message: "Project membership not found" });
|
||||
if (!projectMembership) throw new NotFoundError({ message: "Project membership not found" });
|
||||
|
||||
const { permission } = await permissionService.getProjectPermission(
|
||||
actor,
|
||||
@ -147,13 +147,13 @@ export const projectUserAdditionalPrivilegeServiceFactory = ({
|
||||
|
||||
const deleteById = async ({ actorId, actor, actorOrgId, actorAuthMethod, privilegeId }: TDeleteUserPrivilegeDTO) => {
|
||||
const userPrivilege = await projectUserAdditionalPrivilegeDAL.findById(privilegeId);
|
||||
if (!userPrivilege) throw new BadRequestError({ message: "User additional privilege not found" });
|
||||
if (!userPrivilege) throw new NotFoundError({ message: "User additional privilege not found" });
|
||||
|
||||
const projectMembership = await projectMembershipDAL.findOne({
|
||||
userId: userPrivilege.userId,
|
||||
projectId: userPrivilege.projectId
|
||||
});
|
||||
if (!projectMembership) throw new BadRequestError({ message: "Project membership not found" });
|
||||
if (!projectMembership) throw new NotFoundError({ message: "Project membership not found" });
|
||||
|
||||
const { permission } = await permissionService.getProjectPermission(
|
||||
actor,
|
||||
@ -176,13 +176,13 @@ export const projectUserAdditionalPrivilegeServiceFactory = ({
|
||||
actorAuthMethod
|
||||
}: TGetUserPrivilegeDetailsDTO) => {
|
||||
const userPrivilege = await projectUserAdditionalPrivilegeDAL.findById(privilegeId);
|
||||
if (!userPrivilege) throw new BadRequestError({ message: "User additional privilege not found" });
|
||||
if (!userPrivilege) throw new NotFoundError({ message: "User additional privilege not found" });
|
||||
|
||||
const projectMembership = await projectMembershipDAL.findOne({
|
||||
userId: userPrivilege.userId,
|
||||
projectId: userPrivilege.projectId
|
||||
});
|
||||
if (!projectMembership) throw new BadRequestError({ message: "Project membership not found" });
|
||||
if (!projectMembership) throw new NotFoundError({ message: "Project membership not found" });
|
||||
|
||||
const { permission } = await permissionService.getProjectPermission(
|
||||
actor,
|
||||
@ -204,7 +204,7 @@ export const projectUserAdditionalPrivilegeServiceFactory = ({
|
||||
actorAuthMethod
|
||||
}: TListUserPrivilegesDTO) => {
|
||||
const projectMembership = await projectMembershipDAL.findById(projectMembershipId);
|
||||
if (!projectMembership) throw new BadRequestError({ message: "Project membership not found" });
|
||||
if (!projectMembership) throw new NotFoundError({ message: "Project membership not found" });
|
||||
|
||||
const { permission } = await permissionService.getProjectPermission(
|
||||
actor,
|
||||
|
@ -19,7 +19,7 @@ import {
|
||||
infisicalSymmetricDecrypt,
|
||||
infisicalSymmetricEncypt
|
||||
} from "@app/lib/crypto/encryption";
|
||||
import { BadRequestError } from "@app/lib/errors";
|
||||
import { BadRequestError, ForbiddenRequestError, NotFoundError } from "@app/lib/errors";
|
||||
import { AuthTokenType } from "@app/services/auth/auth-type";
|
||||
import { TAuthTokenServiceFactory } from "@app/services/auth-token/auth-token-service";
|
||||
import { TokenType } from "@app/services/auth-token/auth-token-types";
|
||||
@ -187,7 +187,7 @@ export const samlConfigServiceFactory = ({
|
||||
|
||||
const updateQuery: TSamlConfigsUpdate = { authProvider, isActive, lastUsed: null };
|
||||
const orgBot = await orgBotDAL.findOne({ orgId });
|
||||
if (!orgBot) throw new BadRequestError({ message: "Org bot not found", name: "OrgBotNotFound" });
|
||||
if (!orgBot) throw new NotFoundError({ message: "Organization bot not found", name: "OrgBotNotFound" });
|
||||
const key = infisicalSymmetricDecrypt({
|
||||
ciphertext: orgBot.encryptedSymmetricKey,
|
||||
iv: orgBot.symmetricKeyIV,
|
||||
@ -253,7 +253,7 @@ export const samlConfigServiceFactory = ({
|
||||
|
||||
ssoConfig = await samlConfigDAL.findById(id);
|
||||
}
|
||||
if (!ssoConfig) throw new BadRequestError({ message: "Failed to find organization SSO data" });
|
||||
if (!ssoConfig) throw new NotFoundError({ message: "Failed to find organization SSO data" });
|
||||
|
||||
// when dto is type id means it's internally used
|
||||
if (dto.type === "org") {
|
||||
@ -279,7 +279,7 @@ export const samlConfigServiceFactory = ({
|
||||
} = ssoConfig;
|
||||
|
||||
const orgBot = await orgBotDAL.findOne({ orgId: ssoConfig.orgId });
|
||||
if (!orgBot) throw new BadRequestError({ message: "Org bot not found", name: "OrgBotNotFound" });
|
||||
if (!orgBot) throw new NotFoundError({ message: "Organization bot not found", name: "OrgBotNotFound" });
|
||||
const key = infisicalSymmetricDecrypt({
|
||||
ciphertext: orgBot.encryptedSymmetricKey,
|
||||
iv: orgBot.symmetricKeyIV,
|
||||
@ -338,7 +338,7 @@ export const samlConfigServiceFactory = ({
|
||||
const serverCfg = await getServerCfg();
|
||||
|
||||
if (serverCfg.enabledLoginMethods && !serverCfg.enabledLoginMethods.includes(LoginMethod.SAML)) {
|
||||
throw new BadRequestError({
|
||||
throw new ForbiddenRequestError({
|
||||
message: "Login with SAML is disabled by administrator."
|
||||
});
|
||||
}
|
||||
@ -350,7 +350,7 @@ export const samlConfigServiceFactory = ({
|
||||
});
|
||||
|
||||
const organization = await orgDAL.findOrgById(orgId);
|
||||
if (!organization) throw new BadRequestError({ message: "Org not found" });
|
||||
if (!organization) throw new NotFoundError({ message: "Organization not found" });
|
||||
|
||||
let user: TUsers;
|
||||
if (userAlias) {
|
||||
|
@ -9,7 +9,7 @@ import { addUsersToGroupByUserIds, removeUsersFromGroupByUserIds } from "@app/ee
|
||||
import { TUserGroupMembershipDALFactory } from "@app/ee/services/group/user-group-membership-dal";
|
||||
import { TScimDALFactory } from "@app/ee/services/scim/scim-dal";
|
||||
import { getConfig } from "@app/lib/config/env";
|
||||
import { BadRequestError, ScimRequestError, UnauthorizedError } from "@app/lib/errors";
|
||||
import { BadRequestError, NotFoundError, ScimRequestError, UnauthorizedError } from "@app/lib/errors";
|
||||
import { alphaNumericNanoId } from "@app/lib/nanoid";
|
||||
import { TOrgPermission } from "@app/lib/types";
|
||||
import { AuthTokenType } from "@app/services/auth/auth-type";
|
||||
@ -75,7 +75,14 @@ type TScimServiceFactoryDep = {
|
||||
projectMembershipDAL: Pick<TProjectMembershipDALFactory, "find" | "delete" | "findProjectMembershipsByUserId">;
|
||||
groupDAL: Pick<
|
||||
TGroupDALFactory,
|
||||
"create" | "findOne" | "findAllGroupMembers" | "delete" | "findGroups" | "transaction" | "updateById" | "update"
|
||||
| "create"
|
||||
| "findOne"
|
||||
| "findAllGroupPossibleMembers"
|
||||
| "delete"
|
||||
| "findGroups"
|
||||
| "transaction"
|
||||
| "updateById"
|
||||
| "update"
|
||||
>;
|
||||
groupProjectDAL: Pick<TGroupProjectDALFactory, "find">;
|
||||
userGroupMembershipDAL: Pick<
|
||||
@ -169,7 +176,7 @@ export const scimServiceFactory = ({
|
||||
|
||||
const deleteScimToken = async ({ scimTokenId, actor, actorId, actorAuthMethod, actorOrgId }: TDeleteScimTokenDTO) => {
|
||||
let scimToken = await scimDAL.findById(scimTokenId);
|
||||
if (!scimToken) throw new BadRequestError({ message: "Failed to find SCIM token to delete" });
|
||||
if (!scimToken) throw new NotFoundError({ message: "Failed to find SCIM token to delete" });
|
||||
|
||||
const { permission } = await permissionService.getOrgPermission(
|
||||
actor,
|
||||
@ -775,7 +782,7 @@ export const scimServiceFactory = ({
|
||||
});
|
||||
}
|
||||
|
||||
const users = await groupDAL.findAllGroupMembers({
|
||||
const users = await groupDAL.findAllGroupPossibleMembers({
|
||||
orgId: group.orgId,
|
||||
groupId: group.id
|
||||
});
|
||||
|
@ -12,10 +12,21 @@ export type TSecretApprovalPolicyDALFactory = ReturnType<typeof secretApprovalPo
|
||||
export const secretApprovalPolicyDALFactory = (db: TDbClient) => {
|
||||
const secretApprovalPolicyOrm = ormify(db, TableName.SecretApprovalPolicy);
|
||||
|
||||
const secretApprovalPolicyFindQuery = (tx: Knex, filter: TFindFilter<TSecretApprovalPolicies>) =>
|
||||
const secretApprovalPolicyFindQuery = (
|
||||
tx: Knex,
|
||||
filter: TFindFilter<TSecretApprovalPolicies>,
|
||||
customFilter?: {
|
||||
sapId?: string;
|
||||
}
|
||||
) =>
|
||||
tx(TableName.SecretApprovalPolicy)
|
||||
// eslint-disable-next-line
|
||||
.where(buildFindFilter(filter))
|
||||
.where((qb) => {
|
||||
if (customFilter?.sapId) {
|
||||
void qb.where(`${TableName.SecretApprovalPolicy}.id`, "=", customFilter.sapId);
|
||||
}
|
||||
})
|
||||
.join(TableName.Environment, `${TableName.SecretApprovalPolicy}.envId`, `${TableName.Environment}.id`)
|
||||
.leftJoin(
|
||||
TableName.SecretApprovalPolicyApprover,
|
||||
@ -37,6 +48,7 @@ export const secretApprovalPolicyDALFactory = (db: TDbClient) => {
|
||||
tx.ref("id").withSchema("secretApprovalPolicyApproverUser").as("approverUserId"),
|
||||
tx.ref("email").withSchema("secretApprovalPolicyApproverUser").as("approverEmail"),
|
||||
tx.ref("firstName").withSchema("secretApprovalPolicyApproverUser").as("approverFirstName"),
|
||||
tx.ref("username").withSchema("secretApprovalPolicyApproverUser").as("approverUsername"),
|
||||
tx.ref("lastName").withSchema("secretApprovalPolicyApproverUser").as("approverLastName")
|
||||
)
|
||||
.select(
|
||||
@ -108,9 +120,15 @@ export const secretApprovalPolicyDALFactory = (db: TDbClient) => {
|
||||
}
|
||||
};
|
||||
|
||||
const find = async (filter: TFindFilter<TSecretApprovalPolicies & { projectId: string }>, tx?: Knex) => {
|
||||
const find = async (
|
||||
filter: TFindFilter<TSecretApprovalPolicies & { projectId: string }>,
|
||||
customFilter?: {
|
||||
sapId?: string;
|
||||
},
|
||||
tx?: Knex
|
||||
) => {
|
||||
try {
|
||||
const docs = await secretApprovalPolicyFindQuery(tx || db.replicaNode(), filter);
|
||||
const docs = await secretApprovalPolicyFindQuery(tx || db.replicaNode(), filter, customFilter);
|
||||
const formatedDoc = sqlNestRelationships({
|
||||
data: docs,
|
||||
key: "id",
|
||||
@ -123,8 +141,9 @@ export const secretApprovalPolicyDALFactory = (db: TDbClient) => {
|
||||
{
|
||||
key: "approverUserId",
|
||||
label: "approvers" as const,
|
||||
mapper: ({ approverUserId: id }) => ({
|
||||
mapper: ({ approverUserId: id, approverUsername }) => ({
|
||||
type: ApproverType.User,
|
||||
name: approverUsername,
|
||||
id
|
||||
})
|
||||
},
|
||||
|
@ -3,10 +3,11 @@ import picomatch from "picomatch";
|
||||
|
||||
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service";
|
||||
import { ProjectPermissionActions, ProjectPermissionSub } from "@app/ee/services/permission/project-permission";
|
||||
import { BadRequestError } from "@app/lib/errors";
|
||||
import { BadRequestError, NotFoundError } from "@app/lib/errors";
|
||||
import { removeTrailingSlash } from "@app/lib/fn";
|
||||
import { containsGlobPatterns } from "@app/lib/picomatch";
|
||||
import { TProjectEnvDALFactory } from "@app/services/project-env/project-env-dal";
|
||||
import { TUserDALFactory } from "@app/services/user/user-dal";
|
||||
|
||||
import { ApproverType } from "../access-approval-policy/access-approval-policy-types";
|
||||
import { TLicenseServiceFactory } from "../license/license-service";
|
||||
@ -16,6 +17,7 @@ import {
|
||||
TCreateSapDTO,
|
||||
TDeleteSapDTO,
|
||||
TGetBoardSapDTO,
|
||||
TGetSapByIdDTO,
|
||||
TListSapDTO,
|
||||
TUpdateSapDTO
|
||||
} from "./secret-approval-policy-types";
|
||||
@ -29,6 +31,7 @@ type TSecretApprovalPolicyServiceFactoryDep = {
|
||||
permissionService: Pick<TPermissionServiceFactory, "getProjectPermission">;
|
||||
secretApprovalPolicyDAL: TSecretApprovalPolicyDALFactory;
|
||||
projectEnvDAL: Pick<TProjectEnvDALFactory, "findOne">;
|
||||
userDAL: Pick<TUserDALFactory, "find">;
|
||||
secretApprovalPolicyApproverDAL: TSecretApprovalPolicyApproverDALFactory;
|
||||
licenseService: Pick<TLicenseServiceFactory, "getPlan">;
|
||||
};
|
||||
@ -40,6 +43,7 @@ export const secretApprovalPolicyServiceFactory = ({
|
||||
permissionService,
|
||||
secretApprovalPolicyApproverDAL,
|
||||
projectEnvDAL,
|
||||
userDAL,
|
||||
licenseService
|
||||
}: TSecretApprovalPolicyServiceFactoryDep) => {
|
||||
const createSecretApprovalPolicy = async ({
|
||||
@ -60,9 +64,14 @@ export const secretApprovalPolicyServiceFactory = ({
|
||||
.map((approver) => approver.id);
|
||||
const userApprovers = approvers
|
||||
?.filter((approver) => approver.type === ApproverType.User)
|
||||
.map((approver) => approver.id);
|
||||
.map((approver) => approver.id)
|
||||
.filter(Boolean) as string[];
|
||||
|
||||
if (!groupApprovers && approvals > approvers.length)
|
||||
const userApproverNames = approvers
|
||||
.map((approver) => (approver.type === ApproverType.User ? approver.name : undefined))
|
||||
.filter(Boolean) as string[];
|
||||
|
||||
if (!groupApprovers.length && approvals > approvers.length)
|
||||
throw new BadRequestError({ message: "Approvals cannot be greater than approvers" });
|
||||
|
||||
const { permission } = await permissionService.getProjectPermission(
|
||||
@ -86,7 +95,7 @@ export const secretApprovalPolicyServiceFactory = ({
|
||||
}
|
||||
|
||||
const env = await projectEnvDAL.findOne({ slug: environment, projectId });
|
||||
if (!env) throw new BadRequestError({ message: "Environment not found" });
|
||||
if (!env) throw new NotFoundError({ message: "Environment not found" });
|
||||
|
||||
const secretApproval = await secretApprovalPolicyDAL.transaction(async (tx) => {
|
||||
const doc = await secretApprovalPolicyDAL.create(
|
||||
@ -100,8 +109,31 @@ export const secretApprovalPolicyServiceFactory = ({
|
||||
tx
|
||||
);
|
||||
|
||||
let userApproverIds = userApprovers;
|
||||
if (userApproverNames.length) {
|
||||
const approverUsers = await userDAL.find(
|
||||
{
|
||||
$in: {
|
||||
username: userApproverNames
|
||||
}
|
||||
},
|
||||
{ tx }
|
||||
);
|
||||
|
||||
const approverNamesFromDb = approverUsers.map((user) => user.username);
|
||||
const invalidUsernames = userApproverNames?.filter((username) => !approverNamesFromDb.includes(username));
|
||||
|
||||
if (invalidUsernames?.length) {
|
||||
throw new BadRequestError({
|
||||
message: `Invalid approver user: ${invalidUsernames.join(", ")}`
|
||||
});
|
||||
}
|
||||
|
||||
userApproverIds = userApproverIds.concat(approverUsers.map((user) => user.id));
|
||||
}
|
||||
|
||||
await secretApprovalPolicyApproverDAL.insertMany(
|
||||
userApprovers.map((approverUserId) => ({
|
||||
userApproverIds.map((approverUserId) => ({
|
||||
approverUserId,
|
||||
policyId: doc.id
|
||||
})),
|
||||
@ -117,6 +149,7 @@ export const secretApprovalPolicyServiceFactory = ({
|
||||
);
|
||||
return doc;
|
||||
});
|
||||
|
||||
return { ...secretApproval, environment: env, projectId };
|
||||
};
|
||||
|
||||
@ -137,10 +170,15 @@ export const secretApprovalPolicyServiceFactory = ({
|
||||
.map((approver) => approver.id);
|
||||
const userApprovers = approvers
|
||||
?.filter((approver) => approver.type === ApproverType.User)
|
||||
.map((approver) => approver.id);
|
||||
.map((approver) => approver.id)
|
||||
.filter(Boolean) as string[];
|
||||
|
||||
const userApproverNames = approvers
|
||||
.map((approver) => (approver.type === ApproverType.User ? approver.name : undefined))
|
||||
.filter(Boolean) as string[];
|
||||
|
||||
const secretApprovalPolicy = await secretApprovalPolicyDAL.findById(secretPolicyId);
|
||||
if (!secretApprovalPolicy) throw new BadRequestError({ message: "Secret approval policy not found" });
|
||||
if (!secretApprovalPolicy) throw new NotFoundError({ message: "Secret approval policy not found" });
|
||||
|
||||
const { permission } = await permissionService.getProjectPermission(
|
||||
actor,
|
||||
@ -174,8 +212,31 @@ export const secretApprovalPolicyServiceFactory = ({
|
||||
await secretApprovalPolicyApproverDAL.delete({ policyId: doc.id }, tx);
|
||||
|
||||
if (approvers) {
|
||||
let userApproverIds = userApprovers;
|
||||
if (userApproverNames) {
|
||||
const approverUsers = await userDAL.find(
|
||||
{
|
||||
$in: {
|
||||
username: userApproverNames
|
||||
}
|
||||
},
|
||||
{ tx }
|
||||
);
|
||||
|
||||
const approverNamesFromDb = approverUsers.map((user) => user.username);
|
||||
const invalidUsernames = userApproverNames?.filter((username) => !approverNamesFromDb.includes(username));
|
||||
|
||||
if (invalidUsernames?.length) {
|
||||
throw new BadRequestError({
|
||||
message: `Invalid approver user: ${invalidUsernames.join(", ")}`
|
||||
});
|
||||
}
|
||||
|
||||
userApproverIds = userApproverIds.concat(approverUsers.map((user) => user.id));
|
||||
}
|
||||
|
||||
await secretApprovalPolicyApproverDAL.insertMany(
|
||||
userApprovers.map((approverUserId) => ({
|
||||
userApproverIds.map((approverUserId) => ({
|
||||
approverUserId,
|
||||
policyId: doc.id
|
||||
})),
|
||||
@ -192,6 +253,7 @@ export const secretApprovalPolicyServiceFactory = ({
|
||||
tx
|
||||
);
|
||||
}
|
||||
|
||||
return doc;
|
||||
});
|
||||
return {
|
||||
@ -209,7 +271,7 @@ export const secretApprovalPolicyServiceFactory = ({
|
||||
actorOrgId
|
||||
}: TDeleteSapDTO) => {
|
||||
const sapPolicy = await secretApprovalPolicyDAL.findById(secretPolicyId);
|
||||
if (!sapPolicy) throw new BadRequestError({ message: "Secret approval policy not found" });
|
||||
if (!sapPolicy) throw new NotFoundError({ message: "Secret approval policy not found" });
|
||||
|
||||
const { permission } = await permissionService.getProjectPermission(
|
||||
actor,
|
||||
@ -258,7 +320,7 @@ export const secretApprovalPolicyServiceFactory = ({
|
||||
const getSecretApprovalPolicy = async (projectId: string, environment: string, path: string) => {
|
||||
const secretPath = removeTrailingSlash(path);
|
||||
const env = await projectEnvDAL.findOne({ slug: environment, projectId });
|
||||
if (!env) throw new BadRequestError({ message: "Environment not found" });
|
||||
if (!env) throw new NotFoundError({ message: "Environment not found" });
|
||||
|
||||
const policies = await secretApprovalPolicyDAL.find({ envId: env.id });
|
||||
if (!policies.length) return;
|
||||
@ -296,12 +358,41 @@ export const secretApprovalPolicyServiceFactory = ({
|
||||
return getSecretApprovalPolicy(projectId, environment, secretPath);
|
||||
};
|
||||
|
||||
const getSecretApprovalPolicyById = async ({
|
||||
actorId,
|
||||
actor,
|
||||
actorOrgId,
|
||||
actorAuthMethod,
|
||||
sapId
|
||||
}: TGetSapByIdDTO) => {
|
||||
const [sapPolicy] = await secretApprovalPolicyDAL.find({}, { sapId });
|
||||
|
||||
if (!sapPolicy) {
|
||||
throw new NotFoundError({
|
||||
message: "Cannot find secret approval policy"
|
||||
});
|
||||
}
|
||||
|
||||
const { permission } = await permissionService.getProjectPermission(
|
||||
actor,
|
||||
actorId,
|
||||
sapPolicy.projectId,
|
||||
actorAuthMethod,
|
||||
actorOrgId
|
||||
);
|
||||
|
||||
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.SecretApproval);
|
||||
|
||||
return sapPolicy;
|
||||
};
|
||||
|
||||
return {
|
||||
createSecretApprovalPolicy,
|
||||
updateSecretApprovalPolicy,
|
||||
deleteSecretApprovalPolicy,
|
||||
getSecretApprovalPolicy,
|
||||
getSecretApprovalPolicyByProjectId,
|
||||
getSecretApprovalPolicyOfFolder
|
||||
getSecretApprovalPolicyOfFolder,
|
||||
getSecretApprovalPolicyById
|
||||
};
|
||||
};
|
||||
|
@ -6,7 +6,7 @@ export type TCreateSapDTO = {
|
||||
approvals: number;
|
||||
secretPath?: string | null;
|
||||
environment: string;
|
||||
approvers: { type: ApproverType; id: string }[];
|
||||
approvers: ({ type: ApproverType.Group; id: string } | { type: ApproverType.User; id?: string; name?: string })[];
|
||||
projectId: string;
|
||||
name: string;
|
||||
enforcementLevel: EnforcementLevel;
|
||||
@ -16,7 +16,7 @@ export type TUpdateSapDTO = {
|
||||
secretPolicyId: string;
|
||||
approvals?: number;
|
||||
secretPath?: string | null;
|
||||
approvers: { type: ApproverType; id: string }[];
|
||||
approvers: ({ type: ApproverType.Group; id: string } | { type: ApproverType.User; id?: string; name?: string })[];
|
||||
name?: string;
|
||||
enforcementLevel?: EnforcementLevel;
|
||||
} & Omit<TProjectPermission, "projectId">;
|
||||
@ -27,6 +27,8 @@ export type TDeleteSapDTO = {
|
||||
|
||||
export type TListSapDTO = TProjectPermission;
|
||||
|
||||
export type TGetSapByIdDTO = Omit<TProjectPermission, "projectId"> & { sapId: string };
|
||||
|
||||
export type TGetBoardSapDTO = {
|
||||
projectId: string;
|
||||
environment: string;
|
||||
|
@ -8,7 +8,7 @@ import {
|
||||
TSecretApprovalRequestsSecrets,
|
||||
TSecretTags
|
||||
} from "@app/db/schemas";
|
||||
import { BadRequestError, DatabaseError } from "@app/lib/errors";
|
||||
import { DatabaseError, NotFoundError } from "@app/lib/errors";
|
||||
import { ormify, selectAllTableCols, sqlNestRelationships } from "@app/lib/knex";
|
||||
|
||||
export type TSecretApprovalRequestSecretDALFactory = ReturnType<typeof secretApprovalRequestSecretDALFactory>;
|
||||
@ -31,7 +31,7 @@ export const secretApprovalRequestSecretDALFactory = (db: TDbClient) => {
|
||||
);
|
||||
|
||||
if (existingApprovalSecrets.length !== data.length) {
|
||||
throw new BadRequestError({ message: "Some of the secret approvals do not exist" });
|
||||
throw new NotFoundError({ message: "Some of the secret approvals do not exist" });
|
||||
}
|
||||
|
||||
if (data.length === 0) return [];
|
||||
|
@ -10,7 +10,7 @@ import {
|
||||
} from "@app/db/schemas";
|
||||
import { getConfig } from "@app/lib/config/env";
|
||||
import { decryptSymmetric128BitHexKeyUTF8 } from "@app/lib/crypto";
|
||||
import { BadRequestError, UnauthorizedError } from "@app/lib/errors";
|
||||
import { BadRequestError, ForbiddenRequestError, NotFoundError } from "@app/lib/errors";
|
||||
import { groupBy, pick, unique } from "@app/lib/fn";
|
||||
import { setKnexStringValue } from "@app/lib/knex";
|
||||
import { alphaNumericNanoId } from "@app/lib/nanoid";
|
||||
@ -204,7 +204,7 @@ export const secretApprovalRequestServiceFactory = ({
|
||||
if (actor === ActorType.SERVICE) throw new BadRequestError({ message: "Cannot use service token" });
|
||||
|
||||
const secretApprovalRequest = await secretApprovalRequestDAL.findById(id);
|
||||
if (!secretApprovalRequest) throw new BadRequestError({ message: "Secret approval request not found" });
|
||||
if (!secretApprovalRequest) throw new NotFoundError({ message: "Secret approval request not found" });
|
||||
|
||||
const { projectId } = secretApprovalRequest;
|
||||
const { botKey, shouldUseSecretV2Bridge } = await projectBotService.getBotKey(projectId);
|
||||
@ -222,7 +222,7 @@ export const secretApprovalRequestServiceFactory = ({
|
||||
secretApprovalRequest.committerUserId !== actorId &&
|
||||
!policy.approvers.find(({ userId }) => userId === actorId)
|
||||
) {
|
||||
throw new UnauthorizedError({ message: "User has no access" });
|
||||
throw new ForbiddenRequestError({ message: "User has insufficient privileges" });
|
||||
}
|
||||
|
||||
let secrets;
|
||||
@ -271,7 +271,7 @@ export const secretApprovalRequestServiceFactory = ({
|
||||
: undefined
|
||||
}));
|
||||
} else {
|
||||
if (!botKey) throw new BadRequestError({ message: "Bot key not found" });
|
||||
if (!botKey) throw new NotFoundError({ message: "Project bot key not found" });
|
||||
const encrypedSecrets = await secretApprovalRequestSecretDAL.findByRequestId(secretApprovalRequest.id);
|
||||
secrets = encrypedSecrets.map((el) => ({
|
||||
...el,
|
||||
@ -307,7 +307,7 @@ export const secretApprovalRequestServiceFactory = ({
|
||||
actorOrgId
|
||||
}: TReviewRequestDTO) => {
|
||||
const secretApprovalRequest = await secretApprovalRequestDAL.findById(approvalId);
|
||||
if (!secretApprovalRequest) throw new BadRequestError({ message: "Secret approval request not found" });
|
||||
if (!secretApprovalRequest) throw new NotFoundError({ message: "Secret approval request not found" });
|
||||
if (actor !== ActorType.USER) throw new BadRequestError({ message: "Must be a user" });
|
||||
|
||||
const plan = await licenseService.getPlan(actorOrgId);
|
||||
@ -331,7 +331,7 @@ export const secretApprovalRequestServiceFactory = ({
|
||||
secretApprovalRequest.committerUserId !== actorId &&
|
||||
!policy.approvers.find(({ userId }) => userId === actorId)
|
||||
) {
|
||||
throw new UnauthorizedError({ message: "User has no access" });
|
||||
throw new ForbiddenRequestError({ message: "User has insufficient privileges" });
|
||||
}
|
||||
const reviewStatus = await secretApprovalRequestReviewerDAL.transaction(async (tx) => {
|
||||
const review = await secretApprovalRequestReviewerDAL.findOne(
|
||||
@ -365,7 +365,7 @@ export const secretApprovalRequestServiceFactory = ({
|
||||
actorAuthMethod
|
||||
}: TStatusChangeDTO) => {
|
||||
const secretApprovalRequest = await secretApprovalRequestDAL.findById(approvalId);
|
||||
if (!secretApprovalRequest) throw new BadRequestError({ message: "Secret approval request not found" });
|
||||
if (!secretApprovalRequest) throw new NotFoundError({ message: "Secret approval request not found" });
|
||||
if (actor !== ActorType.USER) throw new BadRequestError({ message: "Must be a user" });
|
||||
|
||||
const plan = await licenseService.getPlan(actorOrgId);
|
||||
@ -389,7 +389,7 @@ export const secretApprovalRequestServiceFactory = ({
|
||||
secretApprovalRequest.committerUserId !== actorId &&
|
||||
!policy.approvers.find(({ userId }) => userId === actorId)
|
||||
) {
|
||||
throw new UnauthorizedError({ message: "User has no access" });
|
||||
throw new ForbiddenRequestError({ message: "User has insufficient privileges" });
|
||||
}
|
||||
|
||||
if (secretApprovalRequest.hasMerged) throw new BadRequestError({ message: "Approval request has been merged" });
|
||||
@ -414,7 +414,7 @@ export const secretApprovalRequestServiceFactory = ({
|
||||
bypassReason
|
||||
}: TMergeSecretApprovalRequestDTO) => {
|
||||
const secretApprovalRequest = await secretApprovalRequestDAL.findById(approvalId);
|
||||
if (!secretApprovalRequest) throw new BadRequestError({ message: "Secret approval request not found" });
|
||||
if (!secretApprovalRequest) throw new NotFoundError({ message: "Secret approval request not found" });
|
||||
if (actor !== ActorType.USER) throw new BadRequestError({ message: "Must be a user" });
|
||||
|
||||
const plan = await licenseService.getPlan(actorOrgId);
|
||||
@ -439,7 +439,7 @@ export const secretApprovalRequestServiceFactory = ({
|
||||
secretApprovalRequest.committerUserId !== actorId &&
|
||||
!policy.approvers.find(({ userId }) => userId === actorId)
|
||||
) {
|
||||
throw new UnauthorizedError({ message: "User has no access" });
|
||||
throw new ForbiddenRequestError({ message: "User has insufficient privileges" });
|
||||
}
|
||||
const reviewers = secretApprovalRequest.reviewers.reduce<Record<string, ApprovalStatus>>(
|
||||
(prev, curr) => ({ ...prev, [curr.userId.toString()]: curr.status as ApprovalStatus }),
|
||||
@ -462,7 +462,7 @@ export const secretApprovalRequestServiceFactory = ({
|
||||
const secretApprovalSecrets = await secretApprovalRequestSecretDAL.findByRequestIdBridgeSecretV2(
|
||||
secretApprovalRequest.id
|
||||
);
|
||||
if (!secretApprovalSecrets) throw new BadRequestError({ message: "No secrets found" });
|
||||
if (!secretApprovalSecrets) throw new NotFoundError({ message: "No secrets found" });
|
||||
|
||||
const { decryptor: secretManagerDecryptor } = await kmsService.createCipherPairWithDataKey({
|
||||
type: KmsDataKey.SecretManager,
|
||||
@ -602,7 +602,7 @@ export const secretApprovalRequestServiceFactory = ({
|
||||
});
|
||||
} else {
|
||||
const secretApprovalSecrets = await secretApprovalRequestSecretDAL.findByRequestId(secretApprovalRequest.id);
|
||||
if (!secretApprovalSecrets) throw new BadRequestError({ message: "No secrets found" });
|
||||
if (!secretApprovalSecrets) throw new NotFoundError({ message: "No secrets found" });
|
||||
|
||||
const conflicts: Array<{ secretId: string; op: SecretOperations }> = [];
|
||||
let secretCreationCommits = secretApprovalSecrets.filter(({ op }) => op === SecretOperations.Create);
|
||||
@ -612,8 +612,8 @@ export const secretApprovalRequestServiceFactory = ({
|
||||
secretDAL,
|
||||
inputSecrets: secretCreationCommits.map(({ secretBlindIndex }) => {
|
||||
if (!secretBlindIndex) {
|
||||
throw new BadRequestError({
|
||||
message: "Missing secret blind index"
|
||||
throw new NotFoundError({
|
||||
message: "Secret blind index not found"
|
||||
});
|
||||
}
|
||||
return { secretBlindIndex };
|
||||
@ -639,8 +639,8 @@ export const secretApprovalRequestServiceFactory = ({
|
||||
.filter(({ secretBlindIndex, secret }) => secret && secret.secretBlindIndex !== secretBlindIndex)
|
||||
.map(({ secretBlindIndex }) => {
|
||||
if (!secretBlindIndex) {
|
||||
throw new BadRequestError({
|
||||
message: "Missing secret blind index"
|
||||
throw new NotFoundError({
|
||||
message: "Secret blind index not found"
|
||||
});
|
||||
}
|
||||
return { secretBlindIndex };
|
||||
@ -762,8 +762,8 @@ export const secretApprovalRequestServiceFactory = ({
|
||||
secretQueueService,
|
||||
inputSecrets: secretDeletionCommits.map(({ secretBlindIndex }) => {
|
||||
if (!secretBlindIndex) {
|
||||
throw new BadRequestError({
|
||||
message: "Missing secret blind index"
|
||||
throw new NotFoundError({
|
||||
message: "Secret blind index not found"
|
||||
});
|
||||
}
|
||||
return { secretBlindIndex, type: SecretType.Shared };
|
||||
@ -789,7 +789,7 @@ export const secretApprovalRequestServiceFactory = ({
|
||||
|
||||
await snapshotService.performSnapshot(folderId);
|
||||
const [folder] = await folderDAL.findSecretPathByFolderIds(projectId, [folderId]);
|
||||
if (!folder) throw new BadRequestError({ message: "Folder not found" });
|
||||
if (!folder) throw new NotFoundError({ message: "Folder not found" });
|
||||
await secretQueueService.syncSecrets({
|
||||
projectId,
|
||||
secretPath: folder.path,
|
||||
@ -860,14 +860,14 @@ export const secretApprovalRequestServiceFactory = ({
|
||||
|
||||
const folder = await folderDAL.findBySecretPath(projectId, environment, secretPath);
|
||||
if (!folder)
|
||||
throw new BadRequestError({
|
||||
throw new NotFoundError({
|
||||
message: "Folder not found for the given environment slug & secret path",
|
||||
name: "GenSecretApproval"
|
||||
});
|
||||
const folderId = folder.id;
|
||||
|
||||
const blindIndexCfg = await secretBlindIndexDAL.findOne({ projectId });
|
||||
if (!blindIndexCfg) throw new BadRequestError({ message: "Blind index not found", name: "Update secret" });
|
||||
if (!blindIndexCfg) throw new NotFoundError({ message: "Blind index not found", name: "Update secret" });
|
||||
|
||||
const commits: Omit<TSecretApprovalRequestsSecretsInsert, "requestId">[] = [];
|
||||
const commitTagIds: Record<string, string[]> = {};
|
||||
@ -961,7 +961,7 @@ export const secretApprovalRequestServiceFactory = ({
|
||||
secretDAL
|
||||
});
|
||||
const secretsGroupedByBlindIndex = groupBy(secrets, (i) => {
|
||||
if (!i.secretBlindIndex) throw new BadRequestError({ message: "Missing secret blind index" });
|
||||
if (!i.secretBlindIndex) throw new NotFoundError({ message: "Secret blind index not found" });
|
||||
return i.secretBlindIndex;
|
||||
});
|
||||
const deletedSecretIds = deletedSecrets.map(
|
||||
@ -972,7 +972,7 @@ export const secretApprovalRequestServiceFactory = ({
|
||||
...deletedSecrets.map((el) => {
|
||||
const secretId = secretsGroupedByBlindIndex[keyName2BlindIndex[el.secretName]][0].id;
|
||||
if (!latestSecretVersions[secretId].secretBlindIndex)
|
||||
throw new BadRequestError({ message: "Failed to find secret blind index" });
|
||||
throw new NotFoundError({ message: "Secret blind index not found" });
|
||||
return {
|
||||
op: SecretOperations.Delete as const,
|
||||
...latestSecretVersions[secretId],
|
||||
@ -988,7 +988,7 @@ export const secretApprovalRequestServiceFactory = ({
|
||||
|
||||
const tagIds = unique(Object.values(commitTagIds).flat());
|
||||
const tags = tagIds.length ? await secretTagDAL.findManyTagsById(projectId, tagIds) : [];
|
||||
if (tagIds.length !== tags.length) throw new BadRequestError({ message: "Tag not found" });
|
||||
if (tagIds.length !== tags.length) throw new NotFoundError({ message: "Tag not found" });
|
||||
|
||||
const secretApprovalRequest = await secretApprovalRequestDAL.transaction(async (tx) => {
|
||||
const doc = await secretApprovalRequestDAL.create(
|
||||
@ -1054,7 +1054,7 @@ export const secretApprovalRequestServiceFactory = ({
|
||||
|
||||
const commitsGroupByBlindIndex = groupBy(approvalCommits, (i) => {
|
||||
if (!i.secretBlindIndex) {
|
||||
throw new BadRequestError({ message: "Missing secret blind index" });
|
||||
throw new NotFoundError({ message: "Secret blind index not found" });
|
||||
}
|
||||
return i.secretBlindIndex;
|
||||
});
|
||||
@ -1132,7 +1132,7 @@ export const secretApprovalRequestServiceFactory = ({
|
||||
|
||||
const folder = await folderDAL.findBySecretPath(projectId, environment, secretPath);
|
||||
if (!folder)
|
||||
throw new BadRequestError({
|
||||
throw new NotFoundError({
|
||||
message: "Folder not found for the given environment slug & secret path",
|
||||
name: "GenSecretApproval"
|
||||
});
|
||||
@ -1191,8 +1191,8 @@ export const secretApprovalRequestServiceFactory = ({
|
||||
}))
|
||||
);
|
||||
if (secretsToUpdateStoredInDB.length !== secretsToUpdate.length)
|
||||
throw new BadRequestError({
|
||||
message: `Secret not exist: ${secretsToUpdateStoredInDB.map((el) => el.key).join(",")}`
|
||||
throw new NotFoundError({
|
||||
message: `Secret does not exist: ${secretsToUpdateStoredInDB.map((el) => el.key).join(",")}`
|
||||
});
|
||||
|
||||
// now find any secret that needs to update its name
|
||||
@ -1207,8 +1207,8 @@ export const secretApprovalRequestServiceFactory = ({
|
||||
}))
|
||||
);
|
||||
if (secrets.length)
|
||||
throw new BadRequestError({
|
||||
message: `Secret not exist: ${secretsToUpdateStoredInDB.map((el) => el.key).join(",")}`
|
||||
throw new NotFoundError({
|
||||
message: `Secret does not exist: ${secretsToUpdateStoredInDB.map((el) => el.key).join(",")}`
|
||||
});
|
||||
}
|
||||
|
||||
@ -1267,8 +1267,8 @@ export const secretApprovalRequestServiceFactory = ({
|
||||
}))
|
||||
);
|
||||
if (secretsToDeleteInDB.length !== deletedSecrets.length)
|
||||
throw new BadRequestError({
|
||||
message: `Secret not exist: ${secretsToDeleteInDB.map((el) => el.key).join(",")}`
|
||||
throw new NotFoundError({
|
||||
message: `Secret does not exist: ${secretsToDeleteInDB.map((el) => el.key).join(",")}`
|
||||
});
|
||||
const secretsGroupedByKey = groupBy(secretsToDeleteInDB, (i) => i.key);
|
||||
const deletedSecretIds = deletedSecrets.map((el) => secretsGroupedByKey[el.secretKey][0].id);
|
||||
@ -1291,7 +1291,7 @@ export const secretApprovalRequestServiceFactory = ({
|
||||
|
||||
const tagIds = unique(Object.values(commitTagIds).flat());
|
||||
const tags = tagIds.length ? await secretTagDAL.findManyTagsById(projectId, tagIds) : [];
|
||||
if (tagIds.length !== tags.length) throw new BadRequestError({ message: "Tag not found" });
|
||||
if (tagIds.length !== tags.length) throw new NotFoundError({ message: "Tag not found" });
|
||||
|
||||
const secretApprovalRequest = await secretApprovalRequestDAL.transaction(async (tx) => {
|
||||
const doc = await secretApprovalRequestDAL.create(
|
||||
|
@ -4,7 +4,7 @@ import { TSecretApprovalRequestDALFactory } from "@app/ee/services/secret-approv
|
||||
import { TSecretApprovalRequestSecretDALFactory } from "@app/ee/services/secret-approval-request/secret-approval-request-secret-dal";
|
||||
import { KeyStorePrefixes, TKeyStoreFactory } from "@app/keystore/keystore";
|
||||
import { decryptSymmetric128BitHexKeyUTF8 } from "@app/lib/crypto";
|
||||
import { BadRequestError } from "@app/lib/errors";
|
||||
import { NotFoundError } from "@app/lib/errors";
|
||||
import { groupBy, unique } from "@app/lib/fn";
|
||||
import { logger } from "@app/lib/logger";
|
||||
import { alphaNumericNanoId } from "@app/lib/nanoid";
|
||||
@ -295,7 +295,7 @@ export const secretReplicationServiceFactory = ({
|
||||
const [destinationFolder] = await folderDAL.findSecretPathByFolderIds(projectId, [
|
||||
destinationSecretImport.folderId
|
||||
]);
|
||||
if (!destinationFolder) throw new BadRequestError({ message: "Imported folder not found" });
|
||||
if (!destinationFolder) throw new NotFoundError({ message: "Imported folder not found" });
|
||||
|
||||
let destinationReplicationFolder = await folderDAL.findOne({
|
||||
parentId: destinationFolder.id,
|
||||
@ -506,7 +506,7 @@ export const secretReplicationServiceFactory = ({
|
||||
return;
|
||||
}
|
||||
|
||||
if (!botKey) throw new BadRequestError({ message: "Bot not found" });
|
||||
if (!botKey) throw new NotFoundError({ message: "Project bot not found" });
|
||||
// these are the secrets to be added in replicated folders
|
||||
const sourceLocalSecrets = await secretDAL.find({ folderId: folder.id, type: SecretType.Shared });
|
||||
const sourceSecretImports = await secretImportDAL.find({ folderId: folder.id });
|
||||
@ -545,7 +545,7 @@ export const secretReplicationServiceFactory = ({
|
||||
const [destinationFolder] = await folderDAL.findSecretPathByFolderIds(projectId, [
|
||||
destinationSecretImport.folderId
|
||||
]);
|
||||
if (!destinationFolder) throw new BadRequestError({ message: "Imported folder not found" });
|
||||
if (!destinationFolder) throw new NotFoundError({ message: "Imported folder not found" });
|
||||
|
||||
let destinationReplicationFolder = await folderDAL.findOne({
|
||||
parentId: destinationFolder.id,
|
||||
|
@ -13,7 +13,7 @@ import {
|
||||
infisicalSymmetricEncypt
|
||||
} from "@app/lib/crypto/encryption";
|
||||
import { daysToMillisecond, secondsToMillis } from "@app/lib/dates";
|
||||
import { BadRequestError } from "@app/lib/errors";
|
||||
import { NotFoundError } from "@app/lib/errors";
|
||||
import { logger } from "@app/lib/logger";
|
||||
import { alphaNumericNanoId } from "@app/lib/nanoid";
|
||||
import { QueueJobs, QueueName, TQueueServiceFactory } from "@app/queue";
|
||||
@ -332,7 +332,7 @@ export const secretRotationQueueFactory = ({
|
||||
);
|
||||
});
|
||||
} else {
|
||||
if (!botKey) throw new BadRequestError({ message: "Bot not found" });
|
||||
if (!botKey) throw new NotFoundError({ message: "Project bot not found" });
|
||||
const encryptedSecrets = rotationOutputs.map(({ key: outputKey, secretId }) => ({
|
||||
secretId,
|
||||
value: encryptSymmetric128BitHexKeyUTF8(
|
||||
@ -372,7 +372,7 @@ export const secretRotationQueueFactory = ({
|
||||
);
|
||||
await secretVersionDAL.insertMany(
|
||||
updatedSecrets.map(({ id, updatedAt, createdAt, ...el }) => {
|
||||
if (!el.secretBlindIndex) throw new BadRequestError({ message: "Missing blind index" });
|
||||
if (!el.secretBlindIndex) throw new NotFoundError({ message: "Secret blind index not found" });
|
||||
return {
|
||||
...el,
|
||||
secretId: id,
|
||||
|
@ -3,7 +3,7 @@ import Ajv from "ajv";
|
||||
|
||||
import { ProjectVersion } from "@app/db/schemas";
|
||||
import { decryptSymmetric128BitHexKeyUTF8, infisicalSymmetricEncypt } from "@app/lib/crypto/encryption";
|
||||
import { BadRequestError } from "@app/lib/errors";
|
||||
import { BadRequestError, NotFoundError } from "@app/lib/errors";
|
||||
import { TProjectPermission } from "@app/lib/types";
|
||||
import { TProjectDALFactory } from "@app/services/project/project-dal";
|
||||
import { TProjectBotServiceFactory } from "@app/services/project-bot/project-bot-service";
|
||||
@ -94,7 +94,7 @@ export const secretRotationServiceFactory = ({
|
||||
);
|
||||
|
||||
const folder = await folderDAL.findBySecretPath(projectId, environment, secretPath);
|
||||
if (!folder) throw new BadRequestError({ message: "Secret path not found" });
|
||||
if (!folder) throw new NotFoundError({ message: "Secret path not found" });
|
||||
ForbiddenError.from(permission).throwUnlessCan(
|
||||
ProjectPermissionActions.Edit,
|
||||
subject(ProjectPermissionSub.Secrets, { environment, secretPath })
|
||||
@ -108,14 +108,14 @@ export const secretRotationServiceFactory = ({
|
||||
$in: { id: Object.values(outputs) }
|
||||
});
|
||||
if (selectedSecrets.length !== Object.values(outputs).length)
|
||||
throw new BadRequestError({ message: "Secrets not found" });
|
||||
throw new NotFoundError({ message: "Secrets not found" });
|
||||
} else {
|
||||
const selectedSecrets = await secretDAL.find({
|
||||
folderId: folder.id,
|
||||
$in: { id: Object.values(outputs) }
|
||||
});
|
||||
if (selectedSecrets.length !== Object.values(outputs).length)
|
||||
throw new BadRequestError({ message: "Secrets not found" });
|
||||
throw new NotFoundError({ message: "Secrets not found" });
|
||||
}
|
||||
|
||||
const plan = await licenseService.getPlan(project.orgId);
|
||||
@ -125,7 +125,7 @@ export const secretRotationServiceFactory = ({
|
||||
});
|
||||
|
||||
const selectedTemplate = rotationTemplates.find(({ name }) => name === provider);
|
||||
if (!selectedTemplate) throw new BadRequestError({ message: "Provider not found" });
|
||||
if (!selectedTemplate) throw new NotFoundError({ message: "Provider not found" });
|
||||
const formattedInputs: Record<string, unknown> = {};
|
||||
Object.entries(inputs).forEach(([key, value]) => {
|
||||
const { type } = selectedTemplate.template.inputs.properties[key];
|
||||
@ -198,7 +198,7 @@ export const secretRotationServiceFactory = ({
|
||||
return docs;
|
||||
}
|
||||
|
||||
if (!botKey) throw new BadRequestError({ message: "bot not found" });
|
||||
if (!botKey) throw new NotFoundError({ message: "Project bot not found" });
|
||||
const docs = await secretRotationDAL.find({ projectId });
|
||||
return docs.map((el) => ({
|
||||
...el,
|
||||
@ -220,7 +220,7 @@ export const secretRotationServiceFactory = ({
|
||||
|
||||
const restartById = async ({ actor, actorId, actorOrgId, actorAuthMethod, rotationId }: TRestartDTO) => {
|
||||
const doc = await secretRotationDAL.findById(rotationId);
|
||||
if (!doc) throw new BadRequestError({ message: "Rotation not found" });
|
||||
if (!doc) throw new NotFoundError({ message: "Rotation not found" });
|
||||
|
||||
const project = await projectDAL.findById(doc.projectId);
|
||||
const plan = await licenseService.getPlan(project.orgId);
|
||||
@ -244,7 +244,7 @@ export const secretRotationServiceFactory = ({
|
||||
|
||||
const deleteById = async ({ actor, actorId, actorOrgId, actorAuthMethod, rotationId }: TDeleteDTO) => {
|
||||
const doc = await secretRotationDAL.findById(rotationId);
|
||||
if (!doc) throw new BadRequestError({ message: "Rotation not found" });
|
||||
if (!doc) throw new NotFoundError({ message: "Rotation not found" });
|
||||
|
||||
const { permission } = await permissionService.getProjectPermission(
|
||||
actor,
|
||||
|
@ -7,7 +7,7 @@ import { ProbotOctokit } from "probot";
|
||||
import { OrgPermissionActions, OrgPermissionSubjects } from "@app/ee/services/permission/org-permission";
|
||||
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service";
|
||||
import { getConfig } from "@app/lib/config/env";
|
||||
import { UnauthorizedError } from "@app/lib/errors";
|
||||
import { NotFoundError } from "@app/lib/errors";
|
||||
|
||||
import { TGitAppDALFactory } from "./git-app-dal";
|
||||
import { TGitAppInstallSessionDALFactory } from "./git-app-install-session-dal";
|
||||
@ -63,7 +63,7 @@ export const secretScanningServiceFactory = ({
|
||||
actorOrgId
|
||||
}: TLinkInstallSessionDTO) => {
|
||||
const session = await gitAppInstallSessionDAL.findOne({ sessionId });
|
||||
if (!session) throw new UnauthorizedError({ message: "Session not found" });
|
||||
if (!session) throw new NotFoundError({ message: "Session was not found" });
|
||||
|
||||
const { permission } = await permissionService.getOrgPermission(
|
||||
actor,
|
||||
|
@ -2,7 +2,7 @@ import { ForbiddenError, subject } from "@casl/ability";
|
||||
|
||||
import { TableName, TSecretTagJunctionInsert, TSecretV2TagJunctionInsert } from "@app/db/schemas";
|
||||
import { decryptSymmetric128BitHexKeyUTF8 } from "@app/lib/crypto";
|
||||
import { BadRequestError, InternalServerError } from "@app/lib/errors";
|
||||
import { InternalServerError, NotFoundError } from "@app/lib/errors";
|
||||
import { groupBy } from "@app/lib/fn";
|
||||
import { logger } from "@app/lib/logger";
|
||||
import { TKmsServiceFactory } from "@app/services/kms/kms-service";
|
||||
@ -99,7 +99,7 @@ export const secretSnapshotServiceFactory = ({
|
||||
);
|
||||
|
||||
const folder = await folderDAL.findBySecretPath(projectId, environment, path);
|
||||
if (!folder) throw new BadRequestError({ message: "Folder not found" });
|
||||
if (!folder) throw new NotFoundError({ message: "Folder not found" });
|
||||
|
||||
return snapshotDAL.countOfSnapshotsByFolderId(folder.id);
|
||||
};
|
||||
@ -131,7 +131,7 @@ export const secretSnapshotServiceFactory = ({
|
||||
);
|
||||
|
||||
const folder = await folderDAL.findBySecretPath(projectId, environment, path);
|
||||
if (!folder) throw new BadRequestError({ message: "Folder not found" });
|
||||
if (!folder) throw new NotFoundError({ message: "Folder not found" });
|
||||
|
||||
const snapshots = await snapshotDAL.find({ folderId: folder.id }, { limit, offset, sort: [["createdAt", "desc"]] });
|
||||
return snapshots;
|
||||
@ -139,7 +139,7 @@ export const secretSnapshotServiceFactory = ({
|
||||
|
||||
const getSnapshotData = async ({ actorId, actor, actorOrgId, actorAuthMethod, id }: TGetSnapshotDataDTO) => {
|
||||
const snapshot = await snapshotDAL.findById(id);
|
||||
if (!snapshot) throw new BadRequestError({ message: "Snapshot not found" });
|
||||
if (!snapshot) throw new NotFoundError({ message: "Snapshot not found" });
|
||||
const { permission } = await permissionService.getProjectPermission(
|
||||
actor,
|
||||
actorId,
|
||||
@ -173,7 +173,7 @@ export const secretSnapshotServiceFactory = ({
|
||||
} else {
|
||||
const encryptedSnapshotDetails = await snapshotDAL.findSecretSnapshotDataById(id);
|
||||
const { botKey } = await projectBotService.getBotKey(snapshot.projectId);
|
||||
if (!botKey) throw new BadRequestError({ message: "bot not found" });
|
||||
if (!botKey) throw new NotFoundError({ message: "Project bot not found" });
|
||||
snapshotDetails = {
|
||||
...encryptedSnapshotDetails,
|
||||
secretVersions: encryptedSnapshotDetails.secretVersions.map((el) => ({
|
||||
@ -225,7 +225,7 @@ export const secretSnapshotServiceFactory = ({
|
||||
try {
|
||||
if (!licenseService.isValidLicense) throw new InternalServerError({ message: "Invalid license" });
|
||||
const folder = await folderDAL.findById(folderId);
|
||||
if (!folder) throw new BadRequestError({ message: "Folder not found" });
|
||||
if (!folder) throw new NotFoundError({ message: "Folder not found" });
|
||||
const shouldUseSecretV2Bridge = folder.projectVersion === 3;
|
||||
|
||||
if (shouldUseSecretV2Bridge) {
|
||||
@ -309,7 +309,7 @@ export const secretSnapshotServiceFactory = ({
|
||||
actorOrgId
|
||||
}: TRollbackSnapshotDTO) => {
|
||||
const snapshot = await snapshotDAL.findById(snapshotId);
|
||||
if (!snapshot) throw new BadRequestError({ message: "Snapshot not found" });
|
||||
if (!snapshot) throw new NotFoundError({ message: "Snapshot not found" });
|
||||
const shouldUseBridge = snapshot.projectVersion === 3;
|
||||
|
||||
const { permission } = await permissionService.getProjectPermission(
|
||||
|
@ -24,6 +24,9 @@ export const GROUPS = {
|
||||
id: "The id of the group to add the user to.",
|
||||
username: "The username of the user to add to the group."
|
||||
},
|
||||
GET_BY_ID: {
|
||||
id: "The id of the group to fetch"
|
||||
},
|
||||
DELETE_USER: {
|
||||
id: "The id of the group to remove the user from.",
|
||||
username: "The username of the user to remove from the group."
|
||||
|
@ -40,9 +40,9 @@ export class ForbiddenRequestError extends Error {
|
||||
|
||||
error: unknown;
|
||||
|
||||
constructor({ name, error, message }: { message?: string; name?: string; error?: unknown }) {
|
||||
constructor({ name, error, message }: { message?: string; name?: string; error?: unknown } = {}) {
|
||||
super(message ?? "You are not allowed to access this resource");
|
||||
this.name = name || "ForbideenError";
|
||||
this.name = name || "ForbiddenError";
|
||||
this.error = error;
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
import net from "node:net";
|
||||
|
||||
import { UnauthorizedError } from "../errors";
|
||||
import { ForbiddenRequestError } from "../errors";
|
||||
|
||||
export enum IPType {
|
||||
IPV4 = "ipv4",
|
||||
@ -126,7 +126,7 @@ export const checkIPAgainstBlocklist = ({ ipAddress, trustedIps }: { ipAddress:
|
||||
const check = blockList.check(ipAddress, type);
|
||||
|
||||
if (!check)
|
||||
throw new UnauthorizedError({
|
||||
message: "Failed to authenticate"
|
||||
throw new ForbiddenRequestError({
|
||||
message: "You are not allowed to access this resource from the current IP address"
|
||||
});
|
||||
};
|
||||
|
@ -20,6 +20,7 @@ import { TQueueServiceFactory } from "@app/queue";
|
||||
import { TSmtpService } from "@app/services/smtp/smtp-service";
|
||||
|
||||
import { globalRateLimiterCfg } from "./config/rateLimiter";
|
||||
import { addErrorsToResponseSchemas } from "./plugins/add-errors-to-response-schemas";
|
||||
import { fastifyErrHandler } from "./plugins/error-handler";
|
||||
import { registerExternalNextjs } from "./plugins/external-nextjs";
|
||||
import { serializerCompiler, validatorCompiler, ZodTypeProvider } from "./plugins/fastify-zod";
|
||||
@ -75,6 +76,8 @@ export const main = async ({ db, smtp, logger, queue, keyStore }: TMain) => {
|
||||
credentials: true,
|
||||
origin: appCfg.SITE_URL || true
|
||||
});
|
||||
|
||||
await server.register(addErrorsToResponseSchemas);
|
||||
// pull ip based on various proxy headers
|
||||
await server.register(fastifyIp);
|
||||
|
||||
|
15
backend/src/server/plugins/add-errors-to-response-schemas.ts
Normal file
15
backend/src/server/plugins/add-errors-to-response-schemas.ts
Normal file
@ -0,0 +1,15 @@
|
||||
/* eslint-disable no-param-reassign */
|
||||
import fp from "fastify-plugin";
|
||||
|
||||
import { DefaultResponseErrorsSchema } from "../routes/sanitizedSchemas";
|
||||
|
||||
export const addErrorsToResponseSchemas = fp(async (server) => {
|
||||
server.addHook("onRoute", (routeOptions) => {
|
||||
if (routeOptions.schema && routeOptions.schema.response) {
|
||||
routeOptions.schema.response = {
|
||||
...DefaultResponseErrorsSchema,
|
||||
...routeOptions.schema.response
|
||||
};
|
||||
}
|
||||
});
|
||||
});
|
@ -70,7 +70,7 @@ export const injectAuditLogInfo = fp(async (server: FastifyZodProvider) => {
|
||||
metadata: {}
|
||||
};
|
||||
} else {
|
||||
throw new BadRequestError({ message: "Missing logic for other actor" });
|
||||
throw new BadRequestError({ message: "Invalid actor type provided" });
|
||||
}
|
||||
req.auditLogInfo = payload;
|
||||
});
|
||||
|
@ -5,7 +5,7 @@ import jwt, { JwtPayload } from "jsonwebtoken";
|
||||
import { TServiceTokens, TUsers } from "@app/db/schemas";
|
||||
import { TScimTokenJwtPayload } from "@app/ee/services/scim/scim-types";
|
||||
import { getConfig } from "@app/lib/config/env";
|
||||
import { UnauthorizedError } from "@app/lib/errors";
|
||||
import { BadRequestError } from "@app/lib/errors";
|
||||
import { ActorType, AuthMethod, AuthMode, AuthModeJwtTokenPayload, AuthTokenType } from "@app/services/auth/auth-type";
|
||||
import { TIdentityAccessTokenJwtPayload } from "@app/services/identity-access-token/identity-access-token-types";
|
||||
|
||||
@ -167,7 +167,7 @@ export const injectIdentity = fp(async (server: FastifyZodProvider) => {
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw new UnauthorizedError({ name: "Unknown token strategy" });
|
||||
throw new BadRequestError({ message: "Invalid token strategy provided" });
|
||||
}
|
||||
});
|
||||
});
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { FastifyReply, FastifyRequest, HookHandlerDoneFunction } from "fastify";
|
||||
|
||||
import { UnauthorizedError } from "@app/lib/errors";
|
||||
import { ForbiddenRequestError } from "@app/lib/errors";
|
||||
import { ActorType } from "@app/services/auth/auth-type";
|
||||
|
||||
export const verifySuperAdmin = <T extends FastifyRequest>(
|
||||
@ -9,9 +9,8 @@ export const verifySuperAdmin = <T extends FastifyRequest>(
|
||||
done: HookHandlerDoneFunction
|
||||
) => {
|
||||
if (req.auth.actor !== ActorType.USER || !req.auth.user.superAdmin)
|
||||
throw new UnauthorizedError({
|
||||
name: "Unauthorized access",
|
||||
message: "Requires superadmin access"
|
||||
throw new ForbiddenRequestError({
|
||||
message: "Requires elevated super admin privileges"
|
||||
});
|
||||
done();
|
||||
};
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { FastifyReply, FastifyRequest, HookHandlerDoneFunction } from "fastify";
|
||||
|
||||
import { UnauthorizedError } from "@app/lib/errors";
|
||||
import { ForbiddenRequestError, UnauthorizedError } from "@app/lib/errors";
|
||||
import { AuthMode } from "@app/services/auth/auth-type";
|
||||
|
||||
interface TAuthOptions {
|
||||
@ -11,11 +11,11 @@ export const verifyAuth =
|
||||
<T extends FastifyRequest>(authStrategies: AuthMode[], options: TAuthOptions = { requireOrg: true }) =>
|
||||
(req: T, _res: FastifyReply, done: HookHandlerDoneFunction) => {
|
||||
if (!Array.isArray(authStrategies)) throw new Error("Auth strategy must be array");
|
||||
if (!req.auth) throw new UnauthorizedError({ name: "Unauthorized access", message: "Token missing" });
|
||||
if (!req.auth) throw new UnauthorizedError({ message: "Token missing" });
|
||||
|
||||
const isAccessAllowed = authStrategies.some((strategy) => strategy === req.auth.authMode);
|
||||
if (!isAccessAllowed) {
|
||||
throw new UnauthorizedError({ name: `${req.url} Unauthorized Access` });
|
||||
throw new ForbiddenRequestError({ name: `Forbidden access to ${req.url}` });
|
||||
}
|
||||
|
||||
// New optional option. There are some routes which do not require an organization ID to be present on the request.
|
||||
|
@ -6,6 +6,7 @@ import { ZodError } from "zod";
|
||||
import {
|
||||
BadRequestError,
|
||||
DatabaseError,
|
||||
ForbiddenRequestError,
|
||||
InternalServerError,
|
||||
NotFoundError,
|
||||
ScimRequestError,
|
||||
@ -18,25 +19,50 @@ enum JWTErrors {
|
||||
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) => {
|
||||
server.setErrorHandler((error, req, res) => {
|
||||
req.log.error(error);
|
||||
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) {
|
||||
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) {
|
||||
void res.status(403).send({ statusCode: 403, 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) {
|
||||
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) {
|
||||
void res.status(403).send({ statusCode: 403, error: "ValidationFailure", message: error.issues });
|
||||
void res
|
||||
.status(HttpStatusCodes.Unauthorized)
|
||||
.send({ statusCode: HttpStatusCodes.Unauthorized, error: "ValidationFailure", message: error.issues });
|
||||
} else if (error instanceof ForbiddenError) {
|
||||
void res.status(401).send({
|
||||
statusCode: 401,
|
||||
void res.status(HttpStatusCodes.Forbidden).send({
|
||||
statusCode: HttpStatusCodes.Forbidden,
|
||||
error: "PermissionDenied",
|
||||
message: `You are not allowed to ${error.action} on ${error.subjectType}`
|
||||
});
|
||||
} else if (error instanceof ForbiddenRequestError) {
|
||||
void res.status(HttpStatusCodes.Forbidden).send({
|
||||
statusCode: HttpStatusCodes.Forbidden,
|
||||
message: error.message,
|
||||
error: error.name
|
||||
});
|
||||
} else if (error instanceof ScimRequestError) {
|
||||
void res.status(error.status).send({
|
||||
schemas: error.schemas,
|
||||
@ -59,8 +85,8 @@ export const fastifyErrHandler = fastifyPlugin(async (server: FastifyZodProvider
|
||||
return error.message;
|
||||
})();
|
||||
|
||||
void res.status(401).send({
|
||||
statusCode: 401,
|
||||
void res.status(HttpStatusCodes.Forbidden).send({
|
||||
statusCode: HttpStatusCodes.Forbidden,
|
||||
error: "TokenError",
|
||||
message
|
||||
});
|
||||
|
@ -380,7 +380,8 @@ export const registerRoutes = async (
|
||||
secretApprovalPolicyApproverDAL: sapApproverDAL,
|
||||
permissionService,
|
||||
secretApprovalPolicyDAL,
|
||||
licenseService
|
||||
licenseService,
|
||||
userDAL
|
||||
});
|
||||
const tokenService = tokenServiceFactory({ tokenDAL: authTokenDAL, userDAL, orgMembershipDAL });
|
||||
|
||||
@ -927,7 +928,8 @@ export const registerRoutes = async (
|
||||
permissionService,
|
||||
projectEnvDAL,
|
||||
projectMembershipDAL,
|
||||
projectDAL
|
||||
projectDAL,
|
||||
userDAL
|
||||
});
|
||||
|
||||
const accessApprovalRequestService = accessApprovalRequestServiceFactory({
|
||||
|
@ -27,6 +27,34 @@ export const integrationAuthPubSchema = IntegrationAuthsSchema.pick({
|
||||
updatedAt: true
|
||||
});
|
||||
|
||||
export const DefaultResponseErrorsSchema = {
|
||||
400: z.object({
|
||||
statusCode: z.literal(400),
|
||||
message: z.string(),
|
||||
error: z.string()
|
||||
}),
|
||||
404: z.object({
|
||||
statusCode: z.literal(404),
|
||||
message: z.string(),
|
||||
error: z.string()
|
||||
}),
|
||||
401: z.object({
|
||||
statusCode: z.literal(401),
|
||||
message: z.any(),
|
||||
error: z.string()
|
||||
}),
|
||||
403: z.object({
|
||||
statusCode: z.literal(403),
|
||||
message: z.string(),
|
||||
error: z.string()
|
||||
}),
|
||||
500: z.object({
|
||||
statusCode: z.literal(500),
|
||||
message: z.string(),
|
||||
error: z.string()
|
||||
})
|
||||
};
|
||||
|
||||
export const sapPubSchema = SecretApprovalPoliciesSchema.merge(
|
||||
z.object({
|
||||
environment: z.object({
|
||||
|
@ -2,7 +2,7 @@ import { z } from "zod";
|
||||
|
||||
import { OrganizationsSchema, SuperAdminSchema, UsersSchema } from "@app/db/schemas";
|
||||
import { getConfig } from "@app/lib/config/env";
|
||||
import { UnauthorizedError } from "@app/lib/errors";
|
||||
import { BadRequestError } from "@app/lib/errors";
|
||||
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
||||
import { verifySuperAdmin } from "@app/server/plugins/auth/superAdmin";
|
||||
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||
@ -227,8 +227,7 @@ export const registerAdminRouter = async (server: FastifyZodProvider) => {
|
||||
handler: async (req, res) => {
|
||||
const appCfg = getConfig();
|
||||
const serverCfg = await getServerCfg();
|
||||
if (serverCfg.initialized)
|
||||
throw new UnauthorizedError({ name: "Admin sign up", message: "Admin has been created" });
|
||||
if (serverCfg.initialized) throw new BadRequestError({ message: "Admin account has already been set up" });
|
||||
const { user, token, organization } = await server.services.superAdmin.adminSignUp({
|
||||
...req.body,
|
||||
ip: req.realIp,
|
||||
|
@ -2,7 +2,7 @@ import jwt from "jsonwebtoken";
|
||||
import { z } from "zod";
|
||||
|
||||
import { getConfig } from "@app/lib/config/env";
|
||||
import { BadRequestError, UnauthorizedError } from "@app/lib/errors";
|
||||
import { NotFoundError, UnauthorizedError } from "@app/lib/errors";
|
||||
import { authRateLimit, writeLimit } from "@app/server/config/rateLimiter";
|
||||
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||
import { AuthMode, AuthModeRefreshJwtTokenPayload, AuthTokenType } from "@app/services/auth/auth-type";
|
||||
@ -71,23 +71,34 @@ export const registerAuthRoutes = async (server: FastifyZodProvider) => {
|
||||
const refreshToken = req.cookies.jid;
|
||||
const appCfg = getConfig();
|
||||
if (!refreshToken)
|
||||
throw new BadRequestError({
|
||||
name: "Auth token route",
|
||||
message: "Failed to find refresh token"
|
||||
throw new NotFoundError({
|
||||
name: "AuthTokenNotFound",
|
||||
message: "Failed to find refresh token"
|
||||
});
|
||||
|
||||
const decodedToken = jwt.verify(refreshToken, appCfg.AUTH_SECRET) as AuthModeRefreshJwtTokenPayload;
|
||||
if (decodedToken.authTokenType !== AuthTokenType.REFRESH_TOKEN)
|
||||
throw new UnauthorizedError({ message: "Invalid token", name: "Auth token route" });
|
||||
throw new UnauthorizedError({
|
||||
message: "The token provided is not a refresh token",
|
||||
name: "InvalidToken"
|
||||
});
|
||||
|
||||
const tokenVersion = await server.services.authToken.getUserTokenSessionById(
|
||||
decodedToken.tokenVersionId,
|
||||
decodedToken.userId
|
||||
);
|
||||
if (!tokenVersion) throw new UnauthorizedError({ message: "Invalid token", name: "Auth token route" });
|
||||
if (!tokenVersion)
|
||||
throw new UnauthorizedError({
|
||||
message: "Valid token version not found",
|
||||
name: "InvalidToken"
|
||||
});
|
||||
|
||||
if (decodedToken.refreshVersion !== tokenVersion.refreshVersion)
|
||||
throw new UnauthorizedError({ message: "Invalid token", name: "Auth token route" });
|
||||
if (decodedToken.refreshVersion !== tokenVersion.refreshVersion) {
|
||||
throw new UnauthorizedError({
|
||||
message: "Token version mismatch",
|
||||
name: "InvalidToken"
|
||||
});
|
||||
}
|
||||
|
||||
const token = jwt.sign(
|
||||
{
|
||||
|
@ -9,6 +9,8 @@ import { AuthMode } from "@app/services/auth/auth-type";
|
||||
import { TIdentityTrustedIp } from "@app/services/identity/identity-types";
|
||||
import { validateAzureAuthField } from "@app/services/identity-azure-auth/identity-azure-auth-validators";
|
||||
|
||||
import {} from "../sanitizedSchemas";
|
||||
|
||||
export const registerIdentityAzureAuthRouter = async (server: FastifyZodProvider) => {
|
||||
server.route({
|
||||
method: "POST",
|
||||
|
@ -11,6 +11,8 @@ import { AuthMode } from "@app/services/auth/auth-type";
|
||||
import { IntegrationMetadataSchema } from "@app/services/integration/integration-schema";
|
||||
import { PostHogEventTypes, TIntegrationCreatedEvent } from "@app/services/telemetry/telemetry-types";
|
||||
|
||||
import {} from "../sanitizedSchemas";
|
||||
|
||||
export const registerIntegrationRouter = async (server: FastifyZodProvider) => {
|
||||
server.route({
|
||||
method: "POST",
|
||||
|
@ -11,6 +11,8 @@ import {
|
||||
} from "@app/db/schemas";
|
||||
import { EventType, UserAgentType } from "@app/ee/services/audit-log/audit-log-types";
|
||||
import { AUDIT_LOGS, ORGANIZATIONS } from "@app/lib/api-docs";
|
||||
import { getConfig } from "@app/lib/config/env";
|
||||
import { BadRequestError } from "@app/lib/errors";
|
||||
import { getLastMidnightDateISO } from "@app/lib/fn";
|
||||
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
||||
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||
@ -143,6 +145,11 @@ export const registerOrgRouter = async (server: FastifyZodProvider) => {
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT]),
|
||||
handler: async (req) => {
|
||||
const appCfg = getConfig();
|
||||
if (appCfg.isCloud) {
|
||||
throw new BadRequestError({ message: "Infisical cloud audit log is in maintenance mode." });
|
||||
}
|
||||
|
||||
const auditLogs = await server.services.auditLog.listAuditLogs({
|
||||
filter: {
|
||||
...req.query,
|
||||
|
@ -14,7 +14,7 @@ import { Strategy as GoogleStrategy } from "passport-google-oauth20";
|
||||
import { z } from "zod";
|
||||
|
||||
import { getConfig } from "@app/lib/config/env";
|
||||
import { BadRequestError } from "@app/lib/errors";
|
||||
import { NotFoundError } from "@app/lib/errors";
|
||||
import { logger } from "@app/lib/logger";
|
||||
import { fetchGithubEmails } from "@app/lib/requests/github";
|
||||
import { AuthMethod } from "@app/services/auth/auth-type";
|
||||
@ -42,9 +42,9 @@ export const registerSsoRouter = async (server: FastifyZodProvider) => {
|
||||
try {
|
||||
const email = profile?.emails?.[0]?.value;
|
||||
if (!email)
|
||||
throw new BadRequestError({
|
||||
throw new NotFoundError({
|
||||
message: "Email not found",
|
||||
name: "Oauth Google Register"
|
||||
name: "OauthGoogleRegister"
|
||||
});
|
||||
|
||||
const { isUserCompleted, providerAuthToken } = await server.services.login.oauth2Login({
|
||||
|
@ -69,7 +69,7 @@ export const registerOrgRouter = async (server: FastifyZodProvider) => {
|
||||
rateLimit: readLimit
|
||||
},
|
||||
schema: {
|
||||
description: "Return projects in organization that user is part of",
|
||||
description: "Return projects in organization that user is apart of",
|
||||
security: [
|
||||
{
|
||||
bearerAuth: []
|
||||
|
@ -1,7 +1,9 @@
|
||||
import { ForbiddenError, subject } from "@casl/ability";
|
||||
import { z } from "zod";
|
||||
|
||||
import { SecretFoldersSchema, SecretImportsSchema, SecretTagsSchema } from "@app/db/schemas";
|
||||
import { EventType, UserAgentType } from "@app/ee/services/audit-log/audit-log-types";
|
||||
import { ProjectPermissionActions, ProjectPermissionSub } from "@app/ee/services/permission/project-permission";
|
||||
import { DASHBOARD } from "@app/lib/api-docs";
|
||||
import { BadRequestError } from "@app/lib/errors";
|
||||
import { removeTrailingSlash } from "@app/lib/fn";
|
||||
@ -173,6 +175,29 @@ export const registerDashboardRouter = async (server: FastifyZodProvider) => {
|
||||
}
|
||||
}
|
||||
|
||||
if (!includeDynamicSecrets && !includeSecrets)
|
||||
return {
|
||||
folders,
|
||||
totalFolderCount,
|
||||
totalCount: totalFolderCount ?? 0
|
||||
};
|
||||
|
||||
const { permission } = await server.services.permission.getProjectPermission(
|
||||
req.permission.type,
|
||||
req.permission.id,
|
||||
projectId,
|
||||
req.permission.authMethod,
|
||||
req.permission.orgId
|
||||
);
|
||||
|
||||
const permissiveEnvs = // filter envs user has access to
|
||||
environments.filter((environment) =>
|
||||
permission.can(
|
||||
ProjectPermissionActions.Read,
|
||||
subject(ProjectPermissionSub.Secrets, { environment, secretPath })
|
||||
)
|
||||
);
|
||||
|
||||
if (includeDynamicSecrets) {
|
||||
// this is the unique count, ie duplicate secrets across envs only count as 1
|
||||
totalDynamicSecretCount = await server.services.dynamicSecret.getCountMultiEnv({
|
||||
@ -182,8 +207,9 @@ export const registerDashboardRouter = async (server: FastifyZodProvider) => {
|
||||
actorOrgId: req.permission.orgId,
|
||||
projectId,
|
||||
search,
|
||||
environmentSlugs: environments,
|
||||
path: secretPath
|
||||
environmentSlugs: permissiveEnvs,
|
||||
path: secretPath,
|
||||
isInternal: true
|
||||
});
|
||||
|
||||
if (remainingLimit > 0 && totalDynamicSecretCount > adjustedOffset) {
|
||||
@ -196,10 +222,11 @@ export const registerDashboardRouter = async (server: FastifyZodProvider) => {
|
||||
search,
|
||||
orderBy,
|
||||
orderDirection,
|
||||
environmentSlugs: environments,
|
||||
environmentSlugs: permissiveEnvs,
|
||||
path: secretPath,
|
||||
limit: remainingLimit,
|
||||
offset: adjustedOffset
|
||||
offset: adjustedOffset,
|
||||
isInternal: true
|
||||
});
|
||||
|
||||
// get the count of unique dynamic secret names to properly adjust remaining limit
|
||||
@ -218,11 +245,12 @@ export const registerDashboardRouter = async (server: FastifyZodProvider) => {
|
||||
actorId: req.permission.id,
|
||||
actor: req.permission.type,
|
||||
actorOrgId: req.permission.orgId,
|
||||
environments,
|
||||
environments: permissiveEnvs,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
projectId,
|
||||
path: secretPath,
|
||||
search
|
||||
search,
|
||||
isInternal: true
|
||||
});
|
||||
|
||||
if (remainingLimit > 0 && totalSecretCount > adjustedOffset) {
|
||||
@ -230,7 +258,7 @@ export const registerDashboardRouter = async (server: FastifyZodProvider) => {
|
||||
actorId: req.permission.id,
|
||||
actor: req.permission.type,
|
||||
actorOrgId: req.permission.orgId,
|
||||
environments,
|
||||
environments: permissiveEnvs,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
projectId,
|
||||
path: secretPath,
|
||||
@ -238,10 +266,11 @@ export const registerDashboardRouter = async (server: FastifyZodProvider) => {
|
||||
orderDirection,
|
||||
search,
|
||||
limit: remainingLimit,
|
||||
offset: adjustedOffset
|
||||
offset: adjustedOffset,
|
||||
isInternal: true
|
||||
});
|
||||
|
||||
for await (const environment of environments) {
|
||||
for await (const environment of permissiveEnvs) {
|
||||
const secretCountFromEnv = secrets.filter((secret) => secret.environment === environment).length;
|
||||
|
||||
if (secretCountFromEnv) {
|
||||
@ -498,56 +527,44 @@ export const registerDashboardRouter = async (server: FastifyZodProvider) => {
|
||||
}
|
||||
}
|
||||
|
||||
if (includeDynamicSecrets) {
|
||||
totalDynamicSecretCount = await server.services.dynamicSecret.getDynamicSecretCount({
|
||||
actor: req.permission.type,
|
||||
actorId: req.permission.id,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
projectId,
|
||||
search,
|
||||
environmentSlug: environment,
|
||||
path: secretPath
|
||||
});
|
||||
|
||||
if (remainingLimit > 0 && totalDynamicSecretCount > adjustedOffset) {
|
||||
dynamicSecrets = await server.services.dynamicSecret.listDynamicSecretsByEnv({
|
||||
try {
|
||||
if (includeDynamicSecrets) {
|
||||
totalDynamicSecretCount = await server.services.dynamicSecret.getDynamicSecretCount({
|
||||
actor: req.permission.type,
|
||||
actorId: req.permission.id,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
projectId,
|
||||
search,
|
||||
orderBy,
|
||||
orderDirection,
|
||||
environmentSlug: environment,
|
||||
path: secretPath,
|
||||
limit: remainingLimit,
|
||||
offset: adjustedOffset
|
||||
path: secretPath
|
||||
});
|
||||
|
||||
remainingLimit -= dynamicSecrets.length;
|
||||
adjustedOffset = 0;
|
||||
} else {
|
||||
adjustedOffset = Math.max(0, adjustedOffset - totalDynamicSecretCount);
|
||||
if (remainingLimit > 0 && totalDynamicSecretCount > adjustedOffset) {
|
||||
dynamicSecrets = await server.services.dynamicSecret.listDynamicSecretsByEnv({
|
||||
actor: req.permission.type,
|
||||
actorId: req.permission.id,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
projectId,
|
||||
search,
|
||||
orderBy,
|
||||
orderDirection,
|
||||
environmentSlug: environment,
|
||||
path: secretPath,
|
||||
limit: remainingLimit,
|
||||
offset: adjustedOffset
|
||||
});
|
||||
|
||||
remainingLimit -= dynamicSecrets.length;
|
||||
adjustedOffset = 0;
|
||||
} else {
|
||||
adjustedOffset = Math.max(0, adjustedOffset - totalDynamicSecretCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (includeSecrets) {
|
||||
totalSecretCount = await server.services.secret.getSecretsCount({
|
||||
actorId: req.permission.id,
|
||||
actor: req.permission.type,
|
||||
actorOrgId: req.permission.orgId,
|
||||
environment,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
projectId,
|
||||
path: secretPath,
|
||||
search,
|
||||
tagSlugs: tags
|
||||
});
|
||||
|
||||
if (remainingLimit > 0 && totalSecretCount > adjustedOffset) {
|
||||
const secretsRaw = await server.services.secret.getSecretsRaw({
|
||||
if (includeSecrets) {
|
||||
totalSecretCount = await server.services.secret.getSecretsCount({
|
||||
actorId: req.permission.id,
|
||||
actor: req.permission.type,
|
||||
actorOrgId: req.permission.orgId,
|
||||
@ -555,44 +572,62 @@ export const registerDashboardRouter = async (server: FastifyZodProvider) => {
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
projectId,
|
||||
path: secretPath,
|
||||
orderBy,
|
||||
orderDirection,
|
||||
search,
|
||||
limit: remainingLimit,
|
||||
offset: adjustedOffset,
|
||||
tagSlugs: tags
|
||||
});
|
||||
|
||||
secrets = secretsRaw.secrets;
|
||||
if (remainingLimit > 0 && totalSecretCount > adjustedOffset) {
|
||||
const secretsRaw = await server.services.secret.getSecretsRaw({
|
||||
actorId: req.permission.id,
|
||||
actor: req.permission.type,
|
||||
actorOrgId: req.permission.orgId,
|
||||
environment,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
projectId,
|
||||
path: secretPath,
|
||||
orderBy,
|
||||
orderDirection,
|
||||
search,
|
||||
limit: remainingLimit,
|
||||
offset: adjustedOffset,
|
||||
tagSlugs: tags
|
||||
});
|
||||
|
||||
await server.services.auditLog.createAuditLog({
|
||||
projectId,
|
||||
...req.auditLogInfo,
|
||||
event: {
|
||||
type: EventType.GET_SECRETS,
|
||||
metadata: {
|
||||
environment,
|
||||
secretPath,
|
||||
numberOfSecrets: secrets.length
|
||||
}
|
||||
}
|
||||
});
|
||||
secrets = secretsRaw.secrets;
|
||||
|
||||
if (getUserAgentType(req.headers["user-agent"]) !== UserAgentType.K8_OPERATOR) {
|
||||
await server.services.telemetry.sendPostHogEvents({
|
||||
event: PostHogEventTypes.SecretPulled,
|
||||
distinctId: getTelemetryDistinctId(req),
|
||||
properties: {
|
||||
numberOfSecrets: secrets.length,
|
||||
workspaceId: projectId,
|
||||
environment,
|
||||
secretPath,
|
||||
channel: getUserAgentType(req.headers["user-agent"]),
|
||||
...req.auditLogInfo
|
||||
await server.services.auditLog.createAuditLog({
|
||||
projectId,
|
||||
...req.auditLogInfo,
|
||||
event: {
|
||||
type: EventType.GET_SECRETS,
|
||||
metadata: {
|
||||
environment,
|
||||
secretPath,
|
||||
numberOfSecrets: secrets.length
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (getUserAgentType(req.headers["user-agent"]) !== UserAgentType.K8_OPERATOR) {
|
||||
await server.services.telemetry.sendPostHogEvents({
|
||||
event: PostHogEventTypes.SecretPulled,
|
||||
distinctId: getTelemetryDistinctId(req),
|
||||
properties: {
|
||||
numberOfSecrets: secrets.length,
|
||||
workspaceId: projectId,
|
||||
environment,
|
||||
secretPath,
|
||||
channel: getUserAgentType(req.headers["user-agent"]),
|
||||
...req.auditLogInfo
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
if (!(error instanceof ForbiddenError)) {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
|
@ -10,7 +10,7 @@ import {
|
||||
} from "@app/db/schemas";
|
||||
import { EventType, UserAgentType } from "@app/ee/services/audit-log/audit-log-types";
|
||||
import { RAW_SECRETS, SECRETS } from "@app/lib/api-docs";
|
||||
import { BadRequestError } from "@app/lib/errors";
|
||||
import { BadRequestError, NotFoundError } from "@app/lib/errors";
|
||||
import { removeTrailingSlash } from "@app/lib/fn";
|
||||
import { secretsLimit, writeLimit } from "@app/server/config/rateLimiter";
|
||||
import { getTelemetryDistinctId } from "@app/server/lib/telemetry";
|
||||
@ -240,7 +240,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
|
||||
actorOrgId: req.permission.orgId
|
||||
});
|
||||
|
||||
if (!workspace) throw new BadRequestError({ message: `No project found with slug ${req.query.workspaceSlug}` });
|
||||
if (!workspace) throw new NotFoundError({ message: `No project found with slug ${req.query.workspaceSlug}` });
|
||||
|
||||
workspaceId = workspace.id;
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ import { z } from "zod";
|
||||
|
||||
import { UsersSchema } from "@app/db/schemas";
|
||||
import { getConfig } from "@app/lib/config/env";
|
||||
import { BadRequestError } from "@app/lib/errors";
|
||||
import { ForbiddenRequestError } from "@app/lib/errors";
|
||||
import { authRateLimit } from "@app/server/config/rateLimiter";
|
||||
import { getServerCfg } from "@app/services/super-admin/super-admin-service";
|
||||
import { PostHogEventTypes } from "@app/services/telemetry/telemetry-types";
|
||||
@ -29,8 +29,8 @@ export const registerSignupRouter = async (server: FastifyZodProvider) => {
|
||||
|
||||
const serverCfg = await getServerCfg();
|
||||
if (!serverCfg.allowSignUp) {
|
||||
throw new BadRequestError({
|
||||
message: "Sign up is disabled"
|
||||
throw new ForbiddenRequestError({
|
||||
message: "Signup's are disabled"
|
||||
});
|
||||
}
|
||||
|
||||
@ -38,7 +38,7 @@ export const registerSignupRouter = async (server: FastifyZodProvider) => {
|
||||
const domain = email.split("@")[1];
|
||||
const allowedDomains = serverCfg.allowedSignUpDomain.split(",").map((e) => e.trim());
|
||||
if (!allowedDomains.includes(domain)) {
|
||||
throw new BadRequestError({
|
||||
throw new ForbiddenRequestError({
|
||||
message: `Email with a domain (@${domain}) is not supported`
|
||||
});
|
||||
}
|
||||
@ -70,13 +70,13 @@ export const registerSignupRouter = async (server: FastifyZodProvider) => {
|
||||
handler: async (req) => {
|
||||
const serverCfg = await getServerCfg();
|
||||
if (!serverCfg.allowSignUp) {
|
||||
throw new BadRequestError({
|
||||
message: "Sign up is disabled"
|
||||
throw new ForbiddenRequestError({
|
||||
message: "Signup's are disabled"
|
||||
});
|
||||
}
|
||||
|
||||
const { token, user } = await server.services.signup.verifyEmailSignup(req.body.email, req.body.code);
|
||||
return { message: "Successfuly verified email", token, user };
|
||||
return { message: "Successfully verified email", token, user };
|
||||
}
|
||||
});
|
||||
|
||||
@ -121,8 +121,8 @@ export const registerSignupRouter = async (server: FastifyZodProvider) => {
|
||||
|
||||
const serverCfg = await getServerCfg();
|
||||
if (!serverCfg.allowSignUp) {
|
||||
throw new BadRequestError({
|
||||
message: "Sign up is disabled"
|
||||
throw new ForbiddenRequestError({
|
||||
message: "Signup's are disabled"
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -4,7 +4,7 @@ import bcrypt from "bcrypt";
|
||||
|
||||
import { TApiKeys } from "@app/db/schemas/api-keys";
|
||||
import { getConfig } from "@app/lib/config/env";
|
||||
import { BadRequestError, UnauthorizedError } from "@app/lib/errors";
|
||||
import { NotFoundError, UnauthorizedError } from "@app/lib/errors";
|
||||
|
||||
import { TUserDALFactory } from "../user/user-dal";
|
||||
import { TApiKeyDALFactory } from "./api-key-dal";
|
||||
@ -45,7 +45,7 @@ export const apiKeyServiceFactory = ({ apiKeyDAL, userDAL }: TApiKeyServiceFacto
|
||||
|
||||
const deleteApiKey = async (userId: string, apiKeyId: string) => {
|
||||
const [apiKeyData] = await apiKeyDAL.delete({ id: apiKeyId, userId });
|
||||
if (!apiKeyData) throw new BadRequestError({ message: "Failed to find api key", name: "delete api key" });
|
||||
if (!apiKeyData) throw new NotFoundError({ message: "API key not found" });
|
||||
return formatApiKey(apiKeyData);
|
||||
};
|
||||
|
||||
|
@ -4,7 +4,7 @@ import bcrypt from "bcrypt";
|
||||
|
||||
import { TAuthTokens, TAuthTokenSessions } from "@app/db/schemas";
|
||||
import { getConfig } from "@app/lib/config/env";
|
||||
import { ForbiddenRequestError, UnauthorizedError } from "@app/lib/errors";
|
||||
import { ForbiddenRequestError, NotFoundError, UnauthorizedError } from "@app/lib/errors";
|
||||
import { TOrgMembershipDALFactory } from "@app/services/org-membership/org-membership-dal";
|
||||
|
||||
import { AuthModeJwtTokenPayload } from "../auth/auth-type";
|
||||
@ -150,11 +150,13 @@ export const tokenServiceFactory = ({ tokenDAL, userDAL, orgMembershipDAL }: TAu
|
||||
id: token.tokenVersionId,
|
||||
userId: token.userId
|
||||
});
|
||||
if (!session) throw new UnauthorizedError({ name: "Session not found" });
|
||||
if (token.accessVersion !== session.accessVersion) throw new UnauthorizedError({ name: "Stale session" });
|
||||
if (!session) throw new NotFoundError({ name: "Session not found" });
|
||||
if (token.accessVersion !== session.accessVersion) {
|
||||
throw new UnauthorizedError({ name: "StaleSession", message: "User session is stale, please re-authenticate" });
|
||||
}
|
||||
|
||||
const user = await userDAL.findById(session.userId);
|
||||
if (!user || !user.isAccepted) throw new UnauthorizedError({ name: "Token user not found" });
|
||||
if (!user || !user.isAccepted) throw new NotFoundError({ message: "User not found" });
|
||||
|
||||
if (token.organizationId) {
|
||||
const orgMembership = await orgMembershipDAL.findOne({
|
||||
@ -162,8 +164,12 @@ export const tokenServiceFactory = ({ tokenDAL, userDAL, orgMembershipDAL }: TAu
|
||||
orgId: token.organizationId
|
||||
});
|
||||
|
||||
if (!orgMembership) throw new ForbiddenRequestError({ message: "User not member of organization" });
|
||||
if (!orgMembership.isActive) throw new ForbiddenRequestError({ message: "User not active in organization" });
|
||||
if (!orgMembership) {
|
||||
throw new ForbiddenRequestError({ message: "User not member of organization" });
|
||||
}
|
||||
if (!orgMembership.isActive) {
|
||||
throw new ForbiddenRequestError({ message: "User organization membership is inactive" });
|
||||
}
|
||||
}
|
||||
|
||||
return { user, tokenVersionId: token.tokenVersionId, orgId: token.organizationId };
|
||||
|
@ -1,7 +1,7 @@
|
||||
import jwt from "jsonwebtoken";
|
||||
|
||||
import { getConfig } from "@app/lib/config/env";
|
||||
import { BadRequestError, UnauthorizedError } from "@app/lib/errors";
|
||||
import { ForbiddenRequestError, UnauthorizedError } from "@app/lib/errors";
|
||||
|
||||
import { AuthModeProviderJwtTokenPayload, AuthModeProviderSignUpTokenPayload, AuthTokenType } from "./auth-type";
|
||||
|
||||
@ -25,15 +25,15 @@ export const validateSignUpAuthorization = (token: string, userId: string, valid
|
||||
const appCfg = getConfig();
|
||||
const [AUTH_TOKEN_TYPE, AUTH_TOKEN_VALUE] = <[string, string]>token?.split(" ", 2) ?? [null, null];
|
||||
if (AUTH_TOKEN_TYPE === null) {
|
||||
throw new BadRequestError({ message: "Missing Authorization Header in the request header." });
|
||||
throw new UnauthorizedError({ message: "Missing Authorization Header in the request header." });
|
||||
}
|
||||
if (AUTH_TOKEN_TYPE.toLowerCase() !== "bearer") {
|
||||
throw new BadRequestError({
|
||||
throw new UnauthorizedError({
|
||||
message: `The provided authentication type '${AUTH_TOKEN_TYPE}' is not supported.`
|
||||
});
|
||||
}
|
||||
if (AUTH_TOKEN_VALUE === null) {
|
||||
throw new BadRequestError({
|
||||
throw new UnauthorizedError({
|
||||
message: "Missing Authorization Body in the request header"
|
||||
});
|
||||
}
|
||||
@ -47,8 +47,8 @@ export const validateSignUpAuthorization = (token: string, userId: string, valid
|
||||
|
||||
export const enforceUserLockStatus = (isLocked: boolean, temporaryLockDateEnd?: Date | null) => {
|
||||
if (isLocked) {
|
||||
throw new UnauthorizedError({
|
||||
name: "User Locked",
|
||||
throw new ForbiddenRequestError({
|
||||
name: "UserLocked",
|
||||
message:
|
||||
"User is locked due to multiple failed login attempts. An email has been sent to you in order to unlock your account. You can also reset your password to unlock your account."
|
||||
});
|
||||
@ -61,8 +61,8 @@ export const enforceUserLockStatus = (isLocked: boolean, temporaryLockDateEnd?:
|
||||
const timeDisplay =
|
||||
secondsDiff > 60 ? `${Math.ceil(secondsDiff / 60)} minutes` : `${Math.ceil(secondsDiff)} seconds`;
|
||||
|
||||
throw new UnauthorizedError({
|
||||
name: "User Locked",
|
||||
throw new ForbiddenRequestError({
|
||||
name: "UserLocked",
|
||||
message: `User is temporary locked due to multiple failed login attempts. Try again after ${timeDisplay}. You can also reset your password now to proceed.`
|
||||
});
|
||||
}
|
||||
|
@ -8,7 +8,7 @@ import { request } from "@app/lib/config/request";
|
||||
import { generateSrpServerKey, srpCheckClientProof } from "@app/lib/crypto";
|
||||
import { infisicalSymmetricEncypt } from "@app/lib/crypto/encryption";
|
||||
import { getUserPrivateKey } from "@app/lib/crypto/srp";
|
||||
import { BadRequestError, DatabaseError, UnauthorizedError } from "@app/lib/errors";
|
||||
import { BadRequestError, DatabaseError, ForbiddenRequestError, UnauthorizedError } from "@app/lib/errors";
|
||||
import { logger } from "@app/lib/logger";
|
||||
import { getServerCfg } from "@app/services/super-admin/super-admin-service";
|
||||
|
||||
@ -350,7 +350,7 @@ export const authLoginServiceFactory = ({
|
||||
const cfg = getConfig();
|
||||
|
||||
if (!authJwtToken) throw new UnauthorizedError({ name: "Authorization header is required" });
|
||||
if (!userAgent) throw new UnauthorizedError({ name: "user agent header is required" });
|
||||
if (!userAgent) throw new UnauthorizedError({ name: "User-Agent header is required" });
|
||||
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
authJwtToken = authJwtToken.replace("Bearer ", ""); // remove bearer from token
|
||||
@ -368,7 +368,7 @@ export const authLoginServiceFactory = ({
|
||||
const selectedOrg = await orgDAL.findById(organizationId);
|
||||
|
||||
if (!hasOrganizationMembership) {
|
||||
throw new UnauthorizedError({
|
||||
throw new ForbiddenRequestError({
|
||||
message: `User does not have access to the organization named ${selectedOrg?.name}`
|
||||
});
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ import { isAuthMethodSaml } from "@app/ee/services/permission/permission-fns";
|
||||
import { getConfig } from "@app/lib/config/env";
|
||||
import { infisicalSymmetricDecrypt, infisicalSymmetricEncypt } from "@app/lib/crypto/encryption";
|
||||
import { generateUserSrpKeys, getUserPrivateKey } from "@app/lib/crypto/srp";
|
||||
import { BadRequestError } from "@app/lib/errors";
|
||||
import { NotFoundError } from "@app/lib/errors";
|
||||
import { isDisposableEmail } from "@app/lib/validator";
|
||||
import { TGroupProjectDALFactory } from "@app/services/group-project/group-project-dal";
|
||||
import { TProjectDALFactory } from "@app/services/project/project-dal";
|
||||
@ -380,7 +380,7 @@ export const authSignupServiceFactory = ({
|
||||
status: OrgMembershipStatus.Invited
|
||||
});
|
||||
if (!orgMembership)
|
||||
throw new BadRequestError({
|
||||
throw new NotFoundError({
|
||||
message: "Failed to find invitation for email",
|
||||
name: "complete account invite"
|
||||
});
|
||||
|
@ -3,7 +3,7 @@ import crypto from "crypto";
|
||||
|
||||
import { getConfig } from "@app/lib/config/env";
|
||||
import { daysToMillisecond, secondsToMillis } from "@app/lib/dates";
|
||||
import { BadRequestError } from "@app/lib/errors";
|
||||
import { NotFoundError } from "@app/lib/errors";
|
||||
import { logger } from "@app/lib/logger";
|
||||
import { QueueJobs, QueueName, TQueueServiceFactory } from "@app/queue";
|
||||
import { TCertificateDALFactory } from "@app/services/certificate/certificate-dal";
|
||||
@ -76,7 +76,7 @@ export const certificateAuthorityQueueFactory = ({
|
||||
logger.info(`secretReminderQueue.process: [secretDocument=${caId}]`);
|
||||
|
||||
const ca = await certificateAuthorityDAL.findById(caId);
|
||||
if (!ca) throw new BadRequestError({ message: "CA not found" });
|
||||
if (!ca) throw new NotFoundError({ message: "CA not found" });
|
||||
|
||||
const caSecret = await certificateAuthoritySecretDAL.findOne({ caId: ca.id });
|
||||
|
||||
|
@ -122,7 +122,7 @@ export const certificateAuthorityServiceFactory = ({
|
||||
actorOrgId
|
||||
}: TCreateCaDTO) => {
|
||||
const project = await projectDAL.findProjectBySlug(projectSlug, actorOrgId);
|
||||
if (!project) throw new BadRequestError({ message: "Project not found" });
|
||||
if (!project) throw new NotFoundError({ message: "Project not found" });
|
||||
|
||||
const { permission } = await permissionService.getProjectPermission(
|
||||
actor,
|
||||
@ -290,7 +290,7 @@ export const certificateAuthorityServiceFactory = ({
|
||||
*/
|
||||
const getCaById = async ({ caId, actorId, actorAuthMethod, actor, actorOrgId }: TGetCaDTO) => {
|
||||
const ca = await certificateAuthorityDAL.findById(caId);
|
||||
if (!ca) throw new BadRequestError({ message: "CA not found" });
|
||||
if (!ca) throw new NotFoundError({ message: "CA not found" });
|
||||
|
||||
const { permission } = await permissionService.getProjectPermission(
|
||||
actor,
|
||||
@ -321,7 +321,7 @@ export const certificateAuthorityServiceFactory = ({
|
||||
actorOrgId
|
||||
}: TUpdateCaDTO) => {
|
||||
const ca = await certificateAuthorityDAL.findById(caId);
|
||||
if (!ca) throw new BadRequestError({ message: "CA not found" });
|
||||
if (!ca) throw new NotFoundError({ message: "CA not found" });
|
||||
|
||||
const { permission } = await permissionService.getProjectPermission(
|
||||
actor,
|
||||
@ -346,7 +346,7 @@ export const certificateAuthorityServiceFactory = ({
|
||||
*/
|
||||
const deleteCaById = async ({ caId, actorId, actorAuthMethod, actor, actorOrgId }: TDeleteCaDTO) => {
|
||||
const ca = await certificateAuthorityDAL.findById(caId);
|
||||
if (!ca) throw new BadRequestError({ message: "CA not found" });
|
||||
if (!ca) throw new NotFoundError({ message: "CA not found" });
|
||||
|
||||
const { permission } = await permissionService.getProjectPermission(
|
||||
actor,
|
||||
@ -371,7 +371,7 @@ export const certificateAuthorityServiceFactory = ({
|
||||
*/
|
||||
const getCaCsr = async ({ caId, actorId, actorAuthMethod, actor, actorOrgId }: TGetCaCsrDTO) => {
|
||||
const ca = await certificateAuthorityDAL.findById(caId);
|
||||
if (!ca) throw new BadRequestError({ message: "CA not found" });
|
||||
if (!ca) throw new NotFoundError({ message: "CA not found" });
|
||||
|
||||
const { permission } = await permissionService.getProjectPermission(
|
||||
actor,
|
||||
@ -430,7 +430,7 @@ export const certificateAuthorityServiceFactory = ({
|
||||
*/
|
||||
const renewCaCert = async ({ caId, notAfter, actorId, actorAuthMethod, actor, actorOrgId }: TRenewCaCertDTO) => {
|
||||
const ca = await certificateAuthorityDAL.findById(caId);
|
||||
if (!ca) throw new BadRequestError({ message: "CA not found" });
|
||||
if (!ca) throw new NotFoundError({ message: "CA not found" });
|
||||
|
||||
if (!ca.activeCaCertId) throw new BadRequestError({ message: "CA does not have a certificate installed" });
|
||||
|
||||
@ -702,7 +702,7 @@ export const certificateAuthorityServiceFactory = ({
|
||||
|
||||
const getCaCerts = async ({ caId, actorId, actorAuthMethod, actor, actorOrgId }: TGetCaCertsDTO) => {
|
||||
const ca = await certificateAuthorityDAL.findById(caId);
|
||||
if (!ca) throw new BadRequestError({ message: "CA not found" });
|
||||
if (!ca) throw new NotFoundError({ message: "CA not found" });
|
||||
|
||||
const { permission } = await permissionService.getProjectPermission(
|
||||
actor,
|
||||
@ -736,7 +736,7 @@ export const certificateAuthorityServiceFactory = ({
|
||||
*/
|
||||
const getCaCert = async ({ caId, actorId, actorAuthMethod, actor, actorOrgId }: TGetCaCertDTO) => {
|
||||
const ca = await certificateAuthorityDAL.findById(caId);
|
||||
if (!ca) throw new BadRequestError({ message: "CA not found" });
|
||||
if (!ca) throw new NotFoundError({ message: "CA not found" });
|
||||
if (!ca.activeCaCertId) throw new BadRequestError({ message: "CA does not have a certificate installed" });
|
||||
|
||||
const { permission } = await permissionService.getProjectPermission(
|
||||
@ -817,7 +817,7 @@ export const certificateAuthorityServiceFactory = ({
|
||||
}: TSignIntermediateDTO) => {
|
||||
const appCfg = getConfig();
|
||||
const ca = await certificateAuthorityDAL.findById(caId);
|
||||
if (!ca) throw new BadRequestError({ message: "CA not found" });
|
||||
if (!ca) throw new NotFoundError({ message: "CA not found" });
|
||||
|
||||
const { permission } = await permissionService.getProjectPermission(
|
||||
actor,
|
||||
@ -963,7 +963,7 @@ export const certificateAuthorityServiceFactory = ({
|
||||
certificateChain
|
||||
}: TImportCertToCaDTO) => {
|
||||
const ca = await certificateAuthorityDAL.findById(caId);
|
||||
if (!ca) throw new BadRequestError({ message: "CA not found" });
|
||||
if (!ca) throw new NotFoundError({ message: "CA not found" });
|
||||
|
||||
const { permission } = await permissionService.getProjectPermission(
|
||||
actor,
|
||||
@ -1124,7 +1124,7 @@ export const certificateAuthorityServiceFactory = ({
|
||||
}
|
||||
|
||||
if (!ca) {
|
||||
throw new BadRequestError({ message: "CA not found" });
|
||||
throw new NotFoundError({ message: "CA not found" });
|
||||
}
|
||||
|
||||
const { permission } = await permissionService.getProjectPermission(
|
||||
@ -1451,7 +1451,7 @@ export const certificateAuthorityServiceFactory = ({
|
||||
}
|
||||
|
||||
if (!ca) {
|
||||
throw new BadRequestError({ message: "CA not found" });
|
||||
throw new NotFoundError({ message: "CA not found" });
|
||||
}
|
||||
|
||||
if (!dto.isInternal) {
|
||||
@ -1810,7 +1810,7 @@ export const certificateAuthorityServiceFactory = ({
|
||||
actorOrgId
|
||||
}: TGetCaCertificateTemplatesDTO) => {
|
||||
const ca = await certificateAuthorityDAL.findById(caId);
|
||||
if (!ca) throw new BadRequestError({ message: "CA not found" });
|
||||
if (!ca) throw new NotFoundError({ message: "CA not found" });
|
||||
|
||||
const { permission } = await permissionService.getProjectPermission(
|
||||
actor,
|
||||
|
@ -66,7 +66,7 @@ export const groupProjectServiceFactory = ({
|
||||
}: TCreateProjectGroupDTO) => {
|
||||
const project = await projectDAL.findById(projectId);
|
||||
|
||||
if (!project) throw new BadRequestError({ 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` });
|
||||
|
||||
const { permission } = await permissionService.getProjectPermission(
|
||||
@ -79,7 +79,7 @@ export const groupProjectServiceFactory = ({
|
||||
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Create, ProjectPermissionSub.Groups);
|
||||
|
||||
const group = await groupDAL.findOne({ orgId: actorOrgId, id: groupId });
|
||||
if (!group) throw new BadRequestError({ message: `Failed to find group with ID ${groupId}` });
|
||||
if (!group) throw new NotFoundError({ message: `Failed to find group with ID ${groupId}` });
|
||||
|
||||
const existingGroup = await groupProjectDAL.findOne({ groupId: group.id, projectId: project.id });
|
||||
if (existingGroup)
|
||||
@ -168,24 +168,24 @@ export const groupProjectServiceFactory = ({
|
||||
const ghostUser = await projectDAL.findProjectGhostUser(project.id, tx);
|
||||
|
||||
if (!ghostUser) {
|
||||
throw new BadRequestError({
|
||||
message: "Failed to find sudo user"
|
||||
throw new NotFoundError({
|
||||
message: "Failed to find project owner"
|
||||
});
|
||||
}
|
||||
|
||||
const ghostUserLatestKey = await projectKeyDAL.findLatestProjectKey(ghostUser.id, project.id, tx);
|
||||
|
||||
if (!ghostUserLatestKey) {
|
||||
throw new BadRequestError({
|
||||
message: "Failed to find sudo user latest key"
|
||||
throw new NotFoundError({
|
||||
message: "Failed to find project owner's latest key"
|
||||
});
|
||||
}
|
||||
|
||||
const bot = await projectBotDAL.findOne({ projectId: project.id }, tx);
|
||||
|
||||
if (!bot) {
|
||||
throw new BadRequestError({
|
||||
message: "Failed to find bot"
|
||||
throw new NotFoundError({
|
||||
message: "Failed to find project bot"
|
||||
});
|
||||
}
|
||||
|
||||
@ -235,7 +235,7 @@ export const groupProjectServiceFactory = ({
|
||||
}: TUpdateProjectGroupDTO) => {
|
||||
const project = await projectDAL.findById(projectId);
|
||||
|
||||
if (!project) throw new BadRequestError({ 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(
|
||||
actor,
|
||||
@ -247,10 +247,10 @@ export const groupProjectServiceFactory = ({
|
||||
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.Groups);
|
||||
|
||||
const group = await groupDAL.findOne({ orgId: actorOrgId, id: groupId });
|
||||
if (!group) throw new BadRequestError({ message: `Failed to find group with ID ${groupId}` });
|
||||
if (!group) throw new NotFoundError({ message: `Failed to find group with ID ${groupId}` });
|
||||
|
||||
const projectGroup = await groupProjectDAL.findOne({ groupId: group.id, projectId: project.id });
|
||||
if (!projectGroup) throw new BadRequestError({ message: `Failed to find group with ID ${groupId}` });
|
||||
if (!projectGroup) throw new NotFoundError({ message: `Failed to find group with ID ${groupId}` });
|
||||
|
||||
for await (const { role: requestedRoleChange } of roles) {
|
||||
const { permission: rolePermission } = await permissionService.getProjectPermissionByRole(
|
||||
@ -331,13 +331,13 @@ export const groupProjectServiceFactory = ({
|
||||
}: TDeleteProjectGroupDTO) => {
|
||||
const project = await projectDAL.findById(projectId);
|
||||
|
||||
if (!project) throw new BadRequestError({ message: `Failed to find project with ID ${projectId}` });
|
||||
if (!project) throw new NotFoundError({ message: `Failed to find project with ID ${projectId}` });
|
||||
|
||||
const group = await groupDAL.findOne({ orgId: actorOrgId, id: groupId });
|
||||
if (!group) throw new BadRequestError({ message: `Failed to find group with ID ${groupId}` });
|
||||
if (!group) throw new NotFoundError({ message: `Failed to find group with ID ${groupId}` });
|
||||
|
||||
const groupProjectMembership = await groupProjectDAL.findOne({ groupId: group.id, projectId: project.id });
|
||||
if (!groupProjectMembership) throw new BadRequestError({ message: `Failed to find group with ID ${groupId}` });
|
||||
if (!groupProjectMembership) throw new NotFoundError({ message: `Failed to find group with ID ${groupId}` });
|
||||
|
||||
const { permission } = await permissionService.getProjectPermission(
|
||||
actor,
|
||||
@ -380,7 +380,7 @@ export const groupProjectServiceFactory = ({
|
||||
const project = await projectDAL.findById(projectId);
|
||||
|
||||
if (!project) {
|
||||
throw new BadRequestError({ message: `Failed to find project with ID ${projectId}` });
|
||||
throw new NotFoundError({ message: `Failed to find project with ID ${projectId}` });
|
||||
}
|
||||
|
||||
const { permission } = await permissionService.getProjectPermission(
|
||||
|
@ -39,7 +39,7 @@ export const identityAccessTokenServiceFactory = ({
|
||||
|
||||
if (accessTokenNumUsesLimit > 0 && accessTokenNumUses > 0 && accessTokenNumUses >= accessTokenNumUsesLimit) {
|
||||
await identityAccessTokenDAL.deleteById(tokenId);
|
||||
throw new BadRequestError({
|
||||
throw new UnauthorizedError({
|
||||
message: "Unable to renew because access token number of uses limit reached"
|
||||
});
|
||||
}
|
||||
@ -81,13 +81,15 @@ export const identityAccessTokenServiceFactory = ({
|
||||
const decodedToken = jwt.verify(accessToken, appCfg.AUTH_SECRET) as JwtPayload & {
|
||||
identityAccessTokenId: string;
|
||||
};
|
||||
if (decodedToken.authTokenType !== AuthTokenType.IDENTITY_ACCESS_TOKEN) throw new UnauthorizedError();
|
||||
if (decodedToken.authTokenType !== AuthTokenType.IDENTITY_ACCESS_TOKEN) {
|
||||
throw new BadRequestError({ message: "Only identity access tokens can be renewed" });
|
||||
}
|
||||
|
||||
const identityAccessToken = await identityAccessTokenDAL.findOne({
|
||||
[`${TableName.IdentityAccessToken}.id` as "id"]: decodedToken.identityAccessTokenId,
|
||||
isAccessTokenRevoked: false
|
||||
});
|
||||
if (!identityAccessToken) throw new UnauthorizedError();
|
||||
if (!identityAccessToken) throw new UnauthorizedError({ message: "No identity access token found" });
|
||||
|
||||
let { accessTokenNumUses } = identityAccessToken;
|
||||
const tokenStatusInCache = await accessTokenQueue.getIdentityTokenDetailsInCache(identityAccessToken.id);
|
||||
@ -134,13 +136,15 @@ export const identityAccessTokenServiceFactory = ({
|
||||
const decodedToken = jwt.verify(accessToken, appCfg.AUTH_SECRET) as JwtPayload & {
|
||||
identityAccessTokenId: string;
|
||||
};
|
||||
if (decodedToken.authTokenType !== AuthTokenType.IDENTITY_ACCESS_TOKEN) throw new UnauthorizedError();
|
||||
if (decodedToken.authTokenType !== AuthTokenType.IDENTITY_ACCESS_TOKEN) {
|
||||
throw new UnauthorizedError({ message: "Only identity access tokens can be revoked" });
|
||||
}
|
||||
|
||||
const identityAccessToken = await identityAccessTokenDAL.findOne({
|
||||
[`${TableName.IdentityAccessToken}.id` as "id"]: decodedToken.identityAccessTokenId,
|
||||
isAccessTokenRevoked: false
|
||||
});
|
||||
if (!identityAccessToken) throw new UnauthorizedError();
|
||||
if (!identityAccessToken) throw new UnauthorizedError({ message: "No identity access token found" });
|
||||
|
||||
const revokedToken = await identityAccessTokenDAL.updateById(identityAccessToken.id, {
|
||||
isAccessTokenRevoked: true
|
||||
@ -154,10 +158,10 @@ export const identityAccessTokenServiceFactory = ({
|
||||
[`${TableName.IdentityAccessToken}.id` as "id"]: token.identityAccessTokenId,
|
||||
isAccessTokenRevoked: false
|
||||
});
|
||||
if (!identityAccessToken) throw new UnauthorizedError();
|
||||
if (!identityAccessToken) throw new UnauthorizedError({ message: "No identity access token found" });
|
||||
if (identityAccessToken.isAccessTokenRevoked)
|
||||
throw new UnauthorizedError({
|
||||
message: "Failed to authorize revoked access token"
|
||||
message: "Failed to authorize revoked access token, access token is revoked"
|
||||
});
|
||||
|
||||
if (ipAddress && identityAccessToken) {
|
||||
@ -172,7 +176,7 @@ export const identityAccessTokenServiceFactory = ({
|
||||
});
|
||||
|
||||
if (!identityOrgMembership) {
|
||||
throw new UnauthorizedError({ message: "Identity does not belong to any organization" });
|
||||
throw new BadRequestError({ message: "Identity does not belong to any organization" });
|
||||
}
|
||||
|
||||
let { accessTokenNumUses } = identityAccessToken;
|
||||
|
@ -9,7 +9,7 @@ import { OrgPermissionActions, OrgPermissionSubjects } from "@app/ee/services/pe
|
||||
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service";
|
||||
import { isAtLeastAsPrivileged } from "@app/lib/casl";
|
||||
import { getConfig } from "@app/lib/config/env";
|
||||
import { BadRequestError, ForbiddenRequestError, UnauthorizedError } from "@app/lib/errors";
|
||||
import { BadRequestError, ForbiddenRequestError, NotFoundError, UnauthorizedError } from "@app/lib/errors";
|
||||
import { extractIPDetails, isValidIpOrCidr } from "@app/lib/ip";
|
||||
|
||||
import { ActorType, AuthTokenType } from "../auth/auth-type";
|
||||
@ -50,7 +50,9 @@ export const identityAwsAuthServiceFactory = ({
|
||||
}: TIdentityAwsAuthServiceFactoryDep) => {
|
||||
const login = async ({ identityId, iamHttpRequestMethod, iamRequestBody, iamRequestHeaders }: TLoginAwsAuthDTO) => {
|
||||
const identityAwsAuth = await identityAwsAuthDAL.findOne({ identityId });
|
||||
if (!identityAwsAuth) throw new UnauthorizedError();
|
||||
if (!identityAwsAuth) {
|
||||
throw new NotFoundError({ message: "AWS auth method not found for identity, did you configure AWS auth?" });
|
||||
}
|
||||
|
||||
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId: identityAwsAuth.identityId });
|
||||
|
||||
@ -79,7 +81,7 @@ export const identityAwsAuthServiceFactory = ({
|
||||
.some((accountId) => accountId === Account);
|
||||
|
||||
if (!isAccountAllowed)
|
||||
throw new ForbiddenRequestError({
|
||||
throw new UnauthorizedError({
|
||||
message: "Access denied: AWS account ID not allowed."
|
||||
});
|
||||
}
|
||||
@ -98,7 +100,7 @@ export const identityAwsAuthServiceFactory = ({
|
||||
});
|
||||
|
||||
if (!isArnAllowed)
|
||||
throw new ForbiddenRequestError({
|
||||
throw new UnauthorizedError({
|
||||
message: "Access denied: AWS principal ARN not allowed."
|
||||
});
|
||||
}
|
||||
@ -152,7 +154,7 @@ export const identityAwsAuthServiceFactory = ({
|
||||
actorOrgId
|
||||
}: TAttachAwsAuthDTO) => {
|
||||
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
|
||||
if (!identityMembershipOrg) throw new BadRequestError({ message: "Failed to find identity" });
|
||||
if (!identityMembershipOrg) throw new NotFoundError({ message: "Failed to find identity" });
|
||||
if (identityMembershipOrg.identity.authMethod)
|
||||
throw new BadRequestError({
|
||||
message: "Failed to add AWS Auth to already configured identity"
|
||||
@ -231,7 +233,7 @@ export const identityAwsAuthServiceFactory = ({
|
||||
actorOrgId
|
||||
}: TUpdateAwsAuthDTO) => {
|
||||
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
|
||||
if (!identityMembershipOrg) throw new BadRequestError({ message: "Failed to find identity" });
|
||||
if (!identityMembershipOrg) throw new NotFoundError({ message: "Failed to find identity" });
|
||||
if (identityMembershipOrg.identity?.authMethod !== IdentityAuthMethod.AWS_AUTH)
|
||||
throw new BadRequestError({
|
||||
message: "Failed to update AWS Auth"
|
||||
@ -290,7 +292,7 @@ export const identityAwsAuthServiceFactory = ({
|
||||
|
||||
const getAwsAuth = async ({ identityId, actorId, actor, actorAuthMethod, actorOrgId }: TGetAwsAuthDTO) => {
|
||||
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
|
||||
if (!identityMembershipOrg) throw new BadRequestError({ message: "Failed to find identity" });
|
||||
if (!identityMembershipOrg) throw new NotFoundError({ message: "Failed to find identity" });
|
||||
if (identityMembershipOrg.identity?.authMethod !== IdentityAuthMethod.AWS_AUTH)
|
||||
throw new BadRequestError({
|
||||
message: "The identity does not have AWS Auth attached"
|
||||
@ -317,7 +319,7 @@ export const identityAwsAuthServiceFactory = ({
|
||||
actorOrgId
|
||||
}: TRevokeAwsAuthDTO) => {
|
||||
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
|
||||
if (!identityMembershipOrg) throw new BadRequestError({ message: "Failed to find identity" });
|
||||
if (!identityMembershipOrg) throw new NotFoundError({ message: "Failed to find identity" });
|
||||
if (identityMembershipOrg.identity?.authMethod !== IdentityAuthMethod.AWS_AUTH)
|
||||
throw new BadRequestError({
|
||||
message: "The identity does not have aws auth"
|
||||
@ -338,8 +340,8 @@ export const identityAwsAuthServiceFactory = ({
|
||||
actorAuthMethod,
|
||||
actorOrgId
|
||||
);
|
||||
const hasPriviledge = isAtLeastAsPrivileged(permission, rolePermission);
|
||||
if (!hasPriviledge)
|
||||
|
||||
if (!isAtLeastAsPrivileged(permission, rolePermission))
|
||||
throw new ForbiddenRequestError({
|
||||
message: "Failed to revoke aws auth of identity with more privileged role"
|
||||
});
|
||||
|
@ -24,7 +24,7 @@ export const validateAzureIdentity = async ({
|
||||
const signingKeys = data.keys;
|
||||
|
||||
const signingKey = signingKeys.find((key) => key.kid === kid);
|
||||
if (!signingKey) throw new UnauthorizedError();
|
||||
if (!signingKey) throw new UnauthorizedError({ message: "Invalid signing key" });
|
||||
|
||||
const publicKey = `-----BEGIN CERTIFICATE-----\n${signingKey.x5c[0]}\n-----END CERTIFICATE-----`;
|
||||
|
||||
|
@ -7,7 +7,7 @@ import { OrgPermissionActions, OrgPermissionSubjects } from "@app/ee/services/pe
|
||||
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service";
|
||||
import { isAtLeastAsPrivileged } from "@app/lib/casl";
|
||||
import { getConfig } from "@app/lib/config/env";
|
||||
import { BadRequestError, ForbiddenRequestError, UnauthorizedError } from "@app/lib/errors";
|
||||
import { BadRequestError, ForbiddenRequestError, NotFoundError, UnauthorizedError } from "@app/lib/errors";
|
||||
import { extractIPDetails, isValidIpOrCidr } from "@app/lib/ip";
|
||||
|
||||
import { ActorType, AuthTokenType } from "../auth/auth-type";
|
||||
@ -49,10 +49,12 @@ export const identityAzureAuthServiceFactory = ({
|
||||
}: TIdentityAzureAuthServiceFactoryDep) => {
|
||||
const login = async ({ identityId, jwt: azureJwt }: TLoginAzureAuthDTO) => {
|
||||
const identityAzureAuth = await identityAzureAuthDAL.findOne({ identityId });
|
||||
if (!identityAzureAuth) throw new UnauthorizedError();
|
||||
if (!identityAzureAuth) {
|
||||
throw new NotFoundError({ message: "Azure auth method not found for identity, did you configure Azure Auth?" });
|
||||
}
|
||||
|
||||
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId: identityAzureAuth.identityId });
|
||||
if (!identityMembershipOrg) throw new UnauthorizedError();
|
||||
if (!identityMembershipOrg) throw new UnauthorizedError({ message: "Identity not attached to a organization" });
|
||||
|
||||
const azureIdentity = await validateAzureIdentity({
|
||||
tenantId: identityAzureAuth.tenantId,
|
||||
@ -60,7 +62,8 @@ export const identityAzureAuthServiceFactory = ({
|
||||
jwt: azureJwt
|
||||
});
|
||||
|
||||
if (azureIdentity.tid !== identityAzureAuth.tenantId) throw new UnauthorizedError();
|
||||
if (azureIdentity.tid !== identityAzureAuth.tenantId)
|
||||
throw new UnauthorizedError({ message: "Tenant ID mismatch" });
|
||||
|
||||
if (identityAzureAuth.allowedServicePrincipalIds) {
|
||||
// validate if the service principal id is in the list of allowed service principal ids
|
||||
@ -70,7 +73,7 @@ export const identityAzureAuthServiceFactory = ({
|
||||
.map((servicePrincipalId) => servicePrincipalId.trim())
|
||||
.some((servicePrincipalId) => servicePrincipalId === azureIdentity.oid);
|
||||
|
||||
if (!isServicePrincipalAllowed) throw new UnauthorizedError();
|
||||
if (!isServicePrincipalAllowed) throw new UnauthorizedError({ message: "Service principal not allowed" });
|
||||
}
|
||||
|
||||
const identityAccessToken = await identityAzureAuthDAL.transaction(async (tx) => {
|
||||
@ -122,7 +125,7 @@ export const identityAzureAuthServiceFactory = ({
|
||||
actorOrgId
|
||||
}: TAttachAzureAuthDTO) => {
|
||||
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
|
||||
if (!identityMembershipOrg) throw new BadRequestError({ message: "Failed to find identity" });
|
||||
if (!identityMembershipOrg) throw new NotFoundError({ message: "Failed to find identity" });
|
||||
if (identityMembershipOrg.identity.authMethod)
|
||||
throw new BadRequestError({
|
||||
message: "Failed to add Azure Auth to already configured identity"
|
||||
@ -200,7 +203,7 @@ export const identityAzureAuthServiceFactory = ({
|
||||
actorOrgId
|
||||
}: TUpdateAzureAuthDTO) => {
|
||||
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
|
||||
if (!identityMembershipOrg) throw new BadRequestError({ message: "Failed to find identity" });
|
||||
if (!identityMembershipOrg) throw new NotFoundError({ message: "Failed to find identity" });
|
||||
if (identityMembershipOrg.identity?.authMethod !== IdentityAuthMethod.AZURE_AUTH)
|
||||
throw new BadRequestError({
|
||||
message: "Failed to update Azure Auth"
|
||||
@ -262,7 +265,7 @@ export const identityAzureAuthServiceFactory = ({
|
||||
|
||||
const getAzureAuth = async ({ identityId, actorId, actor, actorAuthMethod, actorOrgId }: TGetAzureAuthDTO) => {
|
||||
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
|
||||
if (!identityMembershipOrg) throw new BadRequestError({ message: "Failed to find identity" });
|
||||
if (!identityMembershipOrg) throw new NotFoundError({ message: "Failed to find identity" });
|
||||
if (identityMembershipOrg.identity?.authMethod !== IdentityAuthMethod.AZURE_AUTH)
|
||||
throw new BadRequestError({
|
||||
message: "The identity does not have Azure Auth attached"
|
||||
@ -290,7 +293,7 @@ export const identityAzureAuthServiceFactory = ({
|
||||
actorOrgId
|
||||
}: TRevokeAzureAuthDTO) => {
|
||||
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
|
||||
if (!identityMembershipOrg) throw new BadRequestError({ message: "Failed to find identity" });
|
||||
if (!identityMembershipOrg) throw new NotFoundError({ message: "Failed to find identity" });
|
||||
if (identityMembershipOrg.identity?.authMethod !== IdentityAuthMethod.AZURE_AUTH)
|
||||
throw new BadRequestError({
|
||||
message: "The identity does not have azure auth"
|
||||
@ -311,8 +314,7 @@ export const identityAzureAuthServiceFactory = ({
|
||||
actorAuthMethod,
|
||||
actorOrgId
|
||||
);
|
||||
const hasPriviledge = isAtLeastAsPrivileged(permission, rolePermission);
|
||||
if (!hasPriviledge)
|
||||
if (!isAtLeastAsPrivileged(permission, rolePermission))
|
||||
throw new ForbiddenRequestError({
|
||||
message: "Failed to revoke azure auth of identity with more privileged role"
|
||||
});
|
||||
|
@ -65,6 +65,6 @@ export const validateIamIdentity = async ({
|
||||
algorithms: ["RS256"]
|
||||
});
|
||||
|
||||
if (aud !== identityId) throw new UnauthorizedError();
|
||||
if (aud !== identityId) throw new UnauthorizedError({ message: "Invalid audience in GCP IAM Token" });
|
||||
return { email: sub };
|
||||
};
|
||||
|
@ -7,7 +7,7 @@ import { OrgPermissionActions, OrgPermissionSubjects } from "@app/ee/services/pe
|
||||
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service";
|
||||
import { isAtLeastAsPrivileged } from "@app/lib/casl";
|
||||
import { getConfig } from "@app/lib/config/env";
|
||||
import { BadRequestError, ForbiddenRequestError, UnauthorizedError } from "@app/lib/errors";
|
||||
import { BadRequestError, ForbiddenRequestError, NotFoundError, UnauthorizedError } from "@app/lib/errors";
|
||||
import { extractIPDetails, isValidIpOrCidr } from "@app/lib/ip";
|
||||
|
||||
import { ActorType, AuthTokenType } from "../auth/auth-type";
|
||||
@ -47,10 +47,14 @@ export const identityGcpAuthServiceFactory = ({
|
||||
}: TIdentityGcpAuthServiceFactoryDep) => {
|
||||
const login = async ({ identityId, jwt: gcpJwt }: TLoginGcpAuthDTO) => {
|
||||
const identityGcpAuth = await identityGcpAuthDAL.findOne({ identityId });
|
||||
if (!identityGcpAuth) throw new UnauthorizedError();
|
||||
if (!identityGcpAuth) {
|
||||
throw new NotFoundError({ message: "GCP auth method not found for identity, did you configure GCP auth?" });
|
||||
}
|
||||
|
||||
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId: identityGcpAuth.identityId });
|
||||
if (!identityMembershipOrg) throw new UnauthorizedError();
|
||||
if (!identityMembershipOrg) {
|
||||
throw new UnauthorizedError({ message: "Identity does not belong to any organization" });
|
||||
}
|
||||
|
||||
let gcpIdentityDetails: TGcpIdentityDetails;
|
||||
switch (identityGcpAuth.type) {
|
||||
@ -82,7 +86,7 @@ export const identityGcpAuthServiceFactory = ({
|
||||
.some((serviceAccount) => serviceAccount === gcpIdentityDetails.email);
|
||||
|
||||
if (!isServiceAccountAllowed)
|
||||
throw new ForbiddenRequestError({
|
||||
throw new UnauthorizedError({
|
||||
message: "Access denied: GCP service account not allowed."
|
||||
});
|
||||
}
|
||||
@ -96,7 +100,7 @@ export const identityGcpAuthServiceFactory = ({
|
||||
.some((project) => project === gcpIdentityDetails.computeEngineDetails?.project_id);
|
||||
|
||||
if (!isProjectAllowed)
|
||||
throw new ForbiddenRequestError({
|
||||
throw new UnauthorizedError({
|
||||
message: "Access denied: GCP project not allowed."
|
||||
});
|
||||
}
|
||||
@ -108,7 +112,7 @@ export const identityGcpAuthServiceFactory = ({
|
||||
.some((zone) => zone === gcpIdentityDetails.computeEngineDetails?.zone);
|
||||
|
||||
if (!isZoneAllowed)
|
||||
throw new ForbiddenRequestError({
|
||||
throw new UnauthorizedError({
|
||||
message: "Access denied: GCP zone not allowed."
|
||||
});
|
||||
}
|
||||
@ -163,7 +167,7 @@ export const identityGcpAuthServiceFactory = ({
|
||||
actorOrgId
|
||||
}: TAttachGcpAuthDTO) => {
|
||||
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
|
||||
if (!identityMembershipOrg) throw new BadRequestError({ message: "Failed to find identity" });
|
||||
if (!identityMembershipOrg) throw new NotFoundError({ message: "Failed to find identity" });
|
||||
if (identityMembershipOrg.identity.authMethod)
|
||||
throw new BadRequestError({
|
||||
message: "Failed to add GCP Auth to already configured identity"
|
||||
@ -243,7 +247,7 @@ export const identityGcpAuthServiceFactory = ({
|
||||
actorOrgId
|
||||
}: TUpdateGcpAuthDTO) => {
|
||||
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
|
||||
if (!identityMembershipOrg) throw new BadRequestError({ message: "Failed to find identity" });
|
||||
if (!identityMembershipOrg) throw new NotFoundError({ message: "Failed to find identity" });
|
||||
if (identityMembershipOrg.identity?.authMethod !== IdentityAuthMethod.GCP_AUTH)
|
||||
throw new BadRequestError({
|
||||
message: "Failed to update GCP Auth"
|
||||
@ -306,7 +310,7 @@ export const identityGcpAuthServiceFactory = ({
|
||||
|
||||
const getGcpAuth = async ({ identityId, actorId, actor, actorAuthMethod, actorOrgId }: TGetGcpAuthDTO) => {
|
||||
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
|
||||
if (!identityMembershipOrg) throw new BadRequestError({ message: "Failed to find identity" });
|
||||
if (!identityMembershipOrg) throw new NotFoundError({ message: "Failed to find identity" });
|
||||
if (identityMembershipOrg.identity?.authMethod !== IdentityAuthMethod.GCP_AUTH)
|
||||
throw new BadRequestError({
|
||||
message: "The identity does not have GCP Auth attached"
|
||||
@ -334,7 +338,7 @@ export const identityGcpAuthServiceFactory = ({
|
||||
actorOrgId
|
||||
}: TRevokeGcpAuthDTO) => {
|
||||
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
|
||||
if (!identityMembershipOrg) throw new BadRequestError({ message: "Failed to find identity" });
|
||||
if (!identityMembershipOrg) throw new NotFoundError({ message: "Failed to find identity" });
|
||||
if (identityMembershipOrg.identity?.authMethod !== IdentityAuthMethod.GCP_AUTH)
|
||||
throw new BadRequestError({
|
||||
message: "The identity does not have gcp auth"
|
||||
@ -355,8 +359,7 @@ export const identityGcpAuthServiceFactory = ({
|
||||
actorAuthMethod,
|
||||
actorOrgId
|
||||
);
|
||||
const hasPriviledge = isAtLeastAsPrivileged(permission, rolePermission);
|
||||
if (!hasPriviledge)
|
||||
if (!isAtLeastAsPrivileged(permission, rolePermission))
|
||||
throw new ForbiddenRequestError({
|
||||
message: "Failed to revoke gcp auth of identity with more privileged role"
|
||||
});
|
||||
|
@ -17,7 +17,7 @@ import {
|
||||
infisicalSymmetricDecrypt,
|
||||
infisicalSymmetricEncypt
|
||||
} from "@app/lib/crypto/encryption";
|
||||
import { BadRequestError, ForbiddenRequestError, UnauthorizedError } from "@app/lib/errors";
|
||||
import { BadRequestError, ForbiddenRequestError, NotFoundError, UnauthorizedError } from "@app/lib/errors";
|
||||
import { extractIPDetails, isValidIpOrCidr } from "@app/lib/ip";
|
||||
import { TOrgBotDALFactory } from "@app/services/org/org-bot-dal";
|
||||
|
||||
@ -63,15 +63,19 @@ export const identityKubernetesAuthServiceFactory = ({
|
||||
}: TIdentityKubernetesAuthServiceFactoryDep) => {
|
||||
const login = async ({ identityId, jwt: serviceAccountJwt }: TLoginKubernetesAuthDTO) => {
|
||||
const identityKubernetesAuth = await identityKubernetesAuthDAL.findOne({ identityId });
|
||||
if (!identityKubernetesAuth) throw new UnauthorizedError();
|
||||
if (!identityKubernetesAuth) {
|
||||
throw new NotFoundError({
|
||||
message: "Kubernetes auth method not found for identity, did you configure Kubernetes auth?"
|
||||
});
|
||||
}
|
||||
|
||||
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({
|
||||
identityId: identityKubernetesAuth.identityId
|
||||
});
|
||||
if (!identityMembershipOrg) throw new BadRequestError({ message: "Failed to find identity" });
|
||||
if (!identityMembershipOrg) throw new NotFoundError({ message: "Identity organization membership not found" });
|
||||
|
||||
const orgBot = await orgBotDAL.findOne({ orgId: identityMembershipOrg.orgId });
|
||||
if (!orgBot) throw new BadRequestError({ message: "Org bot not found", name: "OrgBotNotFound" });
|
||||
if (!orgBot) throw new NotFoundError({ message: "Organization bot not found", name: "OrgBotNotFound" });
|
||||
|
||||
const key = infisicalSymmetricDecrypt({
|
||||
ciphertext: orgBot.encryptedSymmetricKey,
|
||||
@ -127,7 +131,8 @@ export const identityKubernetesAuthServiceFactory = ({
|
||||
if ("error" in data.status) throw new UnauthorizedError({ message: data.status.error });
|
||||
|
||||
// check the response to determine if the token is valid
|
||||
if (!(data.status && data.status.authenticated)) throw new UnauthorizedError();
|
||||
if (!(data.status && data.status.authenticated))
|
||||
throw new UnauthorizedError({ message: "Kubernetes token not authenticated" });
|
||||
|
||||
const { namespace: targetNamespace, name: targetName } = extractK8sUsername(data.status.user.username);
|
||||
|
||||
@ -140,7 +145,7 @@ export const identityKubernetesAuthServiceFactory = ({
|
||||
.some((namespace) => namespace === targetNamespace);
|
||||
|
||||
if (!isNamespaceAllowed)
|
||||
throw new ForbiddenRequestError({
|
||||
throw new UnauthorizedError({
|
||||
message: "Access denied: K8s namespace not allowed."
|
||||
});
|
||||
}
|
||||
@ -154,7 +159,7 @@ export const identityKubernetesAuthServiceFactory = ({
|
||||
.some((name) => name === targetName);
|
||||
|
||||
if (!isNameAllowed)
|
||||
throw new ForbiddenRequestError({
|
||||
throw new UnauthorizedError({
|
||||
message: "Access denied: K8s name not allowed."
|
||||
});
|
||||
}
|
||||
@ -166,7 +171,7 @@ export const identityKubernetesAuthServiceFactory = ({
|
||||
);
|
||||
|
||||
if (!isAudienceAllowed)
|
||||
throw new ForbiddenRequestError({
|
||||
throw new UnauthorizedError({
|
||||
message: "Access denied: K8s audience not allowed."
|
||||
});
|
||||
}
|
||||
@ -223,7 +228,7 @@ export const identityKubernetesAuthServiceFactory = ({
|
||||
actorOrgId
|
||||
}: TAttachKubernetesAuthDTO) => {
|
||||
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
|
||||
if (!identityMembershipOrg) throw new BadRequestError({ message: "Failed to find identity" });
|
||||
if (!identityMembershipOrg) throw new NotFoundError({ message: "Failed to find identity" });
|
||||
if (identityMembershipOrg.identity.authMethod)
|
||||
throw new BadRequestError({
|
||||
message: "Failed to add Kubernetes Auth to already configured identity"
|
||||
@ -367,7 +372,7 @@ export const identityKubernetesAuthServiceFactory = ({
|
||||
actorOrgId
|
||||
}: TUpdateKubernetesAuthDTO) => {
|
||||
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
|
||||
if (!identityMembershipOrg) throw new BadRequestError({ message: "Failed to find identity" });
|
||||
if (!identityMembershipOrg) throw new NotFoundError({ message: "Failed to find identity" });
|
||||
if (identityMembershipOrg.identity?.authMethod !== IdentityAuthMethod.KUBERNETES_AUTH)
|
||||
throw new BadRequestError({
|
||||
message: "Failed to update Kubernetes Auth"
|
||||
@ -424,7 +429,7 @@ export const identityKubernetesAuthServiceFactory = ({
|
||||
};
|
||||
|
||||
const orgBot = await orgBotDAL.findOne({ orgId: identityMembershipOrg.orgId });
|
||||
if (!orgBot) throw new BadRequestError({ message: "Org bot not found", name: "OrgBotNotFound" });
|
||||
if (!orgBot) throw new NotFoundError({ message: "Org bot not found", name: "OrgBotNotFound" });
|
||||
|
||||
const key = infisicalSymmetricDecrypt({
|
||||
ciphertext: orgBot.encryptedSymmetricKey,
|
||||
@ -491,7 +496,7 @@ export const identityKubernetesAuthServiceFactory = ({
|
||||
actorOrgId
|
||||
}: TGetKubernetesAuthDTO) => {
|
||||
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
|
||||
if (!identityMembershipOrg) throw new BadRequestError({ message: "Failed to find identity" });
|
||||
if (!identityMembershipOrg) throw new NotFoundError({ message: "Failed to find identity" });
|
||||
if (identityMembershipOrg.identity?.authMethod !== IdentityAuthMethod.KUBERNETES_AUTH)
|
||||
throw new BadRequestError({
|
||||
message: "The identity does not have Kubernetes Auth attached"
|
||||
@ -509,7 +514,7 @@ export const identityKubernetesAuthServiceFactory = ({
|
||||
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Identity);
|
||||
|
||||
const orgBot = await orgBotDAL.findOne({ orgId: identityMembershipOrg.orgId });
|
||||
if (!orgBot) throw new BadRequestError({ message: "Org bot not found", name: "OrgBotNotFound" });
|
||||
if (!orgBot) throw new NotFoundError({ message: "Organization bot not found", name: "OrgBotNotFound" });
|
||||
|
||||
const key = infisicalSymmetricDecrypt({
|
||||
ciphertext: orgBot.encryptedSymmetricKey,
|
||||
@ -552,10 +557,10 @@ export const identityKubernetesAuthServiceFactory = ({
|
||||
actorOrgId
|
||||
}: TRevokeKubernetesAuthDTO) => {
|
||||
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
|
||||
if (!identityMembershipOrg) throw new BadRequestError({ message: "Failed to find identity" });
|
||||
if (!identityMembershipOrg) throw new NotFoundError({ message: "Failed to find identity" });
|
||||
if (identityMembershipOrg.identity?.authMethod !== IdentityAuthMethod.KUBERNETES_AUTH)
|
||||
throw new BadRequestError({
|
||||
message: "The identity does not have kubenetes auth"
|
||||
message: "The identity does not have kubernetes auth"
|
||||
});
|
||||
const { permission } = await permissionService.getOrgPermission(
|
||||
actor,
|
||||
@ -573,10 +578,9 @@ export const identityKubernetesAuthServiceFactory = ({
|
||||
actorAuthMethod,
|
||||
actorOrgId
|
||||
);
|
||||
const hasPriviledge = isAtLeastAsPrivileged(permission, rolePermission);
|
||||
if (!hasPriviledge)
|
||||
if (!isAtLeastAsPrivileged(permission, rolePermission))
|
||||
throw new ForbiddenRequestError({
|
||||
message: "Failed to revoke kubenetes auth of identity with more privileged role"
|
||||
message: "Failed to revoke kubernetes auth of identity with more privileged role"
|
||||
});
|
||||
|
||||
const revokedIdentityKubernetesAuth = await identityKubernetesAuthDAL.transaction(async (tx) => {
|
||||
|
@ -61,19 +61,19 @@ export const identityOidcAuthServiceFactory = ({
|
||||
const login = async ({ identityId, jwt: oidcJwt }: TLoginOidcAuthDTO) => {
|
||||
const identityOidcAuth = await identityOidcAuthDAL.findOne({ identityId });
|
||||
if (!identityOidcAuth) {
|
||||
throw new UnauthorizedError();
|
||||
throw new NotFoundError({ message: "GCP auth method not found for identity, did you configure GCP auth?" });
|
||||
}
|
||||
|
||||
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({
|
||||
identityId: identityOidcAuth.identityId
|
||||
});
|
||||
if (!identityMembershipOrg) {
|
||||
throw new NotFoundError({ message: "Failed to find identity in organization" });
|
||||
throw new NotFoundError({ message: "Identity organization membership not found" });
|
||||
}
|
||||
|
||||
const orgBot = await orgBotDAL.findOne({ orgId: identityMembershipOrg.orgId });
|
||||
if (!orgBot) {
|
||||
throw new NotFoundError({ message: "Org bot not found", name: "OrgBotNotFound" });
|
||||
throw new NotFoundError({ message: "Organization bot was not found", name: "OrgBotNotFound" });
|
||||
}
|
||||
|
||||
const key = infisicalSymmetricDecrypt({
|
||||
@ -136,7 +136,7 @@ export const identityOidcAuthServiceFactory = ({
|
||||
|
||||
if (identityOidcAuth.boundSubject) {
|
||||
if (!doesFieldValueMatchOidcPolicy(tokenData.sub, identityOidcAuth.boundSubject)) {
|
||||
throw new UnauthorizedError({
|
||||
throw new ForbiddenRequestError({
|
||||
message: "Access denied: OIDC subject not allowed."
|
||||
});
|
||||
}
|
||||
@ -221,7 +221,7 @@ export const identityOidcAuthServiceFactory = ({
|
||||
}: TAttachOidcAuthDTO) => {
|
||||
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
|
||||
if (!identityMembershipOrg) {
|
||||
throw new BadRequestError({ message: "Failed to find identity" });
|
||||
throw new NotFoundError({ message: "Failed to find identity" });
|
||||
}
|
||||
if (identityMembershipOrg.identity.authMethod)
|
||||
throw new BadRequestError({
|
||||
@ -360,7 +360,7 @@ export const identityOidcAuthServiceFactory = ({
|
||||
}: TUpdateOidcAuthDTO) => {
|
||||
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
|
||||
if (!identityMembershipOrg) {
|
||||
throw new BadRequestError({ message: "Failed to find identity" });
|
||||
throw new NotFoundError({ message: "Failed to find identity" });
|
||||
}
|
||||
|
||||
if (identityMembershipOrg.identity?.authMethod !== IdentityAuthMethod.OIDC_AUTH) {
|
||||
@ -422,7 +422,7 @@ export const identityOidcAuthServiceFactory = ({
|
||||
|
||||
const orgBot = await orgBotDAL.findOne({ orgId: identityMembershipOrg.orgId });
|
||||
if (!orgBot) {
|
||||
throw new BadRequestError({ message: "Org bot not found", name: "OrgBotNotFound" });
|
||||
throw new NotFoundError({ message: "Organization bot not found", name: "OrgBotNotFound" });
|
||||
}
|
||||
|
||||
const key = infisicalSymmetricDecrypt({
|
||||
@ -460,7 +460,7 @@ export const identityOidcAuthServiceFactory = ({
|
||||
const getOidcAuth = async ({ identityId, actorId, actor, actorAuthMethod, actorOrgId }: TGetOidcAuthDTO) => {
|
||||
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
|
||||
if (!identityMembershipOrg) {
|
||||
throw new BadRequestError({ message: "Failed to find identity" });
|
||||
throw new NotFoundError({ message: "Failed to find identity" });
|
||||
}
|
||||
|
||||
if (identityMembershipOrg.identity?.authMethod !== IdentityAuthMethod.OIDC_AUTH) {
|
||||
@ -482,7 +482,7 @@ export const identityOidcAuthServiceFactory = ({
|
||||
|
||||
const orgBot = await orgBotDAL.findOne({ orgId: identityMembershipOrg.orgId });
|
||||
if (!orgBot) {
|
||||
throw new BadRequestError({ message: "Org bot not found", name: "OrgBotNotFound" });
|
||||
throw new NotFoundError({ message: "Organization bot not found", name: "OrgBotNotFound" });
|
||||
}
|
||||
|
||||
const key = infisicalSymmetricDecrypt({
|
||||
@ -505,7 +505,7 @@ export const identityOidcAuthServiceFactory = ({
|
||||
const revokeOidcAuth = async ({ identityId, actorId, actor, actorAuthMethod, actorOrgId }: TRevokeOidcAuthDTO) => {
|
||||
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
|
||||
if (!identityMembershipOrg) {
|
||||
throw new BadRequestError({ message: "Failed to find identity" });
|
||||
throw new NotFoundError({ message: "Failed to find identity" });
|
||||
}
|
||||
|
||||
if (identityMembershipOrg.identity?.authMethod !== IdentityAuthMethod.OIDC_AUTH) {
|
||||
@ -532,8 +532,7 @@ export const identityOidcAuthServiceFactory = ({
|
||||
actorOrgId
|
||||
);
|
||||
|
||||
const hasPriviledge = isAtLeastAsPrivileged(permission, rolePermission);
|
||||
if (!hasPriviledge) {
|
||||
if (!isAtLeastAsPrivileged(permission, rolePermission)) {
|
||||
throw new ForbiddenRequestError({
|
||||
message: "Failed to revoke OIDC auth of identity with more privileged role"
|
||||
});
|
||||
|
@ -5,7 +5,7 @@ import { ProjectMembershipRole } from "@app/db/schemas";
|
||||
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service";
|
||||
import { ProjectPermissionActions, ProjectPermissionSub } from "@app/ee/services/permission/project-permission";
|
||||
import { isAtLeastAsPrivileged } from "@app/lib/casl";
|
||||
import { BadRequestError, ForbiddenRequestError } from "@app/lib/errors";
|
||||
import { BadRequestError, ForbiddenRequestError, NotFoundError } from "@app/lib/errors";
|
||||
import { groupBy } from "@app/lib/fn";
|
||||
|
||||
import { ActorType } from "../auth/auth-type";
|
||||
@ -75,7 +75,7 @@ export const identityProjectServiceFactory = ({
|
||||
orgId: project.orgId
|
||||
});
|
||||
if (!identityOrgMembership)
|
||||
throw new BadRequestError({
|
||||
throw new NotFoundError({
|
||||
message: `Failed to find identity with id ${identityId}`
|
||||
});
|
||||
|
||||
@ -103,7 +103,8 @@ export const identityProjectServiceFactory = ({
|
||||
$in: { slug: customInputRoles.map(({ role }) => role) }
|
||||
})
|
||||
: [];
|
||||
if (customRoles.length !== customInputRoles.length) throw new BadRequestError({ message: "Custom role not found" });
|
||||
if (customRoles.length !== customInputRoles.length)
|
||||
throw new NotFoundError({ message: "Custom project roles not found" });
|
||||
|
||||
const customRolesGroupBySlug = groupBy(customRoles, ({ slug }) => slug);
|
||||
const projectIdentity = await identityProjectDAL.transaction(async (tx) => {
|
||||
@ -164,7 +165,7 @@ export const identityProjectServiceFactory = ({
|
||||
|
||||
const projectIdentity = await identityProjectDAL.findOne({ identityId, projectId });
|
||||
if (!projectIdentity)
|
||||
throw new BadRequestError({
|
||||
throw new NotFoundError({
|
||||
message: `Identity with id ${identityId} doesn't exists in project with id ${projectId}`
|
||||
});
|
||||
|
||||
@ -174,9 +175,7 @@ export const identityProjectServiceFactory = ({
|
||||
projectId
|
||||
);
|
||||
|
||||
const hasRequiredPriviledges = isAtLeastAsPrivileged(permission, rolePermission);
|
||||
|
||||
if (!hasRequiredPriviledges) {
|
||||
if (!isAtLeastAsPrivileged(permission, rolePermission)) {
|
||||
throw new ForbiddenRequestError({ message: "Failed to change to a more privileged role" });
|
||||
}
|
||||
}
|
||||
@ -192,7 +191,8 @@ export const identityProjectServiceFactory = ({
|
||||
$in: { slug: customInputRoles.map(({ role }) => role) }
|
||||
})
|
||||
: [];
|
||||
if (customRoles.length !== customInputRoles.length) throw new BadRequestError({ message: "Custom role not found" });
|
||||
if (customRoles.length !== customInputRoles.length)
|
||||
throw new NotFoundError({ message: "Custom project roles not found" });
|
||||
|
||||
const customRolesGroupBySlug = groupBy(customRoles, ({ slug }) => slug);
|
||||
|
||||
@ -238,7 +238,7 @@ export const identityProjectServiceFactory = ({
|
||||
}: TDeleteProjectIdentityDTO) => {
|
||||
const identityProjectMembership = await identityProjectDAL.findOne({ identityId, projectId });
|
||||
if (!identityProjectMembership)
|
||||
throw new BadRequestError({ message: `Failed to find identity with id ${identityId}` });
|
||||
throw new NotFoundError({ message: `Failed to find identity with id ${identityId}` });
|
||||
|
||||
const { permission } = await permissionService.getProjectPermission(
|
||||
actor,
|
||||
@ -255,8 +255,7 @@ export const identityProjectServiceFactory = ({
|
||||
actorAuthMethod,
|
||||
actorOrgId
|
||||
);
|
||||
const hasRequiredPriviledges = isAtLeastAsPrivileged(permission, identityRolePermission);
|
||||
if (!hasRequiredPriviledges)
|
||||
if (!isAtLeastAsPrivileged(permission, identityRolePermission))
|
||||
throw new ForbiddenRequestError({ message: "Failed to delete more privileged identity" });
|
||||
|
||||
const [deletedIdentity] = await identityProjectDAL.delete({ identityId, projectId });
|
||||
@ -315,7 +314,7 @@ export const identityProjectServiceFactory = ({
|
||||
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Identity);
|
||||
|
||||
const [identityMembership] = await identityProjectDAL.findByProjectId(projectId, { identityId });
|
||||
if (!identityMembership) throw new BadRequestError({ message: `Membership not found for identity ${identityId}` });
|
||||
if (!identityMembership) throw new NotFoundError({ message: `Membership not found for identity ${identityId}` });
|
||||
return identityMembership;
|
||||
};
|
||||
|
||||
|
@ -7,7 +7,7 @@ import { OrgPermissionActions, OrgPermissionSubjects } from "@app/ee/services/pe
|
||||
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service";
|
||||
import { isAtLeastAsPrivileged } from "@app/lib/casl";
|
||||
import { getConfig } from "@app/lib/config/env";
|
||||
import { BadRequestError, ForbiddenRequestError, NotFoundError, UnauthorizedError } from "@app/lib/errors";
|
||||
import { BadRequestError, ForbiddenRequestError, NotFoundError } from "@app/lib/errors";
|
||||
import { extractIPDetails, isValidIpOrCidr } from "@app/lib/ip";
|
||||
|
||||
import { ActorType, AuthTokenType } from "../auth/auth-type";
|
||||
@ -64,7 +64,7 @@ export const identityTokenAuthServiceFactory = ({
|
||||
actorOrgId
|
||||
}: TAttachTokenAuthDTO) => {
|
||||
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
|
||||
if (!identityMembershipOrg) throw new BadRequestError({ message: "Failed to find identity" });
|
||||
if (!identityMembershipOrg) throw new NotFoundError({ message: "Failed to find identity" });
|
||||
if (identityMembershipOrg.identity.authMethod)
|
||||
throw new BadRequestError({
|
||||
message: "Failed to add Token Auth to already configured identity"
|
||||
@ -136,7 +136,7 @@ export const identityTokenAuthServiceFactory = ({
|
||||
actorOrgId
|
||||
}: TUpdateTokenAuthDTO) => {
|
||||
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
|
||||
if (!identityMembershipOrg) throw new BadRequestError({ message: "Failed to find identity" });
|
||||
if (!identityMembershipOrg) throw new NotFoundError({ message: "Failed to find identity" });
|
||||
if (identityMembershipOrg.identity?.authMethod !== IdentityAuthMethod.TOKEN_AUTH)
|
||||
throw new BadRequestError({
|
||||
message: "Failed to update Token Auth"
|
||||
@ -196,7 +196,7 @@ export const identityTokenAuthServiceFactory = ({
|
||||
|
||||
const getTokenAuth = async ({ identityId, actorId, actor, actorAuthMethod, actorOrgId }: TGetTokenAuthDTO) => {
|
||||
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
|
||||
if (!identityMembershipOrg) throw new BadRequestError({ message: "Failed to find identity" });
|
||||
if (!identityMembershipOrg) throw new NotFoundError({ message: "Failed to find identity" });
|
||||
if (identityMembershipOrg.identity?.authMethod !== IdentityAuthMethod.TOKEN_AUTH)
|
||||
throw new BadRequestError({
|
||||
message: "The identity does not have Token Auth attached"
|
||||
@ -224,7 +224,7 @@ export const identityTokenAuthServiceFactory = ({
|
||||
actorOrgId
|
||||
}: TRevokeTokenAuthDTO) => {
|
||||
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
|
||||
if (!identityMembershipOrg) throw new BadRequestError({ message: "Failed to find identity" });
|
||||
if (!identityMembershipOrg) throw new NotFoundError({ message: "Failed to find identity" });
|
||||
if (identityMembershipOrg.identity?.authMethod !== IdentityAuthMethod.TOKEN_AUTH)
|
||||
throw new BadRequestError({
|
||||
message: "The identity does not have Token Auth"
|
||||
@ -245,11 +245,12 @@ export const identityTokenAuthServiceFactory = ({
|
||||
actorAuthMethod,
|
||||
actorOrgId
|
||||
);
|
||||
const hasPriviledge = isAtLeastAsPrivileged(permission, rolePermission);
|
||||
if (!hasPriviledge)
|
||||
throw new UnauthorizedError({
|
||||
|
||||
if (!isAtLeastAsPrivileged(permission, rolePermission)) {
|
||||
throw new ForbiddenRequestError({
|
||||
message: "Failed to revoke Token Auth of identity with more privileged role"
|
||||
});
|
||||
}
|
||||
|
||||
const revokedIdentityTokenAuth = await identityTokenAuthDAL.transaction(async (tx) => {
|
||||
const deletedTokenAuth = await identityTokenAuthDAL.delete({ identityId }, tx);
|
||||
@ -268,7 +269,7 @@ export const identityTokenAuthServiceFactory = ({
|
||||
name
|
||||
}: TCreateTokenAuthTokenDTO) => {
|
||||
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
|
||||
if (!identityMembershipOrg) throw new BadRequestError({ message: "Failed to find identity" });
|
||||
if (!identityMembershipOrg) throw new NotFoundError({ message: "Failed to find identity" });
|
||||
if (identityMembershipOrg.identity?.authMethod !== IdentityAuthMethod.TOKEN_AUTH)
|
||||
throw new BadRequestError({
|
||||
message: "The identity does not have Token Auth"
|
||||
@ -342,7 +343,7 @@ export const identityTokenAuthServiceFactory = ({
|
||||
actorOrgId
|
||||
}: TGetTokenAuthTokensDTO) => {
|
||||
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
|
||||
if (!identityMembershipOrg) throw new BadRequestError({ message: "Failed to find identity" });
|
||||
if (!identityMembershipOrg) throw new NotFoundError({ message: "Failed to find identity" });
|
||||
if (identityMembershipOrg.identity?.authMethod !== IdentityAuthMethod.TOKEN_AUTH)
|
||||
throw new BadRequestError({
|
||||
message: "The identity does not have Token Auth"
|
||||
@ -377,7 +378,7 @@ export const identityTokenAuthServiceFactory = ({
|
||||
const foundToken = await identityAccessTokenDAL.findById(tokenId);
|
||||
if (!foundToken) throw new NotFoundError({ message: "Failed to find token" });
|
||||
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId: foundToken.identityId });
|
||||
if (!identityMembershipOrg) throw new BadRequestError({ message: "Failed to find identity" });
|
||||
if (!identityMembershipOrg) throw new NotFoundError({ message: "Failed to find identity" });
|
||||
if (identityMembershipOrg.identity?.authMethod !== IdentityAuthMethod.TOKEN_AUTH)
|
||||
throw new BadRequestError({
|
||||
message: "The identity does not have Token Auth"
|
||||
@ -438,7 +439,7 @@ export const identityTokenAuthServiceFactory = ({
|
||||
});
|
||||
|
||||
if (!identityOrgMembership) {
|
||||
throw new UnauthorizedError({ message: "Identity does not belong to any organization" });
|
||||
throw new NotFoundError({ message: "No identity organization membership found" });
|
||||
}
|
||||
|
||||
const { permission } = await permissionService.getOrgPermission(
|
||||
|
@ -10,7 +10,7 @@ import { OrgPermissionActions, OrgPermissionSubjects } from "@app/ee/services/pe
|
||||
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service";
|
||||
import { isAtLeastAsPrivileged } from "@app/lib/casl";
|
||||
import { getConfig } from "@app/lib/config/env";
|
||||
import { BadRequestError, ForbiddenRequestError, UnauthorizedError } from "@app/lib/errors";
|
||||
import { BadRequestError, ForbiddenRequestError, NotFoundError, UnauthorizedError } from "@app/lib/errors";
|
||||
import { checkIPAgainstBlocklist, extractIPDetails, isValidIpOrCidr, TIp } from "@app/lib/ip";
|
||||
|
||||
import { ActorType, AuthTokenType } from "../auth/auth-type";
|
||||
@ -54,7 +54,11 @@ export const identityUaServiceFactory = ({
|
||||
}: TIdentityUaServiceFactoryDep) => {
|
||||
const login = async (clientId: string, clientSecret: string, ip: string) => {
|
||||
const identityUa = await identityUaDAL.findOne({ clientId });
|
||||
if (!identityUa) throw new UnauthorizedError({ message: "Invalid credentials" });
|
||||
if (!identityUa) {
|
||||
throw new NotFoundError({
|
||||
message: "No identity with specified client ID was found"
|
||||
});
|
||||
}
|
||||
|
||||
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId: identityUa.identityId });
|
||||
|
||||
@ -85,7 +89,7 @@ export const identityUaServiceFactory = ({
|
||||
});
|
||||
|
||||
throw new UnauthorizedError({
|
||||
message: "Failed to authenticate identity credentials due to expired client secret"
|
||||
message: "Access denied due to expired client secret"
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -97,7 +101,7 @@ export const identityUaServiceFactory = ({
|
||||
isClientSecretRevoked: true
|
||||
});
|
||||
throw new UnauthorizedError({
|
||||
message: "Failed to authenticate identity credentials due to client secret number of uses limit reached"
|
||||
message: "Access denied due to client secret usage limit reached"
|
||||
});
|
||||
}
|
||||
|
||||
@ -151,7 +155,7 @@ export const identityUaServiceFactory = ({
|
||||
actorOrgId
|
||||
}: TAttachUaDTO) => {
|
||||
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
|
||||
if (!identityMembershipOrg) throw new BadRequestError({ message: "Failed to find identity" });
|
||||
if (!identityMembershipOrg) throw new NotFoundError({ message: "Failed to find identity" });
|
||||
if (identityMembershipOrg.identity.authMethod)
|
||||
throw new BadRequestError({
|
||||
message: "Failed to add universal auth to already configured identity"
|
||||
@ -242,7 +246,7 @@ export const identityUaServiceFactory = ({
|
||||
actorOrgId
|
||||
}: TUpdateUaDTO) => {
|
||||
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
|
||||
if (!identityMembershipOrg) throw new BadRequestError({ message: "Failed to find identity" });
|
||||
if (!identityMembershipOrg) throw new NotFoundError({ message: "Failed to find identity" });
|
||||
if (identityMembershipOrg.identity?.authMethod !== IdentityAuthMethod.Univeral)
|
||||
throw new BadRequestError({
|
||||
message: "Failed to updated universal auth"
|
||||
@ -316,7 +320,7 @@ export const identityUaServiceFactory = ({
|
||||
|
||||
const getIdentityUniversalAuth = async ({ identityId, actorId, actor, actorAuthMethod, actorOrgId }: TGetUaDTO) => {
|
||||
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
|
||||
if (!identityMembershipOrg) throw new BadRequestError({ message: "Failed to find identity" });
|
||||
if (!identityMembershipOrg) throw new NotFoundError({ message: "Failed to find identity" });
|
||||
if (identityMembershipOrg.identity?.authMethod !== IdentityAuthMethod.Univeral)
|
||||
throw new BadRequestError({
|
||||
message: "The identity does not have universal auth"
|
||||
@ -343,7 +347,7 @@ export const identityUaServiceFactory = ({
|
||||
actorOrgId
|
||||
}: TRevokeUaDTO) => {
|
||||
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
|
||||
if (!identityMembershipOrg) throw new BadRequestError({ message: "Failed to find identity" });
|
||||
if (!identityMembershipOrg) throw new NotFoundError({ message: "Failed to find identity" });
|
||||
if (identityMembershipOrg.identity?.authMethod !== IdentityAuthMethod.Univeral)
|
||||
throw new BadRequestError({
|
||||
message: "The identity does not have universal auth"
|
||||
@ -364,8 +368,7 @@ export const identityUaServiceFactory = ({
|
||||
actorAuthMethod,
|
||||
actorOrgId
|
||||
);
|
||||
const hasPriviledge = isAtLeastAsPrivileged(permission, rolePermission);
|
||||
if (!hasPriviledge)
|
||||
if (!isAtLeastAsPrivileged(permission, rolePermission))
|
||||
throw new ForbiddenRequestError({
|
||||
message: "Failed to revoke universal auth of identity with more privileged role"
|
||||
});
|
||||
@ -389,7 +392,7 @@ export const identityUaServiceFactory = ({
|
||||
numUsesLimit
|
||||
}: TCreateUaClientSecretDTO) => {
|
||||
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
|
||||
if (!identityMembershipOrg) throw new BadRequestError({ message: "Failed to find identity" });
|
||||
if (!identityMembershipOrg) throw new NotFoundError({ message: "Failed to find identity" });
|
||||
if (identityMembershipOrg.identity?.authMethod !== IdentityAuthMethod.Univeral)
|
||||
throw new BadRequestError({
|
||||
message: "The identity does not have universal auth"
|
||||
@ -449,7 +452,7 @@ export const identityUaServiceFactory = ({
|
||||
identityId
|
||||
}: TGetUaClientSecretsDTO) => {
|
||||
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
|
||||
if (!identityMembershipOrg) throw new BadRequestError({ message: "Failed to find identity" });
|
||||
if (!identityMembershipOrg) throw new NotFoundError({ message: "Failed to find identity" });
|
||||
if (identityMembershipOrg.identity?.authMethod !== IdentityAuthMethod.Univeral)
|
||||
throw new BadRequestError({
|
||||
message: "The identity does not have universal auth"
|
||||
@ -470,8 +473,8 @@ export const identityUaServiceFactory = ({
|
||||
actorAuthMethod,
|
||||
actorOrgId
|
||||
);
|
||||
const hasPriviledge = isAtLeastAsPrivileged(permission, rolePermission);
|
||||
if (!hasPriviledge)
|
||||
|
||||
if (!isAtLeastAsPrivileged(permission, rolePermission))
|
||||
throw new ForbiddenRequestError({
|
||||
message: "Failed to add identity to project with more privileged role"
|
||||
});
|
||||
@ -496,7 +499,7 @@ export const identityUaServiceFactory = ({
|
||||
clientSecretId
|
||||
}: TGetUniversalAuthClientSecretByIdDTO) => {
|
||||
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
|
||||
if (!identityMembershipOrg) throw new BadRequestError({ message: "Failed to find identity" });
|
||||
if (!identityMembershipOrg) throw new NotFoundError({ message: "Failed to find identity" });
|
||||
if (identityMembershipOrg.identity?.authMethod !== IdentityAuthMethod.Univeral)
|
||||
throw new BadRequestError({
|
||||
message: "The identity does not have universal auth"
|
||||
@ -517,8 +520,7 @@ export const identityUaServiceFactory = ({
|
||||
actorAuthMethod,
|
||||
actorOrgId
|
||||
);
|
||||
const hasPriviledge = isAtLeastAsPrivileged(permission, rolePermission);
|
||||
if (!hasPriviledge)
|
||||
if (!isAtLeastAsPrivileged(permission, rolePermission))
|
||||
throw new ForbiddenRequestError({
|
||||
message: "Failed to read identity client secret of project with more privileged role"
|
||||
});
|
||||
@ -536,7 +538,7 @@ export const identityUaServiceFactory = ({
|
||||
clientSecretId
|
||||
}: TRevokeUaClientSecretDTO) => {
|
||||
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
|
||||
if (!identityMembershipOrg) throw new BadRequestError({ message: "Failed to find identity" });
|
||||
if (!identityMembershipOrg) throw new NotFoundError({ message: "Failed to find identity" });
|
||||
if (identityMembershipOrg.identity?.authMethod !== IdentityAuthMethod.Univeral)
|
||||
throw new BadRequestError({
|
||||
message: "The identity does not have universal auth"
|
||||
@ -557,8 +559,8 @@ export const identityUaServiceFactory = ({
|
||||
actorAuthMethod,
|
||||
actorOrgId
|
||||
);
|
||||
const hasPriviledge = isAtLeastAsPrivileged(permission, rolePermission);
|
||||
if (!hasPriviledge)
|
||||
|
||||
if (!isAtLeastAsPrivileged(permission, rolePermission))
|
||||
throw new ForbiddenRequestError({
|
||||
message: "Failed to revoke identity client secret with more privileged role"
|
||||
});
|
||||
|
@ -55,7 +55,8 @@ export const identityServiceFactory = ({
|
||||
);
|
||||
const isCustomRole = Boolean(customRole);
|
||||
const hasRequiredPriviledges = isAtLeastAsPrivileged(permission, rolePermission);
|
||||
if (!hasRequiredPriviledges) throw new BadRequestError({ message: "Failed to create a more privileged identity" });
|
||||
if (!hasRequiredPriviledges)
|
||||
throw new ForbiddenRequestError({ message: "Failed to create a more privileged identity" });
|
||||
|
||||
const plan = await licenseService.getPlan(orgId);
|
||||
|
||||
@ -94,7 +95,7 @@ export const identityServiceFactory = ({
|
||||
actorOrgId
|
||||
}: TUpdateIdentityDTO) => {
|
||||
const identityOrgMembership = await identityOrgMembershipDAL.findOne({ identityId: id });
|
||||
if (!identityOrgMembership) throw new BadRequestError({ 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(
|
||||
actor,
|
||||
@ -126,7 +127,7 @@ export const identityServiceFactory = ({
|
||||
const isCustomRole = Boolean(customOrgRole);
|
||||
const hasRequiredNewRolePermission = isAtLeastAsPrivileged(permission, rolePermission);
|
||||
if (!hasRequiredNewRolePermission)
|
||||
throw new BadRequestError({ message: "Failed to create a more privileged identity" });
|
||||
throw new ForbiddenRequestError({ message: "Failed to create a more privileged identity" });
|
||||
if (isCustomRole) customRole = customOrgRole;
|
||||
}
|
||||
|
||||
@ -153,7 +154,7 @@ export const identityServiceFactory = ({
|
||||
[`${TableName.IdentityOrgMembership}.identityId` as "identityId"]: id
|
||||
});
|
||||
const identity = doc[0];
|
||||
if (!identity) throw new BadRequestError({ message: `Failed to find identity with id ${id}` });
|
||||
if (!identity) throw new NotFoundError({ message: `Failed to find identity with id ${id}` });
|
||||
|
||||
const { permission } = await permissionService.getOrgPermission(
|
||||
actor,
|
||||
@ -168,7 +169,7 @@ export const identityServiceFactory = ({
|
||||
|
||||
const deleteIdentity = async ({ actorId, actor, actorOrgId, actorAuthMethod, id }: TDeleteIdentityDTO) => {
|
||||
const identityOrgMembership = await identityOrgMembershipDAL.findOne({ identityId: id });
|
||||
if (!identityOrgMembership) throw new BadRequestError({ 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(
|
||||
actor,
|
||||
|
@ -2,7 +2,7 @@
|
||||
import { Octokit } from "@octokit/rest";
|
||||
|
||||
import { request } from "@app/lib/config/request";
|
||||
import { BadRequestError } from "@app/lib/errors";
|
||||
import { NotFoundError } from "@app/lib/errors";
|
||||
|
||||
import { Integrations, IntegrationUrls } from "./integration-list";
|
||||
|
||||
@ -1192,6 +1192,6 @@ export const getApps = async ({
|
||||
});
|
||||
|
||||
default:
|
||||
throw new BadRequestError({ message: "integration not found" });
|
||||
throw new NotFoundError({ message: "integration not found" });
|
||||
}
|
||||
};
|
||||
|
@ -7,7 +7,7 @@ import { TPermissionServiceFactory } from "@app/ee/services/permission/permissio
|
||||
import { ProjectPermissionActions, ProjectPermissionSub } from "@app/ee/services/permission/project-permission";
|
||||
import { request } from "@app/lib/config/request";
|
||||
import { decryptSymmetric128BitHexKeyUTF8, encryptSymmetric128BitHexKeyUTF8 } from "@app/lib/crypto";
|
||||
import { BadRequestError } from "@app/lib/errors";
|
||||
import { BadRequestError, NotFoundError } from "@app/lib/errors";
|
||||
import { TProjectPermission } from "@app/lib/types";
|
||||
|
||||
import { TIntegrationDALFactory } from "../integration/integration-dal";
|
||||
@ -88,7 +88,7 @@ export const integrationAuthServiceFactory = ({
|
||||
|
||||
const getIntegrationAuth = async ({ actor, id, actorId, actorAuthMethod, actorOrgId }: TGetIntegrationAuthDTO) => {
|
||||
const integrationAuth = await integrationAuthDAL.findById(id);
|
||||
if (!integrationAuth) throw new BadRequestError({ message: "Failed to find integration" });
|
||||
if (!integrationAuth) throw new NotFoundError({ message: "Failed to find integration" });
|
||||
|
||||
const { permission } = await permissionService.getProjectPermission(
|
||||
actor,
|
||||
@ -162,7 +162,7 @@ export const integrationAuthServiceFactory = ({
|
||||
updateDoc.encryptedAccess = accessToken;
|
||||
}
|
||||
} else {
|
||||
if (!botKey) throw new BadRequestError({ message: "Bot key not found" });
|
||||
if (!botKey) throw new NotFoundError({ message: "Project bot key not found" });
|
||||
if (tokenExchange.refreshToken) {
|
||||
const refreshEncToken = encryptSymmetric128BitHexKeyUTF8(tokenExchange.refreshToken, botKey);
|
||||
updateDoc.refreshIV = refreshEncToken.iv;
|
||||
@ -273,7 +273,7 @@ export const integrationAuthServiceFactory = ({
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!botKey) throw new BadRequestError({ message: "Bot key not found" });
|
||||
if (!botKey) throw new NotFoundError({ message: "Project bot key not found" });
|
||||
if (refreshToken) {
|
||||
const tokenDetails = await exchangeRefresh(
|
||||
integration,
|
||||
@ -379,7 +379,7 @@ export const integrationAuthServiceFactory = ({
|
||||
|
||||
// the old bot key is else
|
||||
} else {
|
||||
if (!botKey) throw new BadRequestError({ message: "bot key is missing" });
|
||||
if (!botKey) throw new NotFoundError({ message: "Project bot key not found" });
|
||||
if (integrationAuth.accessTag && integrationAuth.accessIV && integrationAuth.accessCiphertext) {
|
||||
accessToken = decryptSymmetric128BitHexKeyUTF8({
|
||||
ciphertext: integrationAuth.accessCiphertext,
|
||||
@ -445,7 +445,7 @@ export const integrationAuthServiceFactory = ({
|
||||
workspaceSlug
|
||||
}: TIntegrationAuthAppsDTO) => {
|
||||
const integrationAuth = await integrationAuthDAL.findById(id);
|
||||
if (!integrationAuth) throw new BadRequestError({ message: "Failed to find integration" });
|
||||
if (!integrationAuth) throw new NotFoundError({ message: "Failed to find integration" });
|
||||
|
||||
const { permission } = await permissionService.getProjectPermission(
|
||||
actor,
|
||||
@ -478,7 +478,7 @@ export const integrationAuthServiceFactory = ({
|
||||
id
|
||||
}: TIntegrationAuthTeamsDTO) => {
|
||||
const integrationAuth = await integrationAuthDAL.findById(id);
|
||||
if (!integrationAuth) throw new BadRequestError({ message: "Failed to find integration" });
|
||||
if (!integrationAuth) throw new NotFoundError({ message: "Failed to find integration" });
|
||||
|
||||
const { permission } = await permissionService.getProjectPermission(
|
||||
actor,
|
||||
@ -508,7 +508,7 @@ export const integrationAuthServiceFactory = ({
|
||||
actorOrgId
|
||||
}: TIntegrationAuthVercelBranchesDTO) => {
|
||||
const integrationAuth = await integrationAuthDAL.findById(id);
|
||||
if (!integrationAuth) throw new BadRequestError({ message: "Failed to find integration" });
|
||||
if (!integrationAuth) throw new NotFoundError({ message: "Failed to find integration" });
|
||||
|
||||
const { permission } = await permissionService.getProjectPermission(
|
||||
actor,
|
||||
@ -549,7 +549,7 @@ export const integrationAuthServiceFactory = ({
|
||||
accountId
|
||||
}: TIntegrationAuthChecklyGroupsDTO) => {
|
||||
const integrationAuth = await integrationAuthDAL.findById(id);
|
||||
if (!integrationAuth) throw new BadRequestError({ message: "Failed to find integration" });
|
||||
if (!integrationAuth) throw new NotFoundError({ message: "Failed to find integration" });
|
||||
|
||||
const { permission } = await permissionService.getProjectPermission(
|
||||
actor,
|
||||
@ -576,7 +576,7 @@ export const integrationAuthServiceFactory = ({
|
||||
|
||||
const getGithubOrgs = async ({ actorId, actor, actorOrgId, actorAuthMethod, id }: TIntegrationAuthGithubOrgsDTO) => {
|
||||
const integrationAuth = await integrationAuthDAL.findById(id);
|
||||
if (!integrationAuth) throw new BadRequestError({ message: "Failed to find integration" });
|
||||
if (!integrationAuth) throw new NotFoundError({ message: "Failed to find integration" });
|
||||
|
||||
const { permission } = await permissionService.getProjectPermission(
|
||||
actor,
|
||||
@ -613,7 +613,7 @@ export const integrationAuthServiceFactory = ({
|
||||
repoName
|
||||
}: TIntegrationAuthGithubEnvsDTO) => {
|
||||
const integrationAuth = await integrationAuthDAL.findById(id);
|
||||
if (!integrationAuth) throw new BadRequestError({ message: "Failed to find integration" });
|
||||
if (!integrationAuth) throw new NotFoundError({ message: "Failed to find integration" });
|
||||
|
||||
const { permission } = await permissionService.getProjectPermission(
|
||||
actor,
|
||||
@ -645,7 +645,7 @@ export const integrationAuthServiceFactory = ({
|
||||
|
||||
const getQoveryOrgs = async ({ actorId, actor, actorOrgId, actorAuthMethod, id }: TIntegrationAuthQoveryOrgsDTO) => {
|
||||
const integrationAuth = await integrationAuthDAL.findById(id);
|
||||
if (!integrationAuth) throw new BadRequestError({ message: "Failed to find integration" });
|
||||
if (!integrationAuth) throw new NotFoundError({ message: "Failed to find integration" });
|
||||
|
||||
const { permission } = await permissionService.getProjectPermission(
|
||||
actor,
|
||||
@ -679,7 +679,7 @@ export const integrationAuthServiceFactory = ({
|
||||
region
|
||||
}: TIntegrationAuthAwsKmsKeyDTO) => {
|
||||
const integrationAuth = await integrationAuthDAL.findById(id);
|
||||
if (!integrationAuth) throw new BadRequestError({ message: "Failed to find integration" });
|
||||
if (!integrationAuth) throw new NotFoundError({ message: "Failed to find integration" });
|
||||
|
||||
const { permission } = await permissionService.getProjectPermission(
|
||||
actor,
|
||||
@ -737,7 +737,7 @@ export const integrationAuthServiceFactory = ({
|
||||
orgId
|
||||
}: TIntegrationAuthQoveryProjectDTO) => {
|
||||
const integrationAuth = await integrationAuthDAL.findById(id);
|
||||
if (!integrationAuth) throw new BadRequestError({ message: "Failed to find integration" });
|
||||
if (!integrationAuth) throw new NotFoundError({ message: "Failed to find integration" });
|
||||
|
||||
const { permission } = await permissionService.getProjectPermission(
|
||||
actor,
|
||||
@ -773,7 +773,7 @@ export const integrationAuthServiceFactory = ({
|
||||
actorOrgId
|
||||
}: TIntegrationAuthQoveryEnvironmentsDTO) => {
|
||||
const integrationAuth = await integrationAuthDAL.findById(id);
|
||||
if (!integrationAuth) throw new BadRequestError({ message: "Failed to find integration" });
|
||||
if (!integrationAuth) throw new NotFoundError({ message: "Failed to find integration" });
|
||||
|
||||
const { permission } = await permissionService.getProjectPermission(
|
||||
actor,
|
||||
@ -814,7 +814,7 @@ export const integrationAuthServiceFactory = ({
|
||||
environmentId
|
||||
}: TIntegrationAuthQoveryScopesDTO) => {
|
||||
const integrationAuth = await integrationAuthDAL.findById(id);
|
||||
if (!integrationAuth) throw new BadRequestError({ message: "Failed to find integration" });
|
||||
if (!integrationAuth) throw new NotFoundError({ message: "Failed to find integration" });
|
||||
|
||||
const { permission } = await permissionService.getProjectPermission(
|
||||
actor,
|
||||
@ -854,7 +854,7 @@ export const integrationAuthServiceFactory = ({
|
||||
environmentId
|
||||
}: TIntegrationAuthQoveryScopesDTO) => {
|
||||
const integrationAuth = await integrationAuthDAL.findById(id);
|
||||
if (!integrationAuth) throw new BadRequestError({ message: "Failed to find integration" });
|
||||
if (!integrationAuth) throw new NotFoundError({ message: "Failed to find integration" });
|
||||
|
||||
const { permission } = await permissionService.getProjectPermission(
|
||||
actor,
|
||||
@ -894,7 +894,7 @@ export const integrationAuthServiceFactory = ({
|
||||
environmentId
|
||||
}: TIntegrationAuthQoveryScopesDTO) => {
|
||||
const integrationAuth = await integrationAuthDAL.findById(id);
|
||||
if (!integrationAuth) throw new BadRequestError({ message: "Failed to find integration" });
|
||||
if (!integrationAuth) throw new NotFoundError({ message: "Failed to find integration" });
|
||||
|
||||
const { permission } = await permissionService.getProjectPermission(
|
||||
actor,
|
||||
@ -933,7 +933,7 @@ export const integrationAuthServiceFactory = ({
|
||||
actorOrgId
|
||||
}: TIntegrationAuthHerokuPipelinesDTO) => {
|
||||
const integrationAuth = await integrationAuthDAL.findById(id);
|
||||
if (!integrationAuth) throw new BadRequestError({ message: "Failed to find integration" });
|
||||
if (!integrationAuth) throw new NotFoundError({ message: "Failed to find integration" });
|
||||
|
||||
const { permission } = await permissionService.getProjectPermission(
|
||||
actor,
|
||||
@ -973,7 +973,7 @@ export const integrationAuthServiceFactory = ({
|
||||
appId
|
||||
}: TIntegrationAuthRailwayEnvDTO) => {
|
||||
const integrationAuth = await integrationAuthDAL.findById(id);
|
||||
if (!integrationAuth) throw new BadRequestError({ message: "Failed to find integration" });
|
||||
if (!integrationAuth) throw new NotFoundError({ message: "Failed to find integration" });
|
||||
|
||||
const { permission } = await permissionService.getProjectPermission(
|
||||
actor,
|
||||
@ -1041,7 +1041,7 @@ export const integrationAuthServiceFactory = ({
|
||||
appId
|
||||
}: TIntegrationAuthRailwayServicesDTO) => {
|
||||
const integrationAuth = await integrationAuthDAL.findById(id);
|
||||
if (!integrationAuth) throw new BadRequestError({ message: "Failed to find integration" });
|
||||
if (!integrationAuth) throw new NotFoundError({ message: "Failed to find integration" });
|
||||
|
||||
const { permission } = await permissionService.getProjectPermission(
|
||||
actor,
|
||||
@ -1115,7 +1115,7 @@ export const integrationAuthServiceFactory = ({
|
||||
id
|
||||
}: TIntegrationAuthBitbucketWorkspaceDTO) => {
|
||||
const integrationAuth = await integrationAuthDAL.findById(id);
|
||||
if (!integrationAuth) throw new BadRequestError({ message: "Failed to find integration" });
|
||||
if (!integrationAuth) throw new NotFoundError({ message: "Failed to find integration" });
|
||||
|
||||
const { permission } = await permissionService.getProjectPermission(
|
||||
actor,
|
||||
@ -1164,7 +1164,7 @@ export const integrationAuthServiceFactory = ({
|
||||
appId
|
||||
}: TIntegrationAuthNorthflankSecretGroupDTO) => {
|
||||
const integrationAuth = await integrationAuthDAL.findById(id);
|
||||
if (!integrationAuth) throw new BadRequestError({ message: "Failed to find integration" });
|
||||
if (!integrationAuth) throw new NotFoundError({ message: "Failed to find integration" });
|
||||
|
||||
const { permission } = await permissionService.getProjectPermission(
|
||||
actor,
|
||||
@ -1232,7 +1232,7 @@ export const integrationAuthServiceFactory = ({
|
||||
actor
|
||||
}: TGetIntegrationAuthTeamCityBuildConfigDTO) => {
|
||||
const integrationAuth = await integrationAuthDAL.findById(id);
|
||||
if (!integrationAuth) throw new BadRequestError({ message: "Failed to find integration" });
|
||||
if (!integrationAuth) throw new NotFoundError({ message: "Failed to find integration" });
|
||||
|
||||
const { permission } = await permissionService.getProjectPermission(
|
||||
actor,
|
||||
@ -1294,7 +1294,7 @@ export const integrationAuthServiceFactory = ({
|
||||
actorOrgId
|
||||
}: TDeleteIntegrationAuthByIdDTO) => {
|
||||
const integrationAuth = await integrationAuthDAL.findById(id);
|
||||
if (!integrationAuth) throw new BadRequestError({ message: "Failed to find integration" });
|
||||
if (!integrationAuth) throw new NotFoundError({ message: "Failed to find integration" });
|
||||
|
||||
const { permission } = await permissionService.getProjectPermission(
|
||||
actor,
|
||||
@ -1307,7 +1307,7 @@ export const integrationAuthServiceFactory = ({
|
||||
|
||||
const delIntegrationAuth = await integrationAuthDAL.transaction(async (tx) => {
|
||||
const doc = await integrationAuthDAL.deleteById(integrationAuth.id, tx);
|
||||
if (!doc) throw new BadRequestError({ message: "Faled to find integration" });
|
||||
if (!doc) throw new NotFoundError({ message: "Faled to find integration" });
|
||||
await integrationDAL.delete({ integrationAuthId: doc.id }, tx);
|
||||
return doc;
|
||||
});
|
||||
|
@ -2,7 +2,7 @@ import jwt from "jsonwebtoken";
|
||||
|
||||
import { getConfig } from "@app/lib/config/env";
|
||||
import { request } from "@app/lib/config/request";
|
||||
import { BadRequestError } from "@app/lib/errors";
|
||||
import { BadRequestError, NotFoundError } from "@app/lib/errors";
|
||||
|
||||
import { Integrations, IntegrationUrls } from "./integration-list";
|
||||
|
||||
@ -396,7 +396,7 @@ export const exchangeCode = async ({
|
||||
code
|
||||
});
|
||||
default:
|
||||
throw new BadRequestError({ message: "Unknown integration" });
|
||||
throw new NotFoundError({ message: "Unknown integration" });
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -2,7 +2,7 @@ import { ForbiddenError, subject } from "@casl/ability";
|
||||
|
||||
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service";
|
||||
import { ProjectPermissionActions, ProjectPermissionSub } from "@app/ee/services/permission/project-permission";
|
||||
import { BadRequestError, NotFoundError } from "@app/lib/errors";
|
||||
import { NotFoundError } from "@app/lib/errors";
|
||||
import { TProjectPermission } from "@app/lib/types";
|
||||
|
||||
import { TIntegrationAuthDALFactory } from "../integration-auth/integration-auth-dal";
|
||||
@ -76,7 +76,7 @@ export const integrationServiceFactory = ({
|
||||
targetEnvironmentId
|
||||
}: TCreateIntegrationDTO) => {
|
||||
const integrationAuth = await integrationAuthDAL.findById(integrationAuthId);
|
||||
if (!integrationAuth) throw new BadRequestError({ message: "Integration auth not found" });
|
||||
if (!integrationAuth) throw new NotFoundError({ message: "Integration auth not found" });
|
||||
|
||||
const { permission } = await permissionService.getProjectPermission(
|
||||
actor,
|
||||
@ -93,7 +93,7 @@ export const integrationServiceFactory = ({
|
||||
);
|
||||
|
||||
const folder = await folderDAL.findBySecretPath(integrationAuth.projectId, sourceEnvironment, secretPath);
|
||||
if (!folder) throw new BadRequestError({ message: "Folder path not found" });
|
||||
if (!folder) throw new NotFoundError({ message: "Folder path not found" });
|
||||
|
||||
const integration = await integrationDAL.create({
|
||||
envId: folder.envId,
|
||||
@ -139,7 +139,7 @@ export const integrationServiceFactory = ({
|
||||
metadata
|
||||
}: TUpdateIntegrationDTO) => {
|
||||
const integration = await integrationDAL.findById(id);
|
||||
if (!integration) throw new BadRequestError({ message: "Integration auth not found" });
|
||||
if (!integration) throw new NotFoundError({ message: "Integration auth not found" });
|
||||
|
||||
const { permission } = await permissionService.getProjectPermission(
|
||||
actor,
|
||||
@ -156,7 +156,7 @@ export const integrationServiceFactory = ({
|
||||
);
|
||||
|
||||
const folder = await folderDAL.findBySecretPath(integration.projectId, environment, secretPath);
|
||||
if (!folder) throw new BadRequestError({ message: "Folder path not found" });
|
||||
if (!folder) throw new NotFoundError({ message: "Folder path not found" });
|
||||
|
||||
const updatedIntegration = await integrationDAL.updateById(id, {
|
||||
envId: folder.envId,
|
||||
@ -211,7 +211,7 @@ export const integrationServiceFactory = ({
|
||||
shouldDeleteIntegrationSecrets
|
||||
}: TDeleteIntegrationDTO) => {
|
||||
const integration = await integrationDAL.findById(id);
|
||||
if (!integration) throw new BadRequestError({ message: "Integration auth not found" });
|
||||
if (!integration) throw new NotFoundError({ message: "Integration auth not found" });
|
||||
|
||||
const { permission } = await permissionService.getProjectPermission(
|
||||
actor,
|
||||
@ -285,7 +285,7 @@ export const integrationServiceFactory = ({
|
||||
const syncIntegration = async ({ id, actorId, actor, actorOrgId, actorAuthMethod }: TSyncIntegrationDTO) => {
|
||||
const integration = await integrationDAL.findById(id);
|
||||
if (!integration) {
|
||||
throw new BadRequestError({ message: "Integration not found" });
|
||||
throw new NotFoundError({ message: "Integration not found" });
|
||||
}
|
||||
|
||||
const { permission } = await permissionService.getProjectPermission(
|
||||
|
@ -14,7 +14,7 @@ import { getConfig } from "@app/lib/config/env";
|
||||
import { randomSecureBytes } from "@app/lib/crypto";
|
||||
import { symmetricCipherService, SymmetricEncryption } from "@app/lib/crypto/cipher";
|
||||
import { generateHash } from "@app/lib/crypto/encryption";
|
||||
import { BadRequestError, NotFoundError } from "@app/lib/errors";
|
||||
import { BadRequestError, ForbiddenRequestError, NotFoundError } from "@app/lib/errors";
|
||||
import { logger } from "@app/lib/logger";
|
||||
import { alphaNumericNanoId } from "@app/lib/nanoid";
|
||||
|
||||
@ -105,7 +105,7 @@ export const kmsServiceFactory = ({
|
||||
const deleteInternalKms = async (kmsId: string, orgId: string, tx?: Knex) => {
|
||||
const kms = await kmsDAL.findByIdWithAssociatedKms(kmsId, tx);
|
||||
if (kms.isExternal) return;
|
||||
if (kms.orgId !== orgId) throw new BadRequestError({ message: "KMS doesn't belong to organization" });
|
||||
if (kms.orgId !== orgId) throw new ForbiddenRequestError({ message: "KMS doesn't belong to organization" });
|
||||
return kmsDAL.deleteById(kmsId, tx);
|
||||
};
|
||||
|
||||
@ -638,7 +638,7 @@ export const kmsServiceFactory = ({
|
||||
}
|
||||
|
||||
if (kmsDoc.orgId !== project.orgId) {
|
||||
throw new BadRequestError({
|
||||
throw new ForbiddenRequestError({
|
||||
message: "KMS ID does not belong in the organization."
|
||||
});
|
||||
}
|
||||
@ -722,8 +722,8 @@ export const kmsServiceFactory = ({
|
||||
}
|
||||
|
||||
if (backupProjectId !== projectId) {
|
||||
throw new BadRequestError({
|
||||
message: "Invalid backup for project"
|
||||
throw new ForbiddenRequestError({
|
||||
message: "Backup does not belong to project"
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -4,7 +4,7 @@ import { ProjectMembershipRole, ProjectVersion, SecretKeyEncoding } from "@app/d
|
||||
import { OrgPermissionAdminConsoleAction, OrgPermissionSubjects } from "@app/ee/services/permission/org-permission";
|
||||
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service";
|
||||
import { infisicalSymmetricDecrypt } from "@app/lib/crypto/encryption";
|
||||
import { BadRequestError } from "@app/lib/errors";
|
||||
import { BadRequestError, NotFoundError } from "@app/lib/errors";
|
||||
|
||||
import { TProjectDALFactory } from "../project/project-dal";
|
||||
import { assignWorkspaceKeysToMembers } from "../project/project-fns";
|
||||
@ -90,7 +90,7 @@ export const orgAdminServiceFactory = ({
|
||||
);
|
||||
|
||||
const project = await projectDAL.findById(projectId);
|
||||
if (!project) throw new BadRequestError({ message: "Project not found" });
|
||||
if (!project) throw new NotFoundError({ message: "Project not found" });
|
||||
|
||||
if (project.version === ProjectVersion.V1) {
|
||||
throw new BadRequestError({ message: "Please upgrade your project on your dashboard" });
|
||||
@ -119,22 +119,22 @@ export const orgAdminServiceFactory = ({
|
||||
// missing membership thus add admin back as admin to project
|
||||
const ghostUser = await projectDAL.findProjectGhostUser(projectId);
|
||||
if (!ghostUser) {
|
||||
throw new BadRequestError({
|
||||
message: "Failed to find sudo user"
|
||||
throw new NotFoundError({
|
||||
message: "Failed to find project owner"
|
||||
});
|
||||
}
|
||||
|
||||
const ghostUserLatestKey = await projectKeyDAL.findLatestProjectKey(ghostUser.id, projectId);
|
||||
if (!ghostUserLatestKey) {
|
||||
throw new BadRequestError({
|
||||
message: "Failed to find sudo user latest key"
|
||||
throw new NotFoundError({
|
||||
message: "Failed to find project owner's latest key"
|
||||
});
|
||||
}
|
||||
|
||||
const bot = await projectBotDAL.findOne({ projectId });
|
||||
if (!bot) {
|
||||
throw new BadRequestError({
|
||||
message: "Failed to find bot"
|
||||
throw new NotFoundError({
|
||||
message: "Failed to find project bot"
|
||||
});
|
||||
}
|
||||
|
||||
@ -146,7 +146,7 @@ export const orgAdminServiceFactory = ({
|
||||
});
|
||||
|
||||
const userEncryptionKey = await userDAL.findUserEncKeyByUserId(actorId);
|
||||
if (!userEncryptionKey) throw new BadRequestError({ message: "user encryption key not found" });
|
||||
if (!userEncryptionKey) throw new NotFoundError({ message: "User encryption key not found" });
|
||||
const [newWsMember] = assignWorkspaceKeysToMembers({
|
||||
decryptKey: ghostUserLatestKey,
|
||||
userPrivateKey: botPrivateKey,
|
||||
|
@ -10,7 +10,7 @@ import {
|
||||
OrgPermissionSubjects
|
||||
} from "@app/ee/services/permission/org-permission";
|
||||
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service";
|
||||
import { BadRequestError } from "@app/lib/errors";
|
||||
import { BadRequestError, NotFoundError } from "@app/lib/errors";
|
||||
|
||||
import { ActorAuthMethod } from "../auth/auth-type";
|
||||
import { TOrgRoleDALFactory } from "./org-role-dal";
|
||||
@ -91,7 +91,7 @@ export const orgRoleServiceFactory = ({ orgRoleDAL, permissionService }: TOrgRol
|
||||
}
|
||||
default: {
|
||||
const role = await orgRoleDAL.findOne({ id: roleId, orgId });
|
||||
if (!role) throw new BadRequestError({ message: "Role not found", name: "Get role" });
|
||||
if (!role) throw new NotFoundError({ message: "Organization role not found" });
|
||||
return role;
|
||||
}
|
||||
}
|
||||
@ -116,7 +116,7 @@ export const orgRoleServiceFactory = ({ orgRoleDAL, permissionService }: TOrgRol
|
||||
{ id: roleId, orgId },
|
||||
{ ...data, permissions: data.permissions ? JSON.stringify(data.permissions) : undefined }
|
||||
);
|
||||
if (!updatedRole) throw new BadRequestError({ message: "Role not found", name: "Update role" });
|
||||
if (!updatedRole) throw new NotFoundError({ message: "Organization role not found" });
|
||||
return updatedRole;
|
||||
};
|
||||
|
||||
@ -130,7 +130,7 @@ export const orgRoleServiceFactory = ({ orgRoleDAL, permissionService }: TOrgRol
|
||||
const { permission } = await permissionService.getUserOrgPermission(userId, orgId, actorAuthMethod, actorOrgId);
|
||||
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Delete, OrgPermissionSubjects.Role);
|
||||
const [deletedRole] = await orgRoleDAL.delete({ id: roleId, orgId });
|
||||
if (!deletedRole) throw new BadRequestError({ message: "Role not found", name: "Update role" });
|
||||
if (!deletedRole) throw new NotFoundError({ message: "Organization role not found", name: "Update role" });
|
||||
|
||||
return deletedRole;
|
||||
};
|
||||
|
@ -27,7 +27,7 @@ import { getConfig } from "@app/lib/config/env";
|
||||
import { generateAsymmetricKeyPair } from "@app/lib/crypto";
|
||||
import { generateSymmetricKey, infisicalSymmetricDecrypt, infisicalSymmetricEncypt } from "@app/lib/crypto/encryption";
|
||||
import { generateUserSrpKeys } from "@app/lib/crypto/srp";
|
||||
import { BadRequestError, NotFoundError, UnauthorizedError } from "@app/lib/errors";
|
||||
import { BadRequestError, ForbiddenRequestError, NotFoundError, UnauthorizedError } from "@app/lib/errors";
|
||||
import { groupBy } from "@app/lib/fn";
|
||||
import { alphaNumericNanoId } from "@app/lib/nanoid";
|
||||
import { isDisposableEmail } from "@app/lib/validator";
|
||||
@ -128,7 +128,7 @@ export const orgServiceFactory = ({
|
||||
) => {
|
||||
await permissionService.getUserOrgPermission(userId, orgId, actorAuthMethod, actorOrgId);
|
||||
const org = await orgDAL.findOrgById(orgId);
|
||||
if (!org) throw new BadRequestError({ name: "Org not found", message: "Organization not found" });
|
||||
if (!org) throw new NotFoundError({ message: "Organization not found" });
|
||||
return org;
|
||||
};
|
||||
/*
|
||||
@ -286,8 +286,7 @@ export const orgServiceFactory = ({
|
||||
if (authEnforced) {
|
||||
const samlCfg = await samlConfigDAL.findEnforceableSamlCfg(orgId);
|
||||
if (!samlCfg)
|
||||
throw new BadRequestError({
|
||||
name: "No enforceable SAML config found",
|
||||
throw new NotFoundError({
|
||||
message: "No enforceable SAML config found"
|
||||
});
|
||||
}
|
||||
@ -298,7 +297,7 @@ export const orgServiceFactory = ({
|
||||
authEnforced,
|
||||
scimEnabled
|
||||
});
|
||||
if (!org) throw new BadRequestError({ name: "Org not found", message: "Organization not found" });
|
||||
if (!org) throw new NotFoundError({ message: "Organization not found" });
|
||||
return org;
|
||||
};
|
||||
/*
|
||||
@ -383,7 +382,10 @@ export const orgServiceFactory = ({
|
||||
) => {
|
||||
const { membership } = await permissionService.getUserOrgPermission(userId, orgId, actorAuthMethod, actorOrgId);
|
||||
if ((membership.role as OrgMembershipRole) !== OrgMembershipRole.Admin)
|
||||
throw new UnauthorizedError({ name: "Delete org by id", message: "Not an admin" });
|
||||
throw new ForbiddenRequestError({
|
||||
name: "DeleteOrganizationById",
|
||||
message: "Insufficient privileges"
|
||||
});
|
||||
|
||||
const organization = await orgDAL.deleteById(orgId);
|
||||
if (organization.customerId) {
|
||||
@ -413,12 +415,12 @@ export const orgServiceFactory = ({
|
||||
});
|
||||
if (!foundMembership) throw new NotFoundError({ message: "Failed to find organization membership" });
|
||||
if (foundMembership.userId === userId)
|
||||
throw new BadRequestError({ message: "Cannot update own organization membership" });
|
||||
throw new UnauthorizedError({ message: "Cannot update own organization membership" });
|
||||
|
||||
const isCustomRole = !Object.values(OrgMembershipRole).includes(role as OrgMembershipRole);
|
||||
if (role && isCustomRole) {
|
||||
const customRole = await orgRoleDAL.findOne({ slug: role, orgId });
|
||||
if (!customRole) throw new BadRequestError({ name: "Update membership", message: "Role not found" });
|
||||
if (!customRole) throw new BadRequestError({ name: "UpdateMembership", message: "Organization role not found" });
|
||||
|
||||
const plan = await licenseService.getPlan(orgId);
|
||||
if (!plan?.rbac)
|
||||
@ -461,8 +463,8 @@ export const orgServiceFactory = ({
|
||||
const isEmailInvalid = await isDisposableEmail(inviteeEmails);
|
||||
if (isEmailInvalid) {
|
||||
throw new BadRequestError({
|
||||
message: "Provided a disposable email",
|
||||
name: "Org invite"
|
||||
message: "Disposable emails are not allowed",
|
||||
name: "InviteUser"
|
||||
});
|
||||
}
|
||||
const plan = await licenseService.getPlan(orgId);
|
||||
@ -483,8 +485,8 @@ export const orgServiceFactory = ({
|
||||
})
|
||||
: [];
|
||||
if (projectsToInvite.length !== invitedProjects?.length) {
|
||||
throw new UnauthorizedError({
|
||||
message: "One or more project doesn't have access to"
|
||||
throw new ForbiddenRequestError({
|
||||
message: "Access denied to one or more of the specified projects"
|
||||
});
|
||||
}
|
||||
|
||||
@ -495,7 +497,7 @@ export const orgServiceFactory = ({
|
||||
}
|
||||
|
||||
const mailsForOrgInvitation: { email: string; userId: string; firstName: string; lastName: string }[] = [];
|
||||
const mailsForProjectInvitaion: { email: string[]; projectName: string }[] = [];
|
||||
const mailsForProjectInvitation: { email: string[]; projectName: string }[] = [];
|
||||
const newProjectMemberships: TProjectMemberships[] = [];
|
||||
await orgDAL.transaction(async (tx) => {
|
||||
const users: Pick<TUsers, "id" | "firstName" | "lastName" | "email" | "username">[] = [];
|
||||
@ -563,6 +565,7 @@ export const orgServiceFactory = ({
|
||||
if (plan?.slug !== "enterprise" && plan?.memberLimit && plan.membersUsed >= plan.memberLimit) {
|
||||
// limit imposed on number of members allowed / number of members used exceeds the number of members allowed
|
||||
throw new BadRequestError({
|
||||
name: "InviteUser",
|
||||
message: "Failed to invite member due to member limit reached. Upgrade plan to invite more members."
|
||||
});
|
||||
}
|
||||
@ -570,12 +573,14 @@ export const orgServiceFactory = ({
|
||||
if (plan?.slug !== "enterprise" && plan?.identityLimit && plan.identitiesUsed >= plan.identityLimit) {
|
||||
// limit imposed on number of identities allowed / number of identities used exceeds the number of identities allowed
|
||||
throw new BadRequestError({
|
||||
name: "InviteUser",
|
||||
message: "Failed to invite member due to member limit reached. Upgrade plan to invite more members."
|
||||
});
|
||||
}
|
||||
|
||||
if (org?.authEnforced) {
|
||||
throw new BadRequestError({
|
||||
throw new ForbiddenRequestError({
|
||||
name: "InviteUser",
|
||||
message: "Failed to invite user due to org-level auth enforced for organization"
|
||||
});
|
||||
}
|
||||
@ -587,7 +592,7 @@ export const orgServiceFactory = ({
|
||||
if (isCustomOrgRole) {
|
||||
const customRole = await orgRoleDAL.findOne({ slug: organizationRoleSlug, orgId });
|
||||
if (!customRole)
|
||||
throw new BadRequestError({ name: "Invite membership", message: "Organization role not found" });
|
||||
throw new NotFoundError({ name: "InviteUser", message: "Custom organization role not found" });
|
||||
roleId = customRole.id;
|
||||
}
|
||||
|
||||
@ -660,6 +665,7 @@ export const orgServiceFactory = ({
|
||||
if (hasCustomRole) {
|
||||
if (!plan?.rbac)
|
||||
throw new BadRequestError({
|
||||
name: "InviteUser",
|
||||
message:
|
||||
"Failed to assign custom role due to RBAC restriction. Upgrade plan to assign custom role to member."
|
||||
});
|
||||
@ -671,29 +677,33 @@ export const orgServiceFactory = ({
|
||||
$in: { slug: customProjectRoles.map((role) => role) }
|
||||
})
|
||||
: [];
|
||||
if (customRoles.length !== customProjectRoles.length)
|
||||
throw new BadRequestError({ message: "Custom role not found" });
|
||||
if (customRoles.length !== customProjectRoles.length) {
|
||||
throw new NotFoundError({ name: "InviteUser", message: "Custom project role not found" });
|
||||
}
|
||||
|
||||
const customRolesGroupBySlug = groupBy(customRoles, ({ slug }) => slug);
|
||||
|
||||
const ghostUser = await projectDAL.findProjectGhostUser(projectId, tx);
|
||||
if (!ghostUser) {
|
||||
throw new BadRequestError({
|
||||
message: "Failed to find sudo user"
|
||||
throw new NotFoundError({
|
||||
name: "InviteUser",
|
||||
message: "Failed to find project owner"
|
||||
});
|
||||
}
|
||||
|
||||
const ghostUserLatestKey = await projectKeyDAL.findLatestProjectKey(ghostUser.id, projectId, tx);
|
||||
if (!ghostUserLatestKey) {
|
||||
throw new BadRequestError({
|
||||
message: "Failed to find sudo user latest key"
|
||||
throw new NotFoundError({
|
||||
name: "InviteUser",
|
||||
message: "Failed to find project owner's latest key"
|
||||
});
|
||||
}
|
||||
|
||||
const bot = await projectBotDAL.findOne({ projectId }, tx);
|
||||
if (!bot) {
|
||||
throw new BadRequestError({
|
||||
message: "Failed to find bot"
|
||||
throw new NotFoundError({
|
||||
name: "InviteUser",
|
||||
message: "Failed to find project bot"
|
||||
});
|
||||
}
|
||||
|
||||
@ -746,7 +756,7 @@ export const orgServiceFactory = ({
|
||||
})),
|
||||
tx
|
||||
);
|
||||
mailsForProjectInvitaion.push({
|
||||
mailsForProjectInvitation.push({
|
||||
email: userWithEncryptionKeyInvitedToProject
|
||||
.filter((el) => !userIdsWithOrgInvitation.has(el.userId))
|
||||
.map((el) => el.email || el.username),
|
||||
@ -790,7 +800,7 @@ export const orgServiceFactory = ({
|
||||
);
|
||||
|
||||
await Promise.allSettled(
|
||||
mailsForProjectInvitaion
|
||||
mailsForProjectInvitation
|
||||
.filter((el) => Boolean(el.email.length))
|
||||
.map(async (el) => {
|
||||
return smtpService.sendMail({
|
||||
@ -819,17 +829,17 @@ export const orgServiceFactory = ({
|
||||
const verifyUserToOrg = async ({ orgId, email, code }: TVerifyUserToOrgDTO) => {
|
||||
const user = await userDAL.findUserByUsername(email);
|
||||
if (!user) {
|
||||
throw new BadRequestError({ message: "Invalid request", name: "Verify user to org" });
|
||||
throw new NotFoundError({ message: "User not found" });
|
||||
}
|
||||
const [orgMembership] = await orgDAL.findMembership({
|
||||
[`${TableName.OrgMembership}.userId` as "userId"]: user.id,
|
||||
status: OrgMembershipStatus.Invited,
|
||||
[`${TableName.OrgMembership}.orgId` as "orgId"]: orgId
|
||||
});
|
||||
|
||||
if (!orgMembership)
|
||||
throw new BadRequestError({
|
||||
message: "Failed to find invitation",
|
||||
name: "Verify user to org"
|
||||
throw new NotFoundError({
|
||||
message: "No pending invitation found"
|
||||
});
|
||||
|
||||
await tokenService.validateTokenForUser({
|
||||
@ -881,8 +891,12 @@ export const orgServiceFactory = ({
|
||||
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Member);
|
||||
|
||||
const membership = await orgMembershipDAL.findOrgMembershipById(membershipId);
|
||||
if (!membership) throw new NotFoundError({ message: "Failed to find organization membership" });
|
||||
if (membership.orgId !== orgId) 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 ForbiddenRequestError({ message: "Membership does not belong to organization" });
|
||||
}
|
||||
|
||||
return membership;
|
||||
};
|
||||
@ -923,7 +937,9 @@ export const orgServiceFactory = ({
|
||||
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Member);
|
||||
|
||||
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" });
|
||||
|
||||
const projectMemberships = await projectMembershipDAL.findProjectMembershipsByUserId(orgId, membership.user.id);
|
||||
|
@ -2,7 +2,7 @@ import { ForbiddenError } from "@casl/ability";
|
||||
|
||||
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service";
|
||||
import { ProjectPermissionActions, ProjectPermissionSub } from "@app/ee/services/permission/project-permission";
|
||||
import { NotFoundError, UnauthorizedError } from "@app/lib/errors";
|
||||
import { ForbiddenRequestError, NotFoundError } from "@app/lib/errors";
|
||||
import { groupBy } from "@app/lib/fn";
|
||||
import { TPkiCollectionDALFactory } from "@app/services/pki-collection/pki-collection-dal";
|
||||
import { pkiItemTypeToNameMap } from "@app/services/pki-collection/pki-collection-types";
|
||||
@ -86,7 +86,7 @@ export const pkiAlertServiceFactory = ({
|
||||
const pkiCollection = await pkiCollectionDAL.findById(pkiCollectionId);
|
||||
if (!pkiCollection) throw new NotFoundError({ message: "PKI collection not found" });
|
||||
if (pkiCollection.projectId !== projectId)
|
||||
throw new UnauthorizedError({ message: "PKI collection not found in project" });
|
||||
throw new ForbiddenRequestError({ message: "PKI collection does not belong to the specified project." });
|
||||
|
||||
const alert = await pkiAlertDAL.create({
|
||||
projectId,
|
||||
@ -141,8 +141,9 @@ export const pkiAlertServiceFactory = ({
|
||||
if (pkiCollectionId) {
|
||||
const pkiCollection = await pkiCollectionDAL.findById(pkiCollectionId);
|
||||
if (!pkiCollection) throw new NotFoundError({ message: "PKI collection not found" });
|
||||
if (pkiCollection.projectId !== alert.projectId)
|
||||
throw new UnauthorizedError({ message: "PKI collection not found in project" });
|
||||
if (pkiCollection.projectId !== alert.projectId) {
|
||||
throw new ForbiddenRequestError({ message: "PKI collection does not belong to the specified project." });
|
||||
}
|
||||
}
|
||||
|
||||
alert = await pkiAlertDAL.updateById(alertId, {
|
||||
|
@ -6,7 +6,7 @@ import {
|
||||
infisicalSymmetricDecrypt,
|
||||
infisicalSymmetricEncypt
|
||||
} from "@app/lib/crypto/encryption";
|
||||
import { BadRequestError } from "@app/lib/errors";
|
||||
import { NotFoundError } from "@app/lib/errors";
|
||||
import { TProjectBotDALFactory } from "@app/services/project-bot/project-bot-dal";
|
||||
|
||||
import { TProjectDALFactory } from "../project/project-dal";
|
||||
@ -27,7 +27,7 @@ export const getBotKeyFnFactory = (
|
||||
const getBotKeyFn = async (projectId: string) => {
|
||||
const project = await projectDAL.findById(projectId);
|
||||
if (!project)
|
||||
throw new BadRequestError({
|
||||
throw new NotFoundError({
|
||||
message: "Project not found during bot lookup. Are you sure you are using the correct project ID?"
|
||||
});
|
||||
|
||||
@ -39,7 +39,7 @@ export const getBotKeyFnFactory = (
|
||||
if (!bot || !bot.isActive || !bot.encryptedProjectKey || !bot.encryptedProjectKeyNonce) {
|
||||
// trying to set bot automatically
|
||||
const projectV1Keys = await projectBotDAL.findProjectUserWorkspaceKey(projectId);
|
||||
if (!projectV1Keys) throw new BadRequestError({ message: "Bot not found. Please ask admin user to login" });
|
||||
if (!projectV1Keys) throw new NotFoundError({ message: "Bot not found. Please ask admin user to login" });
|
||||
|
||||
let userPrivateKey = "";
|
||||
if (
|
||||
|
@ -5,7 +5,7 @@ import { TPermissionServiceFactory } from "@app/ee/services/permission/permissio
|
||||
import { ProjectPermissionActions, ProjectPermissionSub } from "@app/ee/services/permission/project-permission";
|
||||
import { generateAsymmetricKeyPair } from "@app/lib/crypto";
|
||||
import { infisicalSymmetricEncypt } from "@app/lib/crypto/encryption";
|
||||
import { BadRequestError } from "@app/lib/errors";
|
||||
import { BadRequestError, NotFoundError } from "@app/lib/errors";
|
||||
|
||||
import { TProjectDALFactory } from "../project/project-dal";
|
||||
import { TProjectBotDALFactory } from "./project-bot-dal";
|
||||
@ -91,7 +91,7 @@ export const projectBotServiceFactory = ({
|
||||
const bot = await projectBotDAL.findProjectByBotId(botId);
|
||||
return bot;
|
||||
} catch (e) {
|
||||
throw new BadRequestError({ message: "Failed to find bot by ID" });
|
||||
throw new NotFoundError({ message: "Failed to find bot by ID" });
|
||||
}
|
||||
};
|
||||
|
||||
@ -105,7 +105,7 @@ export const projectBotServiceFactory = ({
|
||||
isActive
|
||||
}: TSetActiveStateDTO) => {
|
||||
const bot = await projectBotDAL.findById(botId);
|
||||
if (!bot) throw new BadRequestError({ message: "Bot not found" });
|
||||
if (!bot) throw new NotFoundError({ message: "Bot not found" });
|
||||
|
||||
const { permission } = await permissionService.getProjectPermission(
|
||||
actor,
|
||||
@ -119,7 +119,7 @@ export const projectBotServiceFactory = ({
|
||||
const project = await projectBotDAL.findProjectByBotId(botId);
|
||||
|
||||
if (!project) {
|
||||
throw new BadRequestError({ message: "Failed to find project by bot ID" });
|
||||
throw new NotFoundError({ message: "Failed to find project by bot ID" });
|
||||
}
|
||||
|
||||
if (project.version === ProjectVersion.V2) {
|
||||
@ -128,7 +128,7 @@ export const projectBotServiceFactory = ({
|
||||
|
||||
if (isActive) {
|
||||
if (!botKey?.nonce || !botKey?.encryptedKey) {
|
||||
throw new BadRequestError({ message: "Failed to set bot active - missing bot key" });
|
||||
throw new NotFoundError({ message: "Bot key not found, failed to set bot active" });
|
||||
}
|
||||
const doc = await projectBotDAL.updateById(botId, {
|
||||
isActive: true,
|
||||
|
@ -50,7 +50,7 @@ export const projectEnvServiceFactory = ({
|
||||
if (existingEnv)
|
||||
throw new BadRequestError({
|
||||
message: "Environment with slug already exist",
|
||||
name: "Create envv"
|
||||
name: "CreateEnvironment"
|
||||
});
|
||||
|
||||
const project = await projectDAL.findById(projectId);
|
||||
@ -94,14 +94,14 @@ export const projectEnvServiceFactory = ({
|
||||
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.Environments);
|
||||
|
||||
const oldEnv = await projectEnvDAL.findOne({ id, projectId });
|
||||
if (!oldEnv) throw new BadRequestError({ message: "Environment not found" });
|
||||
if (!oldEnv) throw new NotFoundError({ message: "Environment not found" });
|
||||
|
||||
if (slug) {
|
||||
const existingEnv = await projectEnvDAL.findOne({ slug, projectId });
|
||||
if (existingEnv && existingEnv.id !== id) {
|
||||
throw new BadRequestError({
|
||||
message: "Environment with slug already exist",
|
||||
name: "Create envv"
|
||||
name: "UpdateEnvironment"
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -128,9 +128,9 @@ export const projectEnvServiceFactory = ({
|
||||
const env = await projectEnvDAL.transaction(async (tx) => {
|
||||
const [doc] = await projectEnvDAL.delete({ id, projectId }, tx);
|
||||
if (!doc)
|
||||
throw new BadRequestError({
|
||||
throw new NotFoundError({
|
||||
message: "Env doesn't exist",
|
||||
name: "Re-order env"
|
||||
name: "DeleteEnvironment"
|
||||
});
|
||||
|
||||
await projectEnvDAL.updateAllPosition(projectId, doc.position, -1, tx);
|
||||
|
@ -8,7 +8,7 @@ import { TPermissionServiceFactory } from "@app/ee/services/permission/permissio
|
||||
import { ProjectPermissionActions, ProjectPermissionSub } from "@app/ee/services/permission/project-permission";
|
||||
import { TProjectUserAdditionalPrivilegeDALFactory } from "@app/ee/services/project-user-additional-privilege/project-user-additional-privilege-dal";
|
||||
import { getConfig } from "@app/lib/config/env";
|
||||
import { BadRequestError, NotFoundError } from "@app/lib/errors";
|
||||
import { BadRequestError, ForbiddenRequestError, NotFoundError } from "@app/lib/errors";
|
||||
import { groupBy } from "@app/lib/fn";
|
||||
|
||||
import { TUserGroupMembershipDALFactory } from "../../ee/services/group/user-group-membership-dal";
|
||||
@ -143,7 +143,7 @@ export const projectMembershipServiceFactory = ({
|
||||
sendEmails = true
|
||||
}: TAddUsersToWorkspaceDTO) => {
|
||||
const project = await projectDAL.findById(projectId);
|
||||
if (!project) throw new BadRequestError({ message: "Project not found" });
|
||||
if (!project) throw new NotFoundError({ message: "Project not found" });
|
||||
|
||||
const { permission } = await permissionService.getProjectPermission(
|
||||
actor,
|
||||
@ -236,10 +236,7 @@ export const projectMembershipServiceFactory = ({
|
||||
|
||||
const membershipUser = await userDAL.findUserByProjectMembershipId(membershipId);
|
||||
if (membershipUser?.isGhost || membershipUser?.projectId !== projectId) {
|
||||
throw new BadRequestError({
|
||||
message: "Unauthorized member update",
|
||||
name: "Update project membership"
|
||||
});
|
||||
throw new ForbiddenRequestError({ message: "Forbidden member update" });
|
||||
}
|
||||
|
||||
// validate custom roles input
|
||||
@ -261,7 +258,9 @@ export const projectMembershipServiceFactory = ({
|
||||
$in: { slug: customInputRoles.map(({ role }) => role) }
|
||||
})
|
||||
: [];
|
||||
if (customRoles.length !== customInputRoles.length) throw new BadRequestError({ message: "Custom role not found" });
|
||||
if (customRoles.length !== customInputRoles.length) {
|
||||
throw new NotFoundError({ message: "Custom project roles not found" });
|
||||
}
|
||||
const customRolesGroupBySlug = groupBy(customRoles, ({ slug }) => slug);
|
||||
|
||||
const sanitizedProjectMembershipRoles = roles.map((inputRole) => {
|
||||
@ -317,9 +316,9 @@ export const projectMembershipServiceFactory = ({
|
||||
const member = await userDAL.findUserByProjectMembershipId(membershipId);
|
||||
|
||||
if (member?.isGhost) {
|
||||
throw new BadRequestError({
|
||||
message: "Unauthorized member delete",
|
||||
name: "Delete project membership"
|
||||
throw new ForbiddenRequestError({
|
||||
message: "Forbidden membership deletion",
|
||||
name: "DeleteProjectMembership"
|
||||
});
|
||||
}
|
||||
|
||||
@ -352,9 +351,8 @@ export const projectMembershipServiceFactory = ({
|
||||
const project = await projectDAL.findById(projectId);
|
||||
|
||||
if (!project) {
|
||||
throw new BadRequestError({
|
||||
message: "Project not found",
|
||||
name: "Delete project membership"
|
||||
throw new NotFoundError({
|
||||
message: "Project not found"
|
||||
});
|
||||
}
|
||||
|
||||
@ -428,7 +426,7 @@ export const projectMembershipServiceFactory = ({
|
||||
}
|
||||
|
||||
const project = await projectDAL.findById(projectId);
|
||||
if (!project) throw new BadRequestError({ message: "Project not found" });
|
||||
if (!project) throw new NotFoundError({ message: "Project not found" });
|
||||
|
||||
if (project.version === ProjectVersion.V1) {
|
||||
throw new BadRequestError({
|
||||
@ -439,7 +437,7 @@ export const projectMembershipServiceFactory = ({
|
||||
const projectMembers = await projectMembershipDAL.findAllProjectMembers(projectId);
|
||||
|
||||
if (!projectMembers?.length) {
|
||||
throw new BadRequestError({ message: "Failed to find project members" });
|
||||
throw new NotFoundError({ message: "Failed to find project members" });
|
||||
}
|
||||
|
||||
if (projectMembers.length < 2) {
|
||||
|
@ -10,7 +10,7 @@ import {
|
||||
ProjectPermissionSub,
|
||||
validateProjectPermissions
|
||||
} from "@app/ee/services/permission/project-permission";
|
||||
import { BadRequestError } from "@app/lib/errors";
|
||||
import { BadRequestError, NotFoundError } from "@app/lib/errors";
|
||||
|
||||
import { ActorAuthMethod } from "../auth/auth-type";
|
||||
import { TIdentityProjectMembershipRoleDALFactory } from "../identity-project/identity-project-membership-role-dal";
|
||||
@ -44,7 +44,7 @@ export const projectRoleServiceFactory = ({
|
||||
}: TProjectRoleServiceFactoryDep) => {
|
||||
const createRole = async ({ projectSlug, data, actor, actorId, actorAuthMethod, actorOrgId }: TCreateRoleDTO) => {
|
||||
const project = await projectDAL.findProjectBySlug(projectSlug, actorOrgId);
|
||||
if (!project) throw new BadRequestError({ message: "Project not found" });
|
||||
if (!project) throw new NotFoundError({ message: "Project not found" });
|
||||
const projectId = project.id;
|
||||
|
||||
const { permission } = await permissionService.getProjectPermission(
|
||||
@ -56,7 +56,9 @@ export const projectRoleServiceFactory = ({
|
||||
);
|
||||
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Create, ProjectPermissionSub.Role);
|
||||
const existingRole = await projectRoleDAL.findOne({ slug: data.slug, projectId });
|
||||
if (existingRole) throw new BadRequestError({ name: "Create Role", message: "Duplicate role" });
|
||||
if (existingRole) {
|
||||
throw new BadRequestError({ name: "Create Role", message: "Project role with same slug already exists" });
|
||||
}
|
||||
|
||||
validateProjectPermissions(data.permissions);
|
||||
|
||||
@ -76,7 +78,7 @@ export const projectRoleServiceFactory = ({
|
||||
roleSlug
|
||||
}: TGetRoleBySlugDTO) => {
|
||||
const project = await projectDAL.findProjectBySlug(projectSlug, actorOrgId);
|
||||
if (!project) throw new BadRequestError({ message: "Project not found" });
|
||||
if (!project) throw new NotFoundError({ message: "Project not found" });
|
||||
const projectId = project.id;
|
||||
|
||||
const { permission } = await permissionService.getProjectPermission(
|
||||
@ -93,7 +95,7 @@ export const projectRoleServiceFactory = ({
|
||||
}
|
||||
|
||||
const customRole = await projectRoleDAL.findOne({ slug: roleSlug, projectId });
|
||||
if (!customRole) throw new BadRequestError({ message: "Role not found" });
|
||||
if (!customRole) throw new NotFoundError({ message: "Project role not found" });
|
||||
return { ...customRole, permissions: unpackPermissions(customRole.permissions) };
|
||||
};
|
||||
|
||||
@ -107,7 +109,7 @@ export const projectRoleServiceFactory = ({
|
||||
data
|
||||
}: TUpdateRoleDTO) => {
|
||||
const project = await projectDAL.findProjectBySlug(projectSlug, actorOrgId);
|
||||
if (!project) throw new BadRequestError({ message: "Project not found" });
|
||||
if (!project) throw new NotFoundError({ message: "Project not found" });
|
||||
const projectId = project.id;
|
||||
|
||||
const { permission } = await permissionService.getProjectPermission(
|
||||
@ -122,7 +124,7 @@ export const projectRoleServiceFactory = ({
|
||||
if (data?.slug) {
|
||||
const existingRole = await projectRoleDAL.findOne({ slug: data.slug, projectId });
|
||||
if (existingRole && existingRole.id !== roleId)
|
||||
throw new BadRequestError({ name: "Update Role", message: "Duplicate role" });
|
||||
throw new BadRequestError({ name: "Update Role", message: "Project role with the same slug already exists" });
|
||||
}
|
||||
|
||||
if (data.permissions) {
|
||||
@ -136,13 +138,13 @@ export const projectRoleServiceFactory = ({
|
||||
permissions: data.permissions ? data.permissions : undefined
|
||||
}
|
||||
);
|
||||
if (!updatedRole) throw new BadRequestError({ message: "Role not found", name: "Update role" });
|
||||
if (!updatedRole) throw new NotFoundError({ message: "Project role not found", name: "Update role" });
|
||||
return { ...updatedRole, permissions: unpackPermissions(updatedRole.permissions) };
|
||||
};
|
||||
|
||||
const deleteRole = async ({ actor, actorId, actorAuthMethod, actorOrgId, projectSlug, roleId }: TDeleteRoleDTO) => {
|
||||
const project = await projectDAL.findProjectBySlug(projectSlug, actorOrgId);
|
||||
if (!project) throw new BadRequestError({ message: "Project not found" });
|
||||
if (!project) throw new NotFoundError({ message: "Project not found" });
|
||||
const projectId = project.id;
|
||||
|
||||
const { permission } = await permissionService.getProjectPermission(
|
||||
@ -171,7 +173,7 @@ export const projectRoleServiceFactory = ({
|
||||
}
|
||||
|
||||
const [deletedRole] = await projectRoleDAL.delete({ id: roleId, projectId });
|
||||
if (!deletedRole) throw new BadRequestError({ message: "Role not found", name: "Delete role" });
|
||||
if (!deletedRole) throw new NotFoundError({ message: "Project role not found", name: "Delete role" });
|
||||
|
||||
return { ...deletedRole, permissions: unpackPermissions(deletedRole.permissions) };
|
||||
};
|
||||
|
@ -2,7 +2,7 @@ import { Knex } from "knex";
|
||||
|
||||
import { TDbClient } from "@app/db";
|
||||
import { ProjectsSchema, ProjectUpgradeStatus, ProjectVersion, TableName, TProjectsUpdate } from "@app/db/schemas";
|
||||
import { BadRequestError, DatabaseError } from "@app/lib/errors";
|
||||
import { BadRequestError, DatabaseError, NotFoundError, UnauthorizedError } from "@app/lib/errors";
|
||||
import { ormify, selectAllTableCols, sqlNestRelationships } from "@app/lib/knex";
|
||||
|
||||
import { Filter, ProjectFilterType } from "./project-types";
|
||||
@ -186,7 +186,7 @@ export const projectDALFactory = (db: TDbClient) => {
|
||||
})?.[0];
|
||||
|
||||
if (!project) {
|
||||
throw new BadRequestError({ message: "Project not found" });
|
||||
throw new NotFoundError({ message: "Project not found" });
|
||||
}
|
||||
|
||||
return project;
|
||||
@ -198,7 +198,7 @@ export const projectDALFactory = (db: TDbClient) => {
|
||||
const findProjectBySlug = async (slug: string, orgId: string | undefined) => {
|
||||
try {
|
||||
if (!orgId) {
|
||||
throw new BadRequestError({ message: "Organization ID is required when querying with slugs" });
|
||||
throw new UnauthorizedError({ message: "Organization ID is required when querying with slugs" });
|
||||
}
|
||||
|
||||
const projects = await db
|
||||
@ -235,7 +235,7 @@ export const projectDALFactory = (db: TDbClient) => {
|
||||
})?.[0];
|
||||
|
||||
if (!project) {
|
||||
throw new BadRequestError({ message: "Project not found" });
|
||||
throw new NotFoundError({ message: "Project not found" });
|
||||
}
|
||||
|
||||
return project;
|
||||
@ -251,7 +251,7 @@ export const projectDALFactory = (db: TDbClient) => {
|
||||
}
|
||||
if (filter.type === ProjectFilterType.SLUG) {
|
||||
if (!filter.orgId) {
|
||||
throw new BadRequestError({
|
||||
throw new UnauthorizedError({
|
||||
message: "Organization ID is required when querying with slugs"
|
||||
});
|
||||
}
|
||||
@ -295,7 +295,7 @@ export const projectDALFactory = (db: TDbClient) => {
|
||||
.first();
|
||||
|
||||
if (!project) {
|
||||
throw new BadRequestError({ message: "Project not found" });
|
||||
throw new NotFoundError({ message: "Project not found" });
|
||||
}
|
||||
|
||||
return {
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user