Merge pull request #1449 from Infisical/daniel/slug-projects

(Feat): V2 slugified project routes
This commit is contained in:
Maidul Islam
2024-03-17 13:54:20 -04:00
committed by GitHub
127 changed files with 3153 additions and 937 deletions
+3 -1
View File
@@ -10,7 +10,7 @@ import { seedData1 } from "@app/db/seed-data";
import { initEnvConfig } from "@app/lib/config/env"; import { initEnvConfig } from "@app/lib/config/env";
import { initLogger } from "@app/lib/logger"; import { initLogger } from "@app/lib/logger";
import { main } from "@app/server/app"; import { main } from "@app/server/app";
import { AuthTokenType } from "@app/services/auth/auth-type"; import { AuthMethod, AuthTokenType } from "@app/services/auth/auth-type";
import { mockQueue } from "./mocks/queue"; import { mockQueue } from "./mocks/queue";
import { mockSmtpServer } from "./mocks/smtp"; import { mockSmtpServer } from "./mocks/smtp";
@@ -52,6 +52,8 @@ export default {
authTokenType: AuthTokenType.ACCESS_TOKEN, authTokenType: AuthTokenType.ACCESS_TOKEN,
userId: seedData1.id, userId: seedData1.id,
tokenVersionId: seedData1.token.id, tokenVersionId: seedData1.token.id,
authMethod: AuthMethod.EMAIL,
organizationId: seedData1.organization.id,
accessVersion: 1 accessVersion: 1
}, },
cfg.AUTH_SECRET, cfg.AUTH_SECRET,
+2 -1
View File
@@ -19,7 +19,7 @@ import { TApiKeyServiceFactory } from "@app/services/api-key/api-key-service";
import { TAuthLoginFactory } from "@app/services/auth/auth-login-service"; import { TAuthLoginFactory } from "@app/services/auth/auth-login-service";
import { TAuthPasswordFactory } from "@app/services/auth/auth-password-service"; import { TAuthPasswordFactory } from "@app/services/auth/auth-password-service";
import { TAuthSignupFactory } from "@app/services/auth/auth-signup-service"; import { TAuthSignupFactory } from "@app/services/auth/auth-signup-service";
import { ActorType } from "@app/services/auth/auth-type"; import { ActorAuthMethod, ActorType } from "@app/services/auth/auth-type";
import { TAuthTokenServiceFactory } from "@app/services/auth-token/auth-token-service"; import { TAuthTokenServiceFactory } from "@app/services/auth-token/auth-token-service";
import { TIdentityServiceFactory } from "@app/services/identity/identity-service"; import { TIdentityServiceFactory } from "@app/services/identity/identity-service";
import { TIdentityAccessTokenServiceFactory } from "@app/services/identity-access-token/identity-access-token-service"; import { TIdentityAccessTokenServiceFactory } from "@app/services/identity-access-token/identity-access-token-service";
@@ -59,6 +59,7 @@ declare module "fastify" {
// identity injection. depending on which kinda of token the information is filled in auth // identity injection. depending on which kinda of token the information is filled in auth
auth: TAuthMode; auth: TAuthMode;
permission: { permission: {
authMethod: ActorAuthMethod;
type: ActorType; type: ActorType;
id: string; id: string;
orgId?: string; orgId?: string;
+3
View File
@@ -122,6 +122,7 @@ export const registerLdapRouter = async (server: FastifyZodProvider) => {
actor: req.permission.type, actor: req.permission.type,
actorId: req.permission.id, actorId: req.permission.id,
orgId: req.query.organizationId, orgId: req.query.organizationId,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId actorOrgId: req.permission.orgId
}); });
return ldap; return ldap;
@@ -151,6 +152,7 @@ export const registerLdapRouter = async (server: FastifyZodProvider) => {
actor: req.permission.type, actor: req.permission.type,
actorId: req.permission.id, actorId: req.permission.id,
orgId: req.body.organizationId, orgId: req.body.organizationId,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
...req.body ...req.body
}); });
@@ -184,6 +186,7 @@ export const registerLdapRouter = async (server: FastifyZodProvider) => {
actor: req.permission.type, actor: req.permission.type,
actorId: req.permission.id, actorId: req.permission.id,
orgId: req.body.organizationId, orgId: req.body.organizationId,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
...req.body ...req.body
}); });
+19 -1
View File
@@ -24,6 +24,7 @@ export const registerLicenseRouter = async (server: FastifyZodProvider) => {
actor: req.permission.type, actor: req.permission.type,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
orgId: req.params.organizationId, orgId: req.params.organizationId,
actorAuthMethod: req.permission.authMethod,
billingCycle: req.query.billingCycle billingCycle: req.query.billingCycle
}); });
return data; return data;
@@ -45,6 +46,7 @@ export const registerLicenseRouter = async (server: FastifyZodProvider) => {
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
actorAuthMethod: req.permission.authMethod,
orgId: req.params.organizationId orgId: req.params.organizationId
}); });
return { plan }; return { plan };
@@ -66,6 +68,8 @@ export const registerLicenseRouter = async (server: FastifyZodProvider) => {
const data = await server.services.license.getOrgPlan({ const data = await server.services.license.getOrgPlan({
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorOrgId: req.permission.orgId,
actorAuthMethod: req.permission.authMethod,
orgId: req.params.organizationId orgId: req.params.organizationId
}); });
return data; return data;
@@ -89,6 +93,7 @@ export const registerLicenseRouter = async (server: FastifyZodProvider) => {
actor: req.permission.type, actor: req.permission.type,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
orgId: req.params.organizationId, orgId: req.params.organizationId,
actorAuthMethod: req.permission.authMethod,
success_url: req.body.success_url success_url: req.body.success_url
}); });
return data; return data;
@@ -110,6 +115,7 @@ export const registerLicenseRouter = async (server: FastifyZodProvider) => {
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
actorAuthMethod: req.permission.authMethod,
orgId: req.params.organizationId orgId: req.params.organizationId
}); });
return data; return data;
@@ -131,6 +137,7 @@ export const registerLicenseRouter = async (server: FastifyZodProvider) => {
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
actorAuthMethod: req.permission.authMethod,
orgId: req.params.organizationId orgId: req.params.organizationId
}); });
return data; return data;
@@ -152,6 +159,7 @@ export const registerLicenseRouter = async (server: FastifyZodProvider) => {
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
actorAuthMethod: req.permission.authMethod,
orgId: req.params.organizationId orgId: req.params.organizationId
}); });
return data; return data;
@@ -173,6 +181,7 @@ export const registerLicenseRouter = async (server: FastifyZodProvider) => {
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
actorAuthMethod: req.permission.authMethod,
orgId: req.params.organizationId orgId: req.params.organizationId
}); });
return data; return data;
@@ -198,6 +207,7 @@ export const registerLicenseRouter = async (server: FastifyZodProvider) => {
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
actorAuthMethod: req.permission.authMethod,
orgId: req.params.organizationId, orgId: req.params.organizationId,
name: req.body.name, name: req.body.name,
email: req.body.email email: req.body.email
@@ -221,6 +231,7 @@ export const registerLicenseRouter = async (server: FastifyZodProvider) => {
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
actorAuthMethod: req.permission.authMethod,
orgId: req.params.organizationId orgId: req.params.organizationId
}); });
return data; return data;
@@ -246,6 +257,7 @@ export const registerLicenseRouter = async (server: FastifyZodProvider) => {
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
actorAuthMethod: req.permission.authMethod,
orgId: req.params.organizationId, orgId: req.params.organizationId,
success_url: req.body.success_url, success_url: req.body.success_url,
cancel_url: req.body.cancel_url cancel_url: req.body.cancel_url
@@ -271,6 +283,7 @@ export const registerLicenseRouter = async (server: FastifyZodProvider) => {
const data = await server.services.license.delOrgPmtMethods({ const data = await server.services.license.delOrgPmtMethods({
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
orgId: req.params.organizationId, orgId: req.params.organizationId,
pmtMethodId: req.params.pmtMethodId pmtMethodId: req.params.pmtMethodId
@@ -295,6 +308,7 @@ export const registerLicenseRouter = async (server: FastifyZodProvider) => {
const data = await server.services.license.getOrgTaxIds({ const data = await server.services.license.getOrgTaxIds({
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
orgId: req.params.organizationId orgId: req.params.organizationId
}); });
@@ -322,6 +336,7 @@ export const registerLicenseRouter = async (server: FastifyZodProvider) => {
const data = await server.services.license.addOrgTaxId({ const data = await server.services.license.addOrgTaxId({
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
orgId: req.params.organizationId, orgId: req.params.organizationId,
type: req.body.type, type: req.body.type,
@@ -348,6 +363,7 @@ export const registerLicenseRouter = async (server: FastifyZodProvider) => {
const data = await server.services.license.delOrgTaxId({ const data = await server.services.license.delOrgTaxId({
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
orgId: req.params.organizationId, orgId: req.params.organizationId,
taxId: req.params.taxId taxId: req.params.taxId
@@ -373,7 +389,8 @@ export const registerLicenseRouter = async (server: FastifyZodProvider) => {
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
orgId: req.params.organizationId orgId: req.params.organizationId,
actorAuthMethod: req.permission.authMethod
}); });
return data; return data;
} }
@@ -396,6 +413,7 @@ export const registerLicenseRouter = async (server: FastifyZodProvider) => {
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
actorAuthMethod: req.permission.authMethod,
orgId: req.params.organizationId orgId: req.params.organizationId
}); });
return data; return data;
@@ -41,6 +41,7 @@ export const registerOrgRoleRouter = async (server: FastifyZodProvider) => {
req.permission.id, req.permission.id,
req.params.organizationId, req.params.organizationId,
req.body, req.body,
req.permission.authMethod,
req.permission.orgId req.permission.orgId
); );
return { role }; return { role };
@@ -84,6 +85,7 @@ export const registerOrgRoleRouter = async (server: FastifyZodProvider) => {
req.params.organizationId, req.params.organizationId,
req.params.roleId, req.params.roleId,
req.body, req.body,
req.permission.authMethod,
req.permission.orgId req.permission.orgId
); );
return { role }; return { role };
@@ -110,6 +112,7 @@ export const registerOrgRoleRouter = async (server: FastifyZodProvider) => {
req.permission.id, req.permission.id,
req.params.organizationId, req.params.organizationId,
req.params.roleId, req.params.roleId,
req.permission.authMethod,
req.permission.orgId req.permission.orgId
); );
return { role }; return { role };
@@ -138,6 +141,7 @@ export const registerOrgRoleRouter = async (server: FastifyZodProvider) => {
const roles = await server.services.orgRole.listRoles( const roles = await server.services.orgRole.listRoles(
req.permission.id, req.permission.id,
req.params.organizationId, req.params.organizationId,
req.permission.authMethod,
req.permission.orgId req.permission.orgId
); );
return { data: { roles } }; return { data: { roles } };
@@ -163,6 +167,7 @@ export const registerOrgRoleRouter = async (server: FastifyZodProvider) => {
const { permissions, membership } = await server.services.orgRole.getUserPermission( const { permissions, membership } = await server.services.orgRole.getUserPermission(
req.permission.id, req.permission.id,
req.params.organizationId, req.params.organizationId,
req.permission.authMethod,
req.permission.orgId req.permission.orgId
); );
return { permissions, membership }; return { permissions, membership };
@@ -31,6 +31,7 @@ export const registerProjectRoleRouter = async (server: FastifyZodProvider) => {
req.permission.id, req.permission.id,
req.params.projectId, req.params.projectId,
req.body, req.body,
req.permission.authMethod,
req.permission.orgId req.permission.orgId
); );
return { role }; return { role };
@@ -65,6 +66,7 @@ export const registerProjectRoleRouter = async (server: FastifyZodProvider) => {
req.params.projectId, req.params.projectId,
req.params.roleId, req.params.roleId,
req.body, req.body,
req.permission.authMethod,
req.permission.orgId req.permission.orgId
); );
return { role }; return { role };
@@ -92,6 +94,7 @@ export const registerProjectRoleRouter = async (server: FastifyZodProvider) => {
req.permission.id, req.permission.id,
req.params.projectId, req.params.projectId,
req.params.roleId, req.params.roleId,
req.permission.authMethod,
req.permission.orgId req.permission.orgId
); );
return { role }; return { role };
@@ -121,6 +124,7 @@ export const registerProjectRoleRouter = async (server: FastifyZodProvider) => {
req.permission.type, req.permission.type,
req.permission.id, req.permission.id,
req.params.projectId, req.params.projectId,
req.permission.authMethod,
req.permission.orgId req.permission.orgId
); );
return { data: { roles } }; return { data: { roles } };
@@ -148,6 +152,7 @@ export const registerProjectRoleRouter = async (server: FastifyZodProvider) => {
const { permissions, membership } = await server.services.projectRole.getUserPermission( const { permissions, membership } = await server.services.projectRole.getUserPermission(
req.permission.id, req.permission.id,
req.params.projectId, req.params.projectId,
req.permission.authMethod,
req.permission.orgId req.permission.orgId
); );
return { data: { permissions, membership } }; return { data: { permissions, membership } };
@@ -38,6 +38,7 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
handler: async (req) => { handler: async (req) => {
const secretSnapshots = await server.services.snapshot.listSnapshots({ const secretSnapshots = await server.services.snapshot.listSnapshots({
actor: req.permission.type, actor: req.permission.type,
actorAuthMethod: req.permission.authMethod,
actorId: req.permission.id, actorId: req.permission.id,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
projectId: req.params.workspaceId, projectId: req.params.workspaceId,
@@ -69,6 +70,7 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
const count = await server.services.snapshot.projectSecretSnapshotCount({ const count = await server.services.snapshot.projectSecretSnapshotCount({
actor: req.permission.type, actor: req.permission.type,
actorId: req.permission.id, actorId: req.permission.id,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
projectId: req.params.workspaceId, projectId: req.params.workspaceId,
environment: req.query.environment, environment: req.query.environment,
@@ -130,6 +132,7 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
const auditLogs = await server.services.auditLog.listProjectAuditLogs({ const auditLogs = await server.services.auditLog.listProjectAuditLogs({
actorId: req.permission.id, actorId: req.permission.id,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
actorAuthMethod: req.permission.authMethod,
projectId: req.params.workspaceId, projectId: req.params.workspaceId,
...req.query, ...req.query,
auditLogActor: req.query.actor, auditLogActor: req.query.actor,
+3
View File
@@ -231,6 +231,7 @@ export const registerSamlRouter = async (server: FastifyZodProvider) => {
actor: req.permission.type, actor: req.permission.type,
actorId: req.permission.id, actorId: req.permission.id,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
actorAuthMethod: req.permission.authMethod,
orgId: req.query.organizationId, orgId: req.query.organizationId,
type: "org" type: "org"
}); });
@@ -259,6 +260,7 @@ export const registerSamlRouter = async (server: FastifyZodProvider) => {
const saml = await server.services.saml.createSamlCfg({ const saml = await server.services.saml.createSamlCfg({
actor: req.permission.type, actor: req.permission.type,
actorId: req.permission.id, actorId: req.permission.id,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
orgId: req.body.organizationId, orgId: req.body.organizationId,
...req.body ...req.body
@@ -290,6 +292,7 @@ export const registerSamlRouter = async (server: FastifyZodProvider) => {
const saml = await server.services.saml.updateSamlCfg({ const saml = await server.services.saml.updateSamlCfg({
actor: req.permission.type, actor: req.permission.type,
actorId: req.permission.id, actorId: req.permission.id,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
orgId: req.body.organizationId, orgId: req.body.organizationId,
...req.body ...req.body
+3
View File
@@ -39,6 +39,7 @@ export const registerScimRouter = async (server: FastifyZodProvider) => {
actorId: req.permission.id, actorId: req.permission.id,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
orgId: req.body.organizationId, orgId: req.body.organizationId,
actorAuthMethod: req.permission.authMethod,
description: req.body.description, description: req.body.description,
ttlDays: req.body.ttlDays ttlDays: req.body.ttlDays
}); });
@@ -65,6 +66,7 @@ export const registerScimRouter = async (server: FastifyZodProvider) => {
const scimTokens = await server.services.scim.listScimTokens({ const scimTokens = await server.services.scim.listScimTokens({
actor: req.permission.type, actor: req.permission.type,
actorId: req.permission.id, actorId: req.permission.id,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
orgId: req.query.organizationId orgId: req.query.organizationId
}); });
@@ -92,6 +94,7 @@ export const registerScimRouter = async (server: FastifyZodProvider) => {
scimTokenId: req.params.scimTokenId, scimTokenId: req.params.scimTokenId,
actor: req.permission.type, actor: req.permission.type,
actorId: req.permission.id, actorId: req.permission.id,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId actorOrgId: req.permission.orgId
}); });
@@ -34,6 +34,7 @@ export const registerSecretApprovalPolicyRouter = async (server: FastifyZodProvi
const approval = await server.services.secretApprovalPolicy.createSecretApprovalPolicy({ const approval = await server.services.secretApprovalPolicy.createSecretApprovalPolicy({
actor: req.permission.type, actor: req.permission.type,
actorId: req.permission.id, actorId: req.permission.id,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
projectId: req.body.workspaceId, projectId: req.body.workspaceId,
...req.body, ...req.body,
@@ -72,6 +73,7 @@ export const registerSecretApprovalPolicyRouter = async (server: FastifyZodProvi
const approval = await server.services.secretApprovalPolicy.updateSecretApprovalPolicy({ const approval = await server.services.secretApprovalPolicy.updateSecretApprovalPolicy({
actor: req.permission.type, actor: req.permission.type,
actorId: req.permission.id, actorId: req.permission.id,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
...req.body, ...req.body,
secretPolicyId: req.params.sapId secretPolicyId: req.params.sapId
@@ -98,6 +100,7 @@ export const registerSecretApprovalPolicyRouter = async (server: FastifyZodProvi
const approval = await server.services.secretApprovalPolicy.deleteSecretApprovalPolicy({ const approval = await server.services.secretApprovalPolicy.deleteSecretApprovalPolicy({
actor: req.permission.type, actor: req.permission.type,
actorId: req.permission.id, actorId: req.permission.id,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
secretPolicyId: req.params.sapId secretPolicyId: req.params.sapId
}); });
@@ -123,6 +126,7 @@ export const registerSecretApprovalPolicyRouter = async (server: FastifyZodProvi
const approvals = await server.services.secretApprovalPolicy.getSecretApprovalPolicyByProjectId({ const approvals = await server.services.secretApprovalPolicy.getSecretApprovalPolicyByProjectId({
actor: req.permission.type, actor: req.permission.type,
actorId: req.permission.id, actorId: req.permission.id,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
projectId: req.query.workspaceId projectId: req.query.workspaceId
}); });
@@ -150,6 +154,7 @@ export const registerSecretApprovalPolicyRouter = async (server: FastifyZodProvi
const policy = await server.services.secretApprovalPolicy.getSecretApprovalPolicyOfFolder({ const policy = await server.services.secretApprovalPolicy.getSecretApprovalPolicyOfFolder({
actor: req.permission.type, actor: req.permission.type,
actorId: req.permission.id, actorId: req.permission.id,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
projectId: req.query.workspaceId, projectId: req.query.workspaceId,
...req.query ...req.query
@@ -52,6 +52,7 @@ export const registerSecretApprovalRequestRouter = async (server: FastifyZodProv
const approvals = await server.services.secretApprovalRequest.getSecretApprovals({ const approvals = await server.services.secretApprovalRequest.getSecretApprovals({
actor: req.permission.type, actor: req.permission.type,
actorId: req.permission.id, actorId: req.permission.id,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
...req.query, ...req.query,
projectId: req.query.workspaceId projectId: req.query.workspaceId
@@ -81,6 +82,7 @@ export const registerSecretApprovalRequestRouter = async (server: FastifyZodProv
const approvals = await server.services.secretApprovalRequest.requestCount({ const approvals = await server.services.secretApprovalRequest.requestCount({
actor: req.permission.type, actor: req.permission.type,
actorId: req.permission.id, actorId: req.permission.id,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
projectId: req.query.workspaceId projectId: req.query.workspaceId
}); });
@@ -106,6 +108,7 @@ export const registerSecretApprovalRequestRouter = async (server: FastifyZodProv
const { approval } = await server.services.secretApprovalRequest.mergeSecretApprovalRequest({ const { approval } = await server.services.secretApprovalRequest.mergeSecretApprovalRequest({
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
approvalId: req.params.id approvalId: req.params.id
}); });
@@ -134,6 +137,7 @@ export const registerSecretApprovalRequestRouter = async (server: FastifyZodProv
const review = await server.services.secretApprovalRequest.reviewApproval({ const review = await server.services.secretApprovalRequest.reviewApproval({
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
approvalId: req.params.id, approvalId: req.params.id,
status: req.body.status status: req.body.status
@@ -163,6 +167,7 @@ export const registerSecretApprovalRequestRouter = async (server: FastifyZodProv
const approval = await server.services.secretApprovalRequest.updateApprovalStatus({ const approval = await server.services.secretApprovalRequest.updateApprovalStatus({
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
approvalId: req.params.id, approvalId: req.params.id,
status: req.body.status status: req.body.status
@@ -271,6 +276,7 @@ export const registerSecretApprovalRequestRouter = async (server: FastifyZodProv
const approval = await server.services.secretApprovalRequest.getSecretApprovalDetails({ const approval = await server.services.secretApprovalRequest.getSecretApprovalDetails({
actor: req.permission.type, actor: req.permission.type,
actorId: req.permission.id, actorId: req.permission.id,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
id: req.params.id id: req.params.id
}); });
@@ -30,6 +30,7 @@ export const registerSecretRotationProviderRouter = async (server: FastifyZodPro
const providers = await server.services.secretRotation.getProviderTemplates({ const providers = await server.services.secretRotation.getProviderTemplates({
actor: req.permission.type, actor: req.permission.type,
actorId: req.permission.id, actorId: req.permission.id,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
projectId: req.params.workspaceId projectId: req.params.workspaceId
}); });
@@ -39,6 +39,7 @@ export const registerSecretRotationRouter = async (server: FastifyZodProvider) =
handler: async (req) => { handler: async (req) => {
const secretRotation = await server.services.secretRotation.createRotation({ const secretRotation = await server.services.secretRotation.createRotation({
actor: req.permission.type, actor: req.permission.type,
actorAuthMethod: req.permission.authMethod,
actorId: req.permission.id, actorId: req.permission.id,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
...req.body, ...req.body,
@@ -74,6 +75,7 @@ export const registerSecretRotationRouter = async (server: FastifyZodProvider) =
const secretRotation = await server.services.secretRotation.restartById({ const secretRotation = await server.services.secretRotation.restartById({
actor: req.permission.type, actor: req.permission.type,
actorId: req.permission.id, actorId: req.permission.id,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
rotationId: req.body.id rotationId: req.body.id
}); });
@@ -125,6 +127,7 @@ export const registerSecretRotationRouter = async (server: FastifyZodProvider) =
const secretRotations = await server.services.secretRotation.getByProjectId({ const secretRotations = await server.services.secretRotation.getByProjectId({
actor: req.permission.type, actor: req.permission.type,
actorId: req.permission.id, actorId: req.permission.id,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
projectId: req.query.workspaceId projectId: req.query.workspaceId
}); });
@@ -158,6 +161,7 @@ export const registerSecretRotationRouter = async (server: FastifyZodProvider) =
const secretRotation = await server.services.secretRotation.deleteById({ const secretRotation = await server.services.secretRotation.deleteById({
actor: req.permission.type, actor: req.permission.type,
actorId: req.permission.id, actorId: req.permission.id,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
rotationId: req.params.id rotationId: req.params.id
}); });
@@ -22,6 +22,7 @@ export const registerSecretScanningRouter = async (server: FastifyZodProvider) =
const session = await server.services.secretScanning.createInstallationSession({ const session = await server.services.secretScanning.createInstallationSession({
actor: req.permission.type, actor: req.permission.type,
actorId: req.permission.id, actorId: req.permission.id,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
orgId: req.body.organizationId orgId: req.body.organizationId
}); });
@@ -46,6 +47,7 @@ export const registerSecretScanningRouter = async (server: FastifyZodProvider) =
const { installatedApp } = await server.services.secretScanning.linkInstallationToOrg({ const { installatedApp } = await server.services.secretScanning.linkInstallationToOrg({
actor: req.permission.type, actor: req.permission.type,
actorId: req.permission.id, actorId: req.permission.id,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
...req.body ...req.body
}); });
@@ -67,6 +69,7 @@ export const registerSecretScanningRouter = async (server: FastifyZodProvider) =
const appInstallationCompleted = await server.services.secretScanning.getOrgInstallationStatus({ const appInstallationCompleted = await server.services.secretScanning.getOrgInstallationStatus({
actor: req.permission.type, actor: req.permission.type,
actorId: req.permission.id, actorId: req.permission.id,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
orgId: req.params.organizationId orgId: req.params.organizationId
}); });
@@ -88,6 +91,7 @@ export const registerSecretScanningRouter = async (server: FastifyZodProvider) =
const { risks } = await server.services.secretScanning.getRisksByOrg({ const { risks } = await server.services.secretScanning.getRisksByOrg({
actor: req.permission.type, actor: req.permission.type,
actorId: req.permission.id, actorId: req.permission.id,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
orgId: req.params.organizationId orgId: req.params.organizationId
}); });
@@ -110,6 +114,7 @@ export const registerSecretScanningRouter = async (server: FastifyZodProvider) =
const { risk } = await server.services.secretScanning.updateRiskStatus({ const { risk } = await server.services.secretScanning.updateRiskStatus({
actor: req.permission.type, actor: req.permission.type,
actorId: req.permission.id, actorId: req.permission.id,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
orgId: req.params.organizationId, orgId: req.params.organizationId,
riskId: req.params.riskId, riskId: req.params.riskId,
@@ -27,6 +27,7 @@ export const registerSecretVersionRouter = async (server: FastifyZodProvider) =>
const secretVersions = await server.services.secret.getSecretVersions({ const secretVersions = await server.services.secret.getSecretVersions({
actor: req.permission.type, actor: req.permission.type,
actorId: req.permission.id, actorId: req.permission.id,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
limit: req.query.limit, limit: req.query.limit,
offset: req.query.offset, offset: req.query.offset,
@@ -47,6 +47,7 @@ export const registerSnapshotRouter = async (server: FastifyZodProvider) => {
const secretSnapshot = await server.services.snapshot.getSnapshotData({ const secretSnapshot = await server.services.snapshot.getSnapshotData({
actor: req.permission.type, actor: req.permission.type,
actorId: req.permission.id, actorId: req.permission.id,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
id: req.params.secretSnapshotId id: req.params.secretSnapshotId
}); });
@@ -79,6 +80,7 @@ export const registerSnapshotRouter = async (server: FastifyZodProvider) => {
const secretSnapshot = await server.services.snapshot.rollbackSnapshot({ const secretSnapshot = await server.services.snapshot.rollbackSnapshot({
actor: req.permission.type, actor: req.permission.type,
actorId: req.permission.id, actorId: req.permission.id,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
id: req.params.secretSnapshotId id: req.params.secretSnapshotId
}); });
@@ -22,6 +22,7 @@ export const registerTrustedIpRouter = async (server: FastifyZodProvider) => {
onRequest: verifyAuth([AuthMode.JWT]), onRequest: verifyAuth([AuthMode.JWT]),
handler: async (req) => { handler: async (req) => {
const trustedIps = await server.services.trustedIp.listIpsByProjectId({ const trustedIps = await server.services.trustedIp.listIpsByProjectId({
actorAuthMethod: req.permission.authMethod,
projectId: req.params.workspaceId, projectId: req.params.workspaceId,
actor: req.permission.type, actor: req.permission.type,
actorId: req.permission.id, actorId: req.permission.id,
@@ -52,6 +53,7 @@ export const registerTrustedIpRouter = async (server: FastifyZodProvider) => {
onRequest: verifyAuth([AuthMode.JWT]), onRequest: verifyAuth([AuthMode.JWT]),
handler: async (req) => { handler: async (req) => {
const { trustedIp, project } = await server.services.trustedIp.addProjectIp({ const { trustedIp, project } = await server.services.trustedIp.addProjectIp({
actorAuthMethod: req.permission.authMethod,
projectId: req.params.workspaceId, projectId: req.params.workspaceId,
actor: req.permission.type, actor: req.permission.type,
actorId: req.permission.id, actorId: req.permission.id,
@@ -99,6 +101,7 @@ export const registerTrustedIpRouter = async (server: FastifyZodProvider) => {
projectId: req.params.workspaceId, projectId: req.params.workspaceId,
actor: req.permission.type, actor: req.permission.type,
actorId: req.permission.id, actorId: req.permission.id,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
trustedIpId: req.params.trustedIpId, trustedIpId: req.params.trustedIpId,
...req.body ...req.body
@@ -140,6 +143,7 @@ export const registerTrustedIpRouter = async (server: FastifyZodProvider) => {
projectId: req.params.workspaceId, projectId: req.params.workspaceId,
actor: req.permission.type, actor: req.permission.type,
actorId: req.permission.id, actorId: req.permission.id,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
trustedIpId: req.params.trustedIpId trustedIpId: req.params.trustedIpId
}); });
@@ -31,10 +31,17 @@ export const auditLogServiceFactory = ({
actor, actor,
actorId, actorId,
actorOrgId, actorOrgId,
actorAuthMethod,
projectId, projectId,
auditLogActor auditLogActor
}: TListProjectAuditLogDTO) => { }: TListProjectAuditLogDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId); const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.AuditLogs); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.AuditLogs);
const auditLogs = await auditLogDAL.find({ const auditLogs = await auditLogDAL.find({
startDate, startDate,
@@ -55,6 +55,7 @@ export const ldapConfigServiceFactory = ({
actorId, actorId,
orgId, orgId,
actorOrgId, actorOrgId,
actorAuthMethod,
isActive, isActive,
url, url,
bindDN, bindDN,
@@ -62,7 +63,7 @@ export const ldapConfigServiceFactory = ({
searchBase, searchBase,
caCert caCert
}: TCreateLdapCfgDTO) => { }: TCreateLdapCfgDTO) => {
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, actorOrgId); const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, actorAuthMethod, actorOrgId);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Create, OrgPermissionSubjects.Ldap); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Create, OrgPermissionSubjects.Ldap);
const plan = await licenseService.getPlan(orgId); const plan = await licenseService.getPlan(orgId);
@@ -149,13 +150,14 @@ export const ldapConfigServiceFactory = ({
orgId, orgId,
actorOrgId, actorOrgId,
isActive, isActive,
actorAuthMethod,
url, url,
bindDN, bindDN,
bindPass, bindPass,
searchBase, searchBase,
caCert caCert
}: TUpdateLdapCfgDTO) => { }: TUpdateLdapCfgDTO) => {
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, actorOrgId); const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, actorAuthMethod, actorOrgId);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Edit, OrgPermissionSubjects.Ldap); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Edit, OrgPermissionSubjects.Ldap);
const plan = await licenseService.getPlan(orgId); const plan = await licenseService.getPlan(orgId);
@@ -274,8 +276,14 @@ export const ldapConfigServiceFactory = ({
}; };
}; };
const getLdapCfgWithPermissionCheck = async ({ actor, actorId, orgId, actorOrgId }: TOrgPermission) => { const getLdapCfgWithPermissionCheck = async ({
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, actorOrgId); actor,
actorId,
orgId,
actorAuthMethod,
actorOrgId
}: TOrgPermission) => {
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, actorAuthMethod, actorOrgId);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Ldap); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Ldap);
return getLdapCfg({ return getLdapCfg({
orgId orgId
@@ -224,9 +224,10 @@ export const licenseServiceFactory = ({
actor, actor,
actorId, actorId,
actorOrgId, actorOrgId,
actorAuthMethod,
billingCycle billingCycle
}: TOrgPlansTableDTO) => { }: TOrgPlansTableDTO) => {
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, actorOrgId); const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, actorAuthMethod, actorOrgId);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Billing); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Billing);
const { data } = await licenseServerCloudApi.request.get( const { data } = await licenseServerCloudApi.request.get(
`/api/license-server/v1/cloud-products?billing-cycle=${billingCycle}` `/api/license-server/v1/cloud-products?billing-cycle=${billingCycle}`
@@ -234,15 +235,22 @@ export const licenseServiceFactory = ({
return data; return data;
}; };
const getOrgPlan = async ({ orgId, actor, actorId, actorOrgId, projectId }: TOrgPlanDTO) => { const getOrgPlan = async ({ orgId, actor, actorId, actorOrgId, actorAuthMethod, projectId }: TOrgPlanDTO) => {
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, actorOrgId); const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, actorAuthMethod, actorOrgId);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Billing); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Billing);
const plan = await getPlan(orgId, projectId); const plan = await getPlan(orgId, projectId);
return plan; return plan;
}; };
const startOrgTrial = async ({ orgId, actorId, actor, actorOrgId, success_url }: TStartOrgTrialDTO) => { const startOrgTrial = async ({
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, actorOrgId); orgId,
actorId,
actor,
actorOrgId,
actorAuthMethod,
success_url
}: TStartOrgTrialDTO) => {
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, actorAuthMethod, actorOrgId);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Create, OrgPermissionSubjects.Billing); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Create, OrgPermissionSubjects.Billing);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Edit, OrgPermissionSubjects.Billing); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Edit, OrgPermissionSubjects.Billing);
@@ -263,8 +271,14 @@ export const licenseServiceFactory = ({
return { url }; return { url };
}; };
const createOrganizationPortalSession = async ({ orgId, actorId, actor, actorOrgId }: TCreateOrgPortalSession) => { const createOrganizationPortalSession = async ({
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, actorOrgId); orgId,
actorId,
actor,
actorAuthMethod,
actorOrgId
}: TCreateOrgPortalSession) => {
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, actorAuthMethod, actorOrgId);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Create, OrgPermissionSubjects.Billing); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Create, OrgPermissionSubjects.Billing);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Edit, OrgPermissionSubjects.Billing); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Edit, OrgPermissionSubjects.Billing);
@@ -310,8 +324,8 @@ export const licenseServiceFactory = ({
return { url }; return { url };
}; };
const getOrgBillingInfo = async ({ orgId, actor, actorId, actorOrgId }: TGetOrgBillInfoDTO) => { const getOrgBillingInfo = async ({ orgId, actor, actorId, actorAuthMethod, actorOrgId }: TGetOrgBillInfoDTO) => {
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, actorOrgId); const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, actorAuthMethod, actorOrgId);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Billing); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Billing);
const organization = await orgDAL.findOrgById(orgId); const organization = await orgDAL.findOrgById(orgId);
@@ -327,8 +341,8 @@ export const licenseServiceFactory = ({
}; };
// returns org current plan feature table // returns org current plan feature table
const getOrgPlanTable = async ({ orgId, actor, actorId, actorOrgId }: TGetOrgBillInfoDTO) => { const getOrgPlanTable = async ({ orgId, actor, actorId, actorAuthMethod, actorOrgId }: TGetOrgBillInfoDTO) => {
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, actorOrgId); const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, actorAuthMethod, actorOrgId);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Billing); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Billing);
const organization = await orgDAL.findOrgById(orgId); const organization = await orgDAL.findOrgById(orgId);
@@ -343,8 +357,8 @@ export const licenseServiceFactory = ({
return data; return data;
}; };
const getOrgBillingDetails = async ({ orgId, actor, actorId, actorOrgId }: TGetOrgBillInfoDTO) => { const getOrgBillingDetails = async ({ orgId, actor, actorId, actorAuthMethod, actorOrgId }: TGetOrgBillInfoDTO) => {
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, actorOrgId); const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, actorAuthMethod, actorOrgId);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Billing); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Billing);
const organization = await orgDAL.findOrgById(orgId); const organization = await orgDAL.findOrgById(orgId);
@@ -364,11 +378,12 @@ export const licenseServiceFactory = ({
actorId, actorId,
actor, actor,
actorOrgId, actorOrgId,
actorAuthMethod,
orgId, orgId,
name, name,
email email
}: TUpdateOrgBillingDetailsDTO) => { }: TUpdateOrgBillingDetailsDTO) => {
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, actorOrgId); const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, actorAuthMethod, actorOrgId);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Billing); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Billing);
const organization = await orgDAL.findOrgById(orgId); const organization = await orgDAL.findOrgById(orgId);
@@ -387,8 +402,8 @@ export const licenseServiceFactory = ({
return data; return data;
}; };
const getOrgPmtMethods = async ({ orgId, actor, actorId, actorOrgId }: TOrgPmtMethodsDTO) => { const getOrgPmtMethods = async ({ orgId, actor, actorId, actorAuthMethod, actorOrgId }: TOrgPmtMethodsDTO) => {
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, actorOrgId); const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, actorAuthMethod, actorOrgId);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Billing); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Billing);
const organization = await orgDAL.findOrgById(orgId); const organization = await orgDAL.findOrgById(orgId);
@@ -410,11 +425,12 @@ export const licenseServiceFactory = ({
orgId, orgId,
actor, actor,
actorId, actorId,
actorAuthMethod,
actorOrgId, actorOrgId,
success_url, success_url,
cancel_url cancel_url
}: TAddOrgPmtMethodDTO) => { }: TAddOrgPmtMethodDTO) => {
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, actorOrgId); const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, actorAuthMethod, actorOrgId);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Billing); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Billing);
const organization = await orgDAL.findOrgById(orgId); const organization = await orgDAL.findOrgById(orgId);
@@ -435,8 +451,15 @@ export const licenseServiceFactory = ({
return { url }; return { url };
}; };
const delOrgPmtMethods = async ({ actorId, actor, actorOrgId, orgId, pmtMethodId }: TDelOrgPmtMethodDTO) => { const delOrgPmtMethods = async ({
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, actorOrgId); actorId,
actor,
actorAuthMethod,
actorOrgId,
orgId,
pmtMethodId
}: TDelOrgPmtMethodDTO) => {
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, actorAuthMethod, actorOrgId);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Billing); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Billing);
const organization = await orgDAL.findOrgById(orgId); const organization = await orgDAL.findOrgById(orgId);
@@ -452,8 +475,8 @@ export const licenseServiceFactory = ({
return data; return data;
}; };
const getOrgTaxIds = async ({ orgId, actor, actorId, actorOrgId }: TGetOrgTaxIdDTO) => { const getOrgTaxIds = async ({ orgId, actor, actorId, actorAuthMethod, actorOrgId }: TGetOrgTaxIdDTO) => {
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, actorOrgId); const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, actorAuthMethod, actorOrgId);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Billing); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Billing);
const organization = await orgDAL.findOrgById(orgId); const organization = await orgDAL.findOrgById(orgId);
@@ -470,8 +493,8 @@ export const licenseServiceFactory = ({
return taxIds; return taxIds;
}; };
const addOrgTaxId = async ({ actorId, actor, actorOrgId, orgId, type, value }: TAddOrgTaxIdDTO) => { const addOrgTaxId = async ({ actorId, actor, actorAuthMethod, actorOrgId, orgId, type, value }: TAddOrgTaxIdDTO) => {
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, actorOrgId); const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, actorAuthMethod, actorOrgId);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Billing); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Billing);
const organization = await orgDAL.findOrgById(orgId); const organization = await orgDAL.findOrgById(orgId);
@@ -491,8 +514,8 @@ export const licenseServiceFactory = ({
return data; return data;
}; };
const delOrgTaxId = async ({ orgId, actor, actorId, actorOrgId, taxId }: TDelOrgTaxIdDTO) => { const delOrgTaxId = async ({ orgId, actor, actorId, actorAuthMethod, actorOrgId, taxId }: TDelOrgTaxIdDTO) => {
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, actorOrgId); const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, actorAuthMethod, actorOrgId);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Billing); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Billing);
const organization = await orgDAL.findOrgById(orgId); const organization = await orgDAL.findOrgById(orgId);
@@ -508,8 +531,8 @@ export const licenseServiceFactory = ({
return data; return data;
}; };
const getOrgTaxInvoices = async ({ actorId, actor, actorOrgId, orgId }: TOrgInvoiceDTO) => { const getOrgTaxInvoices = async ({ actorId, actor, actorOrgId, actorAuthMethod, orgId }: TOrgInvoiceDTO) => {
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, actorOrgId); const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, actorAuthMethod, actorOrgId);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Billing); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Billing);
const organization = await orgDAL.findOrgById(orgId); const organization = await orgDAL.findOrgById(orgId);
@@ -525,8 +548,8 @@ export const licenseServiceFactory = ({
return invoices; return invoices;
}; };
const getOrgLicenses = async ({ orgId, actor, actorId, actorOrgId }: TOrgLicensesDTO) => { const getOrgLicenses = async ({ orgId, actor, actorId, actorAuthMethod, actorOrgId }: TOrgLicensesDTO) => {
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, actorOrgId); const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, actorAuthMethod, actorOrgId);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Billing); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Billing);
const organization = await orgDAL.findOrgById(orgId); const organization = await orgDAL.findOrgById(orgId);
@@ -129,11 +129,18 @@ export const permissionDALFactory = (db: TDbClient) => {
`${TableName.IdentityProjectMembershipRole}.customRoleId`, `${TableName.IdentityProjectMembershipRole}.customRoleId`,
`${TableName.ProjectRoles}.id` `${TableName.ProjectRoles}.id`
) )
.join(
// Join the Project table to later select orgId
TableName.Project,
`${TableName.IdentityProjectMembership}.projectId`,
`${TableName.Project}.id`
)
.where("identityId", identityId) .where("identityId", identityId)
.where(`${TableName.IdentityProjectMembership}.projectId`, projectId) .where(`${TableName.IdentityProjectMembership}.projectId`, projectId)
.select(selectAllTableCols(TableName.IdentityProjectMembershipRole)) .select(selectAllTableCols(TableName.IdentityProjectMembershipRole))
.select( .select(
db.ref("id").withSchema(TableName.IdentityProjectMembership).as("membershipId"), db.ref("id").withSchema(TableName.IdentityProjectMembership).as("membershipId"),
db.ref("orgId").withSchema(TableName.Project).as("orgId"), // Now you can select orgId from Project
db.ref("role").withSchema(TableName.IdentityProjectMembership).as("oldRoleField"), db.ref("role").withSchema(TableName.IdentityProjectMembership).as("oldRoleField"),
db.ref("createdAt").withSchema(TableName.IdentityProjectMembership).as("membershipCreatedAt"), db.ref("createdAt").withSchema(TableName.IdentityProjectMembership).as("membershipCreatedAt"),
db.ref("updatedAt").withSchema(TableName.IdentityProjectMembership).as("membershipUpdatedAt"), db.ref("updatedAt").withSchema(TableName.IdentityProjectMembership).as("membershipUpdatedAt"),
@@ -144,16 +151,16 @@ export const permissionDALFactory = (db: TDbClient) => {
const permission = sqlNestRelationships({ const permission = sqlNestRelationships({
data: docs, data: docs,
key: "membershipId", key: "membershipId",
parentMapper: ({ membershipId, membershipCreatedAt, membershipUpdatedAt, oldRoleField }) => ({ parentMapper: ({ membershipId, membershipCreatedAt, membershipUpdatedAt, oldRoleField, orgId }) => ({
id: membershipId, id: membershipId,
identityId, identityId,
projectId, projectId,
role: oldRoleField, role: oldRoleField,
createdAt: membershipCreatedAt, createdAt: membershipCreatedAt,
updatedAt: membershipUpdatedAt, updatedAt: membershipUpdatedAt,
orgId,
// just a prefilled value // just a prefilled value
orgAuthEnforced: false, orgAuthEnforced: false
orgId: ""
}), }),
childrenMapper: [ childrenMapper: [
{ {
@@ -0,0 +1,23 @@
import { TOrganizations } from "@app/db/schemas";
import { UnauthorizedError } from "@app/lib/errors";
import { ActorAuthMethod, AuthMethod } from "@app/services/auth/auth-type";
function isAuthMethodSaml(actorAuthMethod: ActorAuthMethod) {
if (!actorAuthMethod) return false;
return [AuthMethod.AZURE_SAML, AuthMethod.OKTA_SAML, AuthMethod.JUMPCLOUD_SAML, AuthMethod.GOOGLE_SAML].includes(
actorAuthMethod
);
}
function validateOrgSAML(actorAuthMethod: ActorAuthMethod, isSamlEnforced: TOrganizations["authEnforced"]) {
if (actorAuthMethod === undefined) {
throw new UnauthorizedError({ name: "No auth method defined" });
}
if (isSamlEnforced && actorAuthMethod !== null && !isAuthMethodSaml(actorAuthMethod)) {
throw new UnauthorizedError({ name: "Cannot access org-scoped resource" });
}
}
export { isAuthMethodSaml, validateOrgSAML };
@@ -11,13 +11,15 @@ import {
} from "@app/db/schemas"; } from "@app/db/schemas";
import { conditionsMatcher } from "@app/lib/casl"; import { conditionsMatcher } from "@app/lib/casl";
import { BadRequestError, UnauthorizedError } from "@app/lib/errors"; import { BadRequestError, UnauthorizedError } from "@app/lib/errors";
import { ActorType } from "@app/services/auth/auth-type"; import { ActorAuthMethod, ActorType } from "@app/services/auth/auth-type";
import { TOrgRoleDALFactory } from "@app/services/org/org-role-dal"; import { TOrgRoleDALFactory } from "@app/services/org/org-role-dal";
import { TProjectDALFactory } from "@app/services/project/project-dal";
import { TProjectRoleDALFactory } from "@app/services/project-role/project-role-dal"; import { TProjectRoleDALFactory } from "@app/services/project-role/project-role-dal";
import { TServiceTokenDALFactory } from "@app/services/service-token/service-token-dal"; import { TServiceTokenDALFactory } from "@app/services/service-token/service-token-dal";
import { orgAdminPermissions, orgMemberPermissions, orgNoAccessPermissions, OrgPermissionSet } from "./org-permission"; import { orgAdminPermissions, orgMemberPermissions, orgNoAccessPermissions, OrgPermissionSet } from "./org-permission";
import { TPermissionDALFactory } from "./permission-dal"; import { TPermissionDALFactory } from "./permission-dal";
import { validateOrgSAML } from "./permission-fns";
import { TBuildProjectPermissionDTO } from "./permission-types"; import { TBuildProjectPermissionDTO } from "./permission-types";
import { import {
buildServiceTokenProjectPermission, buildServiceTokenProjectPermission,
@@ -32,6 +34,7 @@ type TPermissionServiceFactoryDep = {
orgRoleDAL: Pick<TOrgRoleDALFactory, "findOne">; orgRoleDAL: Pick<TOrgRoleDALFactory, "findOne">;
projectRoleDAL: Pick<TProjectRoleDALFactory, "findOne">; projectRoleDAL: Pick<TProjectRoleDALFactory, "findOne">;
serviceTokenDAL: Pick<TServiceTokenDALFactory, "findById">; serviceTokenDAL: Pick<TServiceTokenDALFactory, "findById">;
projectDAL: Pick<TProjectDALFactory, "findById">;
permissionDAL: TPermissionDALFactory; permissionDAL: TPermissionDALFactory;
}; };
@@ -41,7 +44,8 @@ export const permissionServiceFactory = ({
permissionDAL, permissionDAL,
orgRoleDAL, orgRoleDAL,
projectRoleDAL, projectRoleDAL,
serviceTokenDAL serviceTokenDAL,
projectDAL
}: TPermissionServiceFactoryDep) => { }: TPermissionServiceFactoryDep) => {
const buildOrgPermission = (role: string, permission?: unknown) => { const buildOrgPermission = (role: string, permission?: unknown) => {
switch (role) { switch (role) {
@@ -98,16 +102,30 @@ export const permissionServiceFactory = ({
/* /*
* Get user permission in an organization * Get user permission in an organization
* */ */
const getUserOrgPermission = async (userId: string, orgId: string, userOrgId?: string) => { const getUserOrgPermission = async (
userId: string,
orgId: string,
authMethod: ActorAuthMethod,
userOrgId?: string
) => {
const membership = await permissionDAL.getOrgPermission(userId, orgId); const membership = await permissionDAL.getOrgPermission(userId, orgId);
if (!membership) throw new UnauthorizedError({ name: "User not in org" }); if (!membership) throw new UnauthorizedError({ name: "User not in org" });
if (membership.role === OrgMembershipRole.Custom && !membership.permissions) { if (membership.role === OrgMembershipRole.Custom && !membership.permissions) {
throw new BadRequestError({ name: "Custom permission not found" }); throw new BadRequestError({ name: "Custom permission not found" });
} }
if (membership.orgAuthEnforced && membership.orgId !== userOrgId) {
throw new BadRequestError({ name: "Cannot access org-scoped resource" }); // If the org ID is API_KEY, the request is being made with an API Key.
// Since we can't scope API keys to an organization, we'll need to do an arbitrary check to see if the user is a member of the organization.
// 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" });
} }
validateOrgSAML(authMethod, membership.orgAuthEnforced);
return { permission: buildOrgPermission(membership.role, membership.permissions), membership }; return { permission: buildOrgPermission(membership.role, membership.permissions), membership };
}; };
@@ -120,10 +138,16 @@ export const permissionServiceFactory = ({
return { permission: buildOrgPermission(membership.role, membership.permissions), membership }; return { permission: buildOrgPermission(membership.role, membership.permissions), membership };
}; };
const getOrgPermission = async (type: ActorType, id: string, orgId: string, actorOrgId?: string) => { const getOrgPermission = async (
type: ActorType,
id: string,
orgId: string,
authMethod: ActorAuthMethod,
actorOrgId: string | undefined
) => {
switch (type) { switch (type) {
case ActorType.USER: case ActorType.USER:
return getUserOrgPermission(id, orgId, actorOrgId); return getUserOrgPermission(id, orgId, authMethod, actorOrgId);
case ActorType.IDENTITY: case ActorType.IDENTITY:
return getIdentityOrgPermission(id, orgId); return getIdentityOrgPermission(id, orgId);
default: default:
@@ -153,34 +177,39 @@ export const permissionServiceFactory = ({
const getUserProjectPermission = async ( const getUserProjectPermission = async (
userId: string, userId: string,
projectId: string, projectId: string,
authMethod: ActorAuthMethod,
userOrgId?: string userOrgId?: string
): Promise<TProjectPermissionRT<ActorType.USER>> => { ): Promise<TProjectPermissionRT<ActorType.USER>> => {
const userProjectPermission = await permissionDAL.getProjectPermission(userId, projectId); const membership = await permissionDAL.getProjectPermission(userId, projectId);
if (!userProjectPermission) throw new UnauthorizedError({ name: "User not in project" }); if (!membership) throw new UnauthorizedError({ name: "User not in project" });
if ( if (membership.roles.some(({ role, permissions }) => role === ProjectMembershipRole.Custom && !permissions)) {
userProjectPermission.roles.some(({ role, permissions }) => role === ProjectMembershipRole.Custom && !permissions)
) {
throw new BadRequestError({ name: "Custom permission not found" }); throw new BadRequestError({ name: "Custom permission not found" });
} }
if (userProjectPermission.orgAuthEnforced && userProjectPermission.orgId !== userOrgId) { // If the org ID is API_KEY, the request is being made with an API Key.
throw new BadRequestError({ name: "Cannot access org-scoped resource" }); // Since we can't scope API keys to an organization, we'll need to do an arbitrary check to see if the user is a member of the organization.
// 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" });
} }
validateOrgSAML(authMethod, membership.orgAuthEnforced);
return { return {
permission: buildProjectPermission(userProjectPermission.roles), permission: buildProjectPermission(membership.roles),
membership: userProjectPermission, membership,
hasRole: (role: string) => hasRole: (role: string) =>
userProjectPermission.roles.findIndex( membership.roles.findIndex(({ role: slug, customRoleSlug }) => role === slug || slug === customRoleSlug) !== -1
({ role: slug, customRoleSlug }) => role === slug || slug === customRoleSlug
) !== -1
}; };
}; };
const getIdentityProjectPermission = async ( const getIdentityProjectPermission = async (
identityId: string, identityId: string,
projectId: string projectId: string,
identityOrgId: string | undefined
): Promise<TProjectPermissionRT<ActorType.IDENTITY>> => { ): Promise<TProjectPermissionRT<ActorType.IDENTITY>> => {
const identityProjectPermission = await permissionDAL.getProjectIdentityPermission(identityId, projectId); const identityProjectPermission = await permissionDAL.getProjectIdentityPermission(identityId, projectId);
if (!identityProjectPermission) throw new UnauthorizedError({ name: "Identity not in project" }); if (!identityProjectPermission) throw new UnauthorizedError({ name: "Identity not in project" });
@@ -193,6 +222,10 @@ export const permissionServiceFactory = ({
throw new BadRequestError({ name: "Custom permission not found" }); throw new BadRequestError({ name: "Custom permission not found" });
} }
if (identityProjectPermission.orgId !== identityOrgId) {
throw new UnauthorizedError({ name: "You are not a member of this organization" });
}
return { return {
permission: buildProjectPermission(identityProjectPermission.roles), permission: buildProjectPermission(identityProjectPermission.roles),
membership: identityProjectPermission, membership: identityProjectPermission,
@@ -203,14 +236,32 @@ export const permissionServiceFactory = ({
}; };
}; };
const getServiceTokenProjectPermission = async (serviceTokenId: string, projectId: string) => { const getServiceTokenProjectPermission = async (
serviceTokenId: string,
projectId: string,
actorOrgId: string | undefined
) => {
const serviceToken = await serviceTokenDAL.findById(serviceTokenId); const serviceToken = await serviceTokenDAL.findById(serviceTokenId);
if (!serviceToken) throw new BadRequestError({ message: "Service token not found" }); if (!serviceToken) throw new BadRequestError({ 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" });
}
if (serviceToken.projectId !== projectId) if (serviceToken.projectId !== projectId)
throw new UnauthorizedError({ throw new UnauthorizedError({
message: "Failed to find service authorization for given project" message: "Failed to find service authorization for given project"
}); });
if (serviceTokenProject.orgId !== actorOrgId)
throw new UnauthorizedError({
message: "Failed to find service authorization for given project"
});
const scopes = ServiceTokenScopes.parse(serviceToken.scopes || []); const scopes = ServiceTokenScopes.parse(serviceToken.scopes || []);
return { return {
permission: buildServiceTokenProjectPermission(scopes, serviceToken.permissions), permission: buildServiceTokenProjectPermission(scopes, serviceToken.permissions),
@@ -238,15 +289,16 @@ export const permissionServiceFactory = ({
type: T, type: T,
id: string, id: string,
projectId: string, projectId: string,
actorOrgId?: string actorAuthMethod: ActorAuthMethod,
actorOrgId: string | undefined
): Promise<TProjectPermissionRT<T>> => { ): Promise<TProjectPermissionRT<T>> => {
switch (type) { switch (type) {
case ActorType.USER: case ActorType.USER:
return getUserProjectPermission(id, projectId, actorOrgId) as Promise<TProjectPermissionRT<T>>; return getUserProjectPermission(id, projectId, actorAuthMethod, actorOrgId) as Promise<TProjectPermissionRT<T>>;
case ActorType.SERVICE: case ActorType.SERVICE:
return getServiceTokenProjectPermission(id, projectId) as Promise<TProjectPermissionRT<T>>; return getServiceTokenProjectPermission(id, projectId, actorOrgId) as Promise<TProjectPermissionRT<T>>;
case ActorType.IDENTITY: case ActorType.IDENTITY:
return getIdentityProjectPermission(id, projectId) as Promise<TProjectPermissionRT<T>>; return getIdentityProjectPermission(id, projectId, actorOrgId) as Promise<TProjectPermissionRT<T>>;
default: default:
throw new UnauthorizedError({ throw new UnauthorizedError({
message: "Permission not defined", message: "Permission not defined",
@@ -55,6 +55,7 @@ export const samlConfigServiceFactory = ({
const createSamlCfg = async ({ const createSamlCfg = async ({
cert, cert,
actor, actor,
actorAuthMethod,
actorOrgId, actorOrgId,
orgId, orgId,
issuer, issuer,
@@ -63,7 +64,7 @@ export const samlConfigServiceFactory = ({
entryPoint, entryPoint,
authProvider authProvider
}: TCreateSamlCfgDTO) => { }: TCreateSamlCfgDTO) => {
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, actorOrgId); const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, actorAuthMethod, actorOrgId);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Create, OrgPermissionSubjects.Sso); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Create, OrgPermissionSubjects.Sso);
const plan = await licenseService.getPlan(orgId); const plan = await licenseService.getPlan(orgId);
@@ -146,6 +147,7 @@ export const samlConfigServiceFactory = ({
orgId, orgId,
actor, actor,
actorOrgId, actorOrgId,
actorAuthMethod,
cert, cert,
actorId, actorId,
issuer, issuer,
@@ -153,7 +155,7 @@ export const samlConfigServiceFactory = ({
entryPoint, entryPoint,
authProvider authProvider
}: TUpdateSamlCfgDTO) => { }: TUpdateSamlCfgDTO) => {
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, actorOrgId); const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, actorAuthMethod, actorOrgId);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Edit, OrgPermissionSubjects.Sso); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Edit, OrgPermissionSubjects.Sso);
const plan = await licenseService.getPlan(orgId); const plan = await licenseService.getPlan(orgId);
if (!plan.samlSSO) if (!plan.samlSSO)
@@ -238,6 +240,7 @@ export const samlConfigServiceFactory = ({
dto.actor, dto.actor,
dto.actorId, dto.actorId,
ssoConfig.orgId, ssoConfig.orgId,
dto.actorAuthMethod,
dto.actorOrgId dto.actorOrgId
); );
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Sso); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Sso);
@@ -1,5 +1,5 @@
import { TOrgPermission } from "@app/lib/types"; import { TOrgPermission } from "@app/lib/types";
import { ActorType } from "@app/services/auth/auth-type"; import { ActorAuthMethod, ActorType } from "@app/services/auth/auth-type";
export enum SamlProviders { export enum SamlProviders {
OKTA_SAML = "okta-saml", OKTA_SAML = "okta-saml",
@@ -26,7 +26,14 @@ export type TUpdateSamlCfgDTO = Partial<{
TOrgPermission; TOrgPermission;
export type TGetSamlCfgDTO = export type TGetSamlCfgDTO =
| { type: "org"; orgId: string; actor: ActorType; actorId: string; actorOrgId?: string } | {
type: "org";
orgId: string;
actor: ActorType;
actorId: string;
actorAuthMethod: ActorAuthMethod;
actorOrgId: string | undefined;
}
| { | {
type: "orgSlug"; type: "orgSlug";
orgSlug: string; orgSlug: string;
+20 -6
View File
@@ -56,8 +56,16 @@ export const scimServiceFactory = ({
permissionService, permissionService,
smtpService smtpService
}: TScimServiceFactoryDep) => { }: TScimServiceFactoryDep) => {
const createScimToken = async ({ actor, actorId, actorOrgId, orgId, description, ttlDays }: TCreateScimTokenDTO) => { const createScimToken = async ({
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, actorOrgId); actor,
actorId,
actorOrgId,
actorAuthMethod,
orgId,
description,
ttlDays
}: TCreateScimTokenDTO) => {
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, actorAuthMethod, actorOrgId);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Create, OrgPermissionSubjects.Scim); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Create, OrgPermissionSubjects.Scim);
const plan = await licenseService.getPlan(orgId); const plan = await licenseService.getPlan(orgId);
@@ -85,8 +93,8 @@ export const scimServiceFactory = ({
return { scimToken }; return { scimToken };
}; };
const listScimTokens = async ({ actor, actorId, actorOrgId, orgId }: TOrgPermission) => { const listScimTokens = async ({ actor, actorId, actorOrgId, actorAuthMethod, orgId }: TOrgPermission) => {
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, actorOrgId); const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, actorAuthMethod, actorOrgId);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Scim); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Scim);
const plan = await licenseService.getPlan(orgId); const plan = await licenseService.getPlan(orgId);
@@ -99,11 +107,17 @@ export const scimServiceFactory = ({
return scimTokens; return scimTokens;
}; };
const deleteScimToken = async ({ scimTokenId, actor, actorId, actorOrgId }: TDeleteScimTokenDTO) => { const deleteScimToken = async ({ scimTokenId, actor, actorId, actorAuthMethod, actorOrgId }: TDeleteScimTokenDTO) => {
let scimToken = await scimDAL.findById(scimTokenId); let scimToken = await scimDAL.findById(scimTokenId);
if (!scimToken) throw new BadRequestError({ message: "Failed to find SCIM token to delete" }); if (!scimToken) throw new BadRequestError({ message: "Failed to find SCIM token to delete" });
const { permission } = await permissionService.getOrgPermission(actor, actorId, scimToken.orgId, actorOrgId); const { permission } = await permissionService.getOrgPermission(
actor,
actorId,
scimToken.orgId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Delete, OrgPermissionSubjects.Scim); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Delete, OrgPermissionSubjects.Scim);
const plan = await licenseService.getPlan(scimToken.orgId); const plan = await licenseService.getPlan(scimToken.orgId);
@@ -45,6 +45,7 @@ export const secretApprovalPolicyServiceFactory = ({
actor, actor,
actorId, actorId,
actorOrgId, actorOrgId,
actorAuthMethod,
approvals, approvals,
approvers, approvers,
projectId, projectId,
@@ -54,7 +55,13 @@ export const secretApprovalPolicyServiceFactory = ({
if (approvals > approvers.length) if (approvals > approvers.length)
throw new BadRequestError({ message: "Approvals cannot be greater than approvers" }); throw new BadRequestError({ message: "Approvals cannot be greater than approvers" });
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId); const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Create, ProjectPermissionActions.Create,
ProjectPermissionSub.SecretApproval ProjectPermissionSub.SecretApproval
@@ -98,6 +105,7 @@ export const secretApprovalPolicyServiceFactory = ({
actorId, actorId,
actor, actor,
actorOrgId, actorOrgId,
actorAuthMethod,
approvals, approvals,
secretPolicyId secretPolicyId
}: TUpdateSapDTO) => { }: TUpdateSapDTO) => {
@@ -108,6 +116,7 @@ export const secretApprovalPolicyServiceFactory = ({
actor, actor,
actorId, actorId,
secretApprovalPolicy.projectId, secretApprovalPolicy.projectId,
actorAuthMethod,
actorOrgId actorOrgId
); );
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.SecretApproval); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.SecretApproval);
@@ -152,7 +161,13 @@ export const secretApprovalPolicyServiceFactory = ({
}; };
}; };
const deleteSecretApprovalPolicy = async ({ secretPolicyId, actor, actorId, actorOrgId }: TDeleteSapDTO) => { const deleteSecretApprovalPolicy = async ({
secretPolicyId,
actor,
actorId,
actorAuthMethod,
actorOrgId
}: TDeleteSapDTO) => {
const sapPolicy = await secretApprovalPolicyDAL.findById(secretPolicyId); const sapPolicy = await secretApprovalPolicyDAL.findById(secretPolicyId);
if (!sapPolicy) throw new BadRequestError({ message: "Secret approval policy not found" }); if (!sapPolicy) throw new BadRequestError({ message: "Secret approval policy not found" });
@@ -160,6 +175,7 @@ export const secretApprovalPolicyServiceFactory = ({
actor, actor,
actorId, actorId,
sapPolicy.projectId, sapPolicy.projectId,
actorAuthMethod,
actorOrgId actorOrgId
); );
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
@@ -171,8 +187,20 @@ export const secretApprovalPolicyServiceFactory = ({
return sapPolicy; return sapPolicy;
}; };
const getSecretApprovalPolicyByProjectId = async ({ actorId, actor, actorOrgId, projectId }: TListSapDTO) => { const getSecretApprovalPolicyByProjectId = async ({
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId); actorId,
actor,
actorOrgId,
actorAuthMethod,
projectId
}: TListSapDTO) => {
const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.SecretApproval); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.SecretApproval);
const sapPolicies = await secretApprovalPolicyDAL.find({ projectId }); const sapPolicies = await secretApprovalPolicyDAL.find({ projectId });
@@ -201,10 +229,17 @@ export const secretApprovalPolicyServiceFactory = ({
actor, actor,
actorId, actorId,
actorOrgId, actorOrgId,
actorAuthMethod,
environment, environment,
secretPath secretPath
}: TGetBoardSapDTO) => { }: TGetBoardSapDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId); const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Read, ProjectPermissionActions.Read,
subject(ProjectPermissionSub.Secrets, { secretPath, environment }) subject(ProjectPermissionSub.Secrets, { secretPath, environment })
@@ -82,13 +82,14 @@ export const secretApprovalRequestServiceFactory = ({
secretVersionDAL, secretVersionDAL,
secretQueueService secretQueueService
}: TSecretApprovalRequestServiceFactoryDep) => { }: TSecretApprovalRequestServiceFactoryDep) => {
const requestCount = async ({ projectId, actor, actorId, actorOrgId }: TApprovalRequestCountDTO) => { const requestCount = async ({ projectId, actor, actorId, actorOrgId, actorAuthMethod }: TApprovalRequestCountDTO) => {
if (actor === ActorType.SERVICE) throw new BadRequestError({ message: "Cannot use service token" }); if (actor === ActorType.SERVICE) throw new BadRequestError({ message: "Cannot use service token" });
const { membership } = await permissionService.getProjectPermission( const { membership } = await permissionService.getProjectPermission(
actor as ActorType.USER, actor as ActorType.USER,
actorId, actorId,
projectId, projectId,
actorAuthMethod,
actorOrgId actorOrgId
); );
@@ -100,6 +101,7 @@ export const secretApprovalRequestServiceFactory = ({
projectId, projectId,
actorId, actorId,
actor, actor,
actorAuthMethod,
actorOrgId, actorOrgId,
status, status,
environment, environment,
@@ -109,7 +111,13 @@ export const secretApprovalRequestServiceFactory = ({
}: TListApprovalsDTO) => { }: TListApprovalsDTO) => {
if (actor === ActorType.SERVICE) throw new BadRequestError({ message: "Cannot use service token" }); if (actor === ActorType.SERVICE) throw new BadRequestError({ message: "Cannot use service token" });
const { membership } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId); const { membership } = await permissionService.getProjectPermission(
actor,
actorId,
projectId,
actorAuthMethod,
actorOrgId
);
const approvals = await secretApprovalRequestDAL.findByProjectId({ const approvals = await secretApprovalRequestDAL.findByProjectId({
projectId, projectId,
committer, committer,
@@ -122,7 +130,13 @@ export const secretApprovalRequestServiceFactory = ({
return approvals; return approvals;
}; };
const getSecretApprovalDetails = async ({ actor, actorId, actorOrgId, id }: TSecretApprovalDetailsDTO) => { const getSecretApprovalDetails = async ({
actor,
actorId,
actorOrgId,
actorAuthMethod,
id
}: TSecretApprovalDetailsDTO) => {
if (actor === ActorType.SERVICE) throw new BadRequestError({ message: "Cannot use service token" }); if (actor === ActorType.SERVICE) throw new BadRequestError({ message: "Cannot use service token" });
const secretApprovalRequest = await secretApprovalRequestDAL.findById(id); const secretApprovalRequest = await secretApprovalRequestDAL.findById(id);
@@ -133,6 +147,7 @@ export const secretApprovalRequestServiceFactory = ({
actor, actor,
actorId, actorId,
secretApprovalRequest.projectId, secretApprovalRequest.projectId,
actorAuthMethod,
actorOrgId actorOrgId
); );
if ( if (
@@ -150,7 +165,14 @@ export const secretApprovalRequestServiceFactory = ({
return { ...secretApprovalRequest, secretPath: secretPath?.[0]?.path || "/", commits: secrets }; return { ...secretApprovalRequest, secretPath: secretPath?.[0]?.path || "/", commits: secrets };
}; };
const reviewApproval = async ({ approvalId, actor, status, actorId, actorOrgId }: TReviewRequestDTO) => { const reviewApproval = async ({
approvalId,
actor,
status,
actorId,
actorAuthMethod,
actorOrgId
}: TReviewRequestDTO) => {
const secretApprovalRequest = await secretApprovalRequestDAL.findById(approvalId); const secretApprovalRequest = await secretApprovalRequestDAL.findById(approvalId);
if (!secretApprovalRequest) throw new BadRequestError({ message: "Secret approval request not found" }); if (!secretApprovalRequest) throw new BadRequestError({ message: "Secret approval request not found" });
if (actor !== ActorType.USER) throw new BadRequestError({ message: "Must be a user" }); if (actor !== ActorType.USER) throw new BadRequestError({ message: "Must be a user" });
@@ -160,6 +182,7 @@ export const secretApprovalRequestServiceFactory = ({
ActorType.USER, ActorType.USER,
actorId, actorId,
secretApprovalRequest.projectId, secretApprovalRequest.projectId,
actorAuthMethod,
actorOrgId actorOrgId
); );
if ( if (
@@ -192,7 +215,14 @@ export const secretApprovalRequestServiceFactory = ({
return reviewStatus; return reviewStatus;
}; };
const updateApprovalStatus = async ({ actorId, status, approvalId, actor, actorOrgId }: TStatusChangeDTO) => { const updateApprovalStatus = async ({
actorId,
status,
approvalId,
actor,
actorOrgId,
actorAuthMethod
}: TStatusChangeDTO) => {
const secretApprovalRequest = await secretApprovalRequestDAL.findById(approvalId); const secretApprovalRequest = await secretApprovalRequestDAL.findById(approvalId);
if (!secretApprovalRequest) throw new BadRequestError({ message: "Secret approval request not found" }); if (!secretApprovalRequest) throw new BadRequestError({ message: "Secret approval request not found" });
if (actor !== ActorType.USER) throw new BadRequestError({ message: "Must be a user" }); if (actor !== ActorType.USER) throw new BadRequestError({ message: "Must be a user" });
@@ -202,6 +232,7 @@ export const secretApprovalRequestServiceFactory = ({
ActorType.USER, ActorType.USER,
actorId, actorId,
secretApprovalRequest.projectId, secretApprovalRequest.projectId,
actorAuthMethod,
actorOrgId actorOrgId
); );
if ( if (
@@ -229,7 +260,8 @@ export const secretApprovalRequestServiceFactory = ({
approvalId, approvalId,
actor, actor,
actorId, actorId,
actorOrgId actorOrgId,
actorAuthMethod
}: TMergeSecretApprovalRequestDTO) => { }: TMergeSecretApprovalRequestDTO) => {
const secretApprovalRequest = await secretApprovalRequestDAL.findById(approvalId); const secretApprovalRequest = await secretApprovalRequestDAL.findById(approvalId);
if (!secretApprovalRequest) throw new BadRequestError({ message: "Secret approval request not found" }); if (!secretApprovalRequest) throw new BadRequestError({ message: "Secret approval request not found" });
@@ -240,8 +272,10 @@ export const secretApprovalRequestServiceFactory = ({
ActorType.USER, ActorType.USER,
actorId, actorId,
projectId, projectId,
actorAuthMethod,
actorOrgId actorOrgId
); );
if ( if (
!hasRole(ProjectMembershipRole.Admin) && !hasRole(ProjectMembershipRole.Admin) &&
secretApprovalRequest.committerId !== membership.id && secretApprovalRequest.committerId !== membership.id &&
@@ -438,6 +472,7 @@ export const secretApprovalRequestServiceFactory = ({
actorId, actorId,
actor, actor,
actorOrgId, actorOrgId,
actorAuthMethod,
policy, policy,
projectId, projectId,
secretPath, secretPath,
@@ -449,6 +484,7 @@ export const secretApprovalRequestServiceFactory = ({
actor, actor,
actorId, actorId,
projectId, projectId,
actorAuthMethod,
actorOrgId actorOrgId
); );
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
@@ -39,8 +39,20 @@ export const secretRotationServiceFactory = ({
folderDAL, folderDAL,
secretDAL secretDAL
}: TSecretRotationServiceFactoryDep) => { }: TSecretRotationServiceFactoryDep) => {
const getProviderTemplates = async ({ actor, actorId, actorOrgId, projectId }: TProjectPermission) => { const getProviderTemplates = async ({
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId); actor,
actorId,
actorOrgId,
actorAuthMethod,
projectId
}: TProjectPermission) => {
const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.SecretRotation); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.SecretRotation);
return { return {
@@ -54,6 +66,7 @@ export const secretRotationServiceFactory = ({
actorId, actorId,
actor, actor,
actorOrgId, actorOrgId,
actorAuthMethod,
inputs, inputs,
outputs, outputs,
interval, interval,
@@ -61,7 +74,13 @@ export const secretRotationServiceFactory = ({
secretPath, secretPath,
environment environment
}: TCreateSecretRotationDTO) => { }: TCreateSecretRotationDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId); const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Create, ProjectPermissionActions.Create,
ProjectPermissionSub.SecretRotation ProjectPermissionSub.SecretRotation
@@ -139,14 +158,20 @@ export const secretRotationServiceFactory = ({
return secretRotation; return secretRotation;
}; };
const getByProjectId = async ({ actorId, projectId, actor, actorOrgId }: TListByProjectIdDTO) => { const getByProjectId = async ({ actorId, projectId, actor, actorOrgId, actorAuthMethod }: TListByProjectIdDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId); const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.SecretRotation); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.SecretRotation);
const doc = await secretRotationDAL.find({ projectId }); const doc = await secretRotationDAL.find({ projectId });
return doc; return doc;
}; };
const restartById = async ({ actor, actorId, actorOrgId, rotationId }: TRestartDTO) => { const restartById = async ({ actor, actorId, actorOrgId, actorAuthMethod, rotationId }: TRestartDTO) => {
const doc = await secretRotationDAL.findById(rotationId); const doc = await secretRotationDAL.findById(rotationId);
if (!doc) throw new BadRequestError({ message: "Rotation not found" }); if (!doc) throw new BadRequestError({ message: "Rotation not found" });
@@ -157,18 +182,30 @@ export const secretRotationServiceFactory = ({
message: "Failed to add secret rotation due to plan restriction. Upgrade plan to add secret rotation." message: "Failed to add secret rotation due to plan restriction. Upgrade plan to add secret rotation."
}); });
const { permission } = await permissionService.getProjectPermission(actor, actorId, doc.projectId, actorOrgId); const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
doc.projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.SecretRotation); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.SecretRotation);
await secretRotationQueue.removeFromQueue(doc.id, doc.interval); await secretRotationQueue.removeFromQueue(doc.id, doc.interval);
await secretRotationQueue.addToQueue(doc.id, doc.interval); await secretRotationQueue.addToQueue(doc.id, doc.interval);
return doc; return doc;
}; };
const deleteById = async ({ actor, actorId, actorOrgId, rotationId }: TDeleteDTO) => { const deleteById = async ({ actor, actorId, actorOrgId, actorAuthMethod, rotationId }: TDeleteDTO) => {
const doc = await secretRotationDAL.findById(rotationId); const doc = await secretRotationDAL.findById(rotationId);
if (!doc) throw new BadRequestError({ message: "Rotation not found" }); if (!doc) throw new BadRequestError({ message: "Rotation not found" });
const { permission } = await permissionService.getProjectPermission(actor, actorId, doc.projectId, actorOrgId); const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
doc.projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Delete, ProjectPermissionActions.Delete,
ProjectPermissionSub.SecretRotation ProjectPermissionSub.SecretRotation
@@ -39,8 +39,14 @@ export const secretScanningServiceFactory = ({
permissionService, permissionService,
secretScanningQueue secretScanningQueue
}: TSecretScanningServiceFactoryDep) => { }: TSecretScanningServiceFactoryDep) => {
const createInstallationSession = async ({ actor, orgId, actorId, actorOrgId }: TInstallAppSessionDTO) => { const createInstallationSession = async ({
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, actorOrgId); actor,
orgId,
actorId,
actorAuthMethod,
actorOrgId
}: TInstallAppSessionDTO) => {
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, actorAuthMethod, actorOrgId);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Create, OrgPermissionSubjects.SecretScanning); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Create, OrgPermissionSubjects.SecretScanning);
const sessionId = crypto.randomBytes(16).toString("hex"); const sessionId = crypto.randomBytes(16).toString("hex");
@@ -53,12 +59,19 @@ export const secretScanningServiceFactory = ({
actorId, actorId,
installationId, installationId,
actor, actor,
actorAuthMethod,
actorOrgId actorOrgId
}: TLinkInstallSessionDTO) => { }: TLinkInstallSessionDTO) => {
const session = await gitAppInstallSessionDAL.findOne({ sessionId }); const session = await gitAppInstallSessionDAL.findOne({ sessionId });
if (!session) throw new UnauthorizedError({ message: "Session not found" }); if (!session) throw new UnauthorizedError({ message: "Session not found" });
const { permission } = await permissionService.getOrgPermission(actor, actorId, session.orgId, actorOrgId); const { permission } = await permissionService.getOrgPermission(
actor,
actorId,
session.orgId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Create, OrgPermissionSubjects.SecretScanning); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Create, OrgPermissionSubjects.SecretScanning);
const installatedApp = await gitAppOrgDAL.transaction(async (tx) => { const installatedApp = await gitAppOrgDAL.transaction(async (tx) => {
await gitAppInstallSessionDAL.deleteById(session.id, tx); await gitAppInstallSessionDAL.deleteById(session.id, tx);
@@ -89,23 +102,37 @@ export const secretScanningServiceFactory = ({
return { installatedApp }; return { installatedApp };
}; };
const getOrgInstallationStatus = async ({ actorId, orgId, actor, actorOrgId }: TGetOrgInstallStatusDTO) => { const getOrgInstallationStatus = async ({
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, actorOrgId); actorId,
orgId,
actor,
actorAuthMethod,
actorOrgId
}: TGetOrgInstallStatusDTO) => {
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, actorAuthMethod, actorOrgId);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.SecretScanning); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.SecretScanning);
const appInstallation = await gitAppOrgDAL.findOne({ orgId }); const appInstallation = await gitAppOrgDAL.findOne({ orgId });
return Boolean(appInstallation); return Boolean(appInstallation);
}; };
const getRisksByOrg = async ({ actor, orgId, actorId, actorOrgId }: TGetOrgRisksDTO) => { const getRisksByOrg = async ({ actor, orgId, actorId, actorAuthMethod, actorOrgId }: TGetOrgRisksDTO) => {
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, actorOrgId); const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, actorAuthMethod, actorOrgId);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.SecretScanning); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.SecretScanning);
const risks = await secretScanningDAL.find({ orgId }, { sort: [["createdAt", "desc"]] }); const risks = await secretScanningDAL.find({ orgId }, { sort: [["createdAt", "desc"]] });
return { risks }; return { risks };
}; };
const updateRiskStatus = async ({ actorId, orgId, actor, actorOrgId, riskId, status }: TUpdateRiskStatusDTO) => { const updateRiskStatus = async ({
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, actorOrgId); actorId,
orgId,
actor,
actorOrgId,
actorAuthMethod,
riskId,
status
}: TUpdateRiskStatusDTO) => {
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, actorAuthMethod, actorOrgId);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Edit, OrgPermissionSubjects.SecretScanning); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Edit, OrgPermissionSubjects.SecretScanning);
const isRiskResolved = Boolean( const isRiskResolved = Boolean(
@@ -59,9 +59,16 @@ export const secretSnapshotServiceFactory = ({
actorId, actorId,
actor, actor,
actorOrgId, actorOrgId,
actorAuthMethod,
path path
}: TProjectSnapshotCountDTO) => { }: TProjectSnapshotCountDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId); const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.SecretRollback); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.SecretRollback);
const folder = await folderDAL.findBySecretPath(projectId, environment, path); const folder = await folderDAL.findBySecretPath(projectId, environment, path);
@@ -77,11 +84,18 @@ export const secretSnapshotServiceFactory = ({
actorId, actorId,
actor, actor,
actorOrgId, actorOrgId,
actorAuthMethod,
path, path,
limit = 20, limit = 20,
offset = 0 offset = 0
}: TProjectSnapshotListDTO) => { }: TProjectSnapshotListDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId); const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.SecretRollback); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.SecretRollback);
const folder = await folderDAL.findBySecretPath(projectId, environment, path); const folder = await folderDAL.findBySecretPath(projectId, environment, path);
@@ -91,10 +105,16 @@ export const secretSnapshotServiceFactory = ({
return snapshots; return snapshots;
}; };
const getSnapshotData = async ({ actorId, actor, actorOrgId, id }: TGetSnapshotDataDTO) => { const getSnapshotData = async ({ actorId, actor, actorOrgId, actorAuthMethod, id }: TGetSnapshotDataDTO) => {
const snapshot = await snapshotDAL.findSecretSnapshotDataById(id); const snapshot = await snapshotDAL.findSecretSnapshotDataById(id);
if (!snapshot) throw new BadRequestError({ message: "Snapshot not found" }); if (!snapshot) throw new BadRequestError({ message: "Snapshot not found" });
const { permission } = await permissionService.getProjectPermission(actor, actorId, snapshot.projectId, actorOrgId); const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
snapshot.projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.SecretRollback); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.SecretRollback);
return snapshot; return snapshot;
}; };
@@ -145,11 +165,23 @@ export const secretSnapshotServiceFactory = ({
} }
}; };
const rollbackSnapshot = async ({ id: snapshotId, actor, actorId, actorOrgId }: TRollbackSnapshotDTO) => { const rollbackSnapshot = async ({
id: snapshotId,
actor,
actorId,
actorAuthMethod,
actorOrgId
}: TRollbackSnapshotDTO) => {
const snapshot = await snapshotDAL.findById(snapshotId); const snapshot = await snapshotDAL.findById(snapshotId);
if (!snapshot) throw new BadRequestError({ message: "Snapshot not found" }); if (!snapshot) throw new BadRequestError({ message: "Snapshot not found" });
const { permission } = await permissionService.getProjectPermission(actor, actorId, snapshot.projectId, actorOrgId); const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
snapshot.projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Create, ProjectPermissionActions.Create,
ProjectPermissionSub.SecretRollback ProjectPermissionSub.SecretRollback
@@ -26,8 +26,14 @@ export const trustedIpServiceFactory = ({
licenseService, licenseService,
projectDAL projectDAL
}: TTrustedIpServiceFactoryDep) => { }: TTrustedIpServiceFactoryDep) => {
const listIpsByProjectId = async ({ projectId, actor, actorId, actorOrgId }: TProjectPermission) => { const listIpsByProjectId = async ({ projectId, actor, actorId, actorAuthMethod, actorOrgId }: TProjectPermission) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId); const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.IpAllowList); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.IpAllowList);
const trustedIps = await trustedIpDAL.find({ const trustedIps = await trustedIpDAL.find({
projectId projectId
@@ -38,13 +44,20 @@ export const trustedIpServiceFactory = ({
const addProjectIp = async ({ const addProjectIp = async ({
projectId, projectId,
actorId, actorId,
actorAuthMethod,
actor, actor,
actorOrgId, actorOrgId,
ipAddress: ip, ipAddress: ip,
comment, comment,
isActive isActive
}: TCreateIpDTO) => { }: TCreateIpDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId); const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Create, ProjectPermissionSub.IpAllowList); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Create, ProjectPermissionSub.IpAllowList);
const project = await projectDAL.findById(projectId); const project = await projectDAL.findById(projectId);
@@ -78,11 +91,18 @@ export const trustedIpServiceFactory = ({
actorId, actorId,
actor, actor,
actorOrgId, actorOrgId,
actorAuthMethod,
ipAddress: ip, ipAddress: ip,
comment, comment,
trustedIpId trustedIpId
}: TUpdateIpDTO) => { }: TUpdateIpDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId); const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Create, ProjectPermissionSub.IpAllowList); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Create, ProjectPermissionSub.IpAllowList);
const project = await projectDAL.findById(projectId); const project = await projectDAL.findById(projectId);
@@ -113,8 +133,21 @@ export const trustedIpServiceFactory = ({
return { trustedIp, project }; // for audit log return { trustedIp, project }; // for audit log
}; };
const deleteProjectIp = async ({ projectId, actorId, actor, actorOrgId, trustedIpId }: TDeleteIpDTO) => { const deleteProjectIp = async ({
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId); projectId,
actorId,
actor,
actorOrgId,
actorAuthMethod,
trustedIpId
}: TDeleteIpDTO) => {
const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Create, ProjectPermissionSub.IpAllowList); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Create, ProjectPermissionSub.IpAllowList);
const project = await projectDAL.findById(projectId); const project = await projectDAL.findById(projectId);
+2 -1
View File
@@ -84,7 +84,7 @@ export const ORGANIZATIONS = {
export const PROJECTS = { export const PROJECTS = {
CREATE: { CREATE: {
organizationId: "The ID of the organization to create the project in.", organizationSlug: "The slug of the organization to create the project in.",
projectName: "The name of the project to create.", projectName: "The name of the project to create.",
slug: "An optional slug for the project." slug: "An optional slug for the project."
}, },
@@ -197,6 +197,7 @@ export const FOLDERS = {
export const RAW_SECRETS = { export const RAW_SECRETS = {
LIST: { LIST: {
workspaceId: "The ID of the project to list secrets from.", workspaceId: "The ID of the project to list secrets from.",
workspaceSlug: "The slug of the project to list secrets from. This parameter is only usable by machine identities.",
environment: "The slug of the environment to list secrets from.", environment: "The slug of the environment to list secrets from.",
secretPath: "The secret path to list secrets from.", secretPath: "The secret path to list secrets from.",
includeImports: "Weather to include imported secrets or not." includeImports: "Weather to include imported secrets or not."
+5 -3
View File
@@ -1,17 +1,19 @@
import { ActorType } from "@app/services/auth/auth-type"; import { ActorAuthMethod, ActorType } from "@app/services/auth/auth-type";
export type TOrgPermission = { export type TOrgPermission = {
actor: ActorType; actor: ActorType;
actorId: string; actorId: string;
orgId: string; orgId: string;
actorOrgId?: string; actorAuthMethod: ActorAuthMethod;
actorOrgId: string | undefined;
}; };
export type TProjectPermission = { export type TProjectPermission = {
actor: ActorType; actor: ActorType;
actorId: string; actorId: string;
projectId: string; projectId: string;
actorOrgId?: string; actorAuthMethod: ActorAuthMethod;
actorOrgId: string | undefined;
}; };
export type RequiredKeys<T> = { export type RequiredKeys<T> = {
@@ -6,42 +6,49 @@ import { TServiceTokens, TUsers } from "@app/db/schemas";
import { TScimTokenJwtPayload } from "@app/ee/services/scim/scim-types"; import { TScimTokenJwtPayload } from "@app/ee/services/scim/scim-types";
import { getConfig } from "@app/lib/config/env"; import { getConfig } from "@app/lib/config/env";
import { UnauthorizedError } from "@app/lib/errors"; import { UnauthorizedError } from "@app/lib/errors";
import { ActorType, AuthMode, AuthModeJwtTokenPayload, AuthTokenType } from "@app/services/auth/auth-type"; import { ActorType, AuthMethod, AuthMode, AuthModeJwtTokenPayload, AuthTokenType } from "@app/services/auth/auth-type";
import { TIdentityAccessTokenJwtPayload } from "@app/services/identity-access-token/identity-access-token-types"; import { TIdentityAccessTokenJwtPayload } from "@app/services/identity-access-token/identity-access-token-types";
export type TAuthMode = export type TAuthMode =
| { | {
orgId?: string;
authMode: AuthMode.JWT; authMode: AuthMode.JWT;
actor: ActorType.USER; actor: ActorType.USER;
userId: string; userId: string;
tokenVersionId: string; // the session id of token used tokenVersionId: string; // the session id of token used
user: TUsers; user: TUsers;
orgId?: string;
authMethod: AuthMethod;
} }
| { | {
authMode: AuthMode.API_KEY; authMode: AuthMode.API_KEY;
authMethod: null;
actor: ActorType.USER; actor: ActorType.USER;
userId: string; userId: string;
user: TUsers; user: TUsers;
orgId?: string; orgId: string;
} }
| { | {
authMode: AuthMode.SERVICE_TOKEN; authMode: AuthMode.SERVICE_TOKEN;
serviceToken: TServiceTokens & { createdByEmail: string }; serviceToken: TServiceTokens & { createdByEmail: string };
actor: ActorType.SERVICE; actor: ActorType.SERVICE;
serviceTokenId: string; serviceTokenId: string;
orgId: string;
authMethod: null;
} }
| { | {
authMode: AuthMode.IDENTITY_ACCESS_TOKEN; authMode: AuthMode.IDENTITY_ACCESS_TOKEN;
actor: ActorType.IDENTITY; actor: ActorType.IDENTITY;
identityId: string; identityId: string;
identityName: string; identityName: string;
orgId: string;
authMethod: null;
} }
| { | {
authMode: AuthMode.SCIM_TOKEN; authMode: AuthMode.SCIM_TOKEN;
actor: ActorType.SCIM_CLIENT; actor: ActorType.SCIM_CLIENT;
scimTokenId: string; scimTokenId: string;
orgId: string; orgId: string;
authMethod: null;
}; };
const extractAuth = async (req: FastifyRequest, jwtSecret: string) => { const extractAuth = async (req: FastifyRequest, jwtSecret: string) => {
@@ -50,6 +57,7 @@ const extractAuth = async (req: FastifyRequest, jwtSecret: string) => {
return { authMode: AuthMode.API_KEY, token: apiKey, actor: ActorType.USER } as const; return { authMode: AuthMode.API_KEY, token: apiKey, actor: ActorType.USER } as const;
} }
const authHeader = req.headers?.authorization; const authHeader = req.headers?.authorization;
if (!authHeader) return { authMode: null, token: null }; if (!authHeader) return { authMode: null, token: null };
const authTokenValue = authHeader.slice(7); // slice of after Bearer const authTokenValue = authHeader.slice(7); // slice of after Bearer
@@ -71,6 +79,7 @@ const extractAuth = async (req: FastifyRequest, jwtSecret: string) => {
actor: ActorType.USER actor: ActorType.USER
} as const; } as const;
case AuthTokenType.API_KEY: case AuthTokenType.API_KEY:
// throw new Error("API Key auth is no longer supported.");
return { authMode: AuthMode.API_KEY, token: decodedToken, actor: ActorType.USER } as const; return { authMode: AuthMode.API_KEY, token: decodedToken, actor: ActorType.USER } as const;
case AuthTokenType.IDENTITY_ACCESS_TOKEN: case AuthTokenType.IDENTITY_ACCESS_TOKEN:
return { return {
@@ -89,17 +98,30 @@ const extractAuth = async (req: FastifyRequest, jwtSecret: string) => {
} }
}; };
// ! Important: You can only 100% count on the `req.permission.orgId` field being present when the auth method is Identity Access Token (Machine Identity).
export const injectIdentity = fp(async (server: FastifyZodProvider) => { export const injectIdentity = fp(async (server: FastifyZodProvider) => {
server.decorateRequest("auth", null); server.decorateRequest("auth", null);
server.addHook("onRequest", async (req) => { server.addHook("onRequest", async (req) => {
const appCfg = getConfig(); const appCfg = getConfig();
const { authMode, token, actor } = await extractAuth(req, appCfg.AUTH_SECRET); const { authMode, token, actor } = await extractAuth(req, appCfg.AUTH_SECRET);
if (req.url.includes("/api/v3/auth/")) {
return;
}
if (!authMode) return; if (!authMode) return;
switch (authMode) { switch (authMode) {
case AuthMode.JWT: { case AuthMode.JWT: {
const { user, tokenVersionId, orgId } = await server.services.authToken.fnValidateJwtIdentity(token); const { user, tokenVersionId, orgId } = await server.services.authToken.fnValidateJwtIdentity(token);
req.auth = { authMode: AuthMode.JWT, user, userId: user.id, tokenVersionId, actor, orgId }; req.auth = {
authMode: AuthMode.JWT,
user,
userId: user.id,
tokenVersionId,
actor,
orgId,
authMethod: token.authMethod
};
break; break;
} }
case AuthMode.IDENTITY_ACCESS_TOKEN: { case AuthMode.IDENTITY_ACCESS_TOKEN: {
@@ -107,29 +129,40 @@ export const injectIdentity = fp(async (server: FastifyZodProvider) => {
req.auth = { req.auth = {
authMode: AuthMode.IDENTITY_ACCESS_TOKEN, authMode: AuthMode.IDENTITY_ACCESS_TOKEN,
actor, actor,
orgId: identity.orgId,
identityId: identity.identityId, identityId: identity.identityId,
identityName: identity.name identityName: identity.name,
authMethod: null
}; };
break; break;
} }
case AuthMode.SERVICE_TOKEN: { case AuthMode.SERVICE_TOKEN: {
const serviceToken = await server.services.serviceToken.fnValidateServiceToken(token); const serviceToken = await server.services.serviceToken.fnValidateServiceToken(token);
req.auth = { req.auth = {
orgId: serviceToken.orgId,
authMode: AuthMode.SERVICE_TOKEN as const, authMode: AuthMode.SERVICE_TOKEN as const,
serviceToken, serviceToken,
serviceTokenId: serviceToken.id, serviceTokenId: serviceToken.id,
actor actor,
authMethod: null
}; };
break; break;
} }
case AuthMode.API_KEY: { case AuthMode.API_KEY: {
const user = await server.services.apiKey.fnValidateApiKey(token as string); const user = await server.services.apiKey.fnValidateApiKey(token as string);
req.auth = { authMode: AuthMode.API_KEY as const, userId: user.id, actor, user }; req.auth = {
authMode: AuthMode.API_KEY as const,
userId: user.id,
actor,
user,
orgId: "API_KEY", // We set the orgId to an arbitrary value, since we can't link an API key to a specific org. We have to deprecate API keys soon!
authMethod: null
};
break; break;
} }
case AuthMode.SCIM_TOKEN: { case AuthMode.SCIM_TOKEN: {
const { orgId, scimTokenId } = await server.services.scim.fnValidateScimToken(token); const { orgId, scimTokenId } = await server.services.scim.fnValidateScimToken(token);
req.auth = { authMode: AuthMode.SCIM_TOKEN, actor, scimTokenId, orgId }; req.auth = { authMode: AuthMode.SCIM_TOKEN, actor, scimTokenId, orgId, authMethod: null };
break; break;
} }
default: default:
@@ -9,13 +9,33 @@ export const injectPermission = fp(async (server) => {
if (!req.auth) return; if (!req.auth) return;
if (req.auth.actor === ActorType.USER) { if (req.auth.actor === ActorType.USER) {
req.permission = { type: ActorType.USER, id: req.auth.userId, orgId: req.auth?.orgId }; req.permission = {
type: ActorType.USER,
id: req.auth.userId,
orgId: req.auth.orgId, // if the req.auth.authMode is AuthMode.API_KEY, the orgId will be "API_KEY"
authMethod: req.auth.authMethod // if the req.auth.authMode is AuthMode.API_KEY, the authMethod will be null
};
} else if (req.auth.actor === ActorType.IDENTITY) { } else if (req.auth.actor === ActorType.IDENTITY) {
req.permission = { type: ActorType.IDENTITY, id: req.auth.identityId }; req.permission = {
type: ActorType.IDENTITY,
id: req.auth.identityId,
orgId: req.auth.orgId,
authMethod: null
};
} else if (req.auth.actor === ActorType.SERVICE) { } else if (req.auth.actor === ActorType.SERVICE) {
req.permission = { type: ActorType.SERVICE, id: req.auth.serviceTokenId }; req.permission = {
type: ActorType.SERVICE,
id: req.auth.serviceTokenId,
orgId: req.auth.orgId,
authMethod: null
};
} else if (req.auth.actor === ActorType.SCIM_CLIENT) { } else if (req.auth.actor === ActorType.SCIM_CLIENT) {
req.permission = { type: ActorType.SCIM_CLIENT, id: req.auth.scimTokenId, orgId: req.auth.orgId }; req.permission = {
type: ActorType.SCIM_CLIENT,
id: req.auth.scimTokenId,
orgId: req.auth.orgId,
authMethod: null
};
} }
}); });
}); });
+14 -3
View File
@@ -3,15 +3,26 @@ import { FastifyReply, FastifyRequest, HookHandlerDoneFunction } from "fastify";
import { UnauthorizedError } from "@app/lib/errors"; import { UnauthorizedError } from "@app/lib/errors";
import { AuthMode } from "@app/services/auth/auth-type"; import { AuthMode } from "@app/services/auth/auth-type";
interface TAuthOptions {
requireOrg: boolean;
}
export const verifyAuth = export const verifyAuth =
<T extends FastifyRequest>(authStrats: AuthMode[]) => <T extends FastifyRequest>(authStrategies: AuthMode[], options: TAuthOptions = { requireOrg: true }) =>
(req: T, _res: FastifyReply, done: HookHandlerDoneFunction) => { (req: T, _res: FastifyReply, done: HookHandlerDoneFunction) => {
if (!Array.isArray(authStrats)) throw new Error("Auth strategy must be array"); 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({ name: "Unauthorized access", message: "Token missing" });
const isAccessAllowed = authStrats.some((strat) => strat === req.auth.authMode); const isAccessAllowed = authStrategies.some((strategy) => strategy === req.auth.authMode);
if (!isAccessAllowed) { if (!isAccessAllowed) {
throw new UnauthorizedError({ name: `${req.url} Unauthorized Access` }); throw new UnauthorizedError({ name: `${req.url} Unauthorized Access` });
} }
// New optional option. There are some routes which do not require an organization ID to be present on the request.
// An example of this is the /v1 auth routes.
if (req.auth.authMode === AuthMode.JWT && options.requireOrg === true && !req.permission.orgId) {
throw new UnauthorizedError({ name: `${req.url} Unauthorized Access, no organization found in request` });
}
done(); done();
}; };
+10 -4
View File
@@ -201,7 +201,8 @@ export const registerRoutes = async (
permissionDAL, permissionDAL,
orgRoleDAL, orgRoleDAL,
projectRoleDAL, projectRoleDAL,
serviceTokenDAL serviceTokenDAL,
projectDAL
}); });
const licenseService = licenseServiceFactory({ permissionService, orgDAL, licenseDAL, keyStore }); const licenseService = licenseServiceFactory({ permissionService, orgDAL, licenseDAL, keyStore });
const trustedIpService = trustedIpServiceFactory({ const trustedIpService = trustedIpServiceFactory({
@@ -266,7 +267,7 @@ export const registerRoutes = async (
const tokenService = tokenServiceFactory({ tokenDAL: authTokenDAL, userDAL }); const tokenService = tokenServiceFactory({ tokenDAL: authTokenDAL, userDAL });
const userService = userServiceFactory({ userDAL }); const userService = userServiceFactory({ userDAL });
const loginService = authLoginServiceFactory({ userDAL, smtpService, tokenService }); const loginService = authLoginServiceFactory({ userDAL, smtpService, tokenService, orgDAL, tokenDAL: authTokenDAL });
const passwordService = authPaswordServiceFactory({ const passwordService = authPaswordServiceFactory({
tokenService, tokenService,
smtpService, smtpService,
@@ -372,6 +373,7 @@ export const registerRoutes = async (
projectKeyDAL, projectKeyDAL,
userDAL, userDAL,
projectEnvDAL, projectEnvDAL,
orgDAL,
orgService, orgService,
projectMembershipDAL, projectMembershipDAL,
folderDAL, folderDAL,
@@ -517,7 +519,8 @@ export const registerRoutes = async (
projectEnvDAL, projectEnvDAL,
serviceTokenDAL, serviceTokenDAL,
userDAL, userDAL,
permissionService permissionService,
projectDAL
}); });
const identityService = identityServiceFactory({ const identityService = identityServiceFactory({
@@ -525,7 +528,10 @@ export const registerRoutes = async (
identityDAL, identityDAL,
identityOrgMembershipDAL identityOrgMembershipDAL
}); });
const identityAccessTokenService = identityAccessTokenServiceFactory({ identityAccessTokenDAL }); const identityAccessTokenService = identityAccessTokenServiceFactory({
identityAccessTokenDAL,
identityOrgMembershipDAL
});
const identityProjectService = identityProjectServiceFactory({ const identityProjectService = identityProjectServiceFactory({
permissionService, permissionService,
projectDAL, projectDAL,
+2 -1
View File
@@ -21,7 +21,7 @@ export const registerAuthRoutes = async (server: FastifyZodProvider) => {
}) })
} }
}, },
onRequest: verifyAuth([AuthMode.JWT]), onRequest: verifyAuth([AuthMode.JWT], { requireOrg: false }),
handler: async (req, res) => { handler: async (req, res) => {
const appCfg = getConfig(); const appCfg = getConfig();
if (req.auth.authMode === AuthMode.JWT) { if (req.auth.authMode === AuthMode.JWT) {
@@ -85,6 +85,7 @@ export const registerAuthRoutes = async (server: FastifyZodProvider) => {
const token = jwt.sign( const token = jwt.sign(
{ {
authMethod: decodedToken.authMethod,
authTokenType: AuthTokenType.ACCESS_TOKEN, authTokenType: AuthTokenType.ACCESS_TOKEN,
userId: decodedToken.userId, userId: decodedToken.userId,
tokenVersionId: tokenVersion.id, tokenVersionId: tokenVersion.id,
@@ -30,6 +30,7 @@ export const registerProjectBotRouter = async (server: FastifyZodProvider) => {
actor: req.permission.type, actor: req.permission.type,
actorId: req.permission.id, actorId: req.permission.id,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
actorAuthMethod: req.permission.authMethod,
projectId: req.params.projectId projectId: req.params.projectId
}); });
return { bot }; return { bot };
@@ -70,6 +71,7 @@ export const registerProjectBotRouter = async (server: FastifyZodProvider) => {
actor: req.permission.type, actor: req.permission.type,
actorId: req.permission.id, actorId: req.permission.id,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
actorAuthMethod: req.permission.authMethod,
botId: req.params.botId, botId: req.params.botId,
botKey: req.body.botKey, botKey: req.body.botKey,
isActive: req.body.isActive isActive: req.body.isActive
@@ -35,6 +35,7 @@ export const registerIdentityRouter = async (server: FastifyZodProvider) => {
const identity = await server.services.identity.createIdentity({ const identity = await server.services.identity.createIdentity({
actor: req.permission.type, actor: req.permission.type,
actorId: req.permission.id, actorId: req.permission.id,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
...req.body, ...req.body,
orgId: req.body.organizationId orgId: req.body.organizationId
@@ -95,6 +96,7 @@ export const registerIdentityRouter = async (server: FastifyZodProvider) => {
const identity = await server.services.identity.updateIdentity({ const identity = await server.services.identity.updateIdentity({
actor: req.permission.type, actor: req.permission.type,
actorId: req.permission.id, actorId: req.permission.id,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
id: req.params.identityId, id: req.params.identityId,
...req.body ...req.body
@@ -140,6 +142,7 @@ export const registerIdentityRouter = async (server: FastifyZodProvider) => {
const identity = await server.services.identity.deleteIdentity({ const identity = await server.services.identity.deleteIdentity({
actor: req.permission.type, actor: req.permission.type,
actorId: req.permission.id, actorId: req.permission.id,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
id: req.params.identityId id: req.params.identityId
}); });
@@ -131,6 +131,7 @@ export const registerIdentityUaRouter = async (server: FastifyZodProvider) => {
actor: req.permission.type, actor: req.permission.type,
actorId: req.permission.id, actorId: req.permission.id,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
actorAuthMethod: req.permission.authMethod,
...req.body, ...req.body,
identityId: req.params.identityId identityId: req.params.identityId
}); });
@@ -212,6 +213,7 @@ export const registerIdentityUaRouter = async (server: FastifyZodProvider) => {
actor: req.permission.type, actor: req.permission.type,
actorId: req.permission.id, actorId: req.permission.id,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
actorAuthMethod: req.permission.authMethod,
...req.body, ...req.body,
identityId: req.params.identityId identityId: req.params.identityId
}); });
@@ -260,6 +262,7 @@ export const registerIdentityUaRouter = async (server: FastifyZodProvider) => {
const identityUniversalAuth = await server.services.identityUa.getIdentityUa({ const identityUniversalAuth = await server.services.identityUa.getIdentityUa({
actor: req.permission.type, actor: req.permission.type,
actorId: req.permission.id, actorId: req.permission.id,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
identityId: req.params.identityId identityId: req.params.identityId
}); });
@@ -309,6 +312,7 @@ export const registerIdentityUaRouter = async (server: FastifyZodProvider) => {
const { clientSecret, clientSecretData, orgId } = await server.services.identityUa.createUaClientSecret({ const { clientSecret, clientSecretData, orgId } = await server.services.identityUa.createUaClientSecret({
actor: req.permission.type, actor: req.permission.type,
actorId: req.permission.id, actorId: req.permission.id,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
identityId: req.params.identityId, identityId: req.params.identityId,
...req.body ...req.body
@@ -354,6 +358,7 @@ export const registerIdentityUaRouter = async (server: FastifyZodProvider) => {
const { clientSecrets: clientSecretData, orgId } = await server.services.identityUa.getUaClientSecrets({ const { clientSecrets: clientSecretData, orgId } = await server.services.identityUa.getUaClientSecrets({
actor: req.permission.type, actor: req.permission.type,
actorId: req.permission.id, actorId: req.permission.id,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
identityId: req.params.identityId identityId: req.params.identityId
}); });
@@ -397,6 +402,7 @@ export const registerIdentityUaRouter = async (server: FastifyZodProvider) => {
const clientSecretData = await server.services.identityUa.revokeUaClientSecret({ const clientSecretData = await server.services.identityUa.revokeUaClientSecret({
actor: req.permission.type, actor: req.permission.type,
actorId: req.permission.id, actorId: req.permission.id,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
identityId: req.params.identityId, identityId: req.params.identityId,
clientSecretId: req.params.clientSecretId clientSecretId: req.params.clientSecretId
@@ -53,6 +53,7 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider)
const integrationAuth = await server.services.integrationAuth.getIntegrationAuth({ const integrationAuth = await server.services.integrationAuth.getIntegrationAuth({
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
id: req.params.integrationAuthId id: req.params.integrationAuthId
}); });
@@ -80,6 +81,7 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider)
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
actorAuthMethod: req.permission.authMethod,
integration: req.query.integration, integration: req.query.integration,
projectId: req.query.projectId projectId: req.query.projectId
}); });
@@ -117,6 +119,7 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider)
const integrationAuth = await server.services.integrationAuth.deleteIntegrationAuthById({ const integrationAuth = await server.services.integrationAuth.deleteIntegrationAuthById({
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
id: req.params.integrationAuthId id: req.params.integrationAuthId
}); });
@@ -157,6 +160,7 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider)
const integrationAuth = await server.services.integrationAuth.oauthExchange({ const integrationAuth = await server.services.integrationAuth.oauthExchange({
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
projectId: req.body.workspaceId, projectId: req.body.workspaceId,
...req.body ...req.body
@@ -200,6 +204,7 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider)
const integrationAuth = await server.services.integrationAuth.saveIntegrationToken({ const integrationAuth = await server.services.integrationAuth.saveIntegrationToken({
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
projectId: req.body.workspaceId, projectId: req.body.workspaceId,
...req.body ...req.body
@@ -247,6 +252,7 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider)
const apps = await server.services.integrationAuth.getIntegrationApps({ const apps = await server.services.integrationAuth.getIntegrationApps({
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
id: req.params.integrationAuthId, id: req.params.integrationAuthId,
...req.query ...req.query
@@ -278,6 +284,7 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider)
const teams = await server.services.integrationAuth.getIntegrationAuthTeams({ const teams = await server.services.integrationAuth.getIntegrationAuthTeams({
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
id: req.params.integrationAuthId id: req.params.integrationAuthId
}); });
@@ -306,6 +313,7 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider)
const branches = await server.services.integrationAuth.getVercelBranches({ const branches = await server.services.integrationAuth.getVercelBranches({
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
id: req.params.integrationAuthId, id: req.params.integrationAuthId,
appId: req.query.appId appId: req.query.appId
@@ -335,6 +343,7 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider)
const groups = await server.services.integrationAuth.getChecklyGroups({ const groups = await server.services.integrationAuth.getChecklyGroups({
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
id: req.params.integrationAuthId, id: req.params.integrationAuthId,
accountId: req.query.accountId accountId: req.query.accountId
@@ -362,6 +371,7 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider)
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
actorAuthMethod: req.permission.authMethod,
id: req.params.integrationAuthId id: req.params.integrationAuthId
}); });
if (!orgs) throw new Error("No organization found."); if (!orgs) throw new Error("No organization found.");
@@ -394,6 +404,7 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider)
actor: req.permission.type, actor: req.permission.type,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
id: req.params.integrationAuthId, id: req.params.integrationAuthId,
actorAuthMethod: req.permission.authMethod,
repoName: req.query.repoName, repoName: req.query.repoName,
repoOwner: req.query.repoOwner repoOwner: req.query.repoOwner
}); });
@@ -421,6 +432,7 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider)
const orgs = await server.services.integrationAuth.getQoveryOrgs({ const orgs = await server.services.integrationAuth.getQoveryOrgs({
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
id: req.params.integrationAuthId id: req.params.integrationAuthId
}); });
@@ -449,6 +461,7 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider)
const projects = await server.services.integrationAuth.getQoveryProjects({ const projects = await server.services.integrationAuth.getQoveryProjects({
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
id: req.params.integrationAuthId, id: req.params.integrationAuthId,
orgId: req.query.orgId orgId: req.query.orgId
@@ -478,6 +491,7 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider)
const environments = await server.services.integrationAuth.getQoveryEnvs({ const environments = await server.services.integrationAuth.getQoveryEnvs({
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
id: req.params.integrationAuthId, id: req.params.integrationAuthId,
projectId: req.query.projectId projectId: req.query.projectId
@@ -507,6 +521,7 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider)
const apps = await server.services.integrationAuth.getQoveryApps({ const apps = await server.services.integrationAuth.getQoveryApps({
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
id: req.params.integrationAuthId, id: req.params.integrationAuthId,
environmentId: req.query.environmentId environmentId: req.query.environmentId
@@ -536,6 +551,7 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider)
const containers = await server.services.integrationAuth.getQoveryContainers({ const containers = await server.services.integrationAuth.getQoveryContainers({
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
id: req.params.integrationAuthId, id: req.params.integrationAuthId,
environmentId: req.query.environmentId environmentId: req.query.environmentId
@@ -565,6 +581,7 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider)
const jobs = await server.services.integrationAuth.getQoveryJobs({ const jobs = await server.services.integrationAuth.getQoveryJobs({
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
id: req.params.integrationAuthId, id: req.params.integrationAuthId,
environmentId: req.query.environmentId environmentId: req.query.environmentId
@@ -597,6 +614,7 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider)
const pipelines = await server.services.integrationAuth.getHerokuPipelines({ const pipelines = await server.services.integrationAuth.getHerokuPipelines({
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
id: req.params.integrationAuthId id: req.params.integrationAuthId
}); });
@@ -625,6 +643,7 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider)
const environments = await server.services.integrationAuth.getRailwayEnvironments({ const environments = await server.services.integrationAuth.getRailwayEnvironments({
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
id: req.params.integrationAuthId, id: req.params.integrationAuthId,
appId: req.query.appId appId: req.query.appId
@@ -654,6 +673,7 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider)
const services = await server.services.integrationAuth.getRailwayServices({ const services = await server.services.integrationAuth.getRailwayServices({
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
id: req.params.integrationAuthId, id: req.params.integrationAuthId,
appId: req.query.appId appId: req.query.appId
@@ -690,6 +710,7 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider)
const workspaces = await server.services.integrationAuth.getBitbucketWorkspaces({ const workspaces = await server.services.integrationAuth.getBitbucketWorkspaces({
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
id: req.params.integrationAuthId id: req.params.integrationAuthId
}); });
@@ -723,6 +744,7 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider)
const secretGroups = await server.services.integrationAuth.getNorthFlankSecretGroups({ const secretGroups = await server.services.integrationAuth.getNorthFlankSecretGroups({
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
id: req.params.integrationAuthId, id: req.params.integrationAuthId,
appId: req.query.appId appId: req.query.appId
@@ -757,6 +779,7 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider)
const buildConfigs = await server.services.integrationAuth.getTeamcityBuildConfigs({ const buildConfigs = await server.services.integrationAuth.getTeamcityBuildConfigs({
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
id: req.params.integrationAuthId, id: req.params.integrationAuthId,
appId: req.query.appId appId: req.query.appId
@@ -54,6 +54,7 @@ export const registerIntegrationRouter = async (server: FastifyZodProvider) => {
const { integration, integrationAuth } = await server.services.integration.createIntegration({ const { integration, integrationAuth } = await server.services.integration.createIntegration({
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
...req.body ...req.body
}); });
@@ -124,6 +125,7 @@ export const registerIntegrationRouter = async (server: FastifyZodProvider) => {
const integration = await server.services.integration.updateIntegration({ const integration = await server.services.integration.updateIntegration({
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
id: req.params.integrationId, id: req.params.integrationId,
...req.body ...req.body
@@ -149,6 +151,7 @@ export const registerIntegrationRouter = async (server: FastifyZodProvider) => {
handler: async (req) => { handler: async (req) => {
const integration = await server.services.integration.deleteIntegration({ const integration = await server.services.integration.deleteIntegration({
actorId: req.permission.id, actorId: req.permission.id,
actorAuthMethod: req.permission.authMethod,
actor: req.permission.type, actor: req.permission.type,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
id: req.params.integrationId id: req.params.integrationId
@@ -29,6 +29,7 @@ export const registerInviteOrgRouter = async (server: FastifyZodProvider) => {
orgId: req.body.organizationId, orgId: req.body.organizationId,
userId: req.permission.id, userId: req.permission.id,
inviteeEmail: req.body.inviteeEmail, inviteeEmail: req.body.inviteeEmail,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId actorOrgId: req.permission.orgId
}); });
@@ -15,7 +15,7 @@ export const registerOrgRouter = async (server: FastifyZodProvider) => {
}) })
} }
}, },
onRequest: verifyAuth([AuthMode.JWT]), onRequest: verifyAuth([AuthMode.JWT], { requireOrg: false }),
handler: async (req) => { handler: async (req) => {
const organizations = await server.services.org.findAllOrganizationOfUser(req.permission.id); const organizations = await server.services.org.findAllOrganizationOfUser(req.permission.id);
return { organizations }; return { organizations };
@@ -40,6 +40,7 @@ export const registerOrgRouter = async (server: FastifyZodProvider) => {
const organization = await server.services.org.findOrganizationById( const organization = await server.services.org.findOrganizationById(
req.permission.id, req.permission.id,
req.params.organizationId, req.params.organizationId,
req.permission.authMethod,
req.permission.orgId req.permission.orgId
); );
return { organization }; return { organization };
@@ -76,6 +77,7 @@ export const registerOrgRouter = async (server: FastifyZodProvider) => {
const users = await server.services.org.findAllOrgMembers( const users = await server.services.org.findAllOrgMembers(
req.permission.id, req.permission.id,
req.params.organizationId, req.params.organizationId,
req.permission.authMethod,
req.permission.orgId req.permission.orgId
); );
return { users }; return { users };
@@ -111,6 +113,7 @@ export const registerOrgRouter = async (server: FastifyZodProvider) => {
actor: req.permission.type, actor: req.permission.type,
actorId: req.permission.id, actorId: req.permission.id,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
actorAuthMethod: req.permission.authMethod,
orgId: req.params.organizationId, orgId: req.params.organizationId,
data: req.body data: req.body
}); });
@@ -138,6 +141,7 @@ export const registerOrgRouter = async (server: FastifyZodProvider) => {
const incidentContactsOrg = await req.server.services.org.findIncidentContacts( const incidentContactsOrg = await req.server.services.org.findIncidentContacts(
req.permission.id, req.permission.id,
req.params.organizationId, req.params.organizationId,
req.permission.authMethod,
req.permission.orgId req.permission.orgId
); );
return { incidentContactsOrg }; return { incidentContactsOrg };
@@ -162,6 +166,7 @@ export const registerOrgRouter = async (server: FastifyZodProvider) => {
req.permission.id, req.permission.id,
req.params.organizationId, req.params.organizationId,
req.body.email, req.body.email,
req.permission.authMethod,
req.permission.orgId req.permission.orgId
); );
return { incidentContactsOrg }; return { incidentContactsOrg };
@@ -185,6 +190,7 @@ export const registerOrgRouter = async (server: FastifyZodProvider) => {
req.permission.id, req.permission.id,
req.params.organizationId, req.params.organizationId,
req.params.incidentContactId, req.params.incidentContactId,
req.permission.authMethod,
req.permission.orgId req.permission.orgId
); );
return { incidentContactsOrg }; return { incidentContactsOrg };
@@ -39,6 +39,7 @@ export const registerProjectEnvRouter = async (server: FastifyZodProvider) => {
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
actorAuthMethod: req.permission.authMethod,
projectId: req.params.workspaceId, projectId: req.params.workspaceId,
...req.body ...req.body
}); });
@@ -95,6 +96,7 @@ export const registerProjectEnvRouter = async (server: FastifyZodProvider) => {
const { environment, old } = await server.services.projectEnv.updateEnvironment({ const { environment, old } = await server.services.projectEnv.updateEnvironment({
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
projectId: req.params.workspaceId, projectId: req.params.workspaceId,
id: req.params.id, id: req.params.id,
@@ -153,6 +155,7 @@ export const registerProjectEnvRouter = async (server: FastifyZodProvider) => {
const environment = await server.services.projectEnv.deleteEnvironment({ const environment = await server.services.projectEnv.deleteEnvironment({
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
projectId: req.params.workspaceId, projectId: req.params.workspaceId,
id: req.params.id id: req.params.id
@@ -30,6 +30,7 @@ export const registerProjectKeyRouter = async (server: FastifyZodProvider) => {
projectId: req.params.workspaceId, projectId: req.params.workspaceId,
actor: req.permission.type, actor: req.permission.type,
actorId: req.permission.id, actorId: req.permission.id,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
nonce: req.body.key.nonce, nonce: req.body.key.nonce,
receiverId: req.body.key.userId, receiverId: req.body.key.userId,
@@ -66,6 +66,7 @@ export const registerProjectMembershipRouter = async (server: FastifyZodProvider
const memberships = await server.services.projectMembership.getProjectMemberships({ const memberships = await server.services.projectMembership.getProjectMemberships({
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
projectId: req.params.workspaceId projectId: req.params.workspaceId
}); });
@@ -102,6 +103,7 @@ export const registerProjectMembershipRouter = async (server: FastifyZodProvider
const data = await server.services.projectMembership.addUsersToProject({ const data = await server.services.projectMembership.addUsersToProject({
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
projectId: req.params.workspaceId, projectId: req.params.workspaceId,
members: req.body.members members: req.body.members
@@ -170,6 +172,7 @@ export const registerProjectMembershipRouter = async (server: FastifyZodProvider
const roles = await server.services.projectMembership.updateProjectMembership({ const roles = await server.services.projectMembership.updateProjectMembership({
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
projectId: req.params.workspaceId, projectId: req.params.workspaceId,
membershipId: req.params.membershipId, membershipId: req.params.membershipId,
@@ -219,6 +222,7 @@ export const registerProjectMembershipRouter = async (server: FastifyZodProvider
const membership = await server.services.projectMembership.deleteProjectMembership({ const membership = await server.services.projectMembership.deleteProjectMembership({
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
projectId: req.params.workspaceId, projectId: req.params.workspaceId,
membershipId: req.params.membershipId membershipId: req.params.membershipId
+29 -36
View File
@@ -10,6 +10,7 @@ import {
import { PROJECTS } from "@app/lib/api-docs"; import { PROJECTS } from "@app/lib/api-docs";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth"; import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
import { AuthMode } from "@app/services/auth/auth-type"; import { AuthMode } from "@app/services/auth/auth-type";
import { ProjectFilterType } from "@app/services/project/project-types";
import { integrationAuthPubSchema } from "../sanitizedSchemas"; import { integrationAuthPubSchema } from "../sanitizedSchemas";
import { sanitizedServiceTokenSchema } from "../v2/service-token-router"; import { sanitizedServiceTokenSchema } from "../v2/service-token-router";
@@ -45,6 +46,7 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
const publicKeys = await server.services.projectKey.getProjectPublicKeys({ const publicKeys = await server.services.projectKey.getProjectPublicKeys({
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
projectId: req.params.workspaceId projectId: req.params.workspaceId
}); });
@@ -97,6 +99,7 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
const users = await server.services.projectMembership.getProjectMemberships({ const users = await server.services.projectMembership.getProjectMemberships({
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorAuthMethod: req.permission.authMethod,
projectId: req.params.workspaceId, projectId: req.params.workspaceId,
actorOrgId: req.permission.orgId actorOrgId: req.permission.orgId
}); });
@@ -137,37 +140,14 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
onRequest: verifyAuth([AuthMode.JWT, AuthMode.SERVICE_TOKEN, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.SERVICE_TOKEN, AuthMode.IDENTITY_ACCESS_TOKEN]),
handler: async (req) => { handler: async (req) => {
const workspace = await server.services.project.getAProject({ const workspace = await server.services.project.getAProject({
actorId: req.permission.id, filter: {
actor: req.permission.type, type: ProjectFilterType.ID,
actorOrgId: req.permission.orgId,
projectId: req.params.workspaceId projectId: req.params.workspaceId
});
return { workspace };
}
});
server.route({
url: "/",
method: "POST",
schema: {
body: z.object({
workspaceName: z.string().trim(),
organizationId: z.string().trim()
}),
response: {
200: z.object({
workspace: projectWithEnv
})
}
}, },
onRequest: verifyAuth([AuthMode.JWT]), actorAuthMethod: req.permission.authMethod,
handler: async (req) => {
const workspace = await server.services.project.createProject({
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
orgId: req.body.organizationId, actorOrgId: req.permission.orgId
actorOrgId: req.permission.orgId,
workspaceName: req.body.workspaceName
}); });
return { workspace }; return { workspace };
} }
@@ -189,10 +169,14 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
handler: async (req) => { handler: async (req) => {
const workspace = await server.services.project.deleteProject({ const workspace = await server.services.project.deleteProject({
actorId: req.permission.id, filter: {
actor: req.permission.type, type: ProjectFilterType.ID,
actorOrgId: req.permission.orgId,
projectId: req.params.workspaceId projectId: req.params.workspaceId
},
actorId: req.permission.id,
actorAuthMethod: req.permission.authMethod,
actor: req.permission.type,
actorOrgId: req.permission.orgId
}); });
return { workspace }; return { workspace };
} }
@@ -220,6 +204,7 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
const workspace = await server.services.project.updateName({ const workspace = await server.services.project.updateName({
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
projectId: req.params.workspaceId, projectId: req.params.workspaceId,
name: req.body.name name: req.body.name
@@ -253,17 +238,21 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
}) })
} }
}, },
onRequest: verifyAuth([AuthMode.JWT]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
handler: async (req) => { handler: async (req) => {
const workspace = await server.services.project.updateProject({ const workspace = await server.services.project.updateProject({
actorId: req.permission.id, filter: {
actor: req.permission.type, type: ProjectFilterType.ID,
actorOrgId: req.permission.orgId, projectId: req.params.workspaceId
projectId: req.params.workspaceId, },
update: { update: {
name: req.body.name, name: req.body.name,
autoCapitalization: req.body.autoCapitalization autoCapitalization: req.body.autoCapitalization
} },
actorAuthMethod: req.permission.authMethod,
actorId: req.permission.id,
actor: req.permission.type,
actorOrgId: req.permission.orgId
}); });
return { return {
workspace workspace
@@ -293,6 +282,7 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
const workspace = await server.services.project.toggleAutoCapitalization({ const workspace = await server.services.project.toggleAutoCapitalization({
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
projectId: req.params.workspaceId, projectId: req.params.workspaceId,
autoCapitalization: req.body.autoCapitalization autoCapitalization: req.body.autoCapitalization
@@ -329,6 +319,7 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
handler: async (req) => { handler: async (req) => {
const integrations = await server.services.integration.listIntegrationByProject({ const integrations = await server.services.integration.listIntegrationByProject({
actorId: req.permission.id, actorId: req.permission.id,
actorAuthMethod: req.permission.authMethod,
actor: req.permission.type, actor: req.permission.type,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
projectId: req.params.workspaceId projectId: req.params.workspaceId
@@ -354,6 +345,7 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
handler: async (req) => { handler: async (req) => {
const authorizations = await server.services.integrationAuth.listIntegrationAuthByProjectId({ const authorizations = await server.services.integrationAuth.listIntegrationAuthByProjectId({
actorId: req.permission.id, actorId: req.permission.id,
actorAuthMethod: req.permission.authMethod,
actor: req.permission.type, actor: req.permission.type,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
projectId: req.params.workspaceId projectId: req.params.workspaceId
@@ -379,6 +371,7 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
handler: async (req) => { handler: async (req) => {
const serviceTokenData = await server.services.serviceToken.getProjectServiceTokens({ const serviceTokenData = await server.services.serviceToken.getProjectServiceTokens({
actorId: req.permission.id, actorId: req.permission.id,
actorAuthMethod: req.permission.authMethod,
actor: req.permission.type, actor: req.permission.type,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
projectId: req.params.workspaceId projectId: req.params.workspaceId
@@ -39,6 +39,7 @@ export const registerSecretFolderRouter = async (server: FastifyZodProvider) =>
const folder = await server.services.folder.createFolder({ const folder = await server.services.folder.createFolder({
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
...req.body, ...req.body,
projectId: req.body.workspaceId, projectId: req.body.workspaceId,
@@ -96,6 +97,7 @@ export const registerSecretFolderRouter = async (server: FastifyZodProvider) =>
const { folder, old } = await server.services.folder.updateFolder({ const { folder, old } = await server.services.folder.updateFolder({
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
...req.body, ...req.body,
projectId: req.body.workspaceId, projectId: req.body.workspaceId,
@@ -154,6 +156,7 @@ export const registerSecretFolderRouter = async (server: FastifyZodProvider) =>
const folder = await server.services.folder.deleteFolder({ const folder = await server.services.folder.deleteFolder({
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
...req.body, ...req.body,
projectId: req.body.workspaceId, projectId: req.body.workspaceId,
@@ -207,6 +210,7 @@ export const registerSecretFolderRouter = async (server: FastifyZodProvider) =>
const folders = await server.services.folder.getFolders({ const folders = await server.services.folder.getFolders({
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
...req.query, ...req.query,
projectId: req.query.workspaceId, projectId: req.query.workspaceId,
@@ -44,6 +44,7 @@ export const registerSecretImportRouter = async (server: FastifyZodProvider) =>
const secretImport = await server.services.secretImport.createImport({ const secretImport = await server.services.secretImport.createImport({
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
...req.body, ...req.body,
projectId: req.body.workspaceId, projectId: req.body.workspaceId,
@@ -114,6 +115,7 @@ export const registerSecretImportRouter = async (server: FastifyZodProvider) =>
const secretImport = await server.services.secretImport.updateImport({ const secretImport = await server.services.secretImport.updateImport({
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
id: req.params.secretImportId, id: req.params.secretImportId,
...req.body, ...req.body,
@@ -175,6 +177,7 @@ export const registerSecretImportRouter = async (server: FastifyZodProvider) =>
const secretImport = await server.services.secretImport.deleteImport({ const secretImport = await server.services.secretImport.deleteImport({
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
id: req.params.secretImportId, id: req.params.secretImportId,
...req.body, ...req.body,
@@ -234,6 +237,7 @@ export const registerSecretImportRouter = async (server: FastifyZodProvider) =>
const secretImports = await server.services.secretImport.getImports({ const secretImports = await server.services.secretImport.getImports({
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
...req.query, ...req.query,
projectId: req.query.workspaceId projectId: req.query.workspaceId
@@ -287,6 +291,7 @@ export const registerSecretImportRouter = async (server: FastifyZodProvider) =>
const importedSecrets = await server.services.secretImport.getSecretsFromImports({ const importedSecrets = await server.services.secretImport.getSecretsFromImports({
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
...req.query, ...req.query,
projectId: req.query.workspaceId projectId: req.query.workspaceId
@@ -23,6 +23,7 @@ export const registerSecretTagRouter = async (server: FastifyZodProvider) => {
const workspaceTags = await server.services.secretTag.getProjectTags({ const workspaceTags = await server.services.secretTag.getProjectTags({
actor: req.permission.type, actor: req.permission.type,
actorId: req.permission.id, actorId: req.permission.id,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
projectId: req.params.projectId projectId: req.params.projectId
}); });
@@ -53,6 +54,7 @@ export const registerSecretTagRouter = async (server: FastifyZodProvider) => {
const workspaceTag = await server.services.secretTag.createTag({ const workspaceTag = await server.services.secretTag.createTag({
actor: req.permission.type, actor: req.permission.type,
actorId: req.permission.id, actorId: req.permission.id,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
projectId: req.params.projectId, projectId: req.params.projectId,
...req.body ...req.body
@@ -80,6 +82,7 @@ export const registerSecretTagRouter = async (server: FastifyZodProvider) => {
const workspaceTag = await server.services.secretTag.deleteTag({ const workspaceTag = await server.services.secretTag.deleteTag({
actor: req.permission.type, actor: req.permission.type,
actorId: req.permission.id, actorId: req.permission.id,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
id: req.params.tagId id: req.params.tagId
}); });
+1 -1
View File
@@ -15,7 +15,7 @@ export const registerUserRouter = async (server: FastifyZodProvider) => {
}) })
} }
}, },
onRequest: verifyAuth([AuthMode.JWT]), onRequest: verifyAuth([AuthMode.JWT], { requireOrg: false }),
handler: async (req) => { handler: async (req) => {
const user = await server.services.user.getMe(req.permission.id); const user = await server.services.user.getMe(req.permission.id);
return { user }; return { user };
@@ -47,6 +47,7 @@ export const registerWebhookRouter = async (server: FastifyZodProvider) => {
const webhook = await server.services.webhook.createWebhook({ const webhook = await server.services.webhook.createWebhook({
actor: req.permission.type, actor: req.permission.type,
actorId: req.permission.id, actorId: req.permission.id,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
projectId: req.body.workspaceId, projectId: req.body.workspaceId,
...req.body ...req.body
@@ -93,6 +94,7 @@ export const registerWebhookRouter = async (server: FastifyZodProvider) => {
const webhook = await server.services.webhook.updateWebhook({ const webhook = await server.services.webhook.updateWebhook({
actor: req.permission.type, actor: req.permission.type,
actorId: req.permission.id, actorId: req.permission.id,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
id: req.params.webhookId, id: req.params.webhookId,
isDisabled: req.body.isDisabled isDisabled: req.body.isDisabled
@@ -130,6 +132,7 @@ export const registerWebhookRouter = async (server: FastifyZodProvider) => {
const webhook = await server.services.webhook.deleteWebhook({ const webhook = await server.services.webhook.deleteWebhook({
actor: req.permission.type, actor: req.permission.type,
actorId: req.permission.id, actorId: req.permission.id,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
id: req.params.webhookId id: req.params.webhookId
}); });
@@ -172,6 +175,7 @@ export const registerWebhookRouter = async (server: FastifyZodProvider) => {
const webhook = await server.services.webhook.testWebhook({ const webhook = await server.services.webhook.testWebhook({
actor: req.permission.type, actor: req.permission.type,
actorId: req.permission.id, actorId: req.permission.id,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
id: req.params.webhookId id: req.params.webhookId
}); });
@@ -204,6 +208,7 @@ export const registerWebhookRouter = async (server: FastifyZodProvider) => {
const webhooks = await server.services.webhook.listWebhooks({ const webhooks = await server.services.webhook.listWebhooks({
actor: req.permission.type, actor: req.permission.type,
actorId: req.permission.id, actorId: req.permission.id,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
...req.query, ...req.query,
projectId: req.query.workspaceId projectId: req.query.workspaceId
@@ -42,6 +42,7 @@ export const registerIdentityOrgRouter = async (server: FastifyZodProvider) => {
const identityMemberships = await server.services.identity.listOrgIdentities({ const identityMemberships = await server.services.identity.listOrgIdentities({
actor: req.permission.type, actor: req.permission.type,
actorId: req.permission.id, actorId: req.permission.id,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
orgId: req.params.orgId orgId: req.params.orgId
}); });
@@ -35,6 +35,7 @@ export const registerIdentityProjectRouter = async (server: FastifyZodProvider)
const identityMembership = await server.services.identityProject.createProjectIdentity({ const identityMembership = await server.services.identityProject.createProjectIdentity({
actor: req.permission.type, actor: req.permission.type,
actorId: req.permission.id, actorId: req.permission.id,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
identityId: req.params.identityId, identityId: req.params.identityId,
projectId: req.params.projectId, projectId: req.params.projectId,
@@ -89,6 +90,7 @@ export const registerIdentityProjectRouter = async (server: FastifyZodProvider)
const roles = await server.services.identityProject.updateProjectIdentity({ const roles = await server.services.identityProject.updateProjectIdentity({
actor: req.permission.type, actor: req.permission.type,
actorId: req.permission.id, actorId: req.permission.id,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
identityId: req.params.identityId, identityId: req.params.identityId,
projectId: req.params.projectId, projectId: req.params.projectId,
@@ -123,6 +125,7 @@ export const registerIdentityProjectRouter = async (server: FastifyZodProvider)
const identityMembership = await server.services.identityProject.deleteProjectIdentity({ const identityMembership = await server.services.identityProject.deleteProjectIdentity({
actor: req.permission.type, actor: req.permission.type,
actorId: req.permission.id, actorId: req.permission.id,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
identityId: req.params.identityId, identityId: req.params.identityId,
projectId: req.params.projectId projectId: req.params.projectId
@@ -177,6 +180,7 @@ export const registerIdentityProjectRouter = async (server: FastifyZodProvider)
const identityMemberships = await server.services.identityProject.listProjectIdentities({ const identityMemberships = await server.services.identityProject.listProjectIdentities({
actor: req.permission.type, actor: req.permission.type,
actorId: req.permission.id, actorId: req.permission.id,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
projectId: req.params.projectId projectId: req.params.projectId
}); });
@@ -68,11 +68,14 @@ export const registerMfaRouter = async (server: FastifyZodProvider) => {
}, },
handler: async (req, res) => { handler: async (req, res) => {
const userAgent = req.headers["user-agent"]; const userAgent = req.headers["user-agent"];
const mfaJwtToken = req.headers.authorization?.replace("Bearer ", "");
if (!userAgent) throw new Error("user agent header is required"); if (!userAgent) throw new Error("user agent header is required");
if (!mfaJwtToken) throw new Error("authorization header is required");
const appCfg = getConfig(); const appCfg = getConfig();
const { user, token } = await server.services.login.verifyMfaToken({ const { user, token } = await server.services.login.verifyMfaToken({
userAgent, userAgent,
mfaJwtToken,
ip: req.realIp, ip: req.realIp,
userId: req.mfa.userId, userId: req.mfa.userId,
orgId: req.mfa.orgId, orgId: req.mfa.orgId,
@@ -45,6 +45,7 @@ export const registerOrgRouter = async (server: FastifyZodProvider) => {
const users = await server.services.org.findAllOrgMembers( const users = await server.services.org.findAllOrgMembers(
req.permission.id, req.permission.id,
req.params.organizationId, req.params.organizationId,
req.permission.authMethod,
req.permission.orgId req.permission.orgId
); );
return { users }; return { users };
@@ -89,6 +90,7 @@ export const registerOrgRouter = async (server: FastifyZodProvider) => {
actor: req.permission.type, actor: req.permission.type,
actorId: req.permission.id, actorId: req.permission.id,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
actorAuthMethod: req.permission.authMethod,
orgId: req.params.organizationId orgId: req.params.organizationId
}); });
@@ -127,6 +129,7 @@ export const registerOrgRouter = async (server: FastifyZodProvider) => {
const membership = await server.services.org.updateOrgMembership({ const membership = await server.services.org.updateOrgMembership({
userId: req.permission.id, userId: req.permission.id,
role: req.body.role, role: req.body.role,
actorAuthMethod: req.permission.authMethod,
orgId: req.params.organizationId, orgId: req.params.organizationId,
membershipId: req.params.membershipId, membershipId: req.params.membershipId,
actorOrgId: req.permission.orgId actorOrgId: req.permission.orgId
@@ -162,6 +165,7 @@ export const registerOrgRouter = async (server: FastifyZodProvider) => {
const membership = await server.services.org.deleteOrgMembership({ const membership = await server.services.org.deleteOrgMembership({
userId: req.permission.id, userId: req.permission.id,
actorAuthMethod: req.permission.authMethod,
orgId: req.params.organizationId, orgId: req.params.organizationId,
membershipId: req.params.membershipId, membershipId: req.params.membershipId,
actorOrgId: req.permission.orgId actorOrgId: req.permission.orgId
@@ -183,7 +187,7 @@ export const registerOrgRouter = async (server: FastifyZodProvider) => {
}) })
} }
}, },
onRequest: verifyAuth([AuthMode.JWT, AuthMode.API_KEY]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.API_KEY], { requireOrg: false }),
handler: async (req) => { handler: async (req) => {
if (req.auth.actor !== ActorType.USER) return; if (req.auth.actor !== ActorType.USER) return;
@@ -217,6 +221,7 @@ export const registerOrgRouter = async (server: FastifyZodProvider) => {
const organization = await server.services.org.deleteOrganizationById( const organization = await server.services.org.deleteOrganizationById(
req.permission.id, req.permission.id,
req.params.organizationId, req.params.organizationId,
req.permission.authMethod,
req.permission.orgId req.permission.orgId
); );
return { organization }; return { organization };
@@ -28,7 +28,9 @@ export const registerProjectMembershipRouter = async (server: FastifyZodProvider
handler: async (req) => { handler: async (req) => {
const memberships = await server.services.projectMembership.addUsersToProjectNonE2EE({ const memberships = await server.services.projectMembership.addUsersToProjectNonE2EE({
projectId: req.params.projectId, projectId: req.params.projectId,
actorAuthMethod: req.permission.authMethod,
actorId: req.permission.id, actorId: req.permission.id,
actorOrgId: req.permission.orgId,
actor: req.permission.type, actor: req.permission.type,
emails: req.body.emails, emails: req.body.emails,
usernames: req.body.usernames usernames: req.body.usernames
@@ -74,6 +76,7 @@ export const registerProjectMembershipRouter = async (server: FastifyZodProvider
const memberships = await server.services.projectMembership.deleteProjectMemberships({ const memberships = await server.services.projectMembership.deleteProjectMemberships({
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
projectId: req.params.projectId, projectId: req.params.projectId,
emails: req.body.emails, emails: req.body.emails,
+122 -7
View File
@@ -8,6 +8,7 @@ import { authRateLimit } from "@app/server/config/rateLimiter";
import { getTelemetryDistinctId } from "@app/server/lib/telemetry"; import { getTelemetryDistinctId } from "@app/server/lib/telemetry";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth"; import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
import { AuthMode } from "@app/services/auth/auth-type"; import { AuthMode } from "@app/services/auth/auth-type";
import { ProjectFilterType } from "@app/services/project/project-types";
import { PostHogEventTypes } from "@app/services/telemetry/telemetry-types"; import { PostHogEventTypes } from "@app/services/telemetry/telemetry-types";
const projectWithEnv = ProjectsSchema.merge( const projectWithEnv = ProjectsSchema.merge(
@@ -17,6 +18,14 @@ const projectWithEnv = ProjectsSchema.merge(
}) })
); );
const slugSchema = z
.string()
.min(5)
.max(36)
.refine((v) => slugify(v) === v, {
message: "Slug must be at least 5 character but no more than 36"
});
export const registerProjectRouter = async (server: FastifyZodProvider) => { export const registerProjectRouter = async (server: FastifyZodProvider) => {
/* Get project key */ /* Get project key */
server.route({ server.route({
@@ -47,6 +56,7 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
const key = await server.services.projectKey.getLatestProjectKey({ const key = await server.services.projectKey.getLatestProjectKey({
actor: req.permission.type, actor: req.permission.type,
actorId: req.permission.id, actorId: req.permission.id,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
projectId: req.params.workspaceId projectId: req.params.workspaceId
}); });
@@ -74,7 +84,6 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
params: z.object({ params: z.object({
projectId: z.string().trim() projectId: z.string().trim()
}), }),
body: z.object({ body: z.object({
userPrivateKey: z.string().trim() userPrivateKey: z.string().trim()
}), }),
@@ -82,11 +91,13 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
200: z.void() 200: z.void()
} }
}, },
onRequest: verifyAuth([AuthMode.JWT, AuthMode.API_KEY]), onRequest: verifyAuth([AuthMode.JWT]),
handler: async (req) => { handler: async (req) => {
await server.services.project.upgradeProject({ await server.services.project.upgradeProject({
actorId: req.permission.id, actorId: req.permission.id,
actorOrgId: req.permission.orgId,
actor: req.permission.type, actor: req.permission.type,
actorAuthMethod: req.permission.authMethod,
projectId: req.params.projectId, projectId: req.params.projectId,
userPrivateKey: req.body.userPrivateKey userPrivateKey: req.body.userPrivateKey
}); });
@@ -107,9 +118,11 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
}) })
} }
}, },
onRequest: verifyAuth([AuthMode.JWT, AuthMode.API_KEY]), onRequest: verifyAuth([AuthMode.JWT]),
handler: async (req) => { handler: async (req) => {
const status = await server.services.project.getProjectUpgradeStatus({ const status = await server.services.project.getProjectUpgradeStatus({
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId,
projectId: req.params.projectId, projectId: req.params.projectId,
actor: req.permission.type, actor: req.permission.type,
actorId: req.permission.id actorId: req.permission.id
@@ -138,7 +151,7 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
}) })
.optional() .optional()
.describe(PROJECTS.CREATE.slug), .describe(PROJECTS.CREATE.slug),
organizationId: z.string().trim().describe(PROJECTS.CREATE.organizationId) organizationSlug: z.string().trim().describe(PROJECTS.CREATE.organizationSlug)
}), }),
response: { response: {
200: z.object({ 200: z.object({
@@ -146,12 +159,14 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
}) })
} }
}, },
onRequest: verifyAuth([AuthMode.JWT, AuthMode.API_KEY, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
handler: async (req) => { handler: async (req) => {
const project = await server.services.project.createProject({ const project = await server.services.project.createProject({
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
orgId: req.body.organizationId, actorOrgId: req.permission.orgId,
actorAuthMethod: req.permission.authMethod,
orgSlug: req.body.organizationSlug,
workspaceName: req.body.projectName, workspaceName: req.body.projectName,
slug: req.body.slug slug: req.body.slug
}); });
@@ -160,7 +175,7 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
event: PostHogEventTypes.ProjectCreated, event: PostHogEventTypes.ProjectCreated,
distinctId: getTelemetryDistinctId(req), distinctId: getTelemetryDistinctId(req),
properties: { properties: {
orgId: req.body.organizationId, orgId: project.orgId,
name: project.name, name: project.name,
...req.auditLogInfo ...req.auditLogInfo
} }
@@ -169,4 +184,104 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
return { project }; return { project };
} }
}); });
/* Delete a project by slug */
server.route({
method: "DELETE",
url: "/:slug",
schema: {
params: z.object({
slug: slugSchema.describe("The slug of the project to delete.")
}),
response: {
200: ProjectsSchema
}
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
handler: async (req) => {
const project = await server.services.project.deleteProject({
filter: {
type: ProjectFilterType.SLUG,
slug: req.params.slug,
orgId: req.permission.orgId
},
actorId: req.permission.id,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId,
actor: req.permission.type
});
return project;
}
});
/* Get a project by slug */
server.route({
method: "GET",
url: "/:slug",
schema: {
params: z.object({
slug: slugSchema.describe("The slug of the project to get.")
}),
response: {
200: projectWithEnv
}
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
handler: async (req) => {
const project = await server.services.project.getAProject({
filter: {
slug: req.params.slug,
orgId: req.permission.orgId,
type: ProjectFilterType.SLUG
},
actorId: req.permission.id,
actorOrgId: req.permission.orgId,
actorAuthMethod: req.permission.authMethod,
actor: req.permission.type
});
return project;
}
});
/* Update a project by slug */
server.route({
method: "PATCH",
url: "/:slug",
schema: {
params: z.object({
slug: slugSchema.describe("The slug of the project to update.")
}),
body: z.object({
name: z.string().trim().optional().describe("The new name of the project."),
autoCapitalization: z.boolean().optional().describe("The new auto-capitalization setting.")
}),
response: {
200: ProjectsSchema
}
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
handler: async (req) => {
const project = await server.services.project.updateProject({
filter: {
type: ProjectFilterType.SLUG,
slug: req.params.slug,
orgId: req.permission.orgId
},
update: {
name: req.body.name,
autoCapitalization: req.body.autoCapitalization
},
actorId: req.permission.id,
actorAuthMethod: req.permission.authMethod,
actor: req.permission.type,
actorOrgId: req.permission.orgId
});
return project;
}
});
}; };
@@ -46,6 +46,8 @@ export const registerServiceTokenRouter = async (server: FastifyZodProvider) =>
handler: async (req) => { handler: async (req) => {
const { serviceToken, user } = await server.services.serviceToken.getServiceToken({ const { serviceToken, user } = await server.services.serviceToken.getServiceToken({
actorId: req.permission.id, actorId: req.permission.id,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId,
actor: req.permission.type actor: req.permission.type
}); });
@@ -98,6 +100,7 @@ export const registerServiceTokenRouter = async (server: FastifyZodProvider) =>
const { serviceToken, token } = await server.services.serviceToken.createServiceToken({ const { serviceToken, token } = await server.services.serviceToken.createServiceToken({
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
...req.body, ...req.body,
projectId: req.body.workspaceId projectId: req.body.workspaceId
@@ -136,6 +139,7 @@ export const registerServiceTokenRouter = async (server: FastifyZodProvider) =>
const serviceTokenData = await server.services.serviceToken.deleteServiceToken({ const serviceTokenData = await server.services.serviceToken.deleteServiceToken({
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
id: req.params.serviceTokenId id: req.params.serviceTokenId
}); });
+1 -1
View File
@@ -60,7 +60,7 @@ export const registerUserRouter = async (server: FastifyZodProvider) => {
}) })
} }
}, },
preHandler: verifyAuth([AuthMode.JWT, AuthMode.API_KEY]), preHandler: verifyAuth([AuthMode.JWT, AuthMode.API_KEY], { requireOrg: false }),
handler: async (req) => { handler: async (req) => {
const user = await server.services.user.updateAuthMethods(req.permission.id, req.body.authMethods); const user = await server.services.user.updateAuthMethods(req.permission.id, req.body.authMethods);
return { user }; return { user };
@@ -34,6 +34,42 @@ export const registerLoginRouter = async (server: FastifyZodProvider) => {
} }
}); });
server.route({
method: "POST",
url: "/select-organization",
config: {
rateLimit: authRateLimit
},
schema: {
body: z.object({
organizationId: z.string().trim()
}),
response: {
200: z.object({
token: z.string()
})
}
},
handler: async (req, res) => {
const cfg = getConfig();
const tokens = await server.services.login.selectOrganization({
userAgent: req.headers["user-agent"],
authJwtToken: req.headers.authorization,
organizationId: req.body.organizationId,
ipAddress: req.realIp
});
void res.setCookie("jid", tokens.refresh, {
httpOnly: true,
path: "/",
sameSite: "strict",
secure: cfg.HTTPS_ENABLED
});
return { token: tokens.access };
}
});
server.route({ server.route({
method: "POST", method: "POST",
url: "/login2", url: "/login2",
@@ -20,6 +20,7 @@ export const registerSecretBlindIndexRouter = async (server: FastifyZodProvider)
handler: async (req) => { handler: async (req) => {
const count = await server.services.secretBlindIndex.getSecretBlindIndexStatus({ const count = await server.services.secretBlindIndex.getSecretBlindIndexStatus({
projectId: req.params.projectId, projectId: req.params.projectId,
actorAuthMethod: req.permission.authMethod,
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorOrgId: req.permission.orgId actorOrgId: req.permission.orgId
@@ -52,6 +53,7 @@ export const registerSecretBlindIndexRouter = async (server: FastifyZodProvider)
handler: async (req) => { handler: async (req) => {
const secrets = await server.services.secretBlindIndex.getProjectSecrets({ const secrets = await server.services.secretBlindIndex.getProjectSecrets({
projectId: req.params.projectId, projectId: req.params.projectId,
actorAuthMethod: req.permission.authMethod,
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorOrgId: req.permission.orgId actorOrgId: req.permission.orgId
@@ -86,6 +88,7 @@ export const registerSecretBlindIndexRouter = async (server: FastifyZodProvider)
await server.services.secretBlindIndex.updateProjectSecretName({ await server.services.secretBlindIndex.updateProjectSecretName({
projectId: req.params.projectId, projectId: req.params.projectId,
secretsToUpdate: req.body.secretsToUpdate, secretsToUpdate: req.body.secretsToUpdate,
actorAuthMethod: req.permission.authMethod,
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorOrgId: req.permission.orgId actorOrgId: req.permission.orgId
+45 -1
View File
@@ -17,6 +17,7 @@ import { getTelemetryDistinctId } from "@app/server/lib/telemetry";
import { getUserAgentType } from "@app/server/plugins/audit-log"; import { getUserAgentType } from "@app/server/plugins/audit-log";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth"; import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
import { ActorType, AuthMode } from "@app/services/auth/auth-type"; import { ActorType, AuthMode } from "@app/services/auth/auth-type";
import { ProjectFilterType } from "@app/services/project/project-types";
import { PostHogEventTypes } from "@app/services/telemetry/telemetry-types"; import { PostHogEventTypes } from "@app/services/telemetry/telemetry-types";
import { secretRawSchema } from "../sanitizedSchemas"; import { secretRawSchema } from "../sanitizedSchemas";
@@ -35,6 +36,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
], ],
querystring: z.object({ querystring: z.object({
workspaceId: z.string().trim().optional().describe(RAW_SECRETS.LIST.workspaceId), workspaceId: z.string().trim().optional().describe(RAW_SECRETS.LIST.workspaceId),
workspaceSlug: z.string().trim().optional().describe(RAW_SECRETS.LIST.workspaceSlug),
environment: z.string().trim().optional().describe(RAW_SECRETS.LIST.environment), environment: z.string().trim().optional().describe(RAW_SECRETS.LIST.environment),
secretPath: z.string().trim().default("/").transform(removeTrailingSlash).describe(RAW_SECRETS.LIST.secretPath), secretPath: z.string().trim().default("/").transform(removeTrailingSlash).describe(RAW_SECRETS.LIST.secretPath),
include_imports: z include_imports: z
@@ -70,6 +72,22 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
environment = scope[0].environment; environment = scope[0].environment;
workspaceId = req.auth.serviceToken.projectId; workspaceId = req.auth.serviceToken.projectId;
} }
} else if (req.permission.type === ActorType.IDENTITY && req.query.workspaceSlug && !workspaceId) {
const workspace = await server.services.project.getAProject({
filter: {
type: ProjectFilterType.SLUG,
orgId: req.permission.orgId,
slug: req.query.workspaceSlug
},
actorId: req.permission.id,
actorAuthMethod: req.permission.authMethod,
actor: req.permission.type,
actorOrgId: req.permission.orgId
});
if (!workspace) throw new BadRequestError({ message: `No project found with slug ${req.query.workspaceSlug}` });
workspaceId = workspace.id;
} }
if (!workspaceId || !environment) throw new BadRequestError({ message: "Missing workspace id or environment" }); if (!workspaceId || !environment) throw new BadRequestError({ message: "Missing workspace id or environment" });
@@ -79,13 +97,14 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
actor: req.permission.type, actor: req.permission.type,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
environment, environment,
actorAuthMethod: req.permission.authMethod,
projectId: workspaceId, projectId: workspaceId,
path: secretPath, path: secretPath,
includeImports: req.query.include_imports includeImports: req.query.include_imports
}); });
await server.services.auditLog.createAuditLog({ await server.services.auditLog.createAuditLog({
projectId: req.query.workspaceId, projectId: workspaceId,
...req.auditLogInfo, ...req.auditLogInfo,
event: { event: {
type: EventType.GET_SECRETS, type: EventType.GET_SECRETS,
@@ -163,6 +182,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
const secret = await server.services.secret.getSecretByNameRaw({ const secret = await server.services.secret.getSecretByNameRaw({
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
environment, environment,
projectId: workspaceId, projectId: workspaceId,
@@ -248,6 +268,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
actor: req.permission.type, actor: req.permission.type,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
environment: req.body.environment, environment: req.body.environment,
actorAuthMethod: req.permission.authMethod,
projectId: req.body.workspaceId, projectId: req.body.workspaceId,
secretPath: req.body.secretPath, secretPath: req.body.secretPath,
secretName: req.params.secretName, secretName: req.params.secretName,
@@ -331,6 +352,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
actorAuthMethod: req.permission.authMethod,
environment: req.body.environment, environment: req.body.environment,
projectId: req.body.workspaceId, projectId: req.body.workspaceId,
secretPath: req.body.secretPath, secretPath: req.body.secretPath,
@@ -407,6 +429,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
const secret = await server.services.secret.deleteSecretRaw({ const secret = await server.services.secret.deleteSecretRaw({
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
environment: req.body.environment, environment: req.body.environment,
projectId: req.body.workspaceId, projectId: req.body.workspaceId,
@@ -502,6 +525,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
const { secrets, imports } = await server.services.secret.getSecrets({ const { secrets, imports } = await server.services.secret.getSecrets({
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
environment: req.query.environment, environment: req.query.environment,
projectId: req.query.workspaceId, projectId: req.query.workspaceId,
@@ -588,6 +612,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
const secret = await server.services.secret.getSecretByName({ const secret = await server.services.secret.getSecretByName({
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
environment: req.query.environment, environment: req.query.environment,
projectId: req.query.workspaceId, projectId: req.query.workspaceId,
@@ -690,6 +715,8 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
if (req.body.type !== SecretType.Personal && req.permission.type === ActorType.USER) { if (req.body.type !== SecretType.Personal && req.permission.type === ActorType.USER) {
const policy = await server.services.secretApprovalPolicy.getSecretApprovalPolicyOfFolder({ const policy = await server.services.secretApprovalPolicy.getSecretApprovalPolicyOfFolder({
actorId: req.permission.id, actorId: req.permission.id,
actorOrgId: req.permission.orgId,
actorAuthMethod: req.permission.authMethod,
actor: req.permission.type, actor: req.permission.type,
secretPath, secretPath,
environment, environment,
@@ -699,6 +726,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
const approval = await server.services.secretApprovalRequest.generateSecretApprovalRequest({ const approval = await server.services.secretApprovalRequest.generateSecretApprovalRequest({
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
secretPath, secretPath,
environment, environment,
@@ -742,6 +770,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
const secret = await server.services.secret.createSecret({ const secret = await server.services.secret.createSecret({
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
path: secretPath, path: secretPath,
type, type,
@@ -866,6 +895,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
const policy = await server.services.secretApprovalPolicy.getSecretApprovalPolicyOfFolder({ const policy = await server.services.secretApprovalPolicy.getSecretApprovalPolicyOfFolder({
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
secretPath, secretPath,
environment, environment,
@@ -875,6 +905,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
const approval = await server.services.secretApprovalRequest.generateSecretApprovalRequest({ const approval = await server.services.secretApprovalRequest.generateSecretApprovalRequest({
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
secretPath, secretPath,
environment, environment,
@@ -920,6 +951,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
const secret = await server.services.secret.updateSecret({ const secret = await server.services.secret.updateSecret({
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
path: secretPath, path: secretPath,
type, type,
@@ -1010,6 +1042,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
const policy = await server.services.secretApprovalPolicy.getSecretApprovalPolicyOfFolder({ const policy = await server.services.secretApprovalPolicy.getSecretApprovalPolicyOfFolder({
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
secretPath, secretPath,
environment, environment,
@@ -1019,6 +1052,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
const approval = await server.services.secretApprovalRequest.generateSecretApprovalRequest({ const approval = await server.services.secretApprovalRequest.generateSecretApprovalRequest({
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
secretPath, secretPath,
environment, environment,
@@ -1052,6 +1086,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
const secret = await server.services.secret.deleteSecret({ const secret = await server.services.secret.deleteSecret({
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
path: secretPath, path: secretPath,
type, type,
@@ -1134,6 +1169,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
const policy = await server.services.secretApprovalPolicy.getSecretApprovalPolicyOfFolder({ const policy = await server.services.secretApprovalPolicy.getSecretApprovalPolicyOfFolder({
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
secretPath, secretPath,
environment, environment,
@@ -1143,6 +1179,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
const approval = await server.services.secretApprovalRequest.generateSecretApprovalRequest({ const approval = await server.services.secretApprovalRequest.generateSecretApprovalRequest({
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
secretPath, secretPath,
environment, environment,
@@ -1172,6 +1209,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
const secrets = await server.services.secret.createManySecret({ const secrets = await server.services.secret.createManySecret({
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
path: secretPath, path: secretPath,
environment, environment,
@@ -1255,6 +1293,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
const policy = await server.services.secretApprovalPolicy.getSecretApprovalPolicyOfFolder({ const policy = await server.services.secretApprovalPolicy.getSecretApprovalPolicyOfFolder({
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
secretPath, secretPath,
environment, environment,
@@ -1264,6 +1303,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
const approval = await server.services.secretApprovalRequest.generateSecretApprovalRequest({ const approval = await server.services.secretApprovalRequest.generateSecretApprovalRequest({
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
secretPath, secretPath,
environment, environment,
@@ -1292,6 +1332,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
const secrets = await server.services.secret.updateManySecret({ const secrets = await server.services.secret.updateManySecret({
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
path: secretPath, path: secretPath,
environment, environment,
@@ -1364,6 +1405,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
const policy = await server.services.secretApprovalPolicy.getSecretApprovalPolicyOfFolder({ const policy = await server.services.secretApprovalPolicy.getSecretApprovalPolicyOfFolder({
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
secretPath, secretPath,
environment, environment,
@@ -1373,6 +1415,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
const approval = await server.services.secretApprovalRequest.generateSecretApprovalRequest({ const approval = await server.services.secretApprovalRequest.generateSecretApprovalRequest({
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
secretPath, secretPath,
environment, environment,
@@ -1400,6 +1443,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
const secrets = await server.services.secret.deleteManySecret({ const secrets = await server.services.secret.deleteManySecret({
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
path: req.body.secretPath, path: req.body.secretPath,
environment, environment,
@@ -108,7 +108,8 @@ export const registerSignupRouter = async (server: FastifyZodProvider) => {
200: z.object({ 200: z.object({
message: z.string(), message: z.string(),
user: UsersSchema, user: UsersSchema,
token: z.string() token: z.string(),
organizationId: z.string().nullish()
}) })
} }
}, },
@@ -124,7 +125,8 @@ export const registerSignupRouter = async (server: FastifyZodProvider) => {
}); });
} }
const { user, accessToken, refreshToken } = await server.services.signup.completeEmailAccountSignup({ const { user, accessToken, refreshToken, organizationId } =
await server.services.signup.completeEmailAccountSignup({
...req.body, ...req.body,
ip: req.realIp, ip: req.realIp,
userAgent, userAgent,
@@ -152,7 +154,7 @@ export const registerSignupRouter = async (server: FastifyZodProvider) => {
secure: appCfg.HTTPS_ENABLED secure: appCfg.HTTPS_ENABLED
}); });
return { message: "Successfully set up account", user, token: accessToken }; return { message: "Successfully set up account", user, token: accessToken, organizationId };
} }
}); });
+2 -2
View File
@@ -15,10 +15,10 @@ export const validateProviderAuthToken = (providerToken: string, username?: stri
if (decodedToken.username !== username) throw new Error("Invalid auth credentials"); if (decodedToken.username !== username) throw new Error("Invalid auth credentials");
if (decodedToken.organizationId) { if (decodedToken.organizationId) {
return { orgId: decodedToken.organizationId }; return { orgId: decodedToken.organizationId, authMethod: decodedToken.authMethod };
} }
return {}; return { authMethod: decodedToken.authMethod, orgId: null };
}; };
export const validateSignUpAuthorization = (token: string, userId: string, validate = true) => { export const validateSignUpAuthorization = (token: string, userId: string, validate = true) => {
+90 -19
View File
@@ -1,13 +1,16 @@
import jwt from "jsonwebtoken"; import jwt from "jsonwebtoken";
import { TUsers, UserDeviceSchema } from "@app/db/schemas"; import { TUsers, UserDeviceSchema } from "@app/db/schemas";
import { isAuthMethodSaml } from "@app/ee/services/permission/permission-fns";
import { getConfig } from "@app/lib/config/env"; import { getConfig } from "@app/lib/config/env";
import { generateSrpServerKey, srpCheckClientProof } from "@app/lib/crypto"; import { generateSrpServerKey, srpCheckClientProof } from "@app/lib/crypto";
import { BadRequestError } from "@app/lib/errors"; import { BadRequestError, UnauthorizedError } from "@app/lib/errors";
import { getServerCfg } from "@app/services/super-admin/super-admin-service"; import { getServerCfg } from "@app/services/super-admin/super-admin-service";
import { TTokenDALFactory } from "../auth-token/auth-token-dal";
import { TAuthTokenServiceFactory } from "../auth-token/auth-token-service"; import { TAuthTokenServiceFactory } from "../auth-token/auth-token-service";
import { TokenType } from "../auth-token/auth-token-types"; import { TokenType } from "../auth-token/auth-token-types";
import { TOrgDALFactory } from "../org/org-dal";
import { SmtpTemplates, TSmtpService } from "../smtp/smtp-service"; import { SmtpTemplates, TSmtpService } from "../smtp/smtp-service";
import { TUserDALFactory } from "../user/user-dal"; import { TUserDALFactory } from "../user/user-dal";
import { validateProviderAuthToken } from "./auth-fns"; import { validateProviderAuthToken } from "./auth-fns";
@@ -17,16 +20,24 @@ import {
TOauthLoginDTO, TOauthLoginDTO,
TVerifyMfaTokenDTO TVerifyMfaTokenDTO
} from "./auth-login-type"; } from "./auth-login-type";
import { AuthMethod, AuthTokenType } from "./auth-type"; import { AuthMethod, AuthModeJwtTokenPayload, AuthModeMfaJwtTokenPayload, AuthTokenType } from "./auth-type";
type TAuthLoginServiceFactoryDep = { type TAuthLoginServiceFactoryDep = {
userDAL: TUserDALFactory; userDAL: TUserDALFactory;
orgDAL: TOrgDALFactory;
tokenService: TAuthTokenServiceFactory; tokenService: TAuthTokenServiceFactory;
smtpService: TSmtpService; smtpService: TSmtpService;
tokenDAL: TTokenDALFactory;
}; };
export type TAuthLoginFactory = ReturnType<typeof authLoginServiceFactory>; export type TAuthLoginFactory = ReturnType<typeof authLoginServiceFactory>;
export const authLoginServiceFactory = ({ userDAL, tokenService, smtpService }: TAuthLoginServiceFactoryDep) => { export const authLoginServiceFactory = ({
userDAL,
tokenService,
smtpService,
orgDAL,
tokenDAL
}: TAuthLoginServiceFactoryDep) => {
/* /*
* Private * Private
* Not exported. This is to update user device list * Not exported. This is to update user device list
@@ -83,12 +94,14 @@ export const authLoginServiceFactory = ({ userDAL, tokenService, smtpService }:
user, user,
ip, ip,
userAgent, userAgent,
organizationId organizationId,
authMethod
}: { }: {
user: TUsers; user: TUsers;
ip: string; ip: string;
userAgent: string; userAgent: string;
organizationId?: string; organizationId: string | undefined;
authMethod: AuthMethod;
}) => { }) => {
const cfg = getConfig(); const cfg = getConfig();
await updateUserDeviceSession(user, ip, userAgent); await updateUserDeviceSession(user, ip, userAgent);
@@ -98,8 +111,10 @@ export const authLoginServiceFactory = ({ userDAL, tokenService, smtpService }:
userId: user.id userId: user.id
}); });
if (!tokenSession) throw new Error("Failed to create token"); if (!tokenSession) throw new Error("Failed to create token");
const accessToken = jwt.sign( const accessToken = jwt.sign(
{ {
authMethod,
authTokenType: AuthTokenType.ACCESS_TOKEN, authTokenType: AuthTokenType.ACCESS_TOKEN,
userId: user.id, userId: user.id,
tokenVersionId: tokenSession.id, tokenVersionId: tokenSession.id,
@@ -112,6 +127,7 @@ export const authLoginServiceFactory = ({ userDAL, tokenService, smtpService }:
const refreshToken = jwt.sign( const refreshToken = jwt.sign(
{ {
authMethod,
authTokenType: AuthTokenType.REFRESH_TOKEN, authTokenType: AuthTokenType.REFRESH_TOKEN,
userId: user.id, userId: user.id,
tokenVersionId: tokenSession.id, tokenVersionId: tokenSession.id,
@@ -158,9 +174,9 @@ export const authLoginServiceFactory = ({ userDAL, tokenService, smtpService }:
const loginExchangeClientProof = async ({ const loginExchangeClientProof = async ({
email, email,
clientProof, clientProof,
providerAuthToken,
ip, ip,
userAgent userAgent,
providerAuthToken
}: TLoginClientProofDTO) => { }: TLoginClientProofDTO) => {
const userEnc = await userDAL.findUserEncKeyByUsername({ const userEnc = await userDAL.findUserEncKeyByUsername({
username: email username: email
@@ -168,14 +184,16 @@ export const authLoginServiceFactory = ({ userDAL, tokenService, smtpService }:
if (!userEnc) throw new Error("Failed to find user"); if (!userEnc) throw new Error("Failed to find user");
const cfg = getConfig(); const cfg = getConfig();
let organizationId; let authMethod = AuthMethod.EMAIL;
if (!userEnc.authMethods?.includes(AuthMethod.EMAIL)) { let organizationId: string | undefined;
const { orgId } = validateProviderAuthToken(providerAuthToken as string, email);
organizationId = orgId; if (providerAuthToken) {
} else if (providerAuthToken) { const decodedProviderToken = validateProviderAuthToken(providerAuthToken, email);
// SAML SSO
const { orgId } = validateProviderAuthToken(providerAuthToken, email); authMethod = decodedProviderToken.authMethod;
organizationId = orgId; if (isAuthMethodSaml(authMethod) && decodedProviderToken.orgId) {
organizationId = decodedProviderToken.orgId;
}
} }
if (!userEnc.serverPrivateKey || !userEnc.clientPublicKey) throw new Error("Failed to authenticate. Try again?"); if (!userEnc.serverPrivateKey || !userEnc.clientPublicKey) throw new Error("Failed to authenticate. Try again?");
@@ -196,9 +214,9 @@ export const authLoginServiceFactory = ({ userDAL, tokenService, smtpService }:
if (userEnc.isMfaEnabled && userEnc.email) { if (userEnc.isMfaEnabled && userEnc.email) {
const mfaToken = jwt.sign( const mfaToken = jwt.sign(
{ {
authMethod,
authTokenType: AuthTokenType.MFA_TOKEN, authTokenType: AuthTokenType.MFA_TOKEN,
userId: userEnc.userId, userId: userEnc.userId
organizationId
}, },
cfg.AUTH_SECRET, cfg.AUTH_SECRET,
{ {
@@ -221,12 +239,60 @@ export const authLoginServiceFactory = ({ userDAL, tokenService, smtpService }:
}, },
ip, ip,
userAgent, userAgent,
authMethod,
organizationId organizationId
}); });
return { token, isMfaEnabled: false, user: userEnc } as const; return { token, isMfaEnabled: false, user: userEnc } as const;
}; };
const selectOrganization = async ({
userAgent,
authJwtToken,
ipAddress,
organizationId
}: {
userAgent: string | undefined;
authJwtToken: string | undefined;
ipAddress: string;
organizationId: string;
}) => {
const cfg = getConfig();
if (!authJwtToken) throw new UnauthorizedError({ name: "Authorization 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
// The decoded JWT token, which contains the auth method.
const decodedToken = jwt.verify(authJwtToken, cfg.AUTH_SECRET) as AuthModeJwtTokenPayload;
if (!decodedToken.authMethod) throw new UnauthorizedError({ name: "Auth method not found on existing token" });
const user = await userDAL.findUserEncKeyByUserId(decodedToken.userId);
if (!user) throw new BadRequestError({ message: "User not found", name: "Find user from token" });
// Check if the user actually has access to the specified organization.
const userOrgs = await orgDAL.findAllOrgsByUserId(user.id);
const hasOrganizationMembership = userOrgs.some((org) => org.id === organizationId);
if (!hasOrganizationMembership) {
throw new UnauthorizedError({ message: "User does not have access to the organization" });
}
await tokenDAL.incrementTokenSessionVersion(user.id, decodedToken.tokenVersionId);
const tokens = await generateUserTokens({
authMethod: decodedToken.authMethod,
user,
userAgent,
ip: ipAddress,
organizationId
});
return tokens;
};
/* /*
* Multi factor authentication re-send code, Get user id from token * Multi factor authentication re-send code, Get user id from token
* saved in frontend * saved in frontend
@@ -244,12 +310,15 @@ export const authLoginServiceFactory = ({ userDAL, tokenService, smtpService }:
* Multi factor authentication verification of code * Multi factor authentication verification of code
* Third step of login in which user completes with mfa * Third step of login in which user completes with mfa
* */ * */
const verifyMfaToken = async ({ userId, mfaToken, ip, userAgent, orgId }: TVerifyMfaTokenDTO) => { const verifyMfaToken = async ({ userId, mfaToken, mfaJwtToken, ip, userAgent, orgId }: TVerifyMfaTokenDTO) => {
await tokenService.validateTokenForUser({ await tokenService.validateTokenForUser({
type: TokenType.TOKEN_EMAIL_MFA, type: TokenType.TOKEN_EMAIL_MFA,
userId, userId,
code: mfaToken code: mfaToken
}); });
const decodedToken = jwt.verify(mfaJwtToken, getConfig().AUTH_SECRET) as AuthModeMfaJwtTokenPayload;
const userEnc = await userDAL.findUserEncKeyByUserId(userId); const userEnc = await userDAL.findUserEncKeyByUserId(userId);
if (!userEnc) throw new Error("Failed to authenticate user"); if (!userEnc) throw new Error("Failed to authenticate user");
@@ -260,7 +329,8 @@ export const authLoginServiceFactory = ({ userDAL, tokenService, smtpService }:
}, },
ip, ip,
userAgent, userAgent,
organizationId: orgId organizationId: orgId,
authMethod: decodedToken.authMethod
}); });
return { token, user: userEnc }; return { token, user: userEnc };
@@ -339,6 +409,7 @@ export const authLoginServiceFactory = ({ userDAL, tokenService, smtpService }:
oauth2Login, oauth2Login,
resendMfaToken, resendMfaToken,
verifyMfaToken, verifyMfaToken,
selectOrganization,
generateUserTokens generateUserTokens
}; };
}; };
@@ -17,6 +17,7 @@ export type TLoginClientProofDTO = {
export type TVerifyMfaTokenDTO = { export type TVerifyMfaTokenDTO = {
userId: string; userId: string;
mfaToken: string; mfaToken: string;
mfaJwtToken: string;
ip: string; ip: string;
userAgent: string; userAgent: string;
orgId?: string; orgId?: string;
@@ -150,11 +150,15 @@ export const authSignupServiceFactory = ({
}); });
if (!organizationId) { if (!organizationId) {
await orgService.createOrganization({ const newOrganization = await orgService.createOrganization({
userId: user.id, userId: user.id,
userEmail: user.email ?? user.username, userEmail: user.email ?? user.username,
orgName: organizationName orgName: organizationName
}); });
if (!newOrganization) throw new Error("Failed to create organization");
organizationId = newOrganization.id;
} }
const updatedMembersips = await orgDAL.updateMembership( const updatedMembersips = await orgDAL.updateMembership(
@@ -174,6 +178,7 @@ export const authSignupServiceFactory = ({
const accessToken = jwt.sign( const accessToken = jwt.sign(
{ {
authMethod: AuthMethod.EMAIL,
authTokenType: AuthTokenType.ACCESS_TOKEN, authTokenType: AuthTokenType.ACCESS_TOKEN,
userId: updateduser.info.id, userId: updateduser.info.id,
tokenVersionId: tokenSession.id, tokenVersionId: tokenSession.id,
@@ -186,6 +191,7 @@ export const authSignupServiceFactory = ({
const refreshToken = jwt.sign( const refreshToken = jwt.sign(
{ {
authMethod: AuthMethod.EMAIL,
authTokenType: AuthTokenType.REFRESH_TOKEN, authTokenType: AuthTokenType.REFRESH_TOKEN,
userId: updateduser.info.id, userId: updateduser.info.id,
tokenVersionId: tokenSession.id, tokenVersionId: tokenSession.id,
@@ -196,7 +202,7 @@ export const authSignupServiceFactory = ({
{ expiresIn: appCfg.JWT_REFRESH_LIFETIME } { expiresIn: appCfg.JWT_REFRESH_LIFETIME }
); );
return { user: updateduser.info, accessToken, refreshToken }; return { user: updateduser.info, accessToken, refreshToken, organizationId };
}; };
/* /*
@@ -277,6 +283,7 @@ export const authSignupServiceFactory = ({
const accessToken = jwt.sign( const accessToken = jwt.sign(
{ {
authMethod: AuthMethod.EMAIL,
authTokenType: AuthTokenType.ACCESS_TOKEN, authTokenType: AuthTokenType.ACCESS_TOKEN,
userId: updateduser.info.id, userId: updateduser.info.id,
tokenVersionId: tokenSession.id, tokenVersionId: tokenSession.id,
@@ -288,6 +295,7 @@ export const authSignupServiceFactory = ({
const refreshToken = jwt.sign( const refreshToken = jwt.sign(
{ {
authMethod: AuthMethod.EMAIL,
authTokenType: AuthTokenType.REFRESH_TOKEN, authTokenType: AuthTokenType.REFRESH_TOKEN,
userId: updateduser.info.id, userId: updateduser.info.id,
tokenVersionId: tokenSession.id, tokenVersionId: tokenSession.id,
+10
View File
@@ -6,6 +6,7 @@ export enum AuthMethod {
OKTA_SAML = "okta-saml", OKTA_SAML = "okta-saml",
AZURE_SAML = "azure-saml", AZURE_SAML = "azure-saml",
JUMPCLOUD_SAML = "jumpcloud-saml", JUMPCLOUD_SAML = "jumpcloud-saml",
GOOGLE_SAML = "google-saml",
LDAP = "ldap" LDAP = "ldap"
} }
@@ -38,8 +39,12 @@ export enum ActorType { // would extend to AWS, Azure, ...
SCIM_CLIENT = "scimClient" SCIM_CLIENT = "scimClient"
} }
// This will be null unless the token-type is JWT
export type ActorAuthMethod = AuthMethod | null;
export type AuthModeJwtTokenPayload = { export type AuthModeJwtTokenPayload = {
authTokenType: AuthTokenType.ACCESS_TOKEN; authTokenType: AuthTokenType.ACCESS_TOKEN;
authMethod: AuthMethod;
userId: string; userId: string;
tokenVersionId: string; tokenVersionId: string;
accessVersion: number; accessVersion: number;
@@ -48,12 +53,15 @@ export type AuthModeJwtTokenPayload = {
export type AuthModeMfaJwtTokenPayload = { export type AuthModeMfaJwtTokenPayload = {
authTokenType: AuthTokenType.MFA_TOKEN; authTokenType: AuthTokenType.MFA_TOKEN;
authMethod: AuthMethod;
userId: string; userId: string;
organizationId?: string; organizationId?: string;
}; };
export type AuthModeRefreshJwtTokenPayload = { export type AuthModeRefreshJwtTokenPayload = {
// authMode
authTokenType: AuthTokenType.REFRESH_TOKEN; authTokenType: AuthTokenType.REFRESH_TOKEN;
authMethod: AuthMethod;
userId: string; userId: string;
tokenVersionId: string; tokenVersionId: string;
refreshVersion: number; refreshVersion: number;
@@ -63,6 +71,8 @@ export type AuthModeRefreshJwtTokenPayload = {
export type AuthModeProviderJwtTokenPayload = { export type AuthModeProviderJwtTokenPayload = {
authTokenType: AuthTokenType.PROVIDER_TOKEN; authTokenType: AuthTokenType.PROVIDER_TOKEN;
username: string; username: string;
authMethod: AuthMethod;
email: string;
organizationId?: string; organizationId?: string;
}; };
@@ -6,17 +6,20 @@ import { BadRequestError, UnauthorizedError } from "@app/lib/errors";
import { checkIPAgainstBlocklist, TIp } from "@app/lib/ip"; import { checkIPAgainstBlocklist, TIp } from "@app/lib/ip";
import { AuthTokenType } from "../auth/auth-type"; import { AuthTokenType } from "../auth/auth-type";
import { TIdentityOrgDALFactory } from "../identity/identity-org-dal";
import { TIdentityAccessTokenDALFactory } from "./identity-access-token-dal"; import { TIdentityAccessTokenDALFactory } from "./identity-access-token-dal";
import { TIdentityAccessTokenJwtPayload, TRenewAccessTokenDTO } from "./identity-access-token-types"; import { TIdentityAccessTokenJwtPayload, TRenewAccessTokenDTO } from "./identity-access-token-types";
type TIdentityAccessTokenServiceFactoryDep = { type TIdentityAccessTokenServiceFactoryDep = {
identityAccessTokenDAL: TIdentityAccessTokenDALFactory; identityAccessTokenDAL: TIdentityAccessTokenDALFactory;
identityOrgMembershipDAL: TIdentityOrgDALFactory;
}; };
export type TIdentityAccessTokenServiceFactory = ReturnType<typeof identityAccessTokenServiceFactory>; export type TIdentityAccessTokenServiceFactory = ReturnType<typeof identityAccessTokenServiceFactory>;
export const identityAccessTokenServiceFactory = ({ export const identityAccessTokenServiceFactory = ({
identityAccessTokenDAL identityAccessTokenDAL,
identityOrgMembershipDAL
}: TIdentityAccessTokenServiceFactoryDep) => { }: TIdentityAccessTokenServiceFactoryDep) => {
const validateAccessTokenExp = (identityAccessToken: TIdentityAccessTokens) => { const validateAccessTokenExp = (identityAccessToken: TIdentityAccessTokens) => {
const { const {
@@ -117,8 +120,16 @@ export const identityAccessTokenServiceFactory = ({
}); });
} }
const identityOrgMembership = await identityOrgMembershipDAL.findOne({
identityId: identityAccessToken.identityId
});
if (!identityOrgMembership) {
throw new UnauthorizedError({ message: "Identity does not belong to any organization" });
}
validateAccessTokenExp(identityAccessToken); validateAccessTokenExp(identityAccessToken);
return identityAccessToken; return { ...identityAccessToken, orgId: identityOrgMembership.orgId };
}; };
return { renewAccessToken, fnValidateIdentityAccessToken }; return { renewAccessToken, fnValidateIdentityAccessToken };
@@ -49,10 +49,17 @@ export const identityProjectServiceFactory = ({
actor, actor,
actorId, actorId,
actorOrgId, actorOrgId,
actorAuthMethod,
projectId, projectId,
role role
}: TCreateProjectIdentityDTO) => { }: TCreateProjectIdentityDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId); const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Create, ProjectPermissionSub.Identity); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Create, ProjectPermissionSub.Identity);
const existingIdentity = await identityProjectDAL.findOne({ identityId, projectId }); const existingIdentity = await identityProjectDAL.findOne({ identityId, projectId });
@@ -112,9 +119,16 @@ export const identityProjectServiceFactory = ({
roles, roles,
actor, actor,
actorId, actorId,
actorAuthMethod,
actorOrgId actorOrgId
}: TUpdateProjectIdentityDTO) => { }: TUpdateProjectIdentityDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId); const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.Identity); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.Identity);
const projectIdentity = await identityProjectDAL.findOne({ identityId, projectId }); const projectIdentity = await identityProjectDAL.findOne({ identityId, projectId });
@@ -127,6 +141,7 @@ export const identityProjectServiceFactory = ({
ActorType.IDENTITY, ActorType.IDENTITY,
projectIdentity.identityId, projectIdentity.identityId,
projectIdentity.projectId, projectIdentity.projectId,
actorAuthMethod,
actorOrgId actorOrgId
); );
const hasRequiredPriviledges = isAtLeastAsPrivileged(permission, identityRolePermission); const hasRequiredPriviledges = isAtLeastAsPrivileged(permission, identityRolePermission);
@@ -185,6 +200,7 @@ export const identityProjectServiceFactory = ({
actorId, actorId,
actor, actor,
actorOrgId, actorOrgId,
actorAuthMethod,
projectId projectId
}: TDeleteProjectIdentityDTO) => { }: TDeleteProjectIdentityDTO) => {
const identityProjectMembership = await identityProjectDAL.findOne({ identityId, projectId }); const identityProjectMembership = await identityProjectDAL.findOne({ identityId, projectId });
@@ -195,6 +211,7 @@ export const identityProjectServiceFactory = ({
actor, actor,
actorId, actorId,
identityProjectMembership.projectId, identityProjectMembership.projectId,
actorAuthMethod,
actorOrgId actorOrgId
); );
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Delete, ProjectPermissionSub.Identity); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Delete, ProjectPermissionSub.Identity);
@@ -202,6 +219,7 @@ export const identityProjectServiceFactory = ({
ActorType.IDENTITY, ActorType.IDENTITY,
identityId, identityId,
identityProjectMembership.projectId, identityProjectMembership.projectId,
actorAuthMethod,
actorOrgId actorOrgId
); );
const hasRequiredPriviledges = isAtLeastAsPrivileged(permission, identityRolePermission); const hasRequiredPriviledges = isAtLeastAsPrivileged(permission, identityRolePermission);
@@ -212,8 +230,20 @@ export const identityProjectServiceFactory = ({
return deletedIdentity; return deletedIdentity;
}; };
const listProjectIdentities = async ({ projectId, actor, actorId, actorOrgId }: TListProjectIdentityDTO) => { const listProjectIdentities = async ({
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId); projectId,
actor,
actorId,
actorAuthMethod,
actorOrgId
}: TListProjectIdentityDTO) => {
const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Identity); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Identity);
const identityMemberhips = await identityProjectDAL.findByProjectId(projectId); const identityMemberhips = await identityProjectDAL.findByProjectId(projectId);
@@ -144,6 +144,7 @@ export const identityUaServiceFactory = ({
accessTokenTrustedIps, accessTokenTrustedIps,
clientSecretTrustedIps, clientSecretTrustedIps,
actorId, actorId,
actorAuthMethod,
actor, actor,
actorOrgId actorOrgId
}: TAttachUaDTO) => { }: TAttachUaDTO) => {
@@ -162,6 +163,7 @@ export const identityUaServiceFactory = ({
actor, actor,
actorId, actorId,
identityMembershipOrg.orgId, identityMembershipOrg.orgId,
actorAuthMethod,
actorOrgId actorOrgId
); );
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Create, OrgPermissionSubjects.Identity); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Create, OrgPermissionSubjects.Identity);
@@ -233,6 +235,7 @@ export const identityUaServiceFactory = ({
accessTokenTrustedIps, accessTokenTrustedIps,
clientSecretTrustedIps, clientSecretTrustedIps,
actorId, actorId,
actorAuthMethod,
actor, actor,
actorOrgId actorOrgId
}: TUpdateUaDTO) => { }: TUpdateUaDTO) => {
@@ -256,6 +259,7 @@ export const identityUaServiceFactory = ({
actor, actor,
actorId, actorId,
identityMembershipOrg.orgId, identityMembershipOrg.orgId,
actorAuthMethod,
actorOrgId actorOrgId
); );
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Edit, OrgPermissionSubjects.Identity); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Edit, OrgPermissionSubjects.Identity);
@@ -308,7 +312,7 @@ export const identityUaServiceFactory = ({
return { ...updatedUaAuth, orgId: identityMembershipOrg.orgId }; return { ...updatedUaAuth, orgId: identityMembershipOrg.orgId };
}; };
const getIdentityUa = async ({ identityId, actorId, actor, actorOrgId }: TGetUaDTO) => { const getIdentityUa = async ({ identityId, actorId, actor, actorAuthMethod, actorOrgId }: TGetUaDTO) => {
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId }); const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
if (!identityMembershipOrg) throw new BadRequestError({ message: "Failed to find identity" }); if (!identityMembershipOrg) throw new BadRequestError({ message: "Failed to find identity" });
if (identityMembershipOrg.identity?.authMethod !== IdentityAuthMethod.Univeral) if (identityMembershipOrg.identity?.authMethod !== IdentityAuthMethod.Univeral)
@@ -322,6 +326,7 @@ export const identityUaServiceFactory = ({
actor, actor,
actorId, actorId,
identityMembershipOrg.orgId, identityMembershipOrg.orgId,
actorAuthMethod,
actorOrgId actorOrgId
); );
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Identity); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Identity);
@@ -334,6 +339,7 @@ export const identityUaServiceFactory = ({
actorOrgId, actorOrgId,
identityId, identityId,
ttl, ttl,
actorAuthMethod,
description, description,
numUsesLimit numUsesLimit
}: TCreateUaClientSecretDTO) => { }: TCreateUaClientSecretDTO) => {
@@ -347,6 +353,7 @@ export const identityUaServiceFactory = ({
actor, actor,
actorId, actorId,
identityMembershipOrg.orgId, identityMembershipOrg.orgId,
actorAuthMethod,
actorOrgId actorOrgId
); );
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Create, OrgPermissionSubjects.Identity); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Create, OrgPermissionSubjects.Identity);
@@ -355,6 +362,7 @@ export const identityUaServiceFactory = ({
ActorType.IDENTITY, ActorType.IDENTITY,
identityMembershipOrg.identityId, identityMembershipOrg.identityId,
identityMembershipOrg.orgId, identityMembershipOrg.orgId,
actorAuthMethod,
actorOrgId actorOrgId
); );
const hasPriviledge = isAtLeastAsPrivileged(permission, rolePermission); const hasPriviledge = isAtLeastAsPrivileged(permission, rolePermission);
@@ -388,7 +396,13 @@ export const identityUaServiceFactory = ({
}; };
}; };
const getUaClientSecrets = async ({ actor, actorId, actorOrgId, identityId }: TGetUaClientSecretsDTO) => { const getUaClientSecrets = async ({
actor,
actorId,
actorOrgId,
actorAuthMethod,
identityId
}: TGetUaClientSecretsDTO) => {
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId }); const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
if (!identityMembershipOrg) throw new BadRequestError({ message: "Failed to find identity" }); if (!identityMembershipOrg) throw new BadRequestError({ message: "Failed to find identity" });
if (identityMembershipOrg.identity?.authMethod !== IdentityAuthMethod.Univeral) if (identityMembershipOrg.identity?.authMethod !== IdentityAuthMethod.Univeral)
@@ -399,6 +413,7 @@ export const identityUaServiceFactory = ({
actor, actor,
actorId, actorId,
identityMembershipOrg.orgId, identityMembershipOrg.orgId,
actorAuthMethod,
actorOrgId actorOrgId
); );
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Identity); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Identity);
@@ -407,6 +422,7 @@ export const identityUaServiceFactory = ({
ActorType.IDENTITY, ActorType.IDENTITY,
identityMembershipOrg.identityId, identityMembershipOrg.identityId,
identityMembershipOrg.orgId, identityMembershipOrg.orgId,
actorAuthMethod,
actorOrgId actorOrgId
); );
const hasPriviledge = isAtLeastAsPrivileged(permission, rolePermission); const hasPriviledge = isAtLeastAsPrivileged(permission, rolePermission);
@@ -431,6 +447,7 @@ export const identityUaServiceFactory = ({
actorId, actorId,
actor, actor,
actorOrgId, actorOrgId,
actorAuthMethod,
clientSecretId clientSecretId
}: TRevokeUaClientSecretDTO) => { }: TRevokeUaClientSecretDTO) => {
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId }); const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
@@ -443,6 +460,7 @@ export const identityUaServiceFactory = ({
actor, actor,
actorId, actorId,
identityMembershipOrg.orgId, identityMembershipOrg.orgId,
actorAuthMethod,
actorOrgId actorOrgId
); );
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Delete, OrgPermissionSubjects.Identity); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Delete, OrgPermissionSubjects.Identity);
@@ -451,6 +469,7 @@ export const identityUaServiceFactory = ({
ActorType.IDENTITY, ActorType.IDENTITY,
identityMembershipOrg.identityId, identityMembershipOrg.identityId,
identityMembershipOrg.orgId, identityMembershipOrg.orgId,
actorAuthMethod,
actorOrgId actorOrgId
); );
const hasPriviledge = isAtLeastAsPrivileged(permission, rolePermission); const hasPriviledge = isAtLeastAsPrivileged(permission, rolePermission);
@@ -25,8 +25,16 @@ export const identityServiceFactory = ({
identityOrgMembershipDAL, identityOrgMembershipDAL,
permissionService permissionService
}: TIdentityServiceFactoryDep) => { }: TIdentityServiceFactoryDep) => {
const createIdentity = async ({ name, role, actor, orgId, actorId, actorOrgId }: TCreateIdentityDTO) => { const createIdentity = async ({
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, actorOrgId); name,
role,
actor,
orgId,
actorId,
actorAuthMethod,
actorOrgId
}: TCreateIdentityDTO) => {
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, actorAuthMethod, actorOrgId);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Create, OrgPermissionSubjects.Identity); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Create, OrgPermissionSubjects.Identity);
const { permission: rolePermission, role: customRole } = await permissionService.getOrgPermissionByRole( const { permission: rolePermission, role: customRole } = await permissionService.getOrgPermissionByRole(
@@ -54,7 +62,15 @@ export const identityServiceFactory = ({
return identity; return identity;
}; };
const updateIdentity = async ({ id, role, name, actor, actorId, actorOrgId }: TUpdateIdentityDTO) => { const updateIdentity = async ({
id,
role,
name,
actor,
actorId,
actorAuthMethod,
actorOrgId
}: TUpdateIdentityDTO) => {
const identityOrgMembership = await identityOrgMembershipDAL.findOne({ identityId: id }); const identityOrgMembership = await identityOrgMembershipDAL.findOne({ identityId: id });
if (!identityOrgMembership) throw new BadRequestError({ message: `Failed to find identity with id ${id}` }); if (!identityOrgMembership) throw new BadRequestError({ message: `Failed to find identity with id ${id}` });
@@ -62,6 +78,7 @@ export const identityServiceFactory = ({
actor, actor,
actorId, actorId,
identityOrgMembership.orgId, identityOrgMembership.orgId,
actorAuthMethod,
actorOrgId actorOrgId
); );
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Edit, OrgPermissionSubjects.Identity); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Edit, OrgPermissionSubjects.Identity);
@@ -70,6 +87,7 @@ export const identityServiceFactory = ({
ActorType.IDENTITY, ActorType.IDENTITY,
id, id,
identityOrgMembership.orgId, identityOrgMembership.orgId,
actorAuthMethod,
actorOrgId actorOrgId
); );
const hasRequiredPriviledges = isAtLeastAsPrivileged(permission, identityRolePermission); const hasRequiredPriviledges = isAtLeastAsPrivileged(permission, identityRolePermission);
@@ -108,7 +126,7 @@ export const identityServiceFactory = ({
return { ...identity, orgId: identityOrgMembership.orgId }; return { ...identity, orgId: identityOrgMembership.orgId };
}; };
const deleteIdentity = async ({ actorId, actor, actorOrgId, id }: TDeleteIdentityDTO) => { const deleteIdentity = async ({ actorId, actor, actorOrgId, actorAuthMethod, id }: TDeleteIdentityDTO) => {
const identityOrgMembership = await identityOrgMembershipDAL.findOne({ identityId: id }); const identityOrgMembership = await identityOrgMembershipDAL.findOne({ identityId: id });
if (!identityOrgMembership) throw new BadRequestError({ message: `Failed to find identity with id ${id}` }); if (!identityOrgMembership) throw new BadRequestError({ message: `Failed to find identity with id ${id}` });
@@ -116,13 +134,16 @@ export const identityServiceFactory = ({
actor, actor,
actorId, actorId,
identityOrgMembership.orgId, identityOrgMembership.orgId,
actorAuthMethod,
actorOrgId actorOrgId
); );
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Delete, OrgPermissionSubjects.Identity); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Delete, OrgPermissionSubjects.Identity);
const { permission: identityRolePermission } = await permissionService.getOrgPermission( const { permission: identityRolePermission } = await permissionService.getOrgPermission(
ActorType.IDENTITY, ActorType.IDENTITY,
id, id,
identityOrgMembership.orgId identityOrgMembership.orgId,
actorAuthMethod,
actorOrgId
); );
const hasRequiredPriviledges = isAtLeastAsPrivileged(permission, identityRolePermission); const hasRequiredPriviledges = isAtLeastAsPrivileged(permission, identityRolePermission);
if (!hasRequiredPriviledges) if (!hasRequiredPriviledges)
@@ -132,8 +153,8 @@ export const identityServiceFactory = ({
return { ...deletedIdentity, orgId: identityOrgMembership.orgId }; return { ...deletedIdentity, orgId: identityOrgMembership.orgId };
}; };
const listOrgIdentities = async ({ orgId, actor, actorId, actorOrgId }: TOrgPermission) => { const listOrgIdentities = async ({ orgId, actor, actorId, actorAuthMethod, actorOrgId }: TOrgPermission) => {
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, actorOrgId); const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, actorAuthMethod, actorOrgId);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Identity); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Identity);
const identityMemberhips = await identityOrgMembershipDAL.findByOrgId(orgId); const identityMemberhips = await identityOrgMembershipDAL.findByOrgId(orgId);
@@ -64,14 +64,26 @@ export const integrationAuthServiceFactory = ({
projectBotDAL, projectBotDAL,
projectBotService projectBotService
}: TIntegrationAuthServiceFactoryDep) => { }: TIntegrationAuthServiceFactoryDep) => {
const listIntegrationAuthByProjectId = async ({ actorId, actor, actorOrgId, projectId }: TProjectPermission) => { const listIntegrationAuthByProjectId = async ({
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId); actorId,
actor,
actorOrgId,
actorAuthMethod,
projectId
}: TProjectPermission) => {
const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations);
const authorizations = await integrationAuthDAL.find({ projectId }); const authorizations = await integrationAuthDAL.find({ projectId });
return authorizations; return authorizations;
}; };
const getIntegrationAuth = async ({ actor, id, actorId, actorOrgId }: TGetIntegrationAuthDTO) => { const getIntegrationAuth = async ({ actor, id, actorId, actorAuthMethod, actorOrgId }: TGetIntegrationAuthDTO) => {
const integrationAuth = await integrationAuthDAL.findById(id); const integrationAuth = await integrationAuthDAL.findById(id);
if (!integrationAuth) throw new BadRequestError({ message: "Failed to find integration" }); if (!integrationAuth) throw new BadRequestError({ message: "Failed to find integration" });
@@ -79,6 +91,7 @@ export const integrationAuthServiceFactory = ({
actor, actor,
actorId, actorId,
integrationAuth.projectId, integrationAuth.projectId,
actorAuthMethod,
actorOrgId actorOrgId
); );
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations);
@@ -90,6 +103,7 @@ export const integrationAuthServiceFactory = ({
actorId, actorId,
actor, actor,
actorOrgId, actorOrgId,
actorAuthMethod,
integration, integration,
url, url,
code code
@@ -97,7 +111,13 @@ export const integrationAuthServiceFactory = ({
if (!Object.values(Integrations).includes(integration as Integrations)) if (!Object.values(Integrations).includes(integration as Integrations))
throw new BadRequestError({ message: "Invalid integration" }); throw new BadRequestError({ message: "Invalid integration" });
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId); const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Create, ProjectPermissionSub.Integrations); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Create, ProjectPermissionSub.Integrations);
const bot = await projectBotDAL.findOne({ isActive: true, projectId }); const bot = await projectBotDAL.findOne({ isActive: true, projectId });
@@ -153,6 +173,7 @@ export const integrationAuthServiceFactory = ({
url, url,
actor, actor,
actorOrgId, actorOrgId,
actorAuthMethod,
accessId, accessId,
namespace, namespace,
accessToken accessToken
@@ -160,7 +181,13 @@ export const integrationAuthServiceFactory = ({
if (!Object.values(Integrations).includes(integration as Integrations)) if (!Object.values(Integrations).includes(integration as Integrations))
throw new BadRequestError({ message: "Invalid integration" }); throw new BadRequestError({ message: "Invalid integration" });
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId); const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Create, ProjectPermissionSub.Integrations); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Create, ProjectPermissionSub.Integrations);
const bot = await projectBotDAL.findOne({ isActive: true, projectId }); const bot = await projectBotDAL.findOne({ isActive: true, projectId });
@@ -277,6 +304,7 @@ export const integrationAuthServiceFactory = ({
actor, actor,
actorId, actorId,
actorOrgId, actorOrgId,
actorAuthMethod,
teamId, teamId,
id, id,
workspaceSlug workspaceSlug
@@ -288,6 +316,7 @@ export const integrationAuthServiceFactory = ({
actor, actor,
actorId, actorId,
integrationAuth.projectId, integrationAuth.projectId,
actorAuthMethod,
actorOrgId actorOrgId
); );
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations);
@@ -305,7 +334,13 @@ export const integrationAuthServiceFactory = ({
return apps; return apps;
}; };
const getIntegrationAuthTeams = async ({ actor, actorId, actorOrgId, id }: TIntegrationAuthTeamsDTO) => { const getIntegrationAuthTeams = async ({
actor,
actorId,
actorAuthMethod,
actorOrgId,
id
}: TIntegrationAuthTeamsDTO) => {
const integrationAuth = await integrationAuthDAL.findById(id); const integrationAuth = await integrationAuthDAL.findById(id);
if (!integrationAuth) throw new BadRequestError({ message: "Failed to find integration" }); if (!integrationAuth) throw new BadRequestError({ message: "Failed to find integration" });
@@ -313,6 +348,7 @@ export const integrationAuthServiceFactory = ({
actor, actor,
actorId, actorId,
integrationAuth.projectId, integrationAuth.projectId,
actorAuthMethod,
actorOrgId actorOrgId
); );
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations);
@@ -327,7 +363,14 @@ export const integrationAuthServiceFactory = ({
return teams; return teams;
}; };
const getVercelBranches = async ({ appId, id, actor, actorId, actorOrgId }: TIntegrationAuthVercelBranchesDTO) => { const getVercelBranches = async ({
appId,
id,
actor,
actorId,
actorAuthMethod,
actorOrgId
}: TIntegrationAuthVercelBranchesDTO) => {
const integrationAuth = await integrationAuthDAL.findById(id); const integrationAuth = await integrationAuthDAL.findById(id);
if (!integrationAuth) throw new BadRequestError({ message: "Failed to find integration" }); if (!integrationAuth) throw new BadRequestError({ message: "Failed to find integration" });
@@ -335,6 +378,7 @@ export const integrationAuthServiceFactory = ({
actor, actor,
actorId, actorId,
integrationAuth.projectId, integrationAuth.projectId,
actorAuthMethod,
actorOrgId actorOrgId
); );
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations);
@@ -360,7 +404,14 @@ export const integrationAuthServiceFactory = ({
return []; return [];
}; };
const getChecklyGroups = async ({ actorId, actor, actorOrgId, id, accountId }: TIntegrationAuthChecklyGroupsDTO) => { const getChecklyGroups = async ({
actorId,
actor,
actorOrgId,
actorAuthMethod,
id,
accountId
}: TIntegrationAuthChecklyGroupsDTO) => {
const integrationAuth = await integrationAuthDAL.findById(id); const integrationAuth = await integrationAuthDAL.findById(id);
if (!integrationAuth) throw new BadRequestError({ message: "Failed to find integration" }); if (!integrationAuth) throw new BadRequestError({ message: "Failed to find integration" });
@@ -368,6 +419,7 @@ export const integrationAuthServiceFactory = ({
actor, actor,
actorId, actorId,
integrationAuth.projectId, integrationAuth.projectId,
actorAuthMethod,
actorOrgId actorOrgId
); );
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations);
@@ -386,7 +438,7 @@ export const integrationAuthServiceFactory = ({
return []; return [];
}; };
const getGithubOrgs = async ({ actorId, actor, actorOrgId, id }: TIntegrationAuthGithubOrgsDTO) => { const getGithubOrgs = async ({ actorId, actor, actorOrgId, actorAuthMethod, id }: TIntegrationAuthGithubOrgsDTO) => {
const integrationAuth = await integrationAuthDAL.findById(id); const integrationAuth = await integrationAuthDAL.findById(id);
if (!integrationAuth) throw new BadRequestError({ message: "Failed to find integration" }); if (!integrationAuth) throw new BadRequestError({ message: "Failed to find integration" });
@@ -394,6 +446,7 @@ export const integrationAuthServiceFactory = ({
actor, actor,
actorId, actorId,
integrationAuth.projectId, integrationAuth.projectId,
actorAuthMethod,
actorOrgId actorOrgId
); );
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations);
@@ -418,6 +471,7 @@ export const integrationAuthServiceFactory = ({
actorId, actorId,
actor, actor,
actorOrgId, actorOrgId,
actorAuthMethod,
id, id,
repoOwner, repoOwner,
repoName repoName
@@ -429,6 +483,7 @@ export const integrationAuthServiceFactory = ({
actor, actor,
actorId, actorId,
integrationAuth.projectId, integrationAuth.projectId,
actorAuthMethod,
actorOrgId actorOrgId
); );
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations);
@@ -452,7 +507,7 @@ export const integrationAuthServiceFactory = ({
return environments.map(({ id: envId, name }) => ({ name, envId: String(envId) })); return environments.map(({ id: envId, name }) => ({ name, envId: String(envId) }));
}; };
const getQoveryOrgs = async ({ actorId, actor, actorOrgId, id }: TIntegrationAuthQoveryOrgsDTO) => { const getQoveryOrgs = async ({ actorId, actor, actorOrgId, actorAuthMethod, id }: TIntegrationAuthQoveryOrgsDTO) => {
const integrationAuth = await integrationAuthDAL.findById(id); const integrationAuth = await integrationAuthDAL.findById(id);
if (!integrationAuth) throw new BadRequestError({ message: "Failed to find integration" }); if (!integrationAuth) throw new BadRequestError({ message: "Failed to find integration" });
@@ -460,6 +515,7 @@ export const integrationAuthServiceFactory = ({
actor, actor,
actorId, actorId,
integrationAuth.projectId, integrationAuth.projectId,
actorAuthMethod,
actorOrgId actorOrgId
); );
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations);
@@ -478,7 +534,14 @@ export const integrationAuthServiceFactory = ({
return data.results.map(({ name, id: orgId }) => ({ name, orgId })); return data.results.map(({ name, id: orgId }) => ({ name, orgId }));
}; };
const getQoveryProjects = async ({ actorId, actor, actorOrgId, id, orgId }: TIntegrationAuthQoveryProjectDTO) => { const getQoveryProjects = async ({
actorId,
actor,
actorOrgId,
actorAuthMethod,
id,
orgId
}: TIntegrationAuthQoveryProjectDTO) => {
const integrationAuth = await integrationAuthDAL.findById(id); const integrationAuth = await integrationAuthDAL.findById(id);
if (!integrationAuth) throw new BadRequestError({ message: "Failed to find integration" }); if (!integrationAuth) throw new BadRequestError({ message: "Failed to find integration" });
@@ -486,6 +549,7 @@ export const integrationAuthServiceFactory = ({
actor, actor,
actorId, actorId,
integrationAuth.projectId, integrationAuth.projectId,
actorAuthMethod,
actorOrgId actorOrgId
); );
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations);
@@ -511,6 +575,7 @@ export const integrationAuthServiceFactory = ({
id, id,
actor, actor,
actorId, actorId,
actorAuthMethod,
actorOrgId actorOrgId
}: TIntegrationAuthQoveryEnvironmentsDTO) => { }: TIntegrationAuthQoveryEnvironmentsDTO) => {
const integrationAuth = await integrationAuthDAL.findById(id); const integrationAuth = await integrationAuthDAL.findById(id);
@@ -520,6 +585,7 @@ export const integrationAuthServiceFactory = ({
actor, actor,
actorId, actorId,
integrationAuth.projectId, integrationAuth.projectId,
actorAuthMethod,
actorOrgId actorOrgId
); );
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations);
@@ -545,7 +611,14 @@ export const integrationAuthServiceFactory = ({
return []; return [];
}; };
const getQoveryApps = async ({ id, actor, actorId, actorOrgId, environmentId }: TIntegrationAuthQoveryScopesDTO) => { const getQoveryApps = async ({
id,
actor,
actorId,
actorOrgId,
actorAuthMethod,
environmentId
}: TIntegrationAuthQoveryScopesDTO) => {
const integrationAuth = await integrationAuthDAL.findById(id); const integrationAuth = await integrationAuthDAL.findById(id);
if (!integrationAuth) throw new BadRequestError({ message: "Failed to find integration" }); if (!integrationAuth) throw new BadRequestError({ message: "Failed to find integration" });
@@ -553,6 +626,7 @@ export const integrationAuthServiceFactory = ({
actor, actor,
actorId, actorId,
integrationAuth.projectId, integrationAuth.projectId,
actorAuthMethod,
actorOrgId actorOrgId
); );
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations);
@@ -582,6 +656,7 @@ export const integrationAuthServiceFactory = ({
actor, actor,
actorId, actorId,
actorOrgId, actorOrgId,
actorAuthMethod,
environmentId environmentId
}: TIntegrationAuthQoveryScopesDTO) => { }: TIntegrationAuthQoveryScopesDTO) => {
const integrationAuth = await integrationAuthDAL.findById(id); const integrationAuth = await integrationAuthDAL.findById(id);
@@ -591,6 +666,7 @@ export const integrationAuthServiceFactory = ({
actor, actor,
actorId, actorId,
integrationAuth.projectId, integrationAuth.projectId,
actorAuthMethod,
actorOrgId actorOrgId
); );
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations);
@@ -615,7 +691,14 @@ export const integrationAuthServiceFactory = ({
return []; return [];
}; };
const getQoveryJobs = async ({ id, actor, actorId, actorOrgId, environmentId }: TIntegrationAuthQoveryScopesDTO) => { const getQoveryJobs = async ({
id,
actor,
actorId,
actorOrgId,
actorAuthMethod,
environmentId
}: TIntegrationAuthQoveryScopesDTO) => {
const integrationAuth = await integrationAuthDAL.findById(id); const integrationAuth = await integrationAuthDAL.findById(id);
if (!integrationAuth) throw new BadRequestError({ message: "Failed to find integration" }); if (!integrationAuth) throw new BadRequestError({ message: "Failed to find integration" });
@@ -623,6 +706,7 @@ export const integrationAuthServiceFactory = ({
actor, actor,
actorId, actorId,
integrationAuth.projectId, integrationAuth.projectId,
actorAuthMethod,
actorOrgId actorOrgId
); );
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations);
@@ -647,7 +731,13 @@ export const integrationAuthServiceFactory = ({
return []; return [];
}; };
const getHerokuPipelines = async ({ id, actor, actorId, actorOrgId }: TIntegrationAuthHerokuPipelinesDTO) => { const getHerokuPipelines = async ({
id,
actor,
actorId,
actorAuthMethod,
actorOrgId
}: TIntegrationAuthHerokuPipelinesDTO) => {
const integrationAuth = await integrationAuthDAL.findById(id); const integrationAuth = await integrationAuthDAL.findById(id);
if (!integrationAuth) throw new BadRequestError({ message: "Failed to find integration" }); if (!integrationAuth) throw new BadRequestError({ message: "Failed to find integration" });
@@ -655,6 +745,7 @@ export const integrationAuthServiceFactory = ({
actor, actor,
actorId, actorId,
integrationAuth.projectId, integrationAuth.projectId,
actorAuthMethod,
actorOrgId actorOrgId
); );
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations);
@@ -679,7 +770,14 @@ export const integrationAuthServiceFactory = ({
})); }));
}; };
const getRailwayEnvironments = async ({ id, actor, actorId, actorOrgId, appId }: TIntegrationAuthRailwayEnvDTO) => { const getRailwayEnvironments = async ({
id,
actor,
actorId,
actorOrgId,
actorAuthMethod,
appId
}: TIntegrationAuthRailwayEnvDTO) => {
const integrationAuth = await integrationAuthDAL.findById(id); const integrationAuth = await integrationAuthDAL.findById(id);
if (!integrationAuth) throw new BadRequestError({ message: "Failed to find integration" }); if (!integrationAuth) throw new BadRequestError({ message: "Failed to find integration" });
@@ -687,6 +785,7 @@ export const integrationAuthServiceFactory = ({
actor, actor,
actorId, actorId,
integrationAuth.projectId, integrationAuth.projectId,
actorAuthMethod,
actorOrgId actorOrgId
); );
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations);
@@ -739,7 +838,14 @@ export const integrationAuthServiceFactory = ({
return []; return [];
}; };
const getRailwayServices = async ({ id, actor, actorId, actorOrgId, appId }: TIntegrationAuthRailwayServicesDTO) => { const getRailwayServices = async ({
id,
actor,
actorId,
actorOrgId,
actorAuthMethod,
appId
}: TIntegrationAuthRailwayServicesDTO) => {
const integrationAuth = await integrationAuthDAL.findById(id); const integrationAuth = await integrationAuthDAL.findById(id);
if (!integrationAuth) throw new BadRequestError({ message: "Failed to find integration" }); if (!integrationAuth) throw new BadRequestError({ message: "Failed to find integration" });
@@ -747,6 +853,7 @@ export const integrationAuthServiceFactory = ({
actor, actor,
actorId, actorId,
integrationAuth.projectId, integrationAuth.projectId,
actorAuthMethod,
actorOrgId actorOrgId
); );
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations);
@@ -806,7 +913,13 @@ export const integrationAuthServiceFactory = ({
return []; return [];
}; };
const getBitbucketWorkspaces = async ({ actorId, actor, actorOrgId, id }: TIntegrationAuthBitbucketWorkspaceDTO) => { const getBitbucketWorkspaces = async ({
actorId,
actor,
actorOrgId,
actorAuthMethod,
id
}: TIntegrationAuthBitbucketWorkspaceDTO) => {
const integrationAuth = await integrationAuthDAL.findById(id); const integrationAuth = await integrationAuthDAL.findById(id);
if (!integrationAuth) throw new BadRequestError({ message: "Failed to find integration" }); if (!integrationAuth) throw new BadRequestError({ message: "Failed to find integration" });
@@ -814,6 +927,7 @@ export const integrationAuthServiceFactory = ({
actor, actor,
actorId, actorId,
integrationAuth.projectId, integrationAuth.projectId,
actorAuthMethod,
actorOrgId actorOrgId
); );
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations);
@@ -852,6 +966,7 @@ export const integrationAuthServiceFactory = ({
actor, actor,
actorId, actorId,
actorOrgId, actorOrgId,
actorAuthMethod,
appId appId
}: TIntegrationAuthNorthflankSecretGroupDTO) => { }: TIntegrationAuthNorthflankSecretGroupDTO) => {
const integrationAuth = await integrationAuthDAL.findById(id); const integrationAuth = await integrationAuthDAL.findById(id);
@@ -861,6 +976,7 @@ export const integrationAuthServiceFactory = ({
actor, actor,
actorId, actorId,
integrationAuth.projectId, integrationAuth.projectId,
actorAuthMethod,
actorOrgId actorOrgId
); );
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations);
@@ -918,6 +1034,7 @@ export const integrationAuthServiceFactory = ({
id, id,
actorId, actorId,
actorOrgId, actorOrgId,
actorAuthMethod,
actor actor
}: TGetIntegrationAuthTeamCityBuildConfigDTO) => { }: TGetIntegrationAuthTeamCityBuildConfigDTO) => {
const integrationAuth = await integrationAuthDAL.findById(id); const integrationAuth = await integrationAuthDAL.findById(id);
@@ -927,6 +1044,7 @@ export const integrationAuthServiceFactory = ({
actor, actor,
actorId, actorId,
integrationAuth.projectId, integrationAuth.projectId,
actorAuthMethod,
actorOrgId actorOrgId
); );
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations);
@@ -958,16 +1076,29 @@ export const integrationAuthServiceFactory = ({
integration, integration,
actor, actor,
actorId, actorId,
actorAuthMethod,
actorOrgId actorOrgId
}: TDeleteIntegrationAuthsDTO) => { }: TDeleteIntegrationAuthsDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId); const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Delete, ProjectPermissionSub.Integrations); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Delete, ProjectPermissionSub.Integrations);
const integrations = await integrationAuthDAL.delete({ integration, projectId }); const integrations = await integrationAuthDAL.delete({ integration, projectId });
return integrations; return integrations;
}; };
const deleteIntegrationAuthById = async ({ id, actorId, actor, actorOrgId }: TDeleteIntegrationAuthByIdDTO) => { const deleteIntegrationAuthById = async ({
id,
actorId,
actor,
actorAuthMethod,
actorOrgId
}: TDeleteIntegrationAuthByIdDTO) => {
const integrationAuth = await integrationAuthDAL.findById(id); const integrationAuth = await integrationAuthDAL.findById(id);
if (!integrationAuth) throw new BadRequestError({ message: "Failed to find integration" }); if (!integrationAuth) throw new BadRequestError({ message: "Failed to find integration" });
@@ -975,6 +1106,7 @@ export const integrationAuthServiceFactory = ({
actor, actor,
actorId, actorId,
integrationAuth.projectId, integrationAuth.projectId,
actorAuthMethod,
actorOrgId actorOrgId
); );
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Delete, ProjectPermissionSub.Integrations); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Delete, ProjectPermissionSub.Integrations);
@@ -42,6 +42,7 @@ export const integrationServiceFactory = ({
metadata, metadata,
secretPath, secretPath,
targetService, targetService,
actorAuthMethod,
targetServiceId, targetServiceId,
integrationAuthId, integrationAuthId,
sourceEnvironment, sourceEnvironment,
@@ -55,6 +56,7 @@ export const integrationServiceFactory = ({
actor, actor,
actorId, actorId,
integrationAuth.projectId, integrationAuth.projectId,
actorAuthMethod,
actorOrgId actorOrgId
); );
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Create, ProjectPermissionSub.Integrations); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Create, ProjectPermissionSub.Integrations);
@@ -93,6 +95,7 @@ export const integrationServiceFactory = ({
actorId, actorId,
actor, actor,
actorOrgId, actorOrgId,
actorAuthMethod,
targetEnvironment, targetEnvironment,
app, app,
id, id,
@@ -109,6 +112,7 @@ export const integrationServiceFactory = ({
actor, actor,
actorId, actorId,
integration.projectId, integration.projectId,
actorAuthMethod,
actorOrgId actorOrgId
); );
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.Integrations); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.Integrations);
@@ -129,7 +133,7 @@ export const integrationServiceFactory = ({
return updatedIntegration; return updatedIntegration;
}; };
const deleteIntegration = async ({ actorId, id, actor, actorOrgId }: TDeleteIntegrationDTO) => { const deleteIntegration = async ({ actorId, id, actor, actorAuthMethod, actorOrgId }: TDeleteIntegrationDTO) => {
const integration = await integrationDAL.findById(id); const integration = await integrationDAL.findById(id);
if (!integration) throw new BadRequestError({ message: "Integration auth not found" }); if (!integration) throw new BadRequestError({ message: "Integration auth not found" });
@@ -137,6 +141,7 @@ export const integrationServiceFactory = ({
actor, actor,
actorId, actorId,
integration.projectId, integration.projectId,
actorAuthMethod,
actorOrgId actorOrgId
); );
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Delete, ProjectPermissionSub.Integrations); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Delete, ProjectPermissionSub.Integrations);
@@ -145,8 +150,20 @@ export const integrationServiceFactory = ({
return { ...integration, ...deletedIntegration }; return { ...integration, ...deletedIntegration };
}; };
const listIntegrationByProject = async ({ actor, actorId, actorOrgId, projectId }: TProjectPermission) => { const listIntegrationByProject = async ({
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId); actor,
actorId,
actorOrgId,
actorAuthMethod,
projectId
}: TProjectPermission) => {
const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations);
const integrations = await integrationDAL.findByProjectId(projectId); const integrations = await integrationDAL.findByProjectId(projectId);
+34 -10
View File
@@ -12,6 +12,7 @@ import {
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service"; import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service";
import { BadRequestError } from "@app/lib/errors"; import { BadRequestError } from "@app/lib/errors";
import { ActorAuthMethod } from "../auth/auth-type";
import { TOrgRoleDALFactory } from "./org-role-dal"; import { TOrgRoleDALFactory } from "./org-role-dal";
type TOrgRoleServiceFactoryDep = { type TOrgRoleServiceFactoryDep = {
@@ -26,9 +27,10 @@ export const orgRoleServiceFactory = ({ orgRoleDAL, permissionService }: TOrgRol
userId: string, userId: string,
orgId: string, orgId: string,
data: Omit<TOrgRolesInsert, "orgId">, data: Omit<TOrgRolesInsert, "orgId">,
actorOrgId?: string actorAuthMethod: ActorAuthMethod,
actorOrgId: string | undefined
) => { ) => {
const { permission } = await permissionService.getUserOrgPermission(userId, orgId, actorOrgId); const { permission } = await permissionService.getUserOrgPermission(userId, orgId, actorAuthMethod, actorOrgId);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Create, OrgPermissionSubjects.Role); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Create, OrgPermissionSubjects.Role);
const existingRole = await orgRoleDAL.findOne({ slug: data.slug, orgId }); const existingRole = await orgRoleDAL.findOne({ slug: data.slug, orgId });
if (existingRole) throw new BadRequestError({ name: "Create Role", message: "Duplicate role" }); if (existingRole) throw new BadRequestError({ name: "Create Role", message: "Duplicate role" });
@@ -45,9 +47,10 @@ export const orgRoleServiceFactory = ({ orgRoleDAL, permissionService }: TOrgRol
orgId: string, orgId: string,
roleId: string, roleId: string,
data: Omit<TOrgRolesUpdate, "orgId">, data: Omit<TOrgRolesUpdate, "orgId">,
actorOrgId?: string actorAuthMethod: ActorAuthMethod,
actorOrgId: string | undefined
) => { ) => {
const { permission } = await permissionService.getUserOrgPermission(userId, orgId, actorOrgId); const { permission } = await permissionService.getUserOrgPermission(userId, orgId, actorAuthMethod, actorOrgId);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Edit, OrgPermissionSubjects.Role); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Edit, OrgPermissionSubjects.Role);
if (data?.slug) { if (data?.slug) {
const existingRole = await orgRoleDAL.findOne({ slug: data.slug, orgId }); const existingRole = await orgRoleDAL.findOne({ slug: data.slug, orgId });
@@ -62,8 +65,14 @@ export const orgRoleServiceFactory = ({ orgRoleDAL, permissionService }: TOrgRol
return updatedRole; return updatedRole;
}; };
const deleteRole = async (userId: string, orgId: string, roleId: string, actorOrgId?: string) => { const deleteRole = async (
const { permission } = await permissionService.getUserOrgPermission(userId, orgId, actorOrgId); userId: string,
orgId: string,
roleId: string,
actorAuthMethod: ActorAuthMethod,
actorOrgId: string | undefined
) => {
const { permission } = await permissionService.getUserOrgPermission(userId, orgId, actorAuthMethod, actorOrgId);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Delete, OrgPermissionSubjects.Role); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Delete, OrgPermissionSubjects.Role);
const [deletedRole] = await orgRoleDAL.delete({ id: roleId, orgId }); const [deletedRole] = await orgRoleDAL.delete({ id: roleId, orgId });
if (!deletedRole) throw new BadRequestError({ message: "Role not found", name: "Update role" }); if (!deletedRole) throw new BadRequestError({ message: "Role not found", name: "Update role" });
@@ -71,8 +80,13 @@ export const orgRoleServiceFactory = ({ orgRoleDAL, permissionService }: TOrgRol
return deletedRole; return deletedRole;
}; };
const listRoles = async (userId: string, orgId: string, actorOrgId?: string) => { const listRoles = async (
const { permission } = await permissionService.getUserOrgPermission(userId, orgId, actorOrgId); userId: string,
orgId: string,
actorAuthMethod: ActorAuthMethod,
actorOrgId: string | undefined
) => {
const { permission } = await permissionService.getUserOrgPermission(userId, orgId, actorAuthMethod, actorOrgId);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Role); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Role);
const customRoles = await orgRoleDAL.find({ orgId }); const customRoles = await orgRoleDAL.find({ orgId });
const roles = [ const roles = [
@@ -115,8 +129,18 @@ export const orgRoleServiceFactory = ({ orgRoleDAL, permissionService }: TOrgRol
return roles; return roles;
}; };
const getUserPermission = async (userId: string, orgId: string, actorOrgId?: string) => { const getUserPermission = async (
const { permission, membership } = await permissionService.getUserOrgPermission(userId, orgId, actorOrgId); userId: string,
orgId: string,
actorAuthMethod: ActorAuthMethod,
actorOrgId: string | undefined
) => {
const { permission, membership } = await permissionService.getUserOrgPermission(
userId,
orgId,
actorAuthMethod,
actorOrgId
);
return { permissions: packRules(permission.rules), membership }; return { permissions: packRules(permission.rules), membership };
}; };
+83 -24
View File
@@ -18,7 +18,7 @@ import { BadRequestError, UnauthorizedError } from "@app/lib/errors";
import { alphaNumericNanoId } from "@app/lib/nanoid"; import { alphaNumericNanoId } from "@app/lib/nanoid";
import { isDisposableEmail } from "@app/lib/validator"; import { isDisposableEmail } from "@app/lib/validator";
import { ActorType, AuthMethod, AuthTokenType } from "../auth/auth-type"; import { ActorAuthMethod, ActorType, AuthMethod, AuthTokenType } from "../auth/auth-type";
import { TAuthTokenServiceFactory } from "../auth-token/auth-token-service"; import { TAuthTokenServiceFactory } from "../auth-token/auth-token-service";
import { TokenType } from "../auth-token/auth-token-types"; import { TokenType } from "../auth-token/auth-token-types";
import { TProjectDALFactory } from "../project/project-dal"; import { TProjectDALFactory } from "../project/project-dal";
@@ -79,8 +79,13 @@ export const orgServiceFactory = ({
/* /*
* Get organization details by the organization id * Get organization details by the organization id
* */ * */
const findOrganizationById = async (userId: string, orgId: string, actorOrgId?: string) => { const findOrganizationById = async (
await permissionService.getUserOrgPermission(userId, orgId, actorOrgId); userId: string,
orgId: string,
actorAuthMethod: ActorAuthMethod,
actorOrgId: string | undefined
) => {
await permissionService.getUserOrgPermission(userId, orgId, actorAuthMethod, actorOrgId);
const org = await orgDAL.findOrgById(orgId); const org = await orgDAL.findOrgById(orgId);
if (!org) throw new BadRequestError({ name: "Org not found", message: "Organization not found" }); if (!org) throw new BadRequestError({ name: "Org not found", message: "Organization not found" });
return org; return org;
@@ -95,16 +100,28 @@ export const orgServiceFactory = ({
/* /*
* Get all workspace members * Get all workspace members
* */ * */
const findAllOrgMembers = async (userId: string, orgId: string, actorOrgId?: string) => { const findAllOrgMembers = async (
const { permission } = await permissionService.getUserOrgPermission(userId, orgId, actorOrgId); userId: string,
orgId: string,
actorAuthMethod: ActorAuthMethod,
actorOrgId: string | undefined
) => {
const { permission } = await permissionService.getUserOrgPermission(userId, orgId, actorAuthMethod, actorOrgId);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Member); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Member);
const members = await orgDAL.findAllOrgMembers(orgId); const members = await orgDAL.findAllOrgMembers(orgId);
return members; return members;
}; };
const findOrgMembersByUsername = async ({ actor, actorId, orgId, emails }: TFindOrgMembersByEmailDTO) => { const findOrgMembersByUsername = async ({
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId); actor,
actorId,
actorOrgId,
actorAuthMethod,
orgId,
emails
}: TFindOrgMembersByEmailDTO) => {
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, actorAuthMethod, actorOrgId);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Member); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Member);
const members = await orgDAL.findOrgMembersByUsername(orgId, emails); const members = await orgDAL.findOrgMembersByUsername(orgId, emails);
@@ -112,8 +129,8 @@ export const orgServiceFactory = ({
return members; return members;
}; };
const findAllWorkspaces = async ({ actor, actorId, actorOrgId, orgId }: TFindAllWorkspacesDTO) => { const findAllWorkspaces = async ({ actor, actorId, actorOrgId, actorAuthMethod, orgId }: TFindAllWorkspacesDTO) => {
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, actorOrgId); const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, actorAuthMethod, actorOrgId);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Workspace); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Workspace);
const organizationWorkspaceIds = new Set((await projectDAL.find({ orgId })).map((workspace) => workspace.id)); const organizationWorkspaceIds = new Set((await projectDAL.find({ orgId })).map((workspace) => workspace.id));
@@ -193,10 +210,11 @@ export const orgServiceFactory = ({
actor, actor,
actorId, actorId,
actorOrgId, actorOrgId,
actorAuthMethod,
orgId, orgId,
data: { name, slug, authEnforced, scimEnabled } data: { name, slug, authEnforced, scimEnabled }
}: TUpdateOrgDTO) => { }: TUpdateOrgDTO) => {
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, actorOrgId); const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, actorAuthMethod, actorOrgId);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Edit, OrgPermissionSubjects.Settings); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Edit, OrgPermissionSubjects.Settings);
const plan = await licenseService.getPlan(orgId); const plan = await licenseService.getPlan(orgId);
@@ -309,8 +327,13 @@ export const orgServiceFactory = ({
/* /*
* Delete organization by id * Delete organization by id
* */ * */
const deleteOrganizationById = async (userId: string, orgId: string, actorOrgId?: string) => { const deleteOrganizationById = async (
const { membership } = await permissionService.getUserOrgPermission(userId, orgId, actorOrgId); userId: string,
orgId: string,
actorAuthMethod: ActorAuthMethod,
actorOrgId: string | undefined
) => {
const { membership } = await permissionService.getUserOrgPermission(userId, orgId, actorAuthMethod, actorOrgId);
if ((membership.role as OrgMembershipRole) !== OrgMembershipRole.Admin) if ((membership.role as OrgMembershipRole) !== OrgMembershipRole.Admin)
throw new UnauthorizedError({ name: "Delete org by id", message: "Not an admin" }); throw new UnauthorizedError({ name: "Delete org by id", message: "Not an admin" });
@@ -324,8 +347,15 @@ export const orgServiceFactory = ({
* Org membership management * Org membership management
* Not another service because it has close ties with how an org works doesn't make sense to seperate them * Not another service because it has close ties with how an org works doesn't make sense to seperate them
* */ * */
const updateOrgMembership = async ({ role, orgId, userId, membershipId, actorOrgId }: TUpdateOrgMembershipDTO) => { const updateOrgMembership = async ({
const { permission } = await permissionService.getUserOrgPermission(userId, orgId, actorOrgId); role,
orgId,
userId,
membershipId,
actorAuthMethod,
actorOrgId
}: TUpdateOrgMembershipDTO) => {
const { permission } = await permissionService.getUserOrgPermission(userId, orgId, actorAuthMethod, actorOrgId);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Edit, OrgPermissionSubjects.Member); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Edit, OrgPermissionSubjects.Member);
const isCustomRole = !Object.values(OrgMembershipRole).includes(role as OrgMembershipRole); const isCustomRole = !Object.values(OrgMembershipRole).includes(role as OrgMembershipRole);
@@ -355,8 +385,14 @@ export const orgServiceFactory = ({
/* /*
* Invite user to organization * Invite user to organization
*/ */
const inviteUserToOrganization = async ({ orgId, userId, inviteeEmail, actorOrgId }: TInviteUserToOrgDTO) => { const inviteUserToOrganization = async ({
const { permission } = await permissionService.getUserOrgPermission(userId, orgId, actorOrgId); orgId,
userId,
inviteeEmail,
actorAuthMethod,
actorOrgId
}: TInviteUserToOrgDTO) => {
const { permission } = await permissionService.getUserOrgPermission(userId, orgId, actorAuthMethod, actorOrgId);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Create, OrgPermissionSubjects.Member); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Create, OrgPermissionSubjects.Member);
const org = await orgDAL.findOrgById(orgId); const org = await orgDAL.findOrgById(orgId);
@@ -515,8 +551,14 @@ export const orgServiceFactory = ({
return { token, user }; return { token, user };
}; };
const deleteOrgMembership = async ({ orgId, userId, membershipId, actorOrgId }: TDeleteOrgMembershipDTO) => { const deleteOrgMembership = async ({
const { permission } = await permissionService.getUserOrgPermission(userId, orgId, actorOrgId); orgId,
userId,
membershipId,
actorAuthMethod,
actorOrgId
}: TDeleteOrgMembershipDTO) => {
const { permission } = await permissionService.getUserOrgPermission(userId, orgId, actorAuthMethod, actorOrgId);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Delete, OrgPermissionSubjects.Member); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Delete, OrgPermissionSubjects.Member);
const deletedMembership = await orgDAL.transaction(async (tx) => { const deletedMembership = await orgDAL.transaction(async (tx) => {
@@ -568,15 +610,26 @@ export const orgServiceFactory = ({
/* /*
* CRUD operations of incident contacts * CRUD operations of incident contacts
* */ * */
const findIncidentContacts = async (userId: string, orgId: string, actorOrgId?: string) => { const findIncidentContacts = async (
const { permission } = await permissionService.getUserOrgPermission(userId, orgId, actorOrgId); userId: string,
orgId: string,
actorAuthMethod: ActorAuthMethod,
actorOrgId: string | undefined
) => {
const { permission } = await permissionService.getUserOrgPermission(userId, orgId, actorAuthMethod, actorOrgId);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.IncidentAccount); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.IncidentAccount);
const incidentContacts = await incidentContactDAL.findByOrgId(orgId); const incidentContacts = await incidentContactDAL.findByOrgId(orgId);
return incidentContacts; return incidentContacts;
}; };
const createIncidentContact = async (userId: string, orgId: string, email: string, actorOrgId?: string) => { const createIncidentContact = async (
const { permission } = await permissionService.getUserOrgPermission(userId, orgId, actorOrgId); userId: string,
orgId: string,
email: string,
actorAuthMethod: ActorAuthMethod,
actorOrgId: string | undefined
) => {
const { permission } = await permissionService.getUserOrgPermission(userId, orgId, actorAuthMethod, actorOrgId);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Create, OrgPermissionSubjects.IncidentAccount); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Create, OrgPermissionSubjects.IncidentAccount);
const doesIncidentContactExist = await incidentContactDAL.findOne(orgId, { email }); const doesIncidentContactExist = await incidentContactDAL.findOne(orgId, { email });
if (doesIncidentContactExist) { if (doesIncidentContactExist) {
@@ -590,8 +643,14 @@ export const orgServiceFactory = ({
return incidentContact; return incidentContact;
}; };
const deleteIncidentContact = async (userId: string, orgId: string, id: string, actorOrgId?: string) => { const deleteIncidentContact = async (
const { permission } = await permissionService.getUserOrgPermission(userId, orgId, actorOrgId); userId: string,
orgId: string,
id: string,
actorAuthMethod: ActorAuthMethod,
actorOrgId: string | undefined
) => {
const { permission } = await permissionService.getUserOrgPermission(userId, orgId, actorAuthMethod, actorOrgId);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Delete, OrgPermissionSubjects.IncidentAccount); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Delete, OrgPermissionSubjects.IncidentAccount);
const incidentContact = await incidentContactDAL.deleteById(id, orgId); const incidentContact = await incidentContactDAL.deleteById(id, orgId);
+11 -5
View File
@@ -1,26 +1,29 @@
import { TOrgPermission } from "@app/lib/types"; import { TOrgPermission } from "@app/lib/types";
import { ActorType } from "../auth/auth-type"; import { ActorAuthMethod, ActorType } from "../auth/auth-type";
export type TUpdateOrgMembershipDTO = { export type TUpdateOrgMembershipDTO = {
userId: string; userId: string;
orgId: string; orgId: string;
membershipId: string; membershipId: string;
role: string; role: string;
actorOrgId?: string; actorOrgId: string | undefined;
actorAuthMethod: ActorAuthMethod;
}; };
export type TDeleteOrgMembershipDTO = { export type TDeleteOrgMembershipDTO = {
userId: string; userId: string;
orgId: string; orgId: string;
membershipId: string; membershipId: string;
actorOrgId?: string; actorOrgId: string | undefined;
actorAuthMethod: ActorAuthMethod;
}; };
export type TInviteUserToOrgDTO = { export type TInviteUserToOrgDTO = {
userId: string; userId: string;
orgId: string; orgId: string;
actorOrgId?: string; actorOrgId: string | undefined;
actorAuthMethod: ActorAuthMethod;
inviteeEmail: string; inviteeEmail: string;
}; };
@@ -32,7 +35,9 @@ export type TVerifyUserToOrgDTO = {
export type TFindOrgMembersByEmailDTO = { export type TFindOrgMembersByEmailDTO = {
actor: ActorType; actor: ActorType;
actorOrgId: string | undefined;
actorId: string; actorId: string;
actorAuthMethod: ActorAuthMethod;
orgId: string; orgId: string;
emails: string[]; emails: string[];
}; };
@@ -40,7 +45,8 @@ export type TFindOrgMembersByEmailDTO = {
export type TFindAllWorkspacesDTO = { export type TFindAllWorkspacesDTO = {
actor: ActorType; actor: ActorType;
actorId: string; actorId: string;
actorOrgId?: string; actorOrgId: string | undefined;
actorAuthMethod: ActorAuthMethod;
orgId: string; orgId: string;
}; };
@@ -37,10 +37,17 @@ export const projectBotServiceFactory = ({
projectId, projectId,
actorOrgId, actorOrgId,
privateKey, privateKey,
actorAuthMethod,
botKey, botKey,
publicKey publicKey
}: TFindBotByProjectIdDTO) => { }: TFindBotByProjectIdDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId); const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations);
const bot = await projectBotDAL.transaction(async (tx) => { const bot = await projectBotDAL.transaction(async (tx) => {
@@ -88,11 +95,25 @@ export const projectBotServiceFactory = ({
} }
}; };
const setBotActiveState = async ({ actor, botId, botKey, actorId, actorOrgId, isActive }: TSetActiveStateDTO) => { const setBotActiveState = async ({
actor,
botId,
botKey,
actorId,
actorOrgId,
actorAuthMethod,
isActive
}: TSetActiveStateDTO) => {
const bot = await projectBotDAL.findById(botId); const bot = await projectBotDAL.findById(botId);
if (!bot) throw new BadRequestError({ message: "Bot not found" }); if (!bot) throw new BadRequestError({ message: "Bot not found" });
const { permission } = await permissionService.getProjectPermission(actor, actorId, bot.projectId, actorOrgId); const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
bot.projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.Integrations); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.Integrations);
const project = await projectBotDAL.findProjectByBotId(botId); const project = await projectBotDAL.findProjectByBotId(botId);
@@ -27,8 +27,22 @@ export const projectEnvServiceFactory = ({
projectDAL, projectDAL,
folderDAL folderDAL
}: TProjectEnvServiceFactoryDep) => { }: TProjectEnvServiceFactoryDep) => {
const createEnvironment = async ({ projectId, actorId, actor, actorOrgId, name, slug }: TCreateEnvDTO) => { const createEnvironment = async ({
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId); projectId,
actorId,
actor,
actorOrgId,
actorAuthMethod,
name,
slug
}: TCreateEnvDTO) => {
const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Create, ProjectPermissionSub.Environments); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Create, ProjectPermissionSub.Environments);
const envs = await projectEnvDAL.find({ projectId }); const envs = await projectEnvDAL.find({ projectId });
@@ -65,11 +79,18 @@ export const projectEnvServiceFactory = ({
actor, actor,
actorId, actorId,
actorOrgId, actorOrgId,
actorAuthMethod,
name, name,
id, id,
position position
}: TUpdateEnvDTO) => { }: TUpdateEnvDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId); const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.Environments); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.Environments);
const oldEnv = await projectEnvDAL.findOne({ id, projectId }); const oldEnv = await projectEnvDAL.findOne({ id, projectId });
@@ -94,8 +115,14 @@ export const projectEnvServiceFactory = ({
return { environment: env, old: oldEnv }; return { environment: env, old: oldEnv };
}; };
const deleteEnvironment = async ({ projectId, actor, actorId, actorOrgId, id }: TDeleteEnvDTO) => { const deleteEnvironment = async ({ projectId, actor, actorId, actorOrgId, actorAuthMethod, id }: TDeleteEnvDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId); const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Delete, ProjectPermissionSub.Environments); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Delete, ProjectPermissionSub.Environments);
const env = await projectEnvDAL.transaction(async (tx) => { const env = await projectEnvDAL.transaction(async (tx) => {
@@ -26,11 +26,18 @@ export const projectKeyServiceFactory = ({
actor, actor,
actorId, actorId,
actorOrgId, actorOrgId,
actorAuthMethod,
projectId, projectId,
nonce, nonce,
encryptedKey encryptedKey
}: TUploadProjectKeyDTO) => { }: TUploadProjectKeyDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId); const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.Member); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.Member);
const receiverMembership = await projectMembershipDAL.findOne({ const receiverMembership = await projectMembershipDAL.findOne({
@@ -46,14 +53,32 @@ export const projectKeyServiceFactory = ({
await projectKeyDAL.create({ projectId, receiverId, encryptedKey, nonce, senderId: actorId }); await projectKeyDAL.create({ projectId, receiverId, encryptedKey, nonce, senderId: actorId });
}; };
const getLatestProjectKey = async ({ actorId, projectId, actor, actorOrgId }: TGetLatestProjectKeyDTO) => { const getLatestProjectKey = async ({
await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId); actorId,
projectId,
actor,
actorOrgId,
actorAuthMethod
}: TGetLatestProjectKeyDTO) => {
await permissionService.getProjectPermission(actor, actorId, projectId, actorAuthMethod, actorOrgId);
const latestKey = await projectKeyDAL.findLatestProjectKey(actorId, projectId); const latestKey = await projectKeyDAL.findLatestProjectKey(actorId, projectId);
return latestKey; return latestKey;
}; };
const getProjectPublicKeys = async ({ actor, actorId, actorOrgId, projectId }: TGetLatestProjectKeyDTO) => { const getProjectPublicKeys = async ({
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId); actor,
actorId,
actorOrgId,
actorAuthMethod,
projectId
}: TGetLatestProjectKeyDTO) => {
const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Member); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Member);
return projectKeyDAL.findAllProjectUserPubKeys(projectId); return projectKeyDAL.findAllProjectUserPubKeys(projectId);
}; };
@@ -67,8 +67,20 @@ export const projectMembershipServiceFactory = ({
projectKeyDAL, projectKeyDAL,
licenseService licenseService
}: TProjectMembershipServiceFactoryDep) => { }: TProjectMembershipServiceFactoryDep) => {
const getProjectMemberships = async ({ actorId, actor, actorOrgId, projectId }: TGetProjectMembershipDTO) => { const getProjectMemberships = async ({
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId); actorId,
actor,
actorOrgId,
actorAuthMethod,
projectId
}: TGetProjectMembershipDTO) => {
const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Member); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Member);
return projectMembershipDAL.findAllProjectMembers(projectId); return projectMembershipDAL.findAllProjectMembers(projectId);
@@ -79,13 +91,20 @@ export const projectMembershipServiceFactory = ({
actorId, actorId,
actor, actor,
actorOrgId, actorOrgId,
actorAuthMethod,
members, members,
sendEmails = true sendEmails = true
}: TAddUsersToWorkspaceDTO) => { }: TAddUsersToWorkspaceDTO) => {
const project = await projectDAL.findById(projectId); const project = await projectDAL.findById(projectId);
if (!project) throw new BadRequestError({ message: "Project not found" }); if (!project) throw new BadRequestError({ message: "Project not found" });
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId); const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Create, ProjectPermissionSub.Member); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Create, ProjectPermissionSub.Member);
const orgMembers = await orgDAL.findMembership({ const orgMembers = await orgDAL.findMembership({
orgId: project.orgId, orgId: project.orgId,
@@ -145,7 +164,9 @@ export const projectMembershipServiceFactory = ({
const addUsersToProjectNonE2EE = async ({ const addUsersToProjectNonE2EE = async ({
projectId, projectId,
actorId, actorId,
actorAuthMethod,
actor, actor,
actorOrgId,
emails, emails,
usernames, usernames,
sendEmails = true sendEmails = true
@@ -157,7 +178,13 @@ export const projectMembershipServiceFactory = ({
throw new BadRequestError({ message: "Please upgrade your project on your dashboard" }); throw new BadRequestError({ message: "Please upgrade your project on your dashboard" });
} }
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Create, ProjectPermissionSub.Member); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Create, ProjectPermissionSub.Member);
const usernamesAndEmails = [...emails, ...usernames]; const usernamesAndEmails = [...emails, ...usernames];
@@ -273,11 +300,18 @@ export const projectMembershipServiceFactory = ({
actorId, actorId,
actor, actor,
actorOrgId, actorOrgId,
actorAuthMethod,
projectId, projectId,
membershipId, membershipId,
roles roles
}: TUpdateProjectMembershipDTO) => { }: TUpdateProjectMembershipDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId); const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.Member); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.Member);
const membershipUser = await userDAL.findUserByProjectMembershipId(membershipId); const membershipUser = await userDAL.findUserByProjectMembershipId(membershipId);
@@ -347,10 +381,17 @@ export const projectMembershipServiceFactory = ({
actorId, actorId,
actor, actor,
actorOrgId, actorOrgId,
actorAuthMethod,
projectId, projectId,
membershipId membershipId
}: TDeleteProjectMembershipOldDTO) => { }: TDeleteProjectMembershipOldDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId); const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Delete, ProjectPermissionSub.Member); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Delete, ProjectPermissionSub.Member);
const member = await userDAL.findUserByProjectMembershipId(membershipId); const member = await userDAL.findUserByProjectMembershipId(membershipId);
@@ -374,11 +415,18 @@ export const projectMembershipServiceFactory = ({
actorId, actorId,
actor, actor,
actorOrgId, actorOrgId,
actorAuthMethod,
projectId, projectId,
emails, emails,
usernames usernames
}: TDeleteProjectMembershipsDTO) => { }: TDeleteProjectMembershipsDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId); const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Delete, ProjectPermissionSub.Member); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Delete, ProjectPermissionSub.Member);
const project = await projectDAL.findById(projectId); const project = await projectDAL.findById(projectId);
@@ -13,7 +13,7 @@ import {
} from "@app/ee/services/permission/project-permission"; } from "@app/ee/services/permission/project-permission";
import { BadRequestError } from "@app/lib/errors"; import { BadRequestError } from "@app/lib/errors";
import { ActorType } from "../auth/auth-type"; import { ActorAuthMethod, ActorType } from "../auth/auth-type";
import { TProjectRoleDALFactory } from "./project-role-dal"; import { TProjectRoleDALFactory } from "./project-role-dal";
type TProjectRoleServiceFactoryDep = { type TProjectRoleServiceFactoryDep = {
@@ -29,9 +29,16 @@ export const projectRoleServiceFactory = ({ projectRoleDAL, permissionService }:
actorId: string, actorId: string,
projectId: string, projectId: string,
data: Omit<TProjectRolesInsert, "projectId">, data: Omit<TProjectRolesInsert, "projectId">,
actorOrgId?: string actorAuthMethod: ActorAuthMethod,
actorOrgId: string | undefined
) => { ) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId); const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Create, ProjectPermissionSub.Role); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Create, ProjectPermissionSub.Role);
const existingRole = await projectRoleDAL.findOne({ slug: data.slug, projectId }); 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: "Duplicate role" });
@@ -49,9 +56,16 @@ export const projectRoleServiceFactory = ({ projectRoleDAL, permissionService }:
projectId: string, projectId: string,
roleId: string, roleId: string,
data: Omit<TOrgRolesUpdate, "orgId">, data: Omit<TOrgRolesUpdate, "orgId">,
actorOrgId?: string actorAuthMethod: ActorAuthMethod,
actorOrgId: string | undefined
) => { ) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId); const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.Role); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.Role);
if (data?.slug) { if (data?.slug) {
const existingRole = await projectRoleDAL.findOne({ slug: data.slug, projectId }); const existingRole = await projectRoleDAL.findOne({ slug: data.slug, projectId });
@@ -71,9 +85,16 @@ export const projectRoleServiceFactory = ({ projectRoleDAL, permissionService }:
actorId: string, actorId: string,
projectId: string, projectId: string,
roleId: string, roleId: string,
actorOrgId?: string actorAuthMethod: ActorAuthMethod,
actorOrgId: string | undefined
) => { ) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId); const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Delete, ProjectPermissionSub.Role); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Delete, ProjectPermissionSub.Role);
const [deletedRole] = await projectRoleDAL.delete({ id: roleId, projectId }); const [deletedRole] = await projectRoleDAL.delete({ id: roleId, projectId });
if (!deletedRole) throw new BadRequestError({ message: "Role not found", name: "Update role" }); if (!deletedRole) throw new BadRequestError({ message: "Role not found", name: "Update role" });
@@ -81,8 +102,20 @@ export const projectRoleServiceFactory = ({ projectRoleDAL, permissionService }:
return deletedRole; return deletedRole;
}; };
const listRoles = async (actor: ActorType, actorId: string, projectId: string, actorOrgId?: string) => { const listRoles = async (
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId); actor: ActorType,
actorId: string,
projectId: string,
actorAuthMethod: ActorAuthMethod,
actorOrgId: string | undefined
) => {
const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Role); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Role);
const customRoles = await projectRoleDAL.find({ projectId }); const customRoles = await projectRoleDAL.find({ projectId });
const roles = [ const roles = [
@@ -135,8 +168,18 @@ export const projectRoleServiceFactory = ({ projectRoleDAL, permissionService }:
return roles; return roles;
}; };
const getUserPermission = async (userId: string, projectId: string, actorOrgId?: string) => { const getUserPermission = async (
const { permission, membership } = await permissionService.getUserProjectPermission(userId, projectId, actorOrgId); userId: string,
projectId: string,
actorAuthMethod: ActorAuthMethod,
actorOrgId: string | undefined
) => {
const { permission, membership } = await permissionService.getUserProjectPermission(
userId,
projectId,
actorAuthMethod,
actorOrgId
);
return { permissions: packRules(permission.rules), membership }; return { permissions: packRules(permission.rules), membership };
}; };
+80 -1
View File
@@ -5,6 +5,8 @@ import { ProjectsSchema, ProjectUpgradeStatus, ProjectVersion, TableName, TProje
import { BadRequestError, DatabaseError } from "@app/lib/errors"; import { BadRequestError, DatabaseError } from "@app/lib/errors";
import { ormify, selectAllTableCols, sqlNestRelationships } from "@app/lib/knex"; import { ormify, selectAllTableCols, sqlNestRelationships } from "@app/lib/knex";
import { Filter, ProjectFilterType } from "./project-types";
export type TProjectDALFactory = ReturnType<typeof projectDALFactory>; export type TProjectDALFactory = ReturnType<typeof projectDALFactory>;
export const projectDALFactory = (db: TDbClient) => { export const projectDALFactory = (db: TDbClient) => {
@@ -139,7 +141,7 @@ export const projectDALFactory = (db: TDbClient) => {
{ column: `${TableName.Project}.name`, order: "asc" }, { column: `${TableName.Project}.name`, order: "asc" },
{ column: `${TableName.Environment}.position`, order: "asc" } { column: `${TableName.Environment}.position`, order: "asc" }
]); ]);
return sqlNestRelationships({ const project = sqlNestRelationships({
data: workspaces, data: workspaces,
key: "id", key: "id",
parentMapper: ({ _id, ...el }) => ({ _id, ...ProjectsSchema.parse(el) }), parentMapper: ({ _id, ...el }) => ({ _id, ...ProjectsSchema.parse(el) }),
@@ -155,11 +157,86 @@ export const projectDALFactory = (db: TDbClient) => {
} }
] ]
})?.[0]; })?.[0];
if (!project) {
throw new BadRequestError({ message: "Project not found" });
}
return project;
} catch (error) { } catch (error) {
throw new DatabaseError({ error, name: "Find all projects" }); throw new DatabaseError({ error, name: "Find all projects" });
} }
}; };
const findProjectBySlug = async (slug: string, orgId: string) => {
try {
const projects = await db(TableName.ProjectMembership)
.where(`${TableName.Project}.slug`, slug)
.where(`${TableName.Project}.orgId`, orgId)
.join(TableName.Project, `${TableName.ProjectMembership}.projectId`, `${TableName.Project}.id`)
.join(TableName.Environment, `${TableName.Environment}.projectId`, `${TableName.Project}.id`)
.select(
selectAllTableCols(TableName.Project),
db.ref("id").withSchema(TableName.Project).as("_id"),
db.ref("id").withSchema(TableName.Environment).as("envId"),
db.ref("slug").withSchema(TableName.Environment).as("envSlug"),
db.ref("name").withSchema(TableName.Environment).as("envName")
)
.orderBy([
{ column: `${TableName.Project}.name`, order: "asc" },
{ column: `${TableName.Environment}.position`, order: "asc" }
]);
const project = sqlNestRelationships({
data: projects,
key: "id",
parentMapper: ({ _id, ...el }) => ({ _id, ...ProjectsSchema.parse(el) }),
childrenMapper: [
{
key: "envId",
label: "environments" as const,
mapper: ({ envId, envSlug, envName: name }) => ({
id: envId,
slug: envSlug,
name
})
}
]
})?.[0];
if (!project) {
throw new BadRequestError({ message: "Project not found" });
}
return project;
} catch (error) {
throw new DatabaseError({ error, name: "Find project by slug" });
}
};
const findProjectByFilter = async (filter: Filter) => {
try {
if (filter.type === ProjectFilterType.ID) {
return await findProjectById(filter.projectId);
}
if (filter.type === ProjectFilterType.SLUG) {
if (!filter.orgId) {
throw new BadRequestError({
message: "Organization ID is required when querying with slugs"
});
}
return await findProjectBySlug(filter.slug, filter.orgId);
}
throw new BadRequestError({ message: "Invalid filter type" });
} catch (error) {
if (error instanceof BadRequestError) {
throw error;
}
throw new DatabaseError({ error, name: `Failed to find project by ${filter.type}` });
}
};
const checkProjectUpgradeStatus = async (projectId: string) => { const checkProjectUpgradeStatus = async (projectId: string) => {
const project = await projectOrm.findById(projectId); const project = await projectOrm.findById(projectId);
const upgradeInProgress = const upgradeInProgress =
@@ -179,6 +256,8 @@ export const projectDALFactory = (db: TDbClient) => {
findAllProjectsByIdentity, findAllProjectsByIdentity,
findProjectGhostUser, findProjectGhostUser,
findProjectById, findProjectById,
findProjectByFilter,
findProjectBySlug,
checkProjectUpgradeStatus checkProjectUpgradeStatus
}; };
}; };
+111 -26
View File
@@ -18,6 +18,7 @@ import { ActorType } from "../auth/auth-type";
import { TIdentityOrgDALFactory } from "../identity/identity-org-dal"; import { TIdentityOrgDALFactory } from "../identity/identity-org-dal";
import { TIdentityProjectDALFactory } from "../identity-project/identity-project-dal"; import { TIdentityProjectDALFactory } from "../identity-project/identity-project-dal";
import { TIdentityProjectMembershipRoleDALFactory } from "../identity-project/identity-project-membership-role-dal"; import { TIdentityProjectMembershipRoleDALFactory } from "../identity-project/identity-project-membership-role-dal";
import { TOrgDALFactory } from "../org/org-dal";
import { TOrgServiceFactory } from "../org/org-service"; import { TOrgServiceFactory } from "../org/org-service";
import { TProjectBotDALFactory } from "../project-bot/project-bot-dal"; import { TProjectBotDALFactory } from "../project-bot/project-bot-dal";
import { TProjectEnvDALFactory } from "../project-env/project-env-dal"; import { TProjectEnvDALFactory } from "../project-env/project-env-dal";
@@ -34,7 +35,9 @@ import {
TCreateProjectDTO, TCreateProjectDTO,
TDeleteProjectDTO, TDeleteProjectDTO,
TGetProjectDTO, TGetProjectDTO,
TToggleProjectAutoCapitalizationDTO,
TUpdateProjectDTO, TUpdateProjectDTO,
TUpdateProjectNameDTO,
TUpgradeProjectDTO TUpgradeProjectDTO
} from "./project-types"; } from "./project-types";
@@ -61,6 +64,7 @@ type TProjectServiceFactoryDep = {
permissionService: TPermissionServiceFactory; permissionService: TPermissionServiceFactory;
orgService: Pick<TOrgServiceFactory, "addGhostUser">; orgService: Pick<TOrgServiceFactory, "addGhostUser">;
licenseService: Pick<TLicenseServiceFactory, "getPlan">; licenseService: Pick<TLicenseServiceFactory, "getPlan">;
orgDAL: Pick<TOrgDALFactory, "findOne">;
}; };
export type TProjectServiceFactory = ReturnType<typeof projectServiceFactory>; export type TProjectServiceFactory = ReturnType<typeof projectServiceFactory>;
@@ -70,6 +74,7 @@ export const projectServiceFactory = ({
projectQueue, projectQueue,
projectKeyDAL, projectKeyDAL,
permissionService, permissionService,
orgDAL,
userDAL, userDAL,
folderDAL, folderDAL,
orgService, orgService,
@@ -86,11 +91,28 @@ export const projectServiceFactory = ({
/* /*
* Create workspace. Make user the admin * Create workspace. Make user the admin
* */ * */
const createProject = async ({ orgId, actor, actorId, actorOrgId, workspaceName, slug }: TCreateProjectDTO) => { const createProject = async ({
orgSlug,
actor,
actorId,
actorOrgId,
actorAuthMethod,
workspaceName,
slug: projectSlug
}: TCreateProjectDTO) => {
if (!orgSlug) {
throw new BadRequestError({
message: "Must provide organization slug to create project"
});
}
const organization = await orgDAL.findOne({ slug: orgSlug });
const { permission, membership: orgMembership } = await permissionService.getOrgPermission( const { permission, membership: orgMembership } = await permissionService.getOrgPermission(
actor, actor,
actorId, actorId,
orgId, organization.id,
actorAuthMethod,
actorOrgId actorOrgId
); );
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Create, OrgPermissionSubjects.Workspace); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Create, OrgPermissionSubjects.Workspace);
@@ -98,7 +120,7 @@ export const projectServiceFactory = ({
const appCfg = getConfig(); const appCfg = getConfig();
const blindIndex = createSecretBlindIndex(appCfg.ROOT_ENCRYPTION_KEY, appCfg.ENCRYPTION_KEY); const blindIndex = createSecretBlindIndex(appCfg.ROOT_ENCRYPTION_KEY, appCfg.ENCRYPTION_KEY);
const plan = await licenseService.getPlan(orgId); const plan = await licenseService.getPlan(organization.id);
if (plan.workspaceLimit !== null && plan.workspacesUsed >= plan.workspaceLimit) { if (plan.workspaceLimit !== null && plan.workspacesUsed >= plan.workspaceLimit) {
// case: limit imposed on number of workspaces allowed // case: limit imposed on number of workspaces allowed
// case: number of workspaces used exceeds the number of workspaces allowed // case: number of workspaces used exceeds the number of workspaces allowed
@@ -108,13 +130,13 @@ export const projectServiceFactory = ({
} }
const results = await projectDAL.transaction(async (tx) => { const results = await projectDAL.transaction(async (tx) => {
const ghostUser = await orgService.addGhostUser(orgId, tx); const ghostUser = await orgService.addGhostUser(organization.id, tx);
const project = await projectDAL.create( const project = await projectDAL.create(
{ {
name: workspaceName, name: workspaceName,
orgId, orgId: organization.id,
slug: slug || slugify(`${workspaceName}-${alphaNumericNanoId(4)}`), slug: projectSlug || slugify(`${workspaceName}-${alphaNumericNanoId(4)}`),
version: ProjectVersion.V2 version: ProjectVersion.V2
}, },
tx tx
@@ -270,7 +292,7 @@ export const projectServiceFactory = ({
// Get the role permission for the identity // Get the role permission for the identity
const { permission: rolePermission, role: customRole } = await permissionService.getOrgPermissionByRole( const { permission: rolePermission, role: customRole } = await permissionService.getOrgPermissionByRole(
ProjectMembershipRole.Admin, ProjectMembershipRole.Admin,
orgId organization.id
); );
const hasPrivilege = isAtLeastAsPrivileged(permission, rolePermission); const hasPrivilege = isAtLeastAsPrivileged(permission, rolePermission);
@@ -310,20 +332,28 @@ export const projectServiceFactory = ({
return results; return results;
}; };
const deleteProject = async ({ actor, actorId, actorOrgId, projectId }: TDeleteProjectDTO) => { const deleteProject = async ({ actor, actorId, actorOrgId, actorAuthMethod, filter }: TDeleteProjectDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId); const project = await projectDAL.findProjectByFilter(filter);
const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
project.id,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Delete, ProjectPermissionSub.Project); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Delete, ProjectPermissionSub.Project);
const deletedProject = await projectDAL.transaction(async (tx) => { const deletedProject = await projectDAL.transaction(async (tx) => {
const project = await projectDAL.deleteById(projectId, tx); const delProject = await projectDAL.deleteById(project.id, tx);
const projectGhostUser = await projectMembershipDAL.findProjectGhostUser(projectId).catch(() => null); const projectGhostUser = await projectMembershipDAL.findProjectGhostUser(project.id).catch(() => null);
// Delete the org membership for the ghost user if it's found. // Delete the org membership for the ghost user if it's found.
if (projectGhostUser) { if (projectGhostUser) {
await userDAL.deleteById(projectGhostUser.id, tx); await userDAL.deleteById(projectGhostUser.id, tx);
} }
return project; return delProject;
}); });
return deletedProject; return deletedProject;
@@ -334,16 +364,26 @@ export const projectServiceFactory = ({
return workspaces; return workspaces;
}; };
const getAProject = async ({ actorId, actorOrgId, projectId, actor }: TGetProjectDTO) => { const getAProject = async ({ actorId, actorOrgId, actorAuthMethod, filter, actor }: TGetProjectDTO) => {
await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId); const project = await projectDAL.findProjectByFilter(filter);
return projectDAL.findProjectById(projectId);
await permissionService.getProjectPermission(actor, actorId, project.id, actorAuthMethod, actorOrgId);
return project;
}; };
const updateProject = async ({ projectId, actor, actorId, actorOrgId, update }: TUpdateProjectDTO) => { const updateProject = async ({ actor, actorId, actorOrgId, actorAuthMethod, update, filter }: TUpdateProjectDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId); const project = await projectDAL.findProjectByFilter(filter);
const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
project.id,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.Settings); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.Settings);
const updatedProject = await projectDAL.updateById(projectId, { const updatedProject = await projectDAL.updateById(project.id, {
name: update.name, name: update.name,
autoCapitalization: update.autoCapitalization autoCapitalization: update.autoCapitalization
}); });
@@ -355,25 +395,58 @@ export const projectServiceFactory = ({
actor, actor,
actorId, actorId,
actorOrgId, actorOrgId,
actorAuthMethod,
autoCapitalization autoCapitalization
}: TGetProjectDTO & { autoCapitalization: boolean }) => { }: TToggleProjectAutoCapitalizationDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId); const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.Settings); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.Settings);
const updatedProject = await projectDAL.updateById(projectId, { autoCapitalization }); const updatedProject = await projectDAL.updateById(projectId, { autoCapitalization });
return updatedProject; return updatedProject;
}; };
const updateName = async ({ projectId, actor, actorId, actorOrgId, name }: TGetProjectDTO & { name: string }) => { const updateName = async ({
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId); projectId,
actor,
actorId,
actorOrgId,
actorAuthMethod,
name
}: TUpdateProjectNameDTO) => {
const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.Settings); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.Settings);
const updatedProject = await projectDAL.updateById(projectId, { name }); const updatedProject = await projectDAL.updateById(projectId, { name });
return updatedProject; return updatedProject;
}; };
const upgradeProject = async ({ projectId, actor, actorId, userPrivateKey }: TUpgradeProjectDTO) => { const upgradeProject = async ({
const { permission, hasRole } = await permissionService.getProjectPermission(actor, actorId, projectId); projectId,
actor,
actorId,
actorAuthMethod,
actorOrgId,
userPrivateKey
}: TUpgradeProjectDTO) => {
const { permission, hasRole } = await permissionService.getProjectPermission(
actor,
actorId,
projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Delete, ProjectPermissionSub.Project); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Delete, ProjectPermissionSub.Project);
@@ -397,8 +470,20 @@ export const projectServiceFactory = ({
}); });
}; };
const getProjectUpgradeStatus = async ({ projectId, actor, actorId }: TProjectPermission) => { const getProjectUpgradeStatus = async ({
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); projectId,
actor,
actorAuthMethod,
actorOrgId,
actorId
}: TProjectPermission) => {
const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Secrets); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Secrets);
const project = await projectDAL.findProjectById(projectId); const project = await projectDAL.findProjectById(projectId);
+41 -11
View File
@@ -1,37 +1,67 @@
import { ProjectMembershipRole, TProjectKeys } from "@app/db/schemas"; import { ProjectMembershipRole, TProjectKeys } from "@app/db/schemas";
import { TProjectPermission } from "@app/lib/types"; import { TProjectPermission } from "@app/lib/types";
import { ActorType } from "../auth/auth-type"; import { ActorAuthMethod, ActorType } from "../auth/auth-type";
export enum ProjectFilterType {
ID = "id",
SLUG = "slug"
}
export type Filter =
| {
type: ProjectFilterType.ID;
projectId: string;
}
| {
type: ProjectFilterType.SLUG;
slug: string;
orgId: string | undefined;
};
export type TCreateProjectDTO = { export type TCreateProjectDTO = {
actor: ActorType; actor: ActorType;
actorAuthMethod: ActorAuthMethod;
actorId: string; actorId: string;
actorOrgId?: string; actorOrgId?: string;
orgId: string; orgSlug: string;
workspaceName: string; workspaceName: string;
slug?: string; slug?: string;
}; };
export type TDeleteProjectDTO = { export type TDeleteProjectBySlugDTO = {
slug: string;
actor: ActorType; actor: ActorType;
actorId: string; actorId: string;
actorOrgId?: string; actorOrgId: string | undefined;
projectId: string;
}; };
export type TGetProjectDTO = { export type TGetProjectDTO = {
actor: ActorType; filter: Filter;
actorId: string; } & Omit<TProjectPermission, "projectId">;
actorOrgId?: string;
projectId: string; export type TToggleProjectAutoCapitalizationDTO = {
}; autoCapitalization: boolean;
} & TProjectPermission;
export type TUpdateProjectNameDTO = {
name: string;
} & TProjectPermission;
export type TUpdateProjectDTO = { export type TUpdateProjectDTO = {
filter: Filter;
update: { update: {
name?: string; name?: string;
autoCapitalization?: boolean; autoCapitalization?: boolean;
}; };
} & TProjectPermission; } & Omit<TProjectPermission, "projectId">;
export type TDeleteProjectDTO = {
filter: Filter;
actor: ActorType;
actorId: string;
actorOrgId: string | undefined;
} & Omit<TProjectPermission, "projectId">;
export type TUpgradeProjectDTO = { export type TUpgradeProjectDTO = {
userPrivateKey: string; userPrivateKey: string;
@@ -28,16 +28,29 @@ export const secretBlindIndexServiceFactory = ({
actor, actor,
projectId, projectId,
actorId, actorId,
actorAuthMethod,
actorOrgId actorOrgId
}: TGetProjectBlindIndexStatusDTO) => { }: TGetProjectBlindIndexStatusDTO) => {
await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId); await permissionService.getProjectPermission(actor, actorId, projectId, actorAuthMethod, actorOrgId);
const secretCount = await secretBlindIndexDAL.countOfSecretsWithNullSecretBlindIndex(projectId); const secretCount = await secretBlindIndexDAL.countOfSecretsWithNullSecretBlindIndex(projectId);
return Number(secretCount); return Number(secretCount);
}; };
const getProjectSecrets = async ({ projectId, actorId, actor }: TGetProjectSecretsDTO) => { const getProjectSecrets = async ({
const { hasRole } = await permissionService.getProjectPermission(actor, actorId, projectId); projectId,
actorId,
actorAuthMethod,
actorOrgId,
actor
}: TGetProjectSecretsDTO) => {
const { hasRole } = await permissionService.getProjectPermission(
actor,
actorId,
projectId,
actorAuthMethod,
actorOrgId
);
if (!hasRole(ProjectMembershipRole.Admin)) { if (!hasRole(ProjectMembershipRole.Admin)) {
throw new UnauthorizedError({ message: "User must be admin" }); throw new UnauthorizedError({ message: "User must be admin" });
} }
@@ -50,10 +63,17 @@ export const secretBlindIndexServiceFactory = ({
projectId, projectId,
actor, actor,
actorId, actorId,
actorAuthMethod,
actorOrgId, actorOrgId,
secretsToUpdate secretsToUpdate
}: TUpdateProjectSecretNameDTO) => { }: TUpdateProjectSecretNameDTO) => {
const { hasRole } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId); const { hasRole } = await permissionService.getProjectPermission(
actor,
actorId,
projectId,
actorAuthMethod,
actorOrgId
);
if (!hasRole(ProjectMembershipRole.Admin)) { if (!hasRole(ProjectMembershipRole.Admin)) {
throw new UnauthorizedError({ message: "User must be admin" }); throw new UnauthorizedError({ message: "User must be admin" });
} }
@@ -34,12 +34,19 @@ export const secretFolderServiceFactory = ({
projectId, projectId,
actor, actor,
actorId, actorId,
actorAuthMethod,
actorOrgId, actorOrgId,
name, name,
environment, environment,
path: secretPath path: secretPath
}: TCreateFolderDTO) => { }: TCreateFolderDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId); const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Create, ProjectPermissionActions.Create,
subject(ProjectPermissionSub.Secrets, { environment, secretPath }) subject(ProjectPermissionSub.Secrets, { environment, secretPath })
@@ -114,12 +121,19 @@ export const secretFolderServiceFactory = ({
actor, actor,
actorId, actorId,
actorOrgId, actorOrgId,
actorAuthMethod,
name, name,
environment, environment,
path: secretPath, path: secretPath,
id id
}: TUpdateFolderDTO) => { }: TUpdateFolderDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId); const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Edit, ProjectPermissionActions.Edit,
subject(ProjectPermissionSub.Secrets, { environment, secretPath }) subject(ProjectPermissionSub.Secrets, { environment, secretPath })
@@ -162,11 +176,18 @@ export const secretFolderServiceFactory = ({
actor, actor,
actorId, actorId,
actorOrgId, actorOrgId,
actorAuthMethod,
environment, environment,
path: secretPath, path: secretPath,
idOrName idOrName
}: TDeleteFolderDTO) => { }: TDeleteFolderDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId); const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Delete, ProjectPermissionActions.Delete,
subject(ProjectPermissionSub.Secrets, { environment, secretPath }) subject(ProjectPermissionSub.Secrets, { environment, secretPath })
@@ -196,12 +217,13 @@ export const secretFolderServiceFactory = ({
actor, actor,
actorId, actorId,
actorOrgId, actorOrgId,
actorAuthMethod,
environment, environment,
path: secretPath path: secretPath
}: TGetFolderDTO) => { }: TGetFolderDTO) => {
// folder list is allowed to be read by anyone // folder list is allowed to be read by anyone
// permission to check does user has access // permission to check does user has access
await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId); await permissionService.getProjectPermission(actor, actorId, projectId, actorAuthMethod, actorOrgId);
const env = await projectEnvDAL.findOne({ projectId, slug: environment }); const env = await projectEnvDAL.findOne({ projectId, slug: environment });
if (!env) throw new BadRequestError({ message: "Environment not found", name: "get folders" }); if (!env) throw new BadRequestError({ message: "Environment not found", name: "get folders" });
@@ -45,10 +45,17 @@ export const secretImportServiceFactory = ({
actor, actor,
actorId, actorId,
actorOrgId, actorOrgId,
actorAuthMethod,
projectId, projectId,
path path
}: TCreateSecretImportDTO) => { }: TCreateSecretImportDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId); const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
projectId,
actorAuthMethod,
actorOrgId
);
// check if user has permission to import into destination path // check if user has permission to import into destination path
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
@@ -97,10 +104,17 @@ export const secretImportServiceFactory = ({
actor, actor,
actorId, actorId,
actorOrgId, actorOrgId,
actorAuthMethod,
data, data,
id id
}: TUpdateSecretImportDTO) => { }: TUpdateSecretImportDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId); const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Edit, ProjectPermissionActions.Edit,
subject(ProjectPermissionSub.Secrets, { environment, secretPath: path }) subject(ProjectPermissionSub.Secrets, { environment, secretPath: path })
@@ -144,9 +158,16 @@ export const secretImportServiceFactory = ({
actor, actor,
actorId, actorId,
actorOrgId, actorOrgId,
actorAuthMethod,
id id
}: TDeleteSecretImportDTO) => { }: TDeleteSecretImportDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId); const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Delete, ProjectPermissionActions.Delete,
subject(ProjectPermissionSub.Secrets, { environment, secretPath: path }) subject(ProjectPermissionSub.Secrets, { environment, secretPath: path })
@@ -167,8 +188,22 @@ export const secretImportServiceFactory = ({
return secImport; return secImport;
}; };
const getImports = async ({ path, environment, projectId, actor, actorId, actorOrgId }: TGetSecretImportsDTO) => { const getImports = async ({
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId); path,
environment,
projectId,
actor,
actorId,
actorAuthMethod,
actorOrgId
}: TGetSecretImportsDTO) => {
const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Read, ProjectPermissionActions.Read,
subject(ProjectPermissionSub.Secrets, { environment, secretPath: path }) subject(ProjectPermissionSub.Secrets, { environment, secretPath: path })
@@ -186,10 +221,17 @@ export const secretImportServiceFactory = ({
environment, environment,
projectId, projectId,
actor, actor,
actorAuthMethod,
actorId, actorId,
actorOrgId actorOrgId
}: TGetSecretsFromImportDTO) => { }: TGetSecretsFromImportDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId); const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Read, ProjectPermissionActions.Read,
subject(ProjectPermissionSub.Secrets, { environment, secretPath: path }) subject(ProjectPermissionSub.Secrets, { environment, secretPath: path })
@@ -15,8 +15,23 @@ type TSecretTagServiceFactoryDep = {
export type TSecretTagServiceFactory = ReturnType<typeof secretTagServiceFactory>; export type TSecretTagServiceFactory = ReturnType<typeof secretTagServiceFactory>;
export const secretTagServiceFactory = ({ secretTagDAL, permissionService }: TSecretTagServiceFactoryDep) => { export const secretTagServiceFactory = ({ secretTagDAL, permissionService }: TSecretTagServiceFactoryDep) => {
const createTag = async ({ name, slug, actor, color, actorId, actorOrgId, projectId }: TCreateTagDTO) => { const createTag = async ({
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId); name,
slug,
actor,
color,
actorId,
actorOrgId,
actorAuthMethod,
projectId
}: TCreateTagDTO) => {
const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Create, ProjectPermissionSub.Tags); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Create, ProjectPermissionSub.Tags);
const existingTag = await secretTagDAL.findOne({ slug, projectId }); const existingTag = await secretTagDAL.findOne({ slug, projectId });
@@ -32,19 +47,31 @@ export const secretTagServiceFactory = ({ secretTagDAL, permissionService }: TSe
return newTag; return newTag;
}; };
const deleteTag = async ({ actorId, actor, actorOrgId, id }: TDeleteTagDTO) => { const deleteTag = async ({ actorId, actor, actorOrgId, actorAuthMethod, id }: TDeleteTagDTO) => {
const tag = await secretTagDAL.findById(id); const tag = await secretTagDAL.findById(id);
if (!tag) throw new BadRequestError({ message: "Tag doesn't exist" }); if (!tag) throw new BadRequestError({ message: "Tag doesn't exist" });
const { permission } = await permissionService.getProjectPermission(actor, actorId, tag.projectId, actorOrgId); const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
tag.projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Delete, ProjectPermissionSub.Tags); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Delete, ProjectPermissionSub.Tags);
const deletedTag = await secretTagDAL.deleteById(tag.id); const deletedTag = await secretTagDAL.deleteById(tag.id);
return deletedTag; return deletedTag;
}; };
const getProjectTags = async ({ actor, actorId, actorOrgId, projectId }: TListProjectTagsDTO) => { const getProjectTags = async ({ actor, actorId, actorOrgId, actorAuthMethod, projectId }: TListProjectTagsDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId); const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Tags); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Tags);
const tags = await secretTagDAL.find({ projectId }, { sort: [["createdAt", "asc"]] }); const tags = await secretTagDAL.find({ projectId }, { sort: [["createdAt", "asc"]] });
+83 -10
View File
@@ -145,10 +145,17 @@ export const secretServiceFactory = ({
actorId, actorId,
actorOrgId, actorOrgId,
environment, environment,
actorAuthMethod,
projectId, projectId,
...inputSecret ...inputSecret
}: TCreateSecretDTO) => { }: TCreateSecretDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId); const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Create, ProjectPermissionActions.Create,
subject(ProjectPermissionSub.Secrets, { environment, secretPath: path }) subject(ProjectPermissionSub.Secrets, { environment, secretPath: path })
@@ -230,10 +237,17 @@ export const secretServiceFactory = ({
actorId, actorId,
actorOrgId, actorOrgId,
environment, environment,
actorAuthMethod,
projectId, projectId,
...inputSecret ...inputSecret
}: TUpdateSecretDTO) => { }: TUpdateSecretDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId); const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Edit, ProjectPermissionActions.Edit,
subject(ProjectPermissionSub.Secrets, { environment, secretPath: path }) subject(ProjectPermissionSub.Secrets, { environment, secretPath: path })
@@ -341,11 +355,18 @@ export const secretServiceFactory = ({
actor, actor,
actorId, actorId,
actorOrgId, actorOrgId,
actorAuthMethod,
environment, environment,
projectId, projectId,
...inputSecret ...inputSecret
}: TDeleteSecretDTO) => { }: TDeleteSecretDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId); const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Delete, ProjectPermissionActions.Delete,
subject(ProjectPermissionSub.Secrets, { environment, secretPath: path }) subject(ProjectPermissionSub.Secrets, { environment, secretPath: path })
@@ -401,9 +422,16 @@ export const secretServiceFactory = ({
projectId, projectId,
actor, actor,
actorOrgId, actorOrgId,
actorAuthMethod,
includeImports includeImports
}: TGetSecretsDTO) => { }: TGetSecretsDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId); const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Read, ProjectPermissionActions.Read,
subject(ProjectPermissionSub.Secrets, { environment, secretPath: path }) subject(ProjectPermissionSub.Secrets, { environment, secretPath: path })
@@ -445,6 +473,7 @@ export const secretServiceFactory = ({
actorId, actorId,
actor, actor,
actorOrgId, actorOrgId,
actorAuthMethod,
projectId, projectId,
environment, environment,
path, path,
@@ -453,7 +482,13 @@ export const secretServiceFactory = ({
version, version,
includeImports includeImports
}: TGetASecretDTO) => { }: TGetASecretDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId); const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Read, ProjectPermissionActions.Read,
subject(ProjectPermissionSub.Secrets, { environment, secretPath: path }) subject(ProjectPermissionSub.Secrets, { environment, secretPath: path })
@@ -534,12 +569,19 @@ export const secretServiceFactory = ({
path, path,
actor, actor,
actorId, actorId,
actorAuthMethod,
actorOrgId, actorOrgId,
environment, environment,
projectId, projectId,
secrets: inputSecrets secrets: inputSecrets
}: TCreateBulkSecretDTO) => { }: TCreateBulkSecretDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId); const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Create, ProjectPermissionActions.Create,
subject(ProjectPermissionSub.Secrets, { environment, secretPath: path }) subject(ProjectPermissionSub.Secrets, { environment, secretPath: path })
@@ -597,11 +639,18 @@ export const secretServiceFactory = ({
actor, actor,
actorId, actorId,
actorOrgId, actorOrgId,
actorAuthMethod,
environment, environment,
projectId, projectId,
secrets: inputSecrets secrets: inputSecrets
}: TUpdateBulkSecretDTO) => { }: TUpdateBulkSecretDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId); const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Create, ProjectPermissionActions.Create,
subject(ProjectPermissionSub.Secrets, { environment, secretPath: path }) subject(ProjectPermissionSub.Secrets, { environment, secretPath: path })
@@ -678,9 +727,16 @@ export const secretServiceFactory = ({
projectId, projectId,
actor, actor,
actorId, actorId,
actorAuthMethod,
actorOrgId actorOrgId
}: TDeleteBulkSecretDTO) => { }: TDeleteBulkSecretDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId); const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Create, ProjectPermissionActions.Create,
subject(ProjectPermissionSub.Secrets, { environment, secretPath: path }) subject(ProjectPermissionSub.Secrets, { environment, secretPath: path })
@@ -728,6 +784,7 @@ export const secretServiceFactory = ({
actor, actor,
actorId, actorId,
actorOrgId, actorOrgId,
actorAuthMethod,
environment, environment,
includeImports includeImports
}: TGetSecretsRawDTO) => { }: TGetSecretsRawDTO) => {
@@ -740,6 +797,7 @@ export const secretServiceFactory = ({
environment, environment,
actor, actor,
actorOrgId, actorOrgId,
actorAuthMethod,
path, path,
includeImports includeImports
}); });
@@ -763,6 +821,7 @@ export const secretServiceFactory = ({
projectId, projectId,
actorId, actorId,
actorOrgId, actorOrgId,
actorAuthMethod,
secretName, secretName,
includeImports, includeImports,
version version
@@ -773,6 +832,7 @@ export const secretServiceFactory = ({
const secret = await getSecretByName({ const secret = await getSecretByName({
actorId, actorId,
projectId, projectId,
actorAuthMethod,
environment, environment,
actor, actor,
actorOrgId, actorOrgId,
@@ -792,6 +852,7 @@ export const secretServiceFactory = ({
environment, environment,
actor, actor,
actorOrgId, actorOrgId,
actorAuthMethod,
type, type,
secretPath, secretPath,
secretValue, secretValue,
@@ -813,6 +874,7 @@ export const secretServiceFactory = ({
path: secretPath, path: secretPath,
actor, actor,
actorId, actorId,
actorAuthMethod,
actorOrgId, actorOrgId,
secretKeyCiphertext: secretKeyEncrypted.ciphertext, secretKeyCiphertext: secretKeyEncrypted.ciphertext,
secretKeyIV: secretKeyEncrypted.iv, secretKeyIV: secretKeyEncrypted.iv,
@@ -839,6 +901,7 @@ export const secretServiceFactory = ({
environment, environment,
actor, actor,
actorOrgId, actorOrgId,
actorAuthMethod,
type, type,
secretPath, secretPath,
secretValue, secretValue,
@@ -858,6 +921,7 @@ export const secretServiceFactory = ({
actor, actor,
actorId, actorId,
actorOrgId, actorOrgId,
actorAuthMethod,
secretValueCiphertext: secretValueEncrypted.ciphertext, secretValueCiphertext: secretValueEncrypted.ciphertext,
secretValueIV: secretValueEncrypted.iv, secretValueIV: secretValueEncrypted.iv,
secretValueTag: secretValueEncrypted.tag, secretValueTag: secretValueEncrypted.tag,
@@ -877,6 +941,7 @@ export const secretServiceFactory = ({
environment, environment,
actor, actor,
actorOrgId, actorOrgId,
actorAuthMethod,
type, type,
secretPath secretPath
}: TDeleteSecretRawDTO) => { }: TDeleteSecretRawDTO) => {
@@ -891,7 +956,8 @@ export const secretServiceFactory = ({
path: secretPath, path: secretPath,
actor, actor,
actorId, actorId,
actorOrgId actorOrgId,
actorAuthMethod
}); });
await snapshotService.performSnapshot(secret.folderId); await snapshotService.performSnapshot(secret.folderId);
@@ -904,6 +970,7 @@ export const secretServiceFactory = ({
actorId, actorId,
actor, actor,
actorOrgId, actorOrgId,
actorAuthMethod,
limit = 20, limit = 20,
offset = 0, offset = 0,
secretId secretId
@@ -914,7 +981,13 @@ export const secretServiceFactory = ({
const folder = await folderDAL.findById(secret.folderId); const folder = await folderDAL.findById(secret.folderId);
if (!folder) throw new BadRequestError({ message: "Failed to find secret" }); if (!folder) throw new BadRequestError({ message: "Failed to find secret" });
const { permission } = await permissionService.getProjectPermission(actor, actorId, folder.projectId, actorOrgId); const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
folder.projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.SecretRollback); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.SecretRollback);
const secretVersions = await secretVersionDAL.find({ secretId }, { offset, limit, sort: [["createdAt", "desc"]] }); const secretVersions = await secretVersionDAL.find({ secretId }, { offset, limit, sort: [["createdAt", "desc"]] });
@@ -9,6 +9,7 @@ import { getConfig } from "@app/lib/config/env";
import { BadRequestError, UnauthorizedError } from "@app/lib/errors"; import { BadRequestError, UnauthorizedError } from "@app/lib/errors";
import { ActorType } from "../auth/auth-type"; import { ActorType } from "../auth/auth-type";
import { TProjectDALFactory } from "../project/project-dal";
import { TProjectEnvDALFactory } from "../project-env/project-env-dal"; import { TProjectEnvDALFactory } from "../project-env/project-env-dal";
import { TUserDALFactory } from "../user/user-dal"; import { TUserDALFactory } from "../user/user-dal";
import { TServiceTokenDALFactory } from "./service-token-dal"; import { TServiceTokenDALFactory } from "./service-token-dal";
@@ -24,6 +25,7 @@ type TServiceTokenServiceFactoryDep = {
userDAL: TUserDALFactory; userDAL: TUserDALFactory;
permissionService: Pick<TPermissionServiceFactory, "getProjectPermission">; permissionService: Pick<TPermissionServiceFactory, "getProjectPermission">;
projectEnvDAL: Pick<TProjectEnvDALFactory, "findBySlugs">; projectEnvDAL: Pick<TProjectEnvDALFactory, "findBySlugs">;
projectDAL: Pick<TProjectDALFactory, "findById">;
}; };
export type TServiceTokenServiceFactory = ReturnType<typeof serviceTokenServiceFactory>; export type TServiceTokenServiceFactory = ReturnType<typeof serviceTokenServiceFactory>;
@@ -32,7 +34,8 @@ export const serviceTokenServiceFactory = ({
serviceTokenDAL, serviceTokenDAL,
userDAL, userDAL,
permissionService, permissionService,
projectEnvDAL projectEnvDAL,
projectDAL
}: TServiceTokenServiceFactoryDep) => { }: TServiceTokenServiceFactoryDep) => {
const createServiceToken = async ({ const createServiceToken = async ({
iv, iv,
@@ -40,6 +43,7 @@ export const serviceTokenServiceFactory = ({
name, name,
actor, actor,
actorOrgId, actorOrgId,
actorAuthMethod,
scopes, scopes,
actorId, actorId,
projectId, projectId,
@@ -47,7 +51,13 @@ export const serviceTokenServiceFactory = ({
permissions, permissions,
encryptedKey encryptedKey
}: TCreateServiceTokenDTO) => { }: TCreateServiceTokenDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId); const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Create, ProjectPermissionSub.ServiceTokens); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Create, ProjectPermissionSub.ServiceTokens);
scopes.forEach(({ environment, secretPath }) => { scopes.forEach(({ environment, secretPath }) => {
@@ -91,7 +101,7 @@ export const serviceTokenServiceFactory = ({
return { token, serviceToken }; return { token, serviceToken };
}; };
const deleteServiceToken = async ({ actorId, actor, actorOrgId, id }: TDeleteServiceTokenDTO) => { const deleteServiceToken = async ({ actorId, actor, actorOrgId, actorAuthMethod, id }: TDeleteServiceTokenDTO) => {
const serviceToken = await serviceTokenDAL.findById(id); const serviceToken = await serviceTokenDAL.findById(id);
if (!serviceToken) throw new BadRequestError({ message: "Token not found" }); if (!serviceToken) throw new BadRequestError({ message: "Token not found" });
@@ -99,6 +109,7 @@ export const serviceTokenServiceFactory = ({
actor, actor,
actorId, actorId,
serviceToken.projectId, serviceToken.projectId,
actorAuthMethod,
actorOrgId actorOrgId
); );
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Delete, ProjectPermissionSub.ServiceTokens); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Delete, ProjectPermissionSub.ServiceTokens);
@@ -119,8 +130,20 @@ export const serviceTokenServiceFactory = ({
return { serviceToken, user: serviceTokenUser }; return { serviceToken, user: serviceTokenUser };
}; };
const getProjectServiceTokens = async ({ actorId, actor, actorOrgId, projectId }: TProjectServiceTokensDTO) => { const getProjectServiceTokens = async ({
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId); actorId,
actor,
actorOrgId,
actorAuthMethod,
projectId
}: TProjectServiceTokensDTO) => {
const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.ServiceTokens); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.ServiceTokens);
const tokens = await serviceTokenDAL.find({ projectId }, { sort: [["createdAt", "desc"]] }); const tokens = await serviceTokenDAL.find({ projectId }, { sort: [["createdAt", "desc"]] });
@@ -130,7 +153,11 @@ export const serviceTokenServiceFactory = ({
const fnValidateServiceToken = async (token: string) => { const fnValidateServiceToken = async (token: string) => {
const [, TOKEN_IDENTIFIER, TOKEN_SECRET] = <[string, string, string]>token.split(".", 3); const [, TOKEN_IDENTIFIER, TOKEN_SECRET] = <[string, string, string]>token.split(".", 3);
const serviceToken = await serviceTokenDAL.findById(TOKEN_IDENTIFIER); const serviceToken = await serviceTokenDAL.findById(TOKEN_IDENTIFIER);
if (!serviceToken) throw new UnauthorizedError(); if (!serviceToken) throw new UnauthorizedError();
const project = await projectDAL.findById(serviceToken.projectId);
if (!project) throw new UnauthorizedError({ message: "Service token project not found" });
if (serviceToken.expiresAt && new Date(serviceToken.expiresAt) < new Date()) { if (serviceToken.expiresAt && new Date(serviceToken.expiresAt) < new Date()) {
await serviceTokenDAL.deleteById(serviceToken.id); await serviceTokenDAL.deleteById(serviceToken.id);
@@ -142,7 +169,8 @@ export const serviceTokenServiceFactory = ({
const updatedToken = await serviceTokenDAL.updateById(serviceToken.id, { const updatedToken = await serviceTokenDAL.updateById(serviceToken.id, {
lastUsed: new Date() lastUsed: new Date()
}); });
return { ...serviceToken, lastUsed: updatedToken.lastUsed };
return { ...serviceToken, lastUsed: updatedToken.lastUsed, orgId: project.orgId };
}; };
return { return {
@@ -136,6 +136,7 @@ export const superAdminServiceFactory = ({
await updateServerCfg({ initialized: true }); await updateServerCfg({ initialized: true });
const token = await authService.generateUserTokens({ const token = await authService.generateUserTokens({
user: userInfo.user, user: userInfo.user,
authMethod: AuthMethod.EMAIL,
ip, ip,
userAgent, userAgent,
organizationId: undefined organizationId: undefined
@@ -31,13 +31,20 @@ export const webhookServiceFactory = ({ webhookDAL, projectEnvDAL, permissionSer
actor, actor,
actorId, actorId,
actorOrgId, actorOrgId,
actorAuthMethod,
projectId, projectId,
webhookUrl, webhookUrl,
environment, environment,
secretPath, secretPath,
webhookSecretKey webhookSecretKey
}: TCreateWebhookDTO) => { }: TCreateWebhookDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId); const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Create, ProjectPermissionSub.Webhooks); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Create, ProjectPermissionSub.Webhooks);
const env = await projectEnvDAL.findOne({ projectId, slug: environment }); const env = await projectEnvDAL.findOne({ projectId, slug: environment });
if (!env) throw new BadRequestError({ message: "Env not found" }); if (!env) throw new BadRequestError({ message: "Env not found" });
@@ -73,33 +80,51 @@ export const webhookServiceFactory = ({ webhookDAL, projectEnvDAL, permissionSer
return { ...webhook, projectId, environment: env }; return { ...webhook, projectId, environment: env };
}; };
const updateWebhook = async ({ actorId, actor, actorOrgId, id, isDisabled }: TUpdateWebhookDTO) => { const updateWebhook = async ({ actorId, actor, actorOrgId, actorAuthMethod, id, isDisabled }: TUpdateWebhookDTO) => {
const webhook = await webhookDAL.findById(id); const webhook = await webhookDAL.findById(id);
if (!webhook) throw new BadRequestError({ message: "Webhook not found" }); if (!webhook) throw new BadRequestError({ message: "Webhook not found" });
const { permission } = await permissionService.getProjectPermission(actor, actorId, webhook.projectId, actorOrgId); const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
webhook.projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.Webhooks); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.Webhooks);
const updatedWebhook = await webhookDAL.updateById(id, { isDisabled }); const updatedWebhook = await webhookDAL.updateById(id, { isDisabled });
return { ...webhook, ...updatedWebhook }; return { ...webhook, ...updatedWebhook };
}; };
const deleteWebhook = async ({ id, actor, actorId, actorOrgId }: TDeleteWebhookDTO) => { const deleteWebhook = async ({ id, actor, actorId, actorAuthMethod, actorOrgId }: TDeleteWebhookDTO) => {
const webhook = await webhookDAL.findById(id); const webhook = await webhookDAL.findById(id);
if (!webhook) throw new BadRequestError({ message: "Webhook not found" }); if (!webhook) throw new BadRequestError({ message: "Webhook not found" });
const { permission } = await permissionService.getProjectPermission(actor, actorId, webhook.projectId, actorOrgId); const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
webhook.projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Delete, ProjectPermissionSub.Webhooks); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Delete, ProjectPermissionSub.Webhooks);
const deletedWebhook = await webhookDAL.deleteById(id); const deletedWebhook = await webhookDAL.deleteById(id);
return { ...webhook, ...deletedWebhook }; return { ...webhook, ...deletedWebhook };
}; };
const testWebhook = async ({ id, actor, actorId, actorOrgId }: TTestWebhookDTO) => { const testWebhook = async ({ id, actor, actorId, actorAuthMethod, actorOrgId }: TTestWebhookDTO) => {
const webhook = await webhookDAL.findById(id); const webhook = await webhookDAL.findById(id);
if (!webhook) throw new BadRequestError({ message: "Webhook not found" }); if (!webhook) throw new BadRequestError({ message: "Webhook not found" });
const { permission } = await permissionService.getProjectPermission(actor, actorId, webhook.projectId, actorOrgId); const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
webhook.projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Webhooks); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Webhooks);
let webhookError: string | undefined; let webhookError: string | undefined;
@@ -119,8 +144,22 @@ export const webhookServiceFactory = ({ webhookDAL, projectEnvDAL, permissionSer
return { ...webhook, ...updatedWebhook }; return { ...webhook, ...updatedWebhook };
}; };
const listWebhooks = async ({ actorId, actor, actorOrgId, projectId, secretPath, environment }: TListWebhookDTO) => { const listWebhooks = async ({
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId); actorId,
actor,
actorOrgId,
actorAuthMethod,
projectId,
secretPath,
environment
}: TListWebhookDTO) => {
const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Webhooks); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Webhooks);
return webhookDAL.findAllWebhooks(projectId, environment, secretPath); return webhookDAL.findAllWebhooks(projectId, environment, secretPath);
+22
View File
@@ -164,6 +164,28 @@ func CallGetAllOrganizations(httpClient *resty.Client) (GetOrganizationsResponse
return orgResponse, nil return orgResponse, nil
} }
func CallSelectOrganization(httpClient *resty.Client, request SelectOrganizationRequest) (SelectOrganizationResponse, error) {
var selectOrgResponse SelectOrganizationResponse
response, err := httpClient.
R().
SetBody(request).
SetResult(&selectOrgResponse).
SetHeader("User-Agent", USER_AGENT).
Post(fmt.Sprintf("%v/v3/auth/select-organization", config.INFISICAL_URL))
if err != nil {
return SelectOrganizationResponse{}, err
}
if response.IsError() {
return SelectOrganizationResponse{}, fmt.Errorf("CallSelectOrganization: Unsuccessful response: [response=%v]", response)
}
return selectOrgResponse, nil
}
func CallGetAllWorkSpacesUserBelongsTo(httpClient *resty.Client) (GetWorkSpacesResponse, error) { func CallGetAllWorkSpacesUserBelongsTo(httpClient *resty.Client) (GetWorkSpacesResponse, error) {
var workSpacesResponse GetWorkSpacesResponse var workSpacesResponse GetWorkSpacesResponse
response, err := httpClient. response, err := httpClient.
+8
View File
@@ -135,6 +135,14 @@ type GetOrganizationsResponse struct {
} `json:"organizations"` } `json:"organizations"`
} }
type SelectOrganizationResponse struct {
Token string `json:"token"`
}
type SelectOrganizationRequest struct {
OrganizationId string `json:"organizationId"`
}
type Secret struct { type Secret struct {
SecretKeyCiphertext string `json:"secretKeyCiphertext,omitempty"` SecretKeyCiphertext string `json:"secretKeyCiphertext,omitempty"`
SecretKeyIV string `json:"secretKeyIV,omitempty"` SecretKeyIV string `json:"secretKeyIV,omitempty"`
+15
View File
@@ -74,6 +74,21 @@ var initCmd = &cobra.Command{
selectedOrganization := organizations[index] selectedOrganization := organizations[index]
tokenResponse, err := api.CallSelectOrganization(httpClient, api.SelectOrganizationRequest{OrganizationId: selectedOrganization.ID})
if err != nil {
util.HandleError(err, "Unable to select organization")
}
// set the config jwt token to the new token
userCreds.UserCredentials.JTWToken = tokenResponse.Token
err = util.StoreUserCredsInKeyRing(&userCreds.UserCredentials)
httpClient.SetAuthToken(tokenResponse.Token)
if err != nil {
util.HandleError(err, "Unable to store your user credentials")
}
workspaceResponse, err := api.CallGetAllWorkSpacesUserBelongsTo(httpClient) workspaceResponse, err := api.CallGetAllWorkSpacesUserBelongsTo(httpClient)
if err != nil { if err != nil {
util.HandleError(err, "Unable to pull projects that belong to you") util.HandleError(err, "Unable to pull projects that belong to you")

Some files were not shown because too many files have changed in this diff Show More