Compare commits

...

45 Commits

Author SHA1 Message Date
79694750af Remove signup disable check for SAML 2024-02-12 11:43:55 -08:00
03db367a4e Merge pull request #1396 from Infisical/azure-saml
Add disableRequestedAuthnContext for azure saml
2024-02-12 10:40:19 -08:00
b0fb848a92 Add disableRequestedAuthnContext for azure saml 2024-02-12 10:35:38 -08:00
4fdfcd50dc feat: changed check-api-breaking with oasdiff 2024-02-12 22:32:02 +05:30
27f4225c44 Merge pull request #1391 from Infisical/ecs-docs
ECS docs with agent
2024-02-11 19:17:01 -05:00
28a9d8e739 complete ecs dcs 2024-02-11 19:14:14 -05:00
a1321e4749 aws ecs with agent docs 2024-02-09 22:31:29 -05:00
d4db01bbde Merge pull request #1388 from Infisical/azure-ad
Correct spInitiated spelling in Azure SAML
2024-02-09 12:31:41 -08:00
39634b8aae Correct spInitiated spelling in Azure SAML 2024-02-09 12:17:29 -08:00
4815ff13ee Update SAML SSO docs to include enforce SAML SSO toggle 2024-02-09 10:36:23 -08:00
fb503756d9 Merge pull request #1372 from Infisical/org-based-auth
Org-Level Auth Enforcement for SAML Orgs and Enhancements for SAML SSO
2024-02-09 13:15:08 -05:00
069b0cd6fb Fix lint issue, add backend permission check for SAML SSO enforcement toggle 2024-02-09 10:02:12 -08:00
ed23bd40d2 Redirect to SAML portal upon enforcing SAML SSO 2024-02-09 09:50:20 -08:00
82181f078a Patch login with SAML when config is inactive 2024-02-09 09:35:51 -08:00
eeaee4409c revert swap 2024-02-09 12:08:11 -05:00
a9a5e92358 Empty 2024-02-09 09:02:22 -08:00
8d457bb0bf swap src des 2024-02-09 12:01:21 -05:00
5878a221f8 Run lint fix 2024-02-09 08:44:30 -08:00
fdbf59cd78 Redirect users to SAML portal on change org to SAML org 2024-02-09 08:31:19 -08:00
2cc2a91812 Change update slug fallback to undefined 2024-02-08 17:47:58 -08:00
92828b5295 add slug index 2024-02-08 20:47:33 -05:00
50c0fae557 continue ecs docs 2024-02-08 20:29:38 -05:00
4e2f2281f9 Update orgScope to orgId naming for org-level auth ref, rewire user invite saml block to org authEnforce field 2024-02-08 17:29:21 -08:00
70e083bae0 feat: open api-diff added detach mode 2024-02-08 22:20:01 +05:30
6a943e275a Updated open-api diff gh action host docker ip 2024-02-08 22:05:35 +05:30
526dc6141b remove -d mode on docker compose 2024-02-08 11:04:26 -05:00
dcab9dcdda update docker compose up 2024-02-08 10:50:25 -05:00
1b0591def8 fix gha breaking change 2024-02-07 16:17:12 -05:00
4b4305bddc Merge pull request #1375 from akhilmhdh/feat/api-diff
feat: github workflow for api diff check, ts check and lint check on PR
2024-02-07 15:26:04 -05:00
22d89d791c Patch new org creation condition on SAML account signup, enable users to toggle auth methods regardless of what org they are in 2024-02-07 12:13:09 -08:00
fcaff76afa rename git hub action 2024-02-07 14:34:02 -05:00
ae9eb20189 set license server url default 2024-02-07 13:51:55 -05:00
3905d16a7c fix license server axios typo 2024-02-07 13:48:09 -05:00
ecafdb0d01 patch check for version 2024-02-07 13:11:53 -05:00
3f8ce42682 Merge remote-tracking branch 'origin' into org-based-auth 2024-02-07 09:49:13 -08:00
3ecfb3f9d2 Show usage and billing tab on cloud only 2024-02-07 09:45:42 -08:00
9011394c34 Add validation to org slug 2024-02-07 09:39:06 -08:00
c0096ca64c Merge pull request #1378 from Infisical/patch-service-token-fetch
patch get secret by name
2024-02-07 23:00:20 +05:30
8313245ae1 feat: github workflow for api diff check, ts check and lint check on PR 2024-02-07 15:13:08 +05:30
fc7015de83 Add lockout-preventative step in saml config setup, add update org slug section in org settings, revise navigate to org flow to account for org-level auth enforced orgs 2024-02-06 15:51:24 -08:00
c1aa5c840c Add org-scoped auth to project-level endpoints 2024-02-05 14:48:02 -08:00
410476ecb5 Merge remote-tracking branch 'origin' into org-based-auth 2024-02-04 15:03:43 -08:00
f1c41be7d4 Resolve merge conflicts 2024-02-04 15:02:43 -08:00
f138973ac7 Add org-scoped auth to org-level endpoints, add migration file for org enableAuth field 2024-02-04 14:44:08 -08:00
44f087991c ECS documentation 2024-01-31 23:53:41 -05:00
127 changed files with 1987 additions and 1181 deletions

View File

@ -0,0 +1,55 @@
name: "Check API For Breaking Changes"
on:
pull_request:
types: [opened, synchronize]
paths:
- "backend/src/server/routes/**"
jobs:
check-be-api-changes:
name: Check API Changes
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- name: Checkout source
uses: actions/checkout@v3
# - name: Setup Node 20
# uses: actions/setup-node@v3
# with:
# node-version: "20"
# uncomment this when testing locally using nektos/act
- uses: KengoTODA/actions-setup-docker-compose@v1
if: ${{ env.ACT }}
name: Install `docker-compose` for local simulations
with:
version: "2.14.2"
- name: 📦Build the latest image
run: docker build --tag infisical-api .
working-directory: backend
- name: Start postgres and redis
run: touch .env && docker-compose -f docker-compose.pg.yml up -d db redis
- name: Start the server
run: |
echo "SECRET_SCANNING_GIT_APP_ID=793712" >> .env
echo "SECRET_SCANNING_PRIVATE_KEY=some-random" >> .env
echo "SECRET_SCANNING_WEBHOOK_SECRET=some-random" >> .env
docker run --name infisical-api -d -p 4000:4000 -e DB_CONNECTION_URI=$DB_CONNECTION_URI -e REDIS_URL=$REDIS_URL -e JWT_AUTH_SECRET=$JWT_AUTH_SECRET --env-file .env --entrypoint '/bin/sh' infisical-api -c "npm run migration:latest && ls && node dist/main.mjs"
env:
REDIS_URL: redis://172.17.0.1:6379
DB_CONNECTION_URI: postgres://infisical:infisical@172.17.0.1:5432/infisical?sslmode=disable
JWT_AUTH_SECRET: something-random
- uses: actions/setup-go@v5
with:
go-version: '1.21.5'
- name: Wait for containers to be stable
run: timeout 60s sh -c 'until docker ps | grep infisical-api | grep -q healthy; do echo "Waiting for container to be healthy..."; sleep 2; done'
- name: Install openapi-diff
run: go install github.com/tufin/oasdiff@latest
- name: Running OpenAPI Spec diff action
run: oasdiff breaking https://app.infisical.com/api/docs/json http://localhost:4000/api/docs/json --fail-on ERR
- name: cleanup
run: |
docker-compose -f "docker-compose.pg.yml" down
docker stop infisical-api
docker remove infisical-api

View File

@ -1,43 +0,0 @@
name: "Check Backend Pull Request"
on:
pull_request:
types: [opened, synchronize]
paths:
- "backend/**"
- "!backend/README.md"
- "!backend/.*"
- "backend/.eslintrc.js"
jobs:
check-be-pr:
name: Check
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- name: ☁️ Checkout source
uses: actions/checkout@v3
- name: 🔧 Setup Node 16
uses: actions/setup-node@v3
with:
node-version: "16"
cache: "npm"
cache-dependency-path: backend/package-lock.json
- name: 📦 Install dependencies
run: npm ci --only-production
working-directory: backend
# - name: 🧪 Run tests
# run: npm run test:ci
# working-directory: backend
# - name: 📁 Upload test results
# uses: actions/upload-artifact@v3
# if: always()
# with:
# name: be-test-results
# path: |
# ./backend/reports
# ./backend/coverage
- name: 🏗️ Run build
run: npm run build
working-directory: backend

View File

@ -0,0 +1,35 @@
name: "Check Backend PR types and lint"
on:
pull_request:
types: [opened, synchronize]
paths:
- "backend/**"
- "!backend/README.md"
- "!backend/.*"
- "backend/.eslintrc.js"
jobs:
check-be-pr:
name: Check TS and Lint
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- name: ☁️ Checkout source
uses: actions/checkout@v3
- name: 🔧 Setup Node 20
uses: actions/setup-node@v3
with:
node-version: "20"
cache: "npm"
cache-dependency-path: backend/package-lock.json
- name: Install dependencies
run: npm install
working-directory: backend
- name: Run type check
run: npm run type:check
working-directory: backend
- name: Run lint check
run: npm run lint
working-directory: backend

View File

@ -125,4 +125,4 @@
"zod": "^3.22.4", "zod": "^3.22.4",
"zod-to-json-schema": "^3.22.0" "zod-to-json-schema": "^3.22.0"
} }
} }

View File

@ -51,6 +51,7 @@ declare module "fastify" {
// used for mfa session authentication // used for mfa session authentication
mfa: { mfa: {
userId: string; userId: string;
orgId?: string;
user: TUsers; user: TUsers;
}; };
// 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
@ -58,6 +59,7 @@ declare module "fastify" {
permission: { permission: {
type: ActorType; type: ActorType;
id: string; id: string;
orgId?: string;
}; };
// passport data // passport data
passportUser: { passportUser: {

View File

@ -0,0 +1,25 @@
import { Knex } from "knex";
import { TableName } from "../schemas";
export async function up(knex: Knex): Promise<void> {
await knex.schema.alterTable(TableName.Organization, (t) => {
t.boolean("authEnforced").defaultTo(false);
t.index("slug");
});
await knex.schema.alterTable(TableName.SamlConfig, (t) => {
t.datetime("lastUsed");
});
}
export async function down(knex: Knex): Promise<void> {
await knex.schema.alterTable(TableName.Organization, (t) => {
t.dropColumn("authEnforced");
t.dropIndex("slug");
});
await knex.schema.alterTable(TableName.SamlConfig, (t) => {
t.dropColumn("lastUsed");
});
}

View File

@ -13,7 +13,8 @@ export const OrganizationsSchema = z.object({
customerId: z.string().nullable().optional(), customerId: z.string().nullable().optional(),
slug: z.string(), slug: z.string(),
createdAt: z.date(), createdAt: z.date(),
updatedAt: z.date() updatedAt: z.date(),
authEnforced: z.boolean().default(false).nullable().optional()
}); });
export type TOrganizations = z.infer<typeof OrganizationsSchema>; export type TOrganizations = z.infer<typeof OrganizationsSchema>;

View File

@ -22,7 +22,8 @@ export const SamlConfigsSchema = z.object({
certTag: z.string().nullable().optional(), certTag: z.string().nullable().optional(),
createdAt: z.date(), createdAt: z.date(),
updatedAt: z.date(), updatedAt: z.date(),
orgId: z.string().uuid() orgId: z.string().uuid(),
lastUsed: z.date().nullable().optional()
}); });
export type TSamlConfigs = z.infer<typeof SamlConfigsSchema>; export type TSamlConfigs = z.infer<typeof SamlConfigsSchema>;

View File

@ -22,6 +22,7 @@ export const registerLicenseRouter = async (server: FastifyZodProvider) => {
const data = await server.services.license.getOrgPlansTableByBillCycle({ const data = await server.services.license.getOrgPlansTableByBillCycle({
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorOrgId: req.permission.orgId,
orgId: req.params.organizationId, orgId: req.params.organizationId,
billingCycle: req.query.billingCycle billingCycle: req.query.billingCycle
}); });
@ -43,6 +44,7 @@ export const registerLicenseRouter = async (server: FastifyZodProvider) => {
const plan = await server.services.license.getOrgPlan({ const plan = 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,
orgId: req.params.organizationId orgId: req.params.organizationId
}); });
return { plan }; return { plan };
@ -85,6 +87,7 @@ export const registerLicenseRouter = async (server: FastifyZodProvider) => {
const data = await server.services.license.startOrgTrial({ const data = await server.services.license.startOrgTrial({
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorOrgId: req.permission.orgId,
orgId: req.params.organizationId, orgId: req.params.organizationId,
success_url: req.body.success_url success_url: req.body.success_url
}); });
@ -106,6 +109,7 @@ export const registerLicenseRouter = async (server: FastifyZodProvider) => {
const data = await server.services.license.createOrganizationPortalSession({ const data = await server.services.license.createOrganizationPortalSession({
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorOrgId: req.permission.orgId,
orgId: req.params.organizationId orgId: req.params.organizationId
}); });
return data; return data;
@ -126,6 +130,7 @@ export const registerLicenseRouter = async (server: FastifyZodProvider) => {
const data = await server.services.license.getOrgBillingInfo({ const data = await server.services.license.getOrgBillingInfo({
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorOrgId: req.permission.orgId,
orgId: req.params.organizationId orgId: req.params.organizationId
}); });
return data; return data;
@ -146,6 +151,7 @@ export const registerLicenseRouter = async (server: FastifyZodProvider) => {
const data = await server.services.license.getOrgPlanTable({ const data = await server.services.license.getOrgPlanTable({
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorOrgId: req.permission.orgId,
orgId: req.params.organizationId orgId: req.params.organizationId
}); });
return data; return data;
@ -166,6 +172,7 @@ export const registerLicenseRouter = async (server: FastifyZodProvider) => {
const data = await server.services.license.getOrgBillingDetails({ const data = await server.services.license.getOrgBillingDetails({
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorOrgId: req.permission.orgId,
orgId: req.params.organizationId orgId: req.params.organizationId
}); });
return data; return data;
@ -190,6 +197,7 @@ export const registerLicenseRouter = async (server: FastifyZodProvider) => {
const data = await server.services.license.updateOrgBillingDetails({ const data = await server.services.license.updateOrgBillingDetails({
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorOrgId: req.permission.orgId,
orgId: req.params.organizationId, orgId: req.params.organizationId,
name: req.body.name, name: req.body.name,
email: req.body.email email: req.body.email
@ -212,6 +220,7 @@ export const registerLicenseRouter = async (server: FastifyZodProvider) => {
const data = await server.services.license.getOrgPmtMethods({ const data = await server.services.license.getOrgPmtMethods({
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorOrgId: req.permission.orgId,
orgId: req.params.organizationId orgId: req.params.organizationId
}); });
return data; return data;
@ -236,6 +245,7 @@ export const registerLicenseRouter = async (server: FastifyZodProvider) => {
const data = await server.services.license.addOrgPmtMethods({ const data = await server.services.license.addOrgPmtMethods({
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorOrgId: req.permission.orgId,
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
@ -261,6 +271,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,
actorOrgId: req.permission.orgId,
orgId: req.params.organizationId, orgId: req.params.organizationId,
pmtMethodId: req.params.pmtMethodId pmtMethodId: req.params.pmtMethodId
}); });
@ -284,6 +295,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,
actorOrgId: req.permission.orgId,
orgId: req.params.organizationId orgId: req.params.organizationId
}); });
return data; return data;
@ -310,6 +322,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,
actorOrgId: req.permission.orgId,
orgId: req.params.organizationId, orgId: req.params.organizationId,
type: req.body.type, type: req.body.type,
value: req.body.value value: req.body.value
@ -335,6 +348,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,
actorOrgId: req.permission.orgId,
orgId: req.params.organizationId, orgId: req.params.organizationId,
taxId: req.params.taxId taxId: req.params.taxId
}); });
@ -358,6 +372,7 @@ export const registerLicenseRouter = async (server: FastifyZodProvider) => {
const data = await server.services.license.getOrgTaxInvoices({ const data = await server.services.license.getOrgTaxInvoices({
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorOrgId: req.permission.orgId,
orgId: req.params.organizationId orgId: req.params.organizationId
}); });
return data; return data;
@ -380,6 +395,7 @@ export const registerLicenseRouter = async (server: FastifyZodProvider) => {
const data = await server.services.license.getOrgLicenses({ const data = await server.services.license.getOrgLicenses({
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorOrgId: req.permission.orgId,
orgId: req.params.organizationId orgId: req.params.organizationId
}); });
return data; return data;

View File

@ -26,7 +26,12 @@ export const registerOrgRoleRouter = async (server: FastifyZodProvider) => {
}, },
onRequest: verifyAuth([AuthMode.JWT]), onRequest: verifyAuth([AuthMode.JWT]),
handler: async (req) => { handler: async (req) => {
const role = await server.services.orgRole.createRole(req.permission.id, req.params.organizationId, req.body); const role = await server.services.orgRole.createRole(
req.permission.id,
req.params.organizationId,
req.body,
req.permission.orgId
);
return { role }; return { role };
} }
}); });
@ -57,7 +62,8 @@ 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.body req.body,
req.permission.orgId
); );
return { role }; return { role };
} }
@ -82,7 +88,8 @@ export const registerOrgRoleRouter = async (server: FastifyZodProvider) => {
const role = await server.services.orgRole.deleteRole( const role = await server.services.orgRole.deleteRole(
req.permission.id, req.permission.id,
req.params.organizationId, req.params.organizationId,
req.params.roleId req.params.roleId,
req.permission.orgId
); );
return { role }; return { role };
} }
@ -107,7 +114,11 @@ export const registerOrgRoleRouter = async (server: FastifyZodProvider) => {
}, },
onRequest: verifyAuth([AuthMode.JWT]), onRequest: verifyAuth([AuthMode.JWT]),
handler: async (req) => { handler: async (req) => {
const roles = await server.services.orgRole.listRoles(req.permission.id, req.params.organizationId); const roles = await server.services.orgRole.listRoles(
req.permission.id,
req.params.organizationId,
req.permission.orgId
);
return { data: { roles } }; return { data: { roles } };
} }
}); });
@ -130,7 +141,8 @@ export const registerOrgRoleRouter = async (server: FastifyZodProvider) => {
handler: async (req) => { handler: async (req) => {
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.orgId
); );
return { permissions, membership }; return { permissions, membership };
} }

View File

@ -30,7 +30,8 @@ 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.body req.body,
req.permission.orgId
); );
return { role }; return { role };
} }
@ -63,7 +64,8 @@ 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.body req.body,
req.permission.orgId
); );
return { role }; return { role };
} }
@ -89,7 +91,8 @@ 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.params.roleId req.params.roleId,
req.permission.orgId
); );
return { role }; return { role };
} }
@ -117,7 +120,8 @@ export const registerProjectRoleRouter = async (server: FastifyZodProvider) => {
const roles = await server.services.projectRole.listRoles( const roles = await server.services.projectRole.listRoles(
req.permission.type, req.permission.type,
req.permission.id, req.permission.id,
req.params.projectId req.params.projectId,
req.permission.orgId
); );
return { data: { roles } }; return { data: { roles } };
} }
@ -143,7 +147,8 @@ export const registerProjectRoleRouter = async (server: FastifyZodProvider) => {
handler: async (req) => { handler: async (req) => {
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.orgId
); );
return { data: { permissions, membership } }; return { data: { permissions, membership } };
} }

View File

@ -31,6 +31,7 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
const secretSnapshots = await server.services.snapshot.listSnapshots({ const secretSnapshots = await server.services.snapshot.listSnapshots({
actor: req.permission.type, actor: req.permission.type,
actorId: req.permission.id, actorId: req.permission.id,
actorOrgId: req.permission.orgId,
projectId: req.params.workspaceId, projectId: req.params.workspaceId,
...req.query ...req.query
}); });
@ -60,6 +61,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,
actorOrgId: req.permission.orgId,
projectId: req.params.workspaceId, projectId: req.params.workspaceId,
environment: req.query.environment, environment: req.query.environment,
path: req.query.path path: req.query.path
@ -112,6 +114,7 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
handler: async (req) => { handler: async (req) => {
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,
projectId: req.params.workspaceId, projectId: req.params.workspaceId,
...req.query, ...req.query,
auditLogActor: req.query.actor, auditLogActor: req.query.actor,

View File

@ -13,13 +13,12 @@ import { FastifyRequest } from "fastify";
import { z } from "zod"; import { z } from "zod";
import { SamlConfigsSchema } from "@app/db/schemas"; import { SamlConfigsSchema } from "@app/db/schemas";
import { SamlProviders } from "@app/ee/services/saml-config/saml-config-types"; import { SamlProviders, TGetSamlCfgDTO } from "@app/ee/services/saml-config/saml-config-types";
import { getConfig } from "@app/lib/config/env"; import { getConfig } from "@app/lib/config/env";
import { BadRequestError } from "@app/lib/errors"; import { BadRequestError } from "@app/lib/errors";
import { logger } from "@app/lib/logger"; import { logger } from "@app/lib/logger";
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 { getServerCfg } from "@app/services/super-admin/super-admin-service";
type TSAMLConfig = { type TSAMLConfig = {
callbackUrl: string; callbackUrl: string;
@ -28,6 +27,7 @@ type TSAMLConfig = {
cert: string; cert: string;
audience: string; audience: string;
wantAuthnResponseSigned?: boolean; wantAuthnResponseSigned?: boolean;
disableRequestedAuthnContext?: boolean;
}; };
export const registerSamlRouter = async (server: FastifyZodProvider) => { export const registerSamlRouter = async (server: FastifyZodProvider) => {
@ -44,17 +44,30 @@ export const registerSamlRouter = async (server: FastifyZodProvider) => {
// eslint-disable-next-line // eslint-disable-next-line
getSamlOptions: async (req, done) => { getSamlOptions: async (req, done) => {
try { try {
const { ssoIdentifier } = req.params; const { samlConfigId, orgSlug } = req.params;
if (!ssoIdentifier) throw new BadRequestError({ message: "Missing sso identitier" });
const ssoConfig = await server.services.saml.getSaml({ let ssoLookupDetails: TGetSamlCfgDTO;
type: "ssoId",
id: ssoIdentifier if (orgSlug) {
}); ssoLookupDetails = {
if (!ssoConfig) throw new BadRequestError({ message: "SSO config not found" }); type: "orgSlug",
orgSlug
};
} else if (samlConfigId) {
ssoLookupDetails = {
type: "ssoId",
id: samlConfigId
};
} else {
throw new BadRequestError({ message: "Missing sso identitier or org slug" });
}
const ssoConfig = await server.services.saml.getSaml(ssoLookupDetails);
if (!ssoConfig || !ssoConfig.isActive)
throw new BadRequestError({ message: "Failed to authenticate with SAML SSO" });
const samlConfig: TSAMLConfig = { const samlConfig: TSAMLConfig = {
callbackUrl: `${appCfg.SITE_URL}/api/v1/sso/saml2/${ssoIdentifier}`, callbackUrl: `${appCfg.SITE_URL}/api/v1/sso/saml2/${ssoConfig.id}`,
entryPoint: ssoConfig.entryPoint, entryPoint: ssoConfig.entryPoint,
issuer: ssoConfig.issuer, issuer: ssoConfig.issuer,
cert: ssoConfig.cert, cert: ssoConfig.cert,
@ -64,7 +77,8 @@ export const registerSamlRouter = async (server: FastifyZodProvider) => {
samlConfig.wantAuthnResponseSigned = false; samlConfig.wantAuthnResponseSigned = false;
} }
if (ssoConfig.authProvider === SamlProviders.AZURE_SAML) { if (ssoConfig.authProvider === SamlProviders.AZURE_SAML) {
if (req.body.RelayState && JSON.parse(req.body.RelayState).spIntiaited) { samlConfig.disableRequestedAuthnContext = true;
if (req.body?.RelayState && JSON.parse(req.body.RelayState).spInitiated) {
samlConfig.audience = `spn:${ssoConfig.issuer}`; samlConfig.audience = `spn:${ssoConfig.issuer}`;
} }
} }
@ -79,7 +93,6 @@ export const registerSamlRouter = async (server: FastifyZodProvider) => {
// eslint-disable-next-line // eslint-disable-next-line
async (req, profile, cb) => { async (req, profile, cb) => {
try { try {
const serverCfg = await getServerCfg();
if (!profile) throw new BadRequestError({ message: "Missing profile" }); if (!profile) throw new BadRequestError({ message: "Missing profile" });
const { firstName } = profile; const { firstName } = profile;
const email = profile?.email ?? (profile?.emailAddress as string); // emailRippling is added because in Rippling the field `email` reserved const email = profile?.email ?? (profile?.emailAddress as string); // emailRippling is added because in Rippling the field `email` reserved
@ -92,7 +105,6 @@ export const registerSamlRouter = async (server: FastifyZodProvider) => {
email, email,
firstName: profile.firstName as string, firstName: profile.firstName as string,
lastName: profile.lastName as string, lastName: profile.lastName as string,
isSignupAllowed: Boolean(serverCfg.allowSignUp),
relayState: (req.body as { RelayState?: string }).RelayState, relayState: (req.body as { RelayState?: string }).RelayState,
authProvider: (req as unknown as FastifyRequest).ssoConfig?.authProvider as string, authProvider: (req as unknown as FastifyRequest).ssoConfig?.authProvider as string,
orgId: (req as unknown as FastifyRequest).ssoConfig?.orgId as string orgId: (req as unknown as FastifyRequest).ssoConfig?.orgId as string
@ -108,11 +120,11 @@ export const registerSamlRouter = async (server: FastifyZodProvider) => {
); );
server.route({ server.route({
url: "/redirect/saml2/:ssoIdentifier", url: "/redirect/saml2/organizations/:orgSlug",
method: "GET", method: "GET",
schema: { schema: {
params: z.object({ params: z.object({
ssoIdentifier: z.string().trim() orgSlug: z.string().trim()
}), }),
querystring: z.object({ querystring: z.object({
callback_port: z.string().optional() callback_port: z.string().optional()
@ -134,11 +146,37 @@ export const registerSamlRouter = async (server: FastifyZodProvider) => {
}); });
server.route({ server.route({
url: "/saml2/:ssoIdentifier", url: "/redirect/saml2/:samlConfigId",
method: "GET",
schema: {
params: z.object({
samlConfigId: z.string().trim()
}),
querystring: z.object({
callback_port: z.string().optional()
})
},
preValidation: (req, res) =>
(
passport.authenticate("saml", {
failureRedirect: "/",
additionalParams: {
RelayState: JSON.stringify({
spInitiated: true,
callbackPort: req.query.callback_port ?? ""
})
}
} as any) as any
)(req, res),
handler: () => {}
});
server.route({
url: "/saml2/:samlConfigId",
method: "POST", method: "POST",
schema: { schema: {
params: z.object({ params: z.object({
ssoIdentifier: z.string().trim() samlConfigId: z.string().trim()
}) })
}, },
preValidation: passport.authenticate("saml", { preValidation: passport.authenticate("saml", {
@ -177,7 +215,8 @@ export const registerSamlRouter = async (server: FastifyZodProvider) => {
isActive: z.boolean(), isActive: z.boolean(),
entryPoint: z.string(), entryPoint: z.string(),
issuer: z.string(), issuer: z.string(),
cert: z.string() cert: z.string(),
lastUsed: z.date().nullable().optional()
}) })
.optional() .optional()
} }
@ -186,6 +225,7 @@ export const registerSamlRouter = async (server: FastifyZodProvider) => {
const saml = await server.services.saml.getSaml({ const saml = await server.services.saml.getSaml({
actor: req.permission.type, actor: req.permission.type,
actorId: req.permission.id, actorId: req.permission.id,
actorOrgId: req.permission.orgId,
orgId: req.query.organizationId, orgId: req.query.organizationId,
type: "org" type: "org"
}); });
@ -214,6 +254,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,
actorOrgId: req.permission.orgId,
orgId: req.body.organizationId, orgId: req.body.organizationId,
...req.body ...req.body
}); });
@ -244,6 +285,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,
actorOrgId: req.permission.orgId,
orgId: req.body.organizationId, orgId: req.body.organizationId,
...req.body ...req.body
}); });

View File

@ -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,
actorOrgId: req.permission.orgId,
projectId: req.body.workspaceId, projectId: req.body.workspaceId,
...req.body, ...req.body,
name: req.body.name ?? `${req.body.environment}-${nanoid(3)}` name: req.body.name ?? `${req.body.environment}-${nanoid(3)}`
@ -71,6 +72,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,
actorOrgId: req.permission.orgId,
...req.body, ...req.body,
secretPolicyId: req.params.sapId secretPolicyId: req.params.sapId
}); });
@ -96,6 +98,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,
actorOrgId: req.permission.orgId,
secretPolicyId: req.params.sapId secretPolicyId: req.params.sapId
}); });
return { approval }; return { approval };
@ -120,6 +123,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,
actorOrgId: req.permission.orgId,
projectId: req.query.workspaceId projectId: req.query.workspaceId
}); });
return { approvals }; return { approvals };
@ -146,6 +150,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,
actorOrgId: req.permission.orgId,
projectId: req.query.workspaceId, projectId: req.query.workspaceId,
...req.query ...req.query
}); });

View File

@ -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,
actorOrgId: req.permission.orgId,
...req.query, ...req.query,
projectId: req.query.workspaceId projectId: req.query.workspaceId
}); });
@ -80,6 +81,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,
actorOrgId: req.permission.orgId,
projectId: req.query.workspaceId projectId: req.query.workspaceId
}); });
return { approvals }; return { approvals };
@ -104,6 +106,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,
actorOrgId: req.permission.orgId,
approvalId: req.params.id approvalId: req.params.id
}); });
return { approval }; return { approval };
@ -131,6 +134,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,
actorOrgId: req.permission.orgId,
approvalId: req.params.id, approvalId: req.params.id,
status: req.body.status status: req.body.status
}); });
@ -159,6 +163,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,
actorOrgId: req.permission.orgId,
approvalId: req.params.id, approvalId: req.params.id,
status: req.body.status status: req.body.status
}); });
@ -266,6 +271,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,
actorOrgId: req.permission.orgId,
id: req.params.id id: req.params.id
}); });
return { approval }; return { approval };

View File

@ -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,
actorOrgId: req.permission.orgId,
projectId: req.params.workspaceId projectId: req.params.workspaceId
}); });
return providers; return providers;

View File

@ -40,6 +40,7 @@ export const registerSecretRotationRouter = async (server: FastifyZodProvider) =
const secretRotation = await server.services.secretRotation.createRotation({ const secretRotation = await server.services.secretRotation.createRotation({
actor: req.permission.type, actor: req.permission.type,
actorId: req.permission.id, actorId: req.permission.id,
actorOrgId: req.permission.orgId,
...req.body, ...req.body,
projectId: req.body.workspaceId projectId: req.body.workspaceId
}); });
@ -73,6 +74,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,
actorOrgId: req.permission.orgId,
rotationId: req.body.id rotationId: req.body.id
}); });
return { secretRotation }; return { secretRotation };
@ -123,6 +125,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,
actorOrgId: req.permission.orgId,
projectId: req.query.workspaceId projectId: req.query.workspaceId
}); });
return { secretRotations }; return { secretRotations };
@ -155,6 +158,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,
actorOrgId: req.permission.orgId,
rotationId: req.params.id rotationId: req.params.id
}); });
return { secretRotation }; return { secretRotation };

View File

@ -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,
actorOrgId: req.permission.orgId,
orgId: req.body.organizationId orgId: req.body.organizationId
}); });
return session; return session;
@ -45,6 +46,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,
actorOrgId: req.permission.orgId,
...req.body ...req.body
}); });
return installatedApp; return installatedApp;
@ -65,6 +67,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,
actorOrgId: req.permission.orgId,
orgId: req.params.organizationId orgId: req.params.organizationId
}); });
return { appInstallationCompleted }; return { appInstallationCompleted };
@ -85,6 +88,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,
actorOrgId: req.permission.orgId,
orgId: req.params.organizationId orgId: req.params.organizationId
}); });
return { risks }; return { risks };
@ -106,6 +110,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,
actorOrgId: req.permission.orgId,
orgId: req.params.organizationId, orgId: req.params.organizationId,
riskId: req.params.riskId, riskId: req.params.riskId,
...req.body ...req.body

View File

@ -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,
actorOrgId: req.permission.orgId,
limit: req.query.limit, limit: req.query.limit,
offset: req.query.offset, offset: req.query.offset,
secretId: req.params.secretId secretId: req.params.secretId

View File

@ -46,6 +46,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,
actorOrgId: req.permission.orgId,
id: req.params.secretSnapshotId id: req.params.secretSnapshotId
}); });
return { secretSnapshot }; return { secretSnapshot };
@ -70,6 +71,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,
actorOrgId: req.permission.orgId,
id: req.params.secretSnapshotId id: req.params.secretSnapshotId
}); });
return { secretSnapshot }; return { secretSnapshot };

View File

@ -24,7 +24,8 @@ export const registerTrustedIpRouter = async (server: FastifyZodProvider) => {
const trustedIps = await server.services.trustedIp.listIpsByProjectId({ const trustedIps = await server.services.trustedIp.listIpsByProjectId({
projectId: req.params.workspaceId, projectId: req.params.workspaceId,
actor: req.permission.type, actor: req.permission.type,
actorId: req.permission.id actorId: req.permission.id,
actorOrgId: req.permission.orgId
}); });
return { trustedIps }; return { trustedIps };
} }
@ -54,6 +55,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,
actorOrgId: req.permission.orgId,
...req.body ...req.body
}); });
await server.services.auditLog.createAuditLog({ await server.services.auditLog.createAuditLog({
@ -97,6 +99,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,
actorOrgId: req.permission.orgId,
trustedIpId: req.params.trustedIpId, trustedIpId: req.params.trustedIpId,
...req.body ...req.body
}); });
@ -137,6 +140,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,
actorOrgId: req.permission.orgId,
trustedIpId: req.params.trustedIpId trustedIpId: req.params.trustedIpId
}); });
await server.services.auditLog.createAuditLog({ await server.services.auditLog.createAuditLog({

View File

@ -30,10 +30,11 @@ export const auditLogServiceFactory = ({
startDate, startDate,
actor, actor,
actorId, actorId,
actorOrgId,
projectId, projectId,
auditLogActor auditLogActor
}: TListProjectAuditLogDTO) => { }: TListProjectAuditLogDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, 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,

View File

@ -44,7 +44,7 @@ type TLicenseServiceFactoryDep = {
export type TLicenseServiceFactory = ReturnType<typeof licenseServiceFactory>; export type TLicenseServiceFactory = ReturnType<typeof licenseServiceFactory>;
const LICENSE_SERVER_CLOUD_LOGIN = "/api/auth/v1/license-server-login"; const LICENSE_SERVER_CLOUD_LOGIN = "/api/auth/v1/license-server-login";
const LICENSE_SERVER_ON_PREM_LOGIN = "/api/auth/v1/licence-login"; const LICENSE_SERVER_ON_PREM_LOGIN = "/api/auth/v1/license-login";
const FEATURE_CACHE_KEY = (orgId: string, projectId?: string) => `${orgId}-${projectId || ""}`; const FEATURE_CACHE_KEY = (orgId: string, projectId?: string) => `${orgId}-${projectId || ""}`;
export const licenseServiceFactory = ({ orgDAL, permissionService, licenseDAL }: TLicenseServiceFactoryDep) => { export const licenseServiceFactory = ({ orgDAL, permissionService, licenseDAL }: TLicenseServiceFactoryDep) => {
@ -92,7 +92,7 @@ export const licenseServiceFactory = ({ orgDAL, permissionService, licenseDAL }:
// else it would reach catch statement // else it would reach catch statement
isValidLicense = true; isValidLicense = true;
} catch (error) { } catch (error) {
logger.error(`init-license: encountered an error when init license [error]`, error); logger.error(error, `init-license: encountered an error when init license`);
} }
}; };
@ -175,8 +175,14 @@ export const licenseServiceFactory = ({ orgDAL, permissionService, licenseDAL }:
}; };
// below all are api calls // below all are api calls
const getOrgPlansTableByBillCycle = async ({ orgId, actor, actorId, billingCycle }: TOrgPlansTableDTO) => { const getOrgPlansTableByBillCycle = async ({
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId); orgId,
actor,
actorId,
actorOrgId,
billingCycle
}: TOrgPlansTableDTO) => {
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, 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}`
@ -184,15 +190,15 @@ export const licenseServiceFactory = ({ orgDAL, permissionService, licenseDAL }:
return data; return data;
}; };
const getOrgPlan = async ({ orgId, actor, actorId, projectId }: TOrgPlanDTO) => { const getOrgPlan = async ({ orgId, actor, actorId, actorOrgId, projectId }: TOrgPlanDTO) => {
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId); const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, 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, success_url }: TStartOrgTrialDTO) => { const startOrgTrial = async ({ orgId, actorId, actor, actorOrgId, success_url }: TStartOrgTrialDTO) => {
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId); const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, 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);
@ -213,8 +219,8 @@ export const licenseServiceFactory = ({ orgDAL, permissionService, licenseDAL }:
return { url }; return { url };
}; };
const createOrganizationPortalSession = async ({ orgId, actorId, actor }: TCreateOrgPortalSession) => { const createOrganizationPortalSession = async ({ orgId, actorId, actor, actorOrgId }: TCreateOrgPortalSession) => {
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId); const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, 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);
@ -260,8 +266,8 @@ export const licenseServiceFactory = ({ orgDAL, permissionService, licenseDAL }:
return { url }; return { url };
}; };
const getOrgBillingInfo = async ({ orgId, actor, actorId }: TGetOrgBillInfoDTO) => { const getOrgBillingInfo = async ({ orgId, actor, actorId, actorOrgId }: TGetOrgBillInfoDTO) => {
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId); const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, 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);
@ -277,8 +283,8 @@ export const licenseServiceFactory = ({ orgDAL, permissionService, licenseDAL }:
}; };
// returns org current plan feature table // returns org current plan feature table
const getOrgPlanTable = async ({ orgId, actor, actorId }: TGetOrgBillInfoDTO) => { const getOrgPlanTable = async ({ orgId, actor, actorId, actorOrgId }: TGetOrgBillInfoDTO) => {
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId); const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, 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);
@ -293,8 +299,8 @@ export const licenseServiceFactory = ({ orgDAL, permissionService, licenseDAL }:
return data; return data;
}; };
const getOrgBillingDetails = async ({ orgId, actor, actorId }: TGetOrgBillInfoDTO) => { const getOrgBillingDetails = async ({ orgId, actor, actorId, actorOrgId }: TGetOrgBillInfoDTO) => {
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId); const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, 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);
@ -310,8 +316,15 @@ export const licenseServiceFactory = ({ orgDAL, permissionService, licenseDAL }:
return data; return data;
}; };
const updateOrgBillingDetails = async ({ actorId, actor, orgId, name, email }: TUpdateOrgBillingDetailsDTO) => { const updateOrgBillingDetails = async ({
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId); actorId,
actor,
actorOrgId,
orgId,
name,
email
}: TUpdateOrgBillingDetailsDTO) => {
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, 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);
@ -330,8 +343,8 @@ export const licenseServiceFactory = ({ orgDAL, permissionService, licenseDAL }:
return data; return data;
}; };
const getOrgPmtMethods = async ({ orgId, actor, actorId }: TOrgPmtMethodsDTO) => { const getOrgPmtMethods = async ({ orgId, actor, actorId, actorOrgId }: TOrgPmtMethodsDTO) => {
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId); const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, 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);
@ -349,8 +362,15 @@ export const licenseServiceFactory = ({ orgDAL, permissionService, licenseDAL }:
return pmtMethods; return pmtMethods;
}; };
const addOrgPmtMethods = async ({ orgId, actor, actorId, success_url, cancel_url }: TAddOrgPmtMethodDTO) => { const addOrgPmtMethods = async ({
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId); orgId,
actor,
actorId,
actorOrgId,
success_url,
cancel_url
}: TAddOrgPmtMethodDTO) => {
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, 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);
@ -371,8 +391,8 @@ export const licenseServiceFactory = ({ orgDAL, permissionService, licenseDAL }:
return { url }; return { url };
}; };
const delOrgPmtMethods = async ({ actorId, actor, orgId, pmtMethodId }: TDelOrgPmtMethodDTO) => { const delOrgPmtMethods = async ({ actorId, actor, actorOrgId, orgId, pmtMethodId }: TDelOrgPmtMethodDTO) => {
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId); const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, 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);
@ -388,8 +408,8 @@ export const licenseServiceFactory = ({ orgDAL, permissionService, licenseDAL }:
return data; return data;
}; };
const getOrgTaxIds = async ({ orgId, actor, actorId }: TGetOrgTaxIdDTO) => { const getOrgTaxIds = async ({ orgId, actor, actorId, actorOrgId }: TGetOrgTaxIdDTO) => {
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId); const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, 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);
@ -406,8 +426,8 @@ export const licenseServiceFactory = ({ orgDAL, permissionService, licenseDAL }:
return taxIds; return taxIds;
}; };
const addOrgTaxId = async ({ actorId, actor, orgId, type, value }: TAddOrgTaxIdDTO) => { const addOrgTaxId = async ({ actorId, actor, actorOrgId, orgId, type, value }: TAddOrgTaxIdDTO) => {
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId); const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, 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);
@ -427,8 +447,8 @@ export const licenseServiceFactory = ({ orgDAL, permissionService, licenseDAL }:
return data; return data;
}; };
const delOrgTaxId = async ({ orgId, actor, actorId, taxId }: TDelOrgTaxIdDTO) => { const delOrgTaxId = async ({ orgId, actor, actorId, actorOrgId, taxId }: TDelOrgTaxIdDTO) => {
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId); const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, 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);
@ -444,8 +464,8 @@ export const licenseServiceFactory = ({ orgDAL, permissionService, licenseDAL }:
return data; return data;
}; };
const getOrgTaxInvoices = async ({ actorId, actor, orgId }: TOrgInvoiceDTO) => { const getOrgTaxInvoices = async ({ actorId, actor, actorOrgId, orgId }: TOrgInvoiceDTO) => {
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId); const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, 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);
@ -461,8 +481,8 @@ export const licenseServiceFactory = ({ orgDAL, permissionService, licenseDAL }:
return invoices; return invoices;
}; };
const getOrgLicenses = async ({ orgId, actor, actorId }: TOrgLicensesDTO) => { const getOrgLicenses = async ({ orgId, actor, actorId, actorOrgId }: TOrgLicensesDTO) => {
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId); const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, 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);

View File

@ -10,8 +10,10 @@ export const permissionDALFactory = (db: TDbClient) => {
try { try {
const membership = await db(TableName.OrgMembership) const membership = await db(TableName.OrgMembership)
.leftJoin(TableName.OrgRoles, `${TableName.OrgMembership}.roleId`, `${TableName.OrgRoles}.id`) .leftJoin(TableName.OrgRoles, `${TableName.OrgMembership}.roleId`, `${TableName.OrgRoles}.id`)
.join(TableName.Organization, `${TableName.OrgMembership}.orgId`, `${TableName.Organization}.id`)
.where("userId", userId) .where("userId", userId)
.where(`${TableName.OrgMembership}.orgId`, orgId) .where(`${TableName.OrgMembership}.orgId`, orgId)
.select(db.ref("authEnforced").withSchema(TableName.Organization).as("orgAuthEnforced"))
.select("permissions") .select("permissions")
.select(selectAllTableCols(TableName.OrgMembership)) .select(selectAllTableCols(TableName.OrgMembership))
.first(); .first();
@ -26,9 +28,11 @@ export const permissionDALFactory = (db: TDbClient) => {
try { try {
const membership = await db(TableName.IdentityOrgMembership) const membership = await db(TableName.IdentityOrgMembership)
.leftJoin(TableName.OrgRoles, `${TableName.IdentityOrgMembership}.roleId`, `${TableName.OrgRoles}.id`) .leftJoin(TableName.OrgRoles, `${TableName.IdentityOrgMembership}.roleId`, `${TableName.OrgRoles}.id`)
.join(TableName.Organization, `${TableName.IdentityOrgMembership}.orgId`, `${TableName.Organization}.id`)
.where("identityId", identityId) .where("identityId", identityId)
.where(`${TableName.IdentityOrgMembership}.orgId`, orgId) .where(`${TableName.IdentityOrgMembership}.orgId`, orgId)
.select(selectAllTableCols(TableName.IdentityOrgMembership)) .select(selectAllTableCols(TableName.IdentityOrgMembership))
.select(db.ref("authEnforced").withSchema(TableName.Organization).as("orgAuthEnforced"))
.select("permissions") .select("permissions")
.first(); .first();
return membership; return membership;
@ -41,9 +45,15 @@ export const permissionDALFactory = (db: TDbClient) => {
try { try {
const membership = await db(TableName.ProjectMembership) const membership = await db(TableName.ProjectMembership)
.leftJoin(TableName.ProjectRoles, `${TableName.ProjectMembership}.roleId`, `${TableName.ProjectRoles}.id`) .leftJoin(TableName.ProjectRoles, `${TableName.ProjectMembership}.roleId`, `${TableName.ProjectRoles}.id`)
.join(TableName.Project, `${TableName.ProjectMembership}.projectId`, `${TableName.Project}.id`)
.join(TableName.Organization, `${TableName.Project}.orgId`, `${TableName.Organization}.id`)
.where("userId", userId) .where("userId", userId)
.where(`${TableName.ProjectMembership}.projectId`, projectId) .where(`${TableName.ProjectMembership}.projectId`, projectId)
.select(selectAllTableCols(TableName.ProjectMembership)) .select(selectAllTableCols(TableName.ProjectMembership))
.select(
db.ref("authEnforced").withSchema(TableName.Organization).as("orgAuthEnforced"),
db.ref("orgId").withSchema(TableName.Project)
)
.select("permissions") .select("permissions")
.first(); .first();

View File

@ -94,12 +94,15 @@ export const permissionServiceFactory = ({
/* /*
* Get user permission in an organization * Get user permission in an organization
* */ * */
const getUserOrgPermission = async (userId: string, orgId: string) => { const getUserOrgPermission = async (userId: string, orgId: string, 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" });
}
return { permission: buildOrgPermission(membership.role, membership.permissions), membership }; return { permission: buildOrgPermission(membership.role, membership.permissions), membership };
}; };
@ -112,10 +115,10 @@ 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) => { const getOrgPermission = async (type: ActorType, id: string, orgId: string, actorOrgId?: string) => {
switch (type) { switch (type) {
case ActorType.USER: case ActorType.USER:
return getUserOrgPermission(id, orgId); return getUserOrgPermission(id, orgId, actorOrgId);
case ActorType.IDENTITY: case ActorType.IDENTITY:
return getIdentityOrgPermission(id, orgId); return getIdentityOrgPermission(id, orgId);
default: default:
@ -142,12 +145,17 @@ export const permissionServiceFactory = ({
}; };
// user permission for a project in an organization // user permission for a project in an organization
const getUserProjectPermission = async (userId: string, projectId: string) => { const getUserProjectPermission = async (userId: string, projectId: string, userOrgId?: string) => {
const membership = await permissionDAL.getProjectPermission(userId, projectId); const membership = await permissionDAL.getProjectPermission(userId, projectId);
if (!membership) throw new UnauthorizedError({ name: "User not in project" }); if (!membership) throw new UnauthorizedError({ name: "User not in project" });
if (membership.role === ProjectMembershipRole.Custom && !membership.permissions) { if (membership.role === ProjectMembershipRole.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" });
}
return { return {
permission: buildProjectPermission(membership.role, membership.permissions), permission: buildProjectPermission(membership.role, membership.permissions),
membership membership
@ -160,6 +168,7 @@ export const permissionServiceFactory = ({
if (membership.role === ProjectMembershipRole.Custom && !membership.permissions) { if (membership.role === ProjectMembershipRole.Custom && !membership.permissions) {
throw new BadRequestError({ name: "Custom permission not found" }); throw new BadRequestError({ name: "Custom permission not found" });
} }
return { return {
permission: buildProjectPermission(membership.role, membership.permissions), permission: buildProjectPermission(membership.role, membership.permissions),
membership membership
@ -184,6 +193,8 @@ export const permissionServiceFactory = ({
: { : {
permission: MongoAbility<ProjectPermissionSet, MongoQuery>; permission: MongoAbility<ProjectPermissionSet, MongoQuery>;
membership: (T extends ActorType.USER ? TProjectMemberships : TIdentityProjectMemberships) & { membership: (T extends ActorType.USER ? TProjectMemberships : TIdentityProjectMemberships) & {
orgAuthEnforced: boolean;
orgId: string;
permissions?: unknown; permissions?: unknown;
}; };
}; };
@ -191,11 +202,12 @@ export const permissionServiceFactory = ({
const getProjectPermission = async <T extends ActorType>( const getProjectPermission = async <T extends ActorType>(
type: T, type: T,
id: string, id: string,
projectId: string projectId: string,
actorOrgId?: string
): Promise<TProjectPermissionRT<T>> => { ): Promise<TProjectPermissionRT<T>> => {
switch (type) { switch (type) {
case ActorType.USER: case ActorType.USER:
return getUserProjectPermission(id, projectId) as Promise<TProjectPermissionRT<T>>; return getUserProjectPermission(id, projectId, actorOrgId) as Promise<TProjectPermissionRT<T>>;
case ActorType.SERVICE: case ActorType.SERVICE:
return getServiceTokenProjectPermission(id, projectId) as Promise<TProjectPermissionRT<T>>; return getServiceTokenProjectPermission(id, projectId) as Promise<TProjectPermissionRT<T>>;
case ActorType.IDENTITY: case ActorType.IDENTITY:

View File

@ -1,10 +1,31 @@
import { TDbClient } from "@app/db"; import { TDbClient } from "@app/db";
import { TableName } from "@app/db/schemas"; import { TableName } from "@app/db/schemas";
import { DatabaseError } from "@app/lib/errors";
import { ormify } from "@app/lib/knex"; import { ormify } from "@app/lib/knex";
export type TSamlConfigDALFactory = ReturnType<typeof samlConfigDALFactory>; export type TSamlConfigDALFactory = ReturnType<typeof samlConfigDALFactory>;
export const samlConfigDALFactory = (db: TDbClient) => { export const samlConfigDALFactory = (db: TDbClient) => {
const samlCfgOrm = ormify(db, TableName.SamlConfig); const samlCfgOrm = ormify(db, TableName.SamlConfig);
return samlCfgOrm;
const findEnforceableSamlCfg = async (orgId: string) => {
try {
const samlCfg = await db(TableName.SamlConfig)
.where({
orgId,
isActive: true
})
.whereNotNull("lastUsed")
.first();
return samlCfg;
} catch (error) {
throw new DatabaseError({ error, name: "Find org by id" });
}
};
return {
...samlCfgOrm,
findEnforceableSamlCfg
};
}; };

View File

@ -18,7 +18,7 @@ import {
infisicalSymmetricEncypt infisicalSymmetricEncypt
} from "@app/lib/crypto/encryption"; } from "@app/lib/crypto/encryption";
import { BadRequestError } from "@app/lib/errors"; import { BadRequestError } from "@app/lib/errors";
import { AuthTokenType } from "@app/services/auth/auth-type"; import { AuthMethod, AuthTokenType } from "@app/services/auth/auth-type";
import { TOrgBotDALFactory } from "@app/services/org/org-bot-dal"; import { TOrgBotDALFactory } from "@app/services/org/org-bot-dal";
import { TOrgDALFactory } from "@app/services/org/org-dal"; import { TOrgDALFactory } from "@app/services/org/org-dal";
import { TUserDALFactory } from "@app/services/user/user-dal"; import { TUserDALFactory } from "@app/services/user/user-dal";
@ -27,18 +27,15 @@ import { TLicenseServiceFactory } from "../license/license-service";
import { OrgPermissionActions, OrgPermissionSubjects } from "../permission/org-permission"; import { OrgPermissionActions, OrgPermissionSubjects } from "../permission/org-permission";
import { TPermissionServiceFactory } from "../permission/permission-service"; import { TPermissionServiceFactory } from "../permission/permission-service";
import { TSamlConfigDALFactory } from "./saml-config-dal"; import { TSamlConfigDALFactory } from "./saml-config-dal";
import { import { TCreateSamlCfgDTO, TGetSamlCfgDTO, TSamlLoginDTO, TUpdateSamlCfgDTO } from "./saml-config-types";
SamlProviders,
TCreateSamlCfgDTO,
TGetSamlCfgDTO,
TSamlLoginDTO,
TUpdateSamlCfgDTO
} from "./saml-config-types";
type TSamlConfigServiceFactoryDep = { type TSamlConfigServiceFactoryDep = {
samlConfigDAL: TSamlConfigDALFactory; samlConfigDAL: TSamlConfigDALFactory;
userDAL: Pick<TUserDALFactory, "create" | "findUserByEmail" | "transaction" | "updateById">; userDAL: Pick<TUserDALFactory, "create" | "findUserByEmail" | "transaction" | "updateById">;
orgDAL: Pick<TOrgDALFactory, "createMembership" | "updateMembershipById" | "findMembership" | "findOrgById">; orgDAL: Pick<
TOrgDALFactory,
"createMembership" | "updateMembershipById" | "findMembership" | "findOrgById" | "findOne" | "updateById"
>;
orgBotDAL: Pick<TOrgBotDALFactory, "findOne" | "create" | "transaction">; orgBotDAL: Pick<TOrgBotDALFactory, "findOne" | "create" | "transaction">;
permissionService: Pick<TPermissionServiceFactory, "getOrgPermission">; permissionService: Pick<TPermissionServiceFactory, "getOrgPermission">;
licenseService: Pick<TLicenseServiceFactory, "getPlan">; licenseService: Pick<TLicenseServiceFactory, "getPlan">;
@ -57,6 +54,7 @@ export const samlConfigServiceFactory = ({
const createSamlCfg = async ({ const createSamlCfg = async ({
cert, cert,
actor, actor,
actorOrgId,
orgId, orgId,
issuer, issuer,
actorId, actorId,
@ -64,7 +62,7 @@ export const samlConfigServiceFactory = ({
entryPoint, entryPoint,
authProvider authProvider
}: TCreateSamlCfgDTO) => { }: TCreateSamlCfgDTO) => {
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId); const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, 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);
@ -140,12 +138,14 @@ export const samlConfigServiceFactory = ({
certIV, certIV,
certTag certTag
}); });
return samlConfig; return samlConfig;
}; };
const updateSamlCfg = async ({ const updateSamlCfg = async ({
orgId, orgId,
actor, actor,
actorOrgId,
cert, cert,
actorId, actorId,
issuer, issuer,
@ -153,7 +153,7 @@ export const samlConfigServiceFactory = ({
entryPoint, entryPoint,
authProvider authProvider
}: TUpdateSamlCfgDTO) => { }: TUpdateSamlCfgDTO) => {
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId); const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, 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)
@ -162,7 +162,7 @@ export const samlConfigServiceFactory = ({
"Failed to update SAML SSO configuration due to plan restriction. Upgrade plan to update SSO configuration." "Failed to update SAML SSO configuration due to plan restriction. Upgrade plan to update SSO configuration."
}); });
const updateQuery: TSamlConfigsUpdate = { authProvider, isActive }; const updateQuery: TSamlConfigsUpdate = { authProvider, isActive, lastUsed: null };
const orgBot = await orgBotDAL.findOne({ orgId }); const orgBot = await orgBotDAL.findOne({ orgId });
if (!orgBot) throw new BadRequestError({ message: "Org bot not found", name: "OrgBotNotFound" }); if (!orgBot) throw new BadRequestError({ message: "Org bot not found", name: "OrgBotNotFound" });
const key = infisicalSymmetricDecrypt({ const key = infisicalSymmetricDecrypt({
@ -195,6 +195,8 @@ export const samlConfigServiceFactory = ({
updateQuery.certTag = certTag; updateQuery.certTag = certTag;
} }
const [ssoConfig] = await samlConfigDAL.update({ orgId }, updateQuery); const [ssoConfig] = await samlConfigDAL.update({ orgId }, updateQuery);
await orgDAL.updateById(orgId, { authEnforced: false });
return ssoConfig; return ssoConfig;
}; };
@ -203,6 +205,10 @@ export const samlConfigServiceFactory = ({
if (dto.type === "org") { if (dto.type === "org") {
ssoConfig = await samlConfigDAL.findOne({ orgId: dto.orgId }); ssoConfig = await samlConfigDAL.findOne({ orgId: dto.orgId });
if (!ssoConfig) return; if (!ssoConfig) return;
} else if (dto.type === "orgSlug") {
const org = await orgDAL.findOne({ slug: dto.orgSlug });
if (!org) return;
ssoConfig = await samlConfigDAL.findOne({ orgId: org.id });
} else if (dto.type === "ssoId") { } else if (dto.type === "ssoId") {
// TODO: // TODO:
// We made this change because saml config ids were not moved over during the migration // We made this change because saml config ids were not moved over during the migration
@ -227,7 +233,12 @@ export const samlConfigServiceFactory = ({
// when dto is type id means it's internally used // when dto is type id means it's internally used
if (dto.type === "org") { if (dto.type === "org") {
const { permission } = await permissionService.getOrgPermission(dto.actor, dto.actorId, ssoConfig.orgId); const { permission } = await permissionService.getOrgPermission(
dto.actor,
dto.actorId,
ssoConfig.orgId,
dto.actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Sso); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Sso);
} }
const { const {
@ -284,35 +295,20 @@ export const samlConfigServiceFactory = ({
isActive: ssoConfig.isActive, isActive: ssoConfig.isActive,
entryPoint, entryPoint,
issuer, issuer,
cert cert,
lastUsed: ssoConfig.lastUsed
}; };
}; };
const samlLogin = async ({ const samlLogin = async ({ firstName, email, lastName, authProvider, orgId, relayState }: TSamlLoginDTO) => {
firstName,
email,
lastName,
authProvider,
orgId,
relayState,
isSignupAllowed
}: TSamlLoginDTO) => {
const appCfg = getConfig(); const appCfg = getConfig();
let user = await userDAL.findUserByEmail(email); let user = await userDAL.findUserByEmail(email);
const isSamlSignUpDisabled = !isSignupAllowed && !user;
if (isSamlSignUpDisabled) throw new BadRequestError({ message: "User signup disabled", name: "Saml SSO login" });
const organization = await orgDAL.findOrgById(orgId); const organization = await orgDAL.findOrgById(orgId);
if (!organization) throw new BadRequestError({ message: "Org not found" }); if (!organization) throw new BadRequestError({ message: "Org not found" });
if (user) { if (user) {
const hasSamlEnabled = (user.authMethods || []).some((method) =>
Object.values(SamlProviders).includes(method as SamlProviders)
);
await userDAL.transaction(async (tx) => { await userDAL.transaction(async (tx) => {
if (!hasSamlEnabled) {
await userDAL.updateById(user.id, { authMethods: [authProvider] }, tx);
}
const [orgMembership] = await orgDAL.findMembership({ userId: user.id, orgId }, { tx }); const [orgMembership] = await orgDAL.findMembership({ userId: user.id, orgId }, { tx });
if (!orgMembership) { if (!orgMembership) {
await orgDAL.createMembership( await orgDAL.createMembership(
@ -342,7 +338,7 @@ export const samlConfigServiceFactory = ({
email, email,
firstName, firstName,
lastName, lastName,
authMethods: [authProvider] authMethods: [AuthMethod.EMAIL]
}, },
tx tx
); );
@ -378,6 +374,9 @@ export const samlConfigServiceFactory = ({
expiresIn: appCfg.JWT_PROVIDER_AUTH_LIFETIME expiresIn: appCfg.JWT_PROVIDER_AUTH_LIFETIME
} }
); );
await samlConfigDAL.update({ orgId }, { lastUsed: new Date() });
return { isUserCompleted, providerAuthToken }; return { isUserCompleted, providerAuthToken };
}; };

View File

@ -25,7 +25,11 @@ export type TUpdateSamlCfgDTO = Partial<{
TOrgPermission; TOrgPermission;
export type TGetSamlCfgDTO = export type TGetSamlCfgDTO =
| { type: "org"; orgId: string; actor: ActorType; actorId: string } | { type: "org"; orgId: string; actor: ActorType; actorId: string; actorOrgId?: string }
| {
type: "orgSlug";
orgSlug: string;
}
| { | {
type: "ssoId"; type: "ssoId";
id: string; id: string;
@ -37,7 +41,6 @@ export type TSamlLoginDTO = {
lastName?: string; lastName?: string;
authProvider: string; authProvider: string;
orgId: string; orgId: string;
isSignupAllowed: boolean;
// saml thingy // saml thingy
relayState?: string; relayState?: string;
}; };

View File

@ -44,6 +44,7 @@ export const secretApprovalPolicyServiceFactory = ({
name, name,
actor, actor,
actorId, actorId,
actorOrgId,
approvals, approvals,
approvers, approvers,
projectId, projectId,
@ -53,7 +54,7 @@ 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); const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId);
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Create, ProjectPermissionActions.Create,
ProjectPermissionSub.SecretApproval ProjectPermissionSub.SecretApproval
@ -96,13 +97,19 @@ export const secretApprovalPolicyServiceFactory = ({
name, name,
actorId, actorId,
actor, actor,
actorOrgId,
approvals, approvals,
secretPolicyId secretPolicyId
}: TUpdateSapDTO) => { }: TUpdateSapDTO) => {
const secretApprovalPolicy = await secretApprovalPolicyDAL.findById(secretPolicyId); const secretApprovalPolicy = await secretApprovalPolicyDAL.findById(secretPolicyId);
if (!secretApprovalPolicy) throw new BadRequestError({ message: "Secret approval policy not found" }); if (!secretApprovalPolicy) throw new BadRequestError({ message: "Secret approval policy not found" });
const { permission } = await permissionService.getProjectPermission(actor, actorId, secretApprovalPolicy.projectId); const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
secretApprovalPolicy.projectId,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.SecretApproval); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.SecretApproval);
const updatedSap = await secretApprovalPolicyDAL.transaction(async (tx) => { const updatedSap = await secretApprovalPolicyDAL.transaction(async (tx) => {
@ -145,11 +152,16 @@ export const secretApprovalPolicyServiceFactory = ({
}; };
}; };
const deleteSecretApprovalPolicy = async ({ secretPolicyId, actor, actorId }: TDeleteSapDTO) => { const deleteSecretApprovalPolicy = async ({ secretPolicyId, actor, actorId, 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" });
const { permission } = await permissionService.getProjectPermission(actor, actorId, sapPolicy.projectId); const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
sapPolicy.projectId,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Delete, ProjectPermissionActions.Delete,
ProjectPermissionSub.SecretApproval ProjectPermissionSub.SecretApproval
@ -159,8 +171,8 @@ export const secretApprovalPolicyServiceFactory = ({
return sapPolicy; return sapPolicy;
}; };
const getSecretApprovalPolicyByProjectId = async ({ actorId, actor, projectId }: TListSapDTO) => { const getSecretApprovalPolicyByProjectId = async ({ actorId, actor, actorOrgId, projectId }: TListSapDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, 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 });
@ -188,10 +200,11 @@ export const secretApprovalPolicyServiceFactory = ({
projectId, projectId,
actor, actor,
actorId, actorId,
actorOrgId,
environment, environment,
secretPath secretPath
}: TGetBoardSapDTO) => { }: TGetBoardSapDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId);
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Read, ProjectPermissionActions.Read,
subject(ProjectPermissionSub.Secrets, { secretPath, environment }) subject(ProjectPermissionSub.Secrets, { secretPath, environment })

View File

@ -73,10 +73,15 @@ export const secretApprovalRequestServiceFactory = ({
secretVersionDAL, secretVersionDAL,
secretQueueService secretQueueService
}: TSecretApprovalRequestServiceFactoryDep) => { }: TSecretApprovalRequestServiceFactoryDep) => {
const requestCount = async ({ projectId, actor, actorId }: TApprovalRequestCountDTO) => { const requestCount = async ({ projectId, actor, actorId, actorOrgId }: 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(actor as ActorType.USER, actorId, projectId); const { membership } = await permissionService.getProjectPermission(
actor as ActorType.USER,
actorId,
projectId,
actorOrgId
);
const count = await secretApprovalRequestDAL.findProjectRequestCount(projectId, membership.id); const count = await secretApprovalRequestDAL.findProjectRequestCount(projectId, membership.id);
return count; return count;
@ -86,6 +91,7 @@ export const secretApprovalRequestServiceFactory = ({
projectId, projectId,
actorId, actorId,
actor, actor,
actorOrgId,
status, status,
environment, environment,
committer, committer,
@ -94,7 +100,7 @@ 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); const { membership } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId);
const approvals = await secretApprovalRequestDAL.findByProjectId({ const approvals = await secretApprovalRequestDAL.findByProjectId({
projectId, projectId,
committer, committer,
@ -107,7 +113,7 @@ export const secretApprovalRequestServiceFactory = ({
return approvals; return approvals;
}; };
const getSecretApprovalDetails = async ({ actor, actorId, id }: TSecretApprovalDetailsDTO) => { const getSecretApprovalDetails = async ({ actor, actorId, actorOrgId, 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);
@ -117,7 +123,8 @@ export const secretApprovalRequestServiceFactory = ({
const { membership } = await permissionService.getProjectPermission( const { membership } = await permissionService.getProjectPermission(
actor, actor,
actorId, actorId,
secretApprovalRequest.projectId secretApprovalRequest.projectId,
actorOrgId
); );
if ( if (
membership.role !== ProjectMembershipRole.Admin && membership.role !== ProjectMembershipRole.Admin &&
@ -134,7 +141,7 @@ 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 }: TReviewRequestDTO) => { const reviewApproval = async ({ approvalId, actor, status, actorId, 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" });
@ -143,7 +150,8 @@ export const secretApprovalRequestServiceFactory = ({
const { membership } = await permissionService.getProjectPermission( const { membership } = await permissionService.getProjectPermission(
ActorType.USER, ActorType.USER,
actorId, actorId,
secretApprovalRequest.projectId secretApprovalRequest.projectId,
actorOrgId
); );
if ( if (
membership.role !== ProjectMembershipRole.Admin && membership.role !== ProjectMembershipRole.Admin &&
@ -175,7 +183,7 @@ export const secretApprovalRequestServiceFactory = ({
return reviewStatus; return reviewStatus;
}; };
const updateApprovalStatus = async ({ actorId, status, approvalId, actor }: TStatusChangeDTO) => { const updateApprovalStatus = async ({ actorId, status, approvalId, actor, actorOrgId }: 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" });
@ -184,7 +192,8 @@ export const secretApprovalRequestServiceFactory = ({
const { membership } = await permissionService.getProjectPermission( const { membership } = await permissionService.getProjectPermission(
ActorType.USER, ActorType.USER,
actorId, actorId,
secretApprovalRequest.projectId secretApprovalRequest.projectId,
actorOrgId
); );
if ( if (
membership.role !== ProjectMembershipRole.Admin && membership.role !== ProjectMembershipRole.Admin &&
@ -207,13 +216,18 @@ export const secretApprovalRequestServiceFactory = ({
return { ...secretApprovalRequest, ...updatedRequest }; return { ...secretApprovalRequest, ...updatedRequest };
}; };
const mergeSecretApprovalRequest = async ({ approvalId, actor, actorId }: TMergeSecretApprovalRequestDTO) => { const mergeSecretApprovalRequest = async ({
approvalId,
actor,
actorId,
actorOrgId
}: 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" });
if (actor !== ActorType.USER) throw new BadRequestError({ message: "Must be a user" }); if (actor !== ActorType.USER) throw new BadRequestError({ message: "Must be a user" });
const { policy, folderId, projectId } = secretApprovalRequest; const { policy, folderId, projectId } = secretApprovalRequest;
const { membership } = await permissionService.getProjectPermission(ActorType.USER, actorId, projectId); const { membership } = await permissionService.getProjectPermission(ActorType.USER, actorId, projectId, actorOrgId);
if ( if (
membership.role !== ProjectMembershipRole.Admin && membership.role !== ProjectMembershipRole.Admin &&
secretApprovalRequest.committerId !== membership.id && secretApprovalRequest.committerId !== membership.id &&
@ -401,6 +415,7 @@ export const secretApprovalRequestServiceFactory = ({
data, data,
actorId, actorId,
actor, actor,
actorOrgId,
policy, policy,
projectId, projectId,
secretPath, secretPath,
@ -408,7 +423,12 @@ export const secretApprovalRequestServiceFactory = ({
}: TGenerateSecretApprovalRequestDTO) => { }: TGenerateSecretApprovalRequestDTO) => {
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 { permission, membership } = await permissionService.getProjectPermission(actor, actorId, projectId); const { permission, membership } = await permissionService.getProjectPermission(
actor,
actorId,
projectId,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Read, ProjectPermissionActions.Read,
subject(ProjectPermissionSub.Secrets, { environment, secretPath }) subject(ProjectPermissionSub.Secrets, { environment, secretPath })

View File

@ -14,13 +14,7 @@ import { ProjectPermissionActions, ProjectPermissionSub } from "../permission/pr
import { TSecretRotationDALFactory } from "./secret-rotation-dal"; import { TSecretRotationDALFactory } from "./secret-rotation-dal";
import { TSecretRotationQueueFactory } from "./secret-rotation-queue"; import { TSecretRotationQueueFactory } from "./secret-rotation-queue";
import { TSecretRotationEncData } from "./secret-rotation-queue/secret-rotation-queue-types"; import { TSecretRotationEncData } from "./secret-rotation-queue/secret-rotation-queue-types";
import { import { TCreateSecretRotationDTO, TDeleteDTO, TListByProjectIdDTO, TRestartDTO } from "./secret-rotation-types";
TCreateSecretRotationDTO,
TDeleteDTO,
TGetByIdDTO,
TListByProjectIdDTO,
TRestartDTO
} from "./secret-rotation-types";
import { rotationTemplates } from "./templates"; import { rotationTemplates } from "./templates";
type TSecretRotationServiceFactoryDep = { type TSecretRotationServiceFactoryDep = {
@ -45,8 +39,8 @@ export const secretRotationServiceFactory = ({
folderDAL, folderDAL,
secretDAL secretDAL
}: TSecretRotationServiceFactoryDep) => { }: TSecretRotationServiceFactoryDep) => {
const getProviderTemplates = async ({ actor, actorId, projectId }: TProjectPermission) => { const getProviderTemplates = async ({ actor, actorId, actorOrgId, projectId }: TProjectPermission) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.SecretRotation); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.SecretRotation);
return { return {
@ -59,6 +53,7 @@ export const secretRotationServiceFactory = ({
projectId, projectId,
actorId, actorId,
actor, actor,
actorOrgId,
inputs, inputs,
outputs, outputs,
interval, interval,
@ -66,7 +61,7 @@ export const secretRotationServiceFactory = ({
secretPath, secretPath,
environment environment
}: TCreateSecretRotationDTO) => { }: TCreateSecretRotationDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId);
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Create, ProjectPermissionActions.Create,
ProjectPermissionSub.SecretRotation ProjectPermissionSub.SecretRotation
@ -144,23 +139,14 @@ export const secretRotationServiceFactory = ({
return secretRotation; return secretRotation;
}; };
const getById = async ({ rotationId, actor, actorId }: TGetByIdDTO) => { const getByProjectId = async ({ actorId, projectId, actor, actorOrgId }: TListByProjectIdDTO) => {
const [doc] = await secretRotationDAL.find({ id: rotationId }); const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId);
if (!doc) throw new BadRequestError({ message: "Rotation not found" });
const { permission } = await permissionService.getProjectPermission(actor, actorId, doc.projectId);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.SecretRotation);
return doc;
};
const getByProjectId = async ({ actorId, projectId, actor }: TListByProjectIdDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId);
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, rotationId }: TRestartDTO) => { const restartById = async ({ actor, actorId, actorOrgId, 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" });
@ -171,18 +157,18 @@ 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); const { permission } = await permissionService.getProjectPermission(actor, actorId, doc.projectId, 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, rotationId }: TDeleteDTO) => { const deleteById = async ({ actor, actorId, actorOrgId, 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); const { permission } = await permissionService.getProjectPermission(actor, actorId, doc.projectId, actorOrgId);
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Delete, ProjectPermissionActions.Delete,
ProjectPermissionSub.SecretRotation ProjectPermissionSub.SecretRotation
@ -197,7 +183,6 @@ export const secretRotationServiceFactory = ({
return { return {
getProviderTemplates, getProviderTemplates,
getById,
getByProjectId, getByProjectId,
createRotation, createRotation,
restartById, restartById,

View File

@ -18,7 +18,3 @@ export type TDeleteDTO = {
export type TRestartDTO = { export type TRestartDTO = {
rotationId: string; rotationId: string;
} & Omit<TProjectPermission, "projectId">; } & Omit<TProjectPermission, "projectId">;
export type TGetByIdDTO = {
rotationId: string;
} & Omit<TProjectPermission, "projectId">;

View File

@ -39,8 +39,8 @@ export const secretScanningServiceFactory = ({
permissionService, permissionService,
secretScanningQueue secretScanningQueue
}: TSecretScanningServiceFactoryDep) => { }: TSecretScanningServiceFactoryDep) => {
const createInstallationSession = async ({ actor, orgId, actorId }: TInstallAppSessionDTO) => { const createInstallationSession = async ({ actor, orgId, actorId, actorOrgId }: TInstallAppSessionDTO) => {
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId); const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, 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");
@ -48,11 +48,17 @@ export const secretScanningServiceFactory = ({
return { sessionId }; return { sessionId };
}; };
const linkInstallationToOrg = async ({ sessionId, actorId, installationId, actor }: TLinkInstallSessionDTO) => { const linkInstallationToOrg = async ({
sessionId,
actorId,
installationId,
actor,
actorOrgId
}: 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); const { permission } = await permissionService.getOrgPermission(actor, actorId, session.orgId, 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);
@ -83,23 +89,23 @@ export const secretScanningServiceFactory = ({
return { installatedApp }; return { installatedApp };
}; };
const getOrgInstallationStatus = async ({ actorId, orgId, actor }: TGetOrgInstallStatusDTO) => { const getOrgInstallationStatus = async ({ actorId, orgId, actor, actorOrgId }: TGetOrgInstallStatusDTO) => {
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId); const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, 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 }: TGetOrgRisksDTO) => { const getRisksByOrg = async ({ actor, orgId, actorId, actorOrgId }: TGetOrgRisksDTO) => {
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId); const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, 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, riskId, status }: TUpdateRiskStatusDTO) => { const updateRiskStatus = async ({ actorId, orgId, actor, actorOrgId, riskId, status }: TUpdateRiskStatusDTO) => {
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId); const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, actorOrgId);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Edit, OrgPermissionSubjects.SecretScanning); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Edit, OrgPermissionSubjects.SecretScanning);
const isRiskResolved = Boolean( const isRiskResolved = Boolean(

View File

@ -58,9 +58,10 @@ export const secretSnapshotServiceFactory = ({
projectId, projectId,
actorId, actorId,
actor, actor,
actorOrgId,
path path
}: TProjectSnapshotCountDTO) => { }: TProjectSnapshotCountDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, 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);
@ -75,11 +76,12 @@ export const secretSnapshotServiceFactory = ({
projectId, projectId,
actorId, actorId,
actor, actor,
actorOrgId,
path, path,
limit = 20, limit = 20,
offset = 0 offset = 0
}: TProjectSnapshotListDTO) => { }: TProjectSnapshotListDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, 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);
@ -89,10 +91,10 @@ export const secretSnapshotServiceFactory = ({
return snapshots; return snapshots;
}; };
const getSnapshotData = async ({ actorId, actor, id }: TGetSnapshotDataDTO) => { const getSnapshotData = async ({ actorId, actor, actorOrgId, 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); const { permission } = await permissionService.getProjectPermission(actor, actorId, snapshot.projectId, actorOrgId);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.SecretRollback); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.SecretRollback);
return snapshot; return snapshot;
}; };
@ -143,11 +145,11 @@ export const secretSnapshotServiceFactory = ({
} }
}; };
const rollbackSnapshot = async ({ id: snapshotId, actor, actorId }: TRollbackSnapshotDTO) => { const rollbackSnapshot = async ({ id: snapshotId, actor, actorId, 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); const { permission } = await permissionService.getProjectPermission(actor, actorId, snapshot.projectId, actorOrgId);
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Create, ProjectPermissionActions.Create,
ProjectPermissionSub.SecretRollback ProjectPermissionSub.SecretRollback

View File

@ -26,8 +26,8 @@ export const trustedIpServiceFactory = ({
licenseService, licenseService,
projectDAL projectDAL
}: TTrustedIpServiceFactoryDep) => { }: TTrustedIpServiceFactoryDep) => {
const listIpsByProjectId = async ({ projectId, actor, actorId }: TProjectPermission) => { const listIpsByProjectId = async ({ projectId, actor, actorId, actorOrgId }: TProjectPermission) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, 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
@ -35,8 +35,16 @@ export const trustedIpServiceFactory = ({
return trustedIps; return trustedIps;
}; };
const addProjectIp = async ({ projectId, actorId, actor, ipAddress: ip, comment, isActive }: TCreateIpDTO) => { const addProjectIp = async ({
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); projectId,
actorId,
actor,
actorOrgId,
ipAddress: ip,
comment,
isActive
}: TCreateIpDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, 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);
@ -65,8 +73,16 @@ export const trustedIpServiceFactory = ({
return { trustedIp, project }; // for audit log return { trustedIp, project }; // for audit log
}; };
const updateProjectIp = async ({ projectId, actorId, actor, ipAddress: ip, comment, trustedIpId }: TUpdateIpDTO) => { const updateProjectIp = async ({
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); projectId,
actorId,
actor,
actorOrgId,
ipAddress: ip,
comment,
trustedIpId
}: TUpdateIpDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, 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);
@ -97,8 +113,8 @@ export const trustedIpServiceFactory = ({
return { trustedIp, project }; // for audit log return { trustedIp, project }; // for audit log
}; };
const deleteProjectIp = async ({ projectId, actorId, actor, trustedIpId }: TDeleteIpDTO) => { const deleteProjectIp = async ({ projectId, actorId, actor, actorOrgId, trustedIpId }: TDeleteIpDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, 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);

View File

@ -95,7 +95,7 @@ const envSchema = z
SECRET_SCANNING_GIT_APP_ID: zpStr(z.string().optional()), SECRET_SCANNING_GIT_APP_ID: zpStr(z.string().optional()),
SECRET_SCANNING_PRIVATE_KEY: zpStr(z.string().optional()), SECRET_SCANNING_PRIVATE_KEY: zpStr(z.string().optional()),
// LICENCE // LICENCE
LICENSE_SERVER_URL: zpStr(z.string().optional()), LICENSE_SERVER_URL: zpStr(z.string().optional().default("https://portal.infisical.com")),
LICENSE_SERVER_KEY: zpStr(z.string().optional()), LICENSE_SERVER_KEY: zpStr(z.string().optional()),
LICENSE_KEY: zpStr(z.string().optional()), LICENSE_KEY: zpStr(z.string().optional()),
STANDALONE_MODE: z STANDALONE_MODE: z

View File

@ -4,12 +4,14 @@ export type TOrgPermission = {
actor: ActorType; actor: ActorType;
actorId: string; actorId: string;
orgId: string; orgId: string;
actorOrgId?: string;
}; };
export type TProjectPermission = { export type TProjectPermission = {
actor: ActorType; actor: ActorType;
actorId: string; actorId: string;
projectId: string; projectId: string;
actorOrgId?: string;
}; };
export type RequiredKeys<T> = { export type RequiredKeys<T> = {

View File

@ -10,6 +10,7 @@ import { TIdentityAccessTokenJwtPayload } from "@app/services/identity-access-to
export type TAuthMode = export type TAuthMode =
| { | {
orgId?: string;
authMode: AuthMode.JWT; authMode: AuthMode.JWT;
actor: ActorType.USER; actor: ActorType.USER;
userId: string; userId: string;
@ -21,6 +22,7 @@ export type TAuthMode =
actor: ActorType.USER; actor: ActorType.USER;
userId: string; userId: string;
user: TUsers; user: TUsers;
orgId?: string;
} }
| { | {
authMode: AuthMode.SERVICE_TOKEN; authMode: AuthMode.SERVICE_TOKEN;
@ -82,8 +84,8 @@ export const injectIdentity = fp(async (server: FastifyZodProvider) => {
switch (authMode) { switch (authMode) {
case AuthMode.JWT: { case AuthMode.JWT: {
const { user, tokenVersionId } = 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 }; req.auth = { authMode: AuthMode.JWT, user, userId: user.id, tokenVersionId, actor, orgId };
break; break;
} }
case AuthMode.IDENTITY_ACCESS_TOKEN: { case AuthMode.IDENTITY_ACCESS_TOKEN: {

View File

@ -9,7 +9,7 @@ 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 }; req.permission = { type: ActorType.USER, id: req.auth.userId, orgId: req.auth?.orgId };
} 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 };
} else if (req.auth.actor === ActorType.SERVICE) { } else if (req.auth.actor === ActorType.SERVICE) {

View File

@ -88,7 +88,8 @@ export const registerAuthRoutes = async (server: FastifyZodProvider) => {
authTokenType: AuthTokenType.ACCESS_TOKEN, authTokenType: AuthTokenType.ACCESS_TOKEN,
userId: decodedToken.userId, userId: decodedToken.userId,
tokenVersionId: tokenVersion.id, tokenVersionId: tokenVersion.id,
accessVersion: tokenVersion.accessVersion accessVersion: tokenVersion.accessVersion,
organizationId: decodedToken.organizationId
}, },
appCfg.AUTH_SECRET, appCfg.AUTH_SECRET,
{ expiresIn: appCfg.JWT_AUTH_LIFETIME } { expiresIn: appCfg.JWT_AUTH_LIFETIME }

View File

@ -29,6 +29,7 @@ export const registerProjectBotRouter = async (server: FastifyZodProvider) => {
const bot = await server.services.projectBot.findBotByProjectId({ const bot = await server.services.projectBot.findBotByProjectId({
actor: req.permission.type, actor: req.permission.type,
actorId: req.permission.id, actorId: req.permission.id,
actorOrgId: req.permission.orgId,
projectId: req.params.projectId projectId: req.params.projectId
}); });
return { bot }; return { bot };
@ -68,6 +69,7 @@ export const registerProjectBotRouter = async (server: FastifyZodProvider) => {
const bot = await server.services.projectBot.setBotActiveState({ const bot = await server.services.projectBot.setBotActiveState({
actor: req.permission.type, actor: req.permission.type,
actorId: req.permission.id, actorId: req.permission.id,
actorOrgId: req.permission.orgId,
botId: req.params.botId, botId: req.params.botId,
botKey: req.body.botKey, botKey: req.body.botKey,
isActive: req.body.isActive isActive: req.body.isActive

View File

@ -26,6 +26,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,
actorOrgId: req.permission.orgId,
...req.body, ...req.body,
orgId: req.body.organizationId orgId: req.body.organizationId
}); });
@ -68,6 +69,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,
actorOrgId: req.permission.orgId,
id: req.params.identityId, id: req.params.identityId,
...req.body ...req.body
}); });
@ -106,6 +108,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,
actorOrgId: req.permission.orgId,
id: req.params.identityId id: req.params.identityId
}); });

View File

@ -112,6 +112,7 @@ export const registerIdentityUaRouter = async (server: FastifyZodProvider) => {
const identityUniversalAuth = await server.services.identityUa.attachUa({ const identityUniversalAuth = await server.services.identityUa.attachUa({
actor: req.permission.type, actor: req.permission.type,
actorId: req.permission.id, actorId: req.permission.id,
actorOrgId: req.permission.orgId,
...req.body, ...req.body,
identityId: req.params.identityId identityId: req.params.identityId
}); });
@ -178,6 +179,7 @@ export const registerIdentityUaRouter = async (server: FastifyZodProvider) => {
const identityUniversalAuth = await server.services.identityUa.updateUa({ const identityUniversalAuth = await server.services.identityUa.updateUa({
actor: req.permission.type, actor: req.permission.type,
actorId: req.permission.id, actorId: req.permission.id,
actorOrgId: req.permission.orgId,
...req.body, ...req.body,
identityId: req.params.identityId identityId: req.params.identityId
}); });
@ -220,6 +222,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,
actorOrgId: req.permission.orgId,
identityId: req.params.identityId identityId: req.params.identityId
}); });
@ -262,6 +265,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,
actorOrgId: req.permission.orgId,
identityId: req.params.identityId, identityId: req.params.identityId,
...req.body ...req.body
}); });
@ -300,6 +304,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,
actorOrgId: req.permission.orgId,
identityId: req.params.identityId identityId: req.params.identityId
}); });
@ -336,6 +341,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,
actorOrgId: req.permission.orgId,
identityId: req.params.identityId, identityId: req.params.identityId,
clientSecretId: req.params.clientSecretId clientSecretId: req.params.clientSecretId
}); });

View File

@ -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,
actorOrgId: req.permission.orgId,
id: req.params.integrationAuthId id: req.params.integrationAuthId
}); });
return { integrationAuth }; return { integrationAuth };
@ -78,6 +79,7 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider)
const integrationAuth = await server.services.integrationAuth.deleteIntegrationAuths({ const integrationAuth = await server.services.integrationAuth.deleteIntegrationAuths({
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorOrgId: req.permission.orgId,
integration: req.query.integration, integration: req.query.integration,
projectId: req.query.projectId projectId: req.query.projectId
}); });
@ -115,6 +117,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,
actorOrgId: req.permission.orgId,
id: req.params.integrationAuthId id: req.params.integrationAuthId
}); });
@ -154,6 +157,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,
actorOrgId: req.permission.orgId,
projectId: req.body.workspaceId, projectId: req.body.workspaceId,
...req.body ...req.body
}); });
@ -196,6 +200,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,
actorOrgId: req.permission.orgId,
projectId: req.body.workspaceId, projectId: req.body.workspaceId,
...req.body ...req.body
}); });
@ -242,6 +247,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,
actorOrgId: req.permission.orgId,
id: req.params.integrationAuthId, id: req.params.integrationAuthId,
...req.query ...req.query
}); });
@ -272,6 +278,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,
actorOrgId: req.permission.orgId,
id: req.params.integrationAuthId id: req.params.integrationAuthId
}); });
return { teams }; return { teams };
@ -299,6 +306,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,
actorOrgId: req.permission.orgId,
id: req.params.integrationAuthId, id: req.params.integrationAuthId,
appId: req.query.appId appId: req.query.appId
}); });
@ -327,6 +335,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,
actorOrgId: req.permission.orgId,
id: req.params.integrationAuthId, id: req.params.integrationAuthId,
accountId: req.query.accountId accountId: req.query.accountId
}); });
@ -352,6 +361,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,
actorOrgId: req.permission.orgId,
id: req.params.integrationAuthId id: req.params.integrationAuthId
}); });
return { orgs }; return { orgs };
@ -379,6 +389,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,
actorOrgId: req.permission.orgId,
id: req.params.integrationAuthId, id: req.params.integrationAuthId,
orgId: req.query.orgId orgId: req.query.orgId
}); });
@ -407,6 +418,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,
actorOrgId: req.permission.orgId,
id: req.params.integrationAuthId, id: req.params.integrationAuthId,
projectId: req.query.projectId projectId: req.query.projectId
}); });
@ -435,6 +447,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,
actorOrgId: req.permission.orgId,
id: req.params.integrationAuthId, id: req.params.integrationAuthId,
environmentId: req.query.environmentId environmentId: req.query.environmentId
}); });
@ -463,6 +476,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,
actorOrgId: req.permission.orgId,
id: req.params.integrationAuthId, id: req.params.integrationAuthId,
environmentId: req.query.environmentId environmentId: req.query.environmentId
}); });
@ -491,6 +505,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,
actorOrgId: req.permission.orgId,
id: req.params.integrationAuthId, id: req.params.integrationAuthId,
environmentId: req.query.environmentId environmentId: req.query.environmentId
}); });
@ -519,6 +534,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,
actorOrgId: req.permission.orgId,
id: req.params.integrationAuthId, id: req.params.integrationAuthId,
appId: req.query.appId appId: req.query.appId
}); });
@ -547,6 +563,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,
actorOrgId: req.permission.orgId,
id: req.params.integrationAuthId, id: req.params.integrationAuthId,
appId: req.query.appId appId: req.query.appId
}); });
@ -582,6 +599,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,
actorOrgId: req.permission.orgId,
id: req.params.integrationAuthId id: req.params.integrationAuthId
}); });
return { workspaces }; return { workspaces };
@ -614,6 +632,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,
actorOrgId: req.permission.orgId,
id: req.params.integrationAuthId, id: req.params.integrationAuthId,
appId: req.query.appId appId: req.query.appId
}); });
@ -647,6 +666,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,
actorOrgId: req.permission.orgId,
id: req.params.integrationAuthId, id: req.params.integrationAuthId,
appId: req.query.appId appId: req.query.appId
}); });

View File

@ -50,6 +50,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,
actorOrgId: req.permission.orgId,
...req.body ...req.body
}); });
await server.services.auditLog.createAuditLog({ await server.services.auditLog.createAuditLog({
@ -107,6 +108,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,
actorOrgId: req.permission.orgId,
id: req.params.integrationId, id: req.params.integrationId,
...req.body ...req.body
}); });
@ -132,6 +134,7 @@ export const registerIntegrationRouter = async (server: FastifyZodProvider) => {
const integration = await server.services.integration.deleteIntegration({ const integration = await server.services.integration.deleteIntegration({
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorOrgId: req.permission.orgId,
id: req.params.integrationId id: req.params.integrationId
}); });

View File

@ -26,7 +26,8 @@ export const registerInviteOrgRouter = async (server: FastifyZodProvider) => {
const completeInviteLink = await server.services.org.inviteUserToOrganization({ const completeInviteLink = await server.services.org.inviteUserToOrganization({
orgId: req.body.organizationId, orgId: req.body.organizationId,
userId: req.permission.id, userId: req.permission.id,
inviteeEmail: req.body.inviteeEmail inviteeEmail: req.body.inviteeEmail,
actorOrgId: req.permission.orgId
}); });
return { return {

View File

@ -37,7 +37,11 @@ export const registerOrgRouter = async (server: FastifyZodProvider) => {
}, },
onRequest: verifyAuth([AuthMode.JWT]), onRequest: verifyAuth([AuthMode.JWT]),
handler: async (req) => { handler: async (req) => {
const organization = await server.services.org.findOrganizationById(req.permission.id, req.params.organizationId); const organization = await server.services.org.findOrganizationById(
req.permission.id,
req.params.organizationId,
req.permission.orgId
);
return { organization }; return { organization };
} }
}); });
@ -68,17 +72,29 @@ export const registerOrgRouter = async (server: FastifyZodProvider) => {
}, },
onRequest: verifyAuth([AuthMode.JWT]), onRequest: verifyAuth([AuthMode.JWT]),
handler: async (req) => { handler: async (req) => {
const users = await server.services.org.findAllOrgMembers(req.permission.id, req.params.organizationId); const users = await server.services.org.findAllOrgMembers(
req.permission.id,
req.params.organizationId,
req.permission.orgId
);
return { users }; return { users };
} }
}); });
server.route({ server.route({
method: "PATCH", method: "PATCH",
url: "/:organizationId/name", url: "/:organizationId",
schema: { schema: {
params: z.object({ organizationId: z.string().trim() }), params: z.object({ organizationId: z.string().trim() }),
body: z.object({ name: z.string().trim() }), body: z.object({
name: z.string().trim().optional(),
slug: z
.string()
.trim()
.regex(/^[a-zA-Z0-9-]+$/, "Name must only contain alphanumeric characters or hyphens")
.optional(),
authEnforced: z.boolean().optional()
}),
response: { response: {
200: z.object({ 200: z.object({
message: z.string(), message: z.string(),
@ -88,11 +104,14 @@ export const registerOrgRouter = async (server: FastifyZodProvider) => {
}, },
onRequest: verifyAuth([AuthMode.JWT]), onRequest: verifyAuth([AuthMode.JWT]),
handler: async (req) => { handler: async (req) => {
const organization = await server.services.org.updateOrgName( const organization = await server.services.org.updateOrg({
req.permission.id, actor: req.permission.type,
req.params.organizationId, actorId: req.permission.id,
req.body.name actorOrgId: req.permission.orgId,
); orgId: req.params.organizationId,
data: req.body
});
return { return {
message: "Successfully changed organization name", message: "Successfully changed organization name",
organization organization
@ -115,7 +134,8 @@ export const registerOrgRouter = async (server: FastifyZodProvider) => {
handler: async (req) => { handler: async (req) => {
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.orgId
); );
return { incidentContactsOrg }; return { incidentContactsOrg };
} }
@ -138,7 +158,8 @@ export const registerOrgRouter = async (server: FastifyZodProvider) => {
const incidentContactsOrg = await req.server.services.org.createIncidentContact( const incidentContactsOrg = await req.server.services.org.createIncidentContact(
req.permission.id, req.permission.id,
req.params.organizationId, req.params.organizationId,
req.body.email req.body.email,
req.permission.orgId
); );
return { incidentContactsOrg }; return { incidentContactsOrg };
} }
@ -160,7 +181,8 @@ export const registerOrgRouter = async (server: FastifyZodProvider) => {
const incidentContactsOrg = await req.server.services.org.deleteIncidentContact( const incidentContactsOrg = await req.server.services.org.deleteIncidentContact(
req.permission.id, req.permission.id,
req.params.organizationId, req.params.organizationId,
req.params.incidentContactId req.params.incidentContactId,
req.permission.orgId
); );
return { incidentContactsOrg }; return { incidentContactsOrg };
} }

View File

@ -30,6 +30,7 @@ export const registerProjectEnvRouter = async (server: FastifyZodProvider) => {
const environment = await server.services.projectEnv.createEnvironment({ const environment = await server.services.projectEnv.createEnvironment({
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorOrgId: req.permission.orgId,
projectId: req.params.workspaceId, projectId: req.params.workspaceId,
...req.body ...req.body
}); });
@ -79,6 +80,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,
actorOrgId: req.permission.orgId,
projectId: req.params.workspaceId, projectId: req.params.workspaceId,
id: req.params.id, id: req.params.id,
...req.body ...req.body
@ -129,6 +131,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,
actorOrgId: req.permission.orgId,
projectId: req.params.workspaceId, projectId: req.params.workspaceId,
id: req.params.id id: req.params.id
}); });

View File

@ -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,
actorOrgId: req.permission.orgId,
nonce: req.body.key.nonce, nonce: req.body.key.nonce,
receiverId: req.body.key.userId, receiverId: req.body.key.userId,
encryptedKey: req.body.key.encryptedKey encryptedKey: req.body.key.encryptedKey

View File

@ -35,6 +35,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,
actorOrgId: req.permission.orgId,
projectId: req.params.workspaceId projectId: req.params.workspaceId
}); });
return { memberships }; return { memberships };
@ -70,6 +71,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,
actorOrgId: req.permission.orgId,
projectId: req.params.workspaceId, projectId: req.params.workspaceId,
members: req.body.members members: req.body.members
}); });
@ -112,6 +114,7 @@ export const registerProjectMembershipRouter = async (server: FastifyZodProvider
const membership = await server.services.projectMembership.updateProjectMembership({ const membership = await server.services.projectMembership.updateProjectMembership({
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorOrgId: req.permission.orgId,
projectId: req.params.workspaceId, projectId: req.params.workspaceId,
membershipId: req.params.membershipId, membershipId: req.params.membershipId,
role: req.body.role role: req.body.role
@ -153,6 +156,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,
actorOrgId: req.permission.orgId,
projectId: req.params.workspaceId, projectId: req.params.workspaceId,
membershipId: req.params.membershipId membershipId: req.params.membershipId
}); });

View File

@ -46,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,
actorOrgId: req.permission.orgId,
projectId: req.params.workspaceId projectId: req.params.workspaceId
}); });
return { publicKeys }; return { publicKeys };
@ -81,7 +82,8 @@ 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,
projectId: req.params.workspaceId projectId: req.params.workspaceId,
actorOrgId: req.permission.orgId
}); });
return { users }; return { users };
} }
@ -122,6 +124,7 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
const workspace = await server.services.project.getAProject({ const workspace = await server.services.project.getAProject({
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorOrgId: req.permission.orgId,
projectId: req.params.workspaceId projectId: req.params.workspaceId
}); });
return { workspace }; return { workspace };
@ -148,6 +151,7 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
orgId: req.body.organizationId, orgId: req.body.organizationId,
actorOrgId: req.permission.orgId,
workspaceName: req.body.workspaceName workspaceName: req.body.workspaceName
}); });
return { workspace }; return { workspace };
@ -172,6 +176,7 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
const workspace = await server.services.project.deleteProject({ const workspace = await server.services.project.deleteProject({
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorOrgId: req.permission.orgId,
projectId: req.params.workspaceId projectId: req.params.workspaceId
}); });
return { workspace }; return { workspace };
@ -200,6 +205,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,
actorOrgId: req.permission.orgId,
projectId: req.params.workspaceId, projectId: req.params.workspaceId,
name: req.body.name name: req.body.name
}); });
@ -232,6 +238,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,
actorOrgId: req.permission.orgId,
projectId: req.params.workspaceId, projectId: req.params.workspaceId,
autoCapitalization: req.body.autoCapitalization autoCapitalization: req.body.autoCapitalization
}); });
@ -264,6 +271,7 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
const { invitee, latestKey } = await server.services.projectMembership.inviteUserToProject({ const { invitee, latestKey } = await server.services.projectMembership.inviteUserToProject({
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorOrgId: req.permission.orgId,
projectId: req.params.workspaceId, projectId: req.params.workspaceId,
email: req.body.email email: req.body.email
}); });
@ -309,6 +317,7 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
const integrations = await server.services.integration.listIntegrationByProject({ const integrations = await server.services.integration.listIntegrationByProject({
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorOrgId: req.permission.orgId,
projectId: req.params.workspaceId projectId: req.params.workspaceId
}); });
return { integrations }; return { integrations };
@ -333,6 +342,7 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
const authorizations = await server.services.integrationAuth.listIntegrationAuthByProjectId({ const authorizations = await server.services.integrationAuth.listIntegrationAuthByProjectId({
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorOrgId: req.permission.orgId,
projectId: req.params.workspaceId projectId: req.params.workspaceId
}); });
return { authorizations }; return { authorizations };
@ -357,6 +367,7 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
const serviceTokenData = await server.services.serviceToken.getProjectServiceTokens({ const serviceTokenData = await server.services.serviceToken.getProjectServiceTokens({
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorOrgId: req.permission.orgId,
projectId: req.params.workspaceId projectId: req.params.workspaceId
}); });
return { serviceTokenData }; return { serviceTokenData };

View File

@ -31,6 +31,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,
actorOrgId: req.permission.orgId,
...req.body, ...req.body,
projectId: req.body.workspaceId, projectId: req.body.workspaceId,
path path
@ -80,6 +81,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,
actorOrgId: req.permission.orgId,
...req.body, ...req.body,
projectId: req.body.workspaceId, projectId: req.body.workspaceId,
id: req.params.folderId, id: req.params.folderId,
@ -129,6 +131,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,
actorOrgId: req.permission.orgId,
...req.body, ...req.body,
projectId: req.body.workspaceId, projectId: req.body.workspaceId,
id: req.params.folderId, id: req.params.folderId,
@ -174,6 +177,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,
actorOrgId: req.permission.orgId,
...req.query, ...req.query,
projectId: req.query.workspaceId, projectId: req.query.workspaceId,
path path

View File

@ -36,6 +36,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,
actorOrgId: req.permission.orgId,
...req.body, ...req.body,
projectId: req.body.workspaceId, projectId: req.body.workspaceId,
data: req.body.import data: req.body.import
@ -97,6 +98,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,
actorOrgId: req.permission.orgId,
id: req.params.secretImportId, id: req.params.secretImportId,
...req.body, ...req.body,
projectId: req.body.workspaceId, projectId: req.body.workspaceId,
@ -150,6 +152,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,
actorOrgId: req.permission.orgId,
id: req.params.secretImportId, id: req.params.secretImportId,
...req.body, ...req.body,
projectId: req.body.workspaceId projectId: req.body.workspaceId
@ -201,6 +204,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,
actorOrgId: req.permission.orgId,
...req.query, ...req.query,
projectId: req.query.workspaceId projectId: req.query.workspaceId
}); });
@ -253,6 +257,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,
actorOrgId: req.permission.orgId,
...req.query, ...req.query,
projectId: req.query.workspaceId projectId: req.query.workspaceId
}); });

View File

@ -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,
actorOrgId: req.permission.orgId,
projectId: req.params.projectId projectId: req.params.projectId
}); });
return { workspaceTags }; return { workspaceTags };
@ -52,6 +53,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,
actorOrgId: req.permission.orgId,
projectId: req.params.projectId, projectId: req.params.projectId,
...req.body ...req.body
}); });
@ -78,6 +80,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,
actorOrgId: req.permission.orgId,
id: req.params.tagId id: req.params.tagId
}); });
return { workspaceTag }; return { workspaceTag };

View File

@ -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,
actorOrgId: req.permission.orgId,
projectId: req.body.workspaceId, projectId: req.body.workspaceId,
...req.body ...req.body
}); });
@ -92,6 +93,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,
actorOrgId: req.permission.orgId,
id: req.params.webhookId, id: req.params.webhookId,
isDisabled: req.body.isDisabled isDisabled: req.body.isDisabled
}); });
@ -128,6 +130,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,
actorOrgId: req.permission.orgId,
id: req.params.webhookId id: req.params.webhookId
}); });
@ -169,6 +172,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,
actorOrgId: req.permission.orgId,
id: req.params.webhookId id: req.params.webhookId
}); });
return { message: "Successfully tested webhook", webhook }; return { message: "Successfully tested webhook", webhook };
@ -200,6 +204,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,
actorOrgId: req.permission.orgId,
...req.query, ...req.query,
projectId: req.query.workspaceId projectId: req.query.workspaceId
}); });

View File

@ -34,6 +34,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,
actorOrgId: req.permission.orgId,
orgId: req.params.orgId orgId: req.params.orgId
}); });
return { identityMemberships }; return { identityMemberships };

View File

@ -32,6 +32,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,
actorOrgId: req.permission.orgId,
identityId: req.params.identityId, identityId: req.params.identityId,
projectId: req.params.projectId, projectId: req.params.projectId,
role: req.body.role role: req.body.role
@ -62,6 +63,7 @@ export const registerIdentityProjectRouter = async (server: FastifyZodProvider)
const identityMembership = await server.services.identityProject.updateProjectIdentity({ const identityMembership = await server.services.identityProject.updateProjectIdentity({
actor: req.permission.type, actor: req.permission.type,
actorId: req.permission.id, actorId: req.permission.id,
actorOrgId: req.permission.orgId,
identityId: req.params.identityId, identityId: req.params.identityId,
projectId: req.params.projectId, projectId: req.params.projectId,
role: req.body.role role: req.body.role
@ -89,6 +91,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,
actorOrgId: req.permission.orgId,
identityId: req.params.identityId, identityId: req.params.identityId,
projectId: req.params.projectId projectId: req.params.projectId
}); });
@ -125,6 +128,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,
actorOrgId: req.permission.orgId,
projectId: req.params.projectId projectId: req.params.projectId
}); });
return { identityMemberships }; return { identityMemberships };

View File

@ -26,7 +26,7 @@ export const registerMfaRouter = async (server: FastifyZodProvider) => {
const user = await server.store.user.findById(decodedToken.userId); const user = await server.store.user.findById(decodedToken.userId);
if (!user) throw new Error("User not found"); if (!user) throw new Error("User not found");
req.mfa = { userId: user.id, user }; req.mfa = { userId: user.id, user, orgId: decodedToken.organizationId };
}); });
server.route({ server.route({
@ -75,6 +75,7 @@ export const registerMfaRouter = async (server: FastifyZodProvider) => {
userAgent, userAgent,
ip: req.realIp, ip: req.realIp,
userId: req.mfa.userId, userId: req.mfa.userId,
orgId: req.mfa.orgId,
mfaToken: req.body.mfaToken mfaToken: req.body.mfaToken
}); });

View File

@ -33,7 +33,11 @@ export const registerOrgRouter = async (server: FastifyZodProvider) => {
handler: async (req) => { handler: async (req) => {
if (req.auth.actor !== ActorType.USER) return; if (req.auth.actor !== ActorType.USER) return;
const users = await server.services.org.findAllOrgMembers(req.permission.id, req.params.organizationId); const users = await server.services.org.findAllOrgMembers(
req.permission.id,
req.params.organizationId,
req.permission.orgId
);
return { users }; return { users };
} }
}); });
@ -68,6 +72,7 @@ export const registerOrgRouter = async (server: FastifyZodProvider) => {
const workspaces = await server.services.org.findAllWorkspaces({ const workspaces = await server.services.org.findAllWorkspaces({
actor: req.permission.type, actor: req.permission.type,
actorId: req.permission.id, actorId: req.permission.id,
actorOrgId: req.permission.orgId,
orgId: req.params.organizationId orgId: req.params.organizationId
}); });
@ -97,7 +102,8 @@ export const registerOrgRouter = async (server: FastifyZodProvider) => {
userId: req.permission.id, userId: req.permission.id,
role: req.body.role, role: req.body.role,
orgId: req.params.organizationId, orgId: req.params.organizationId,
membershipId: req.params.membershipId membershipId: req.params.membershipId,
actorOrgId: req.permission.orgId
}); });
return { membership }; return { membership };
} }
@ -121,7 +127,8 @@ 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,
orgId: req.params.organizationId, orgId: req.params.organizationId,
membershipId: req.params.membershipId membershipId: req.params.membershipId,
actorOrgId: req.permission.orgId
}); });
return { membership }; return { membership };
} }
@ -172,7 +179,8 @@ 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.orgId
); );
return { organization }; return { organization };
} }

View File

@ -28,7 +28,8 @@ 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,
projectId: req.params.workspaceId projectId: req.params.workspaceId,
actorOrgId: req.permission.orgId
}); });
await server.services.auditLog.createAuditLog({ await server.services.auditLog.createAuditLog({

View File

@ -92,6 +92,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,
actorOrgId: req.permission.orgId,
...req.body, ...req.body,
projectId: req.body.workspaceId projectId: req.body.workspaceId
}); });
@ -129,6 +130,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,
actorOrgId: req.permission.orgId,
id: req.params.serviceTokenId id: req.params.serviceTokenId
}); });

View File

@ -21,7 +21,8 @@ export const registerSecretBlindIndexRouter = async (server: FastifyZodProvider)
const count = await server.services.secretBlindIndex.getSecretBlindIndexStatus({ const count = await server.services.secretBlindIndex.getSecretBlindIndexStatus({
projectId: req.params.projectId, projectId: req.params.projectId,
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type actor: req.permission.type,
actorOrgId: req.permission.orgId
}); });
return count === 0; return count === 0;
} }
@ -52,7 +53,8 @@ export const registerSecretBlindIndexRouter = async (server: FastifyZodProvider)
const secrets = await server.services.secretBlindIndex.getProjectSecrets({ const secrets = await server.services.secretBlindIndex.getProjectSecrets({
projectId: req.params.projectId, projectId: req.params.projectId,
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type actor: req.permission.type,
actorOrgId: req.permission.orgId
}); });
return { secrets }; return { secrets };
} }
@ -85,7 +87,8 @@ export const registerSecretBlindIndexRouter = async (server: FastifyZodProvider)
projectId: req.params.projectId, projectId: req.params.projectId,
secretsToUpdate: req.body.secretsToUpdate, secretsToUpdate: req.body.secretsToUpdate,
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type actor: req.permission.type,
actorOrgId: req.permission.orgId
}); });
return { message: "Successfully named workspace secrets" }; return { message: "Successfully named workspace secrets" };
} }

View File

@ -81,6 +81,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
const { secrets, imports } = await server.services.secret.getSecretsRaw({ const { secrets, imports } = await server.services.secret.getSecretsRaw({
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorOrgId: req.permission.orgId,
environment, environment,
projectId: workspaceId, projectId: workspaceId,
path: secretPath, path: secretPath,
@ -158,6 +159,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,
actorOrgId: req.permission.orgId,
environment, environment,
projectId: workspaceId, projectId: workspaceId,
path: secretPath, path: secretPath,
@ -225,6 +227,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
const secret = await server.services.secret.createSecretRaw({ const secret = await server.services.secret.createSecretRaw({
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorOrgId: req.permission.orgId,
environment: req.body.environment, environment: req.body.environment,
projectId: req.body.workspaceId, projectId: req.body.workspaceId,
secretPath: req.body.secretPath, secretPath: req.body.secretPath,
@ -293,6 +296,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
const secret = await server.services.secret.updateSecretRaw({ const secret = await server.services.secret.updateSecretRaw({
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorOrgId: req.permission.orgId,
environment: req.body.environment, environment: req.body.environment,
projectId: req.body.workspaceId, projectId: req.body.workspaceId,
secretPath: req.body.secretPath, secretPath: req.body.secretPath,
@ -357,6 +361,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,
actorOrgId: req.permission.orgId,
environment: req.body.environment, environment: req.body.environment,
projectId: req.body.workspaceId, projectId: req.body.workspaceId,
secretPath: req.body.secretPath, secretPath: req.body.secretPath,
@ -451,6 +456,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,
actorOrgId: req.permission.orgId,
environment: req.query.environment, environment: req.query.environment,
projectId: req.query.workspaceId, projectId: req.query.workspaceId,
path: req.query.secretPath, path: req.query.secretPath,
@ -536,6 +542,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,
actorOrgId: req.permission.orgId,
environment: req.query.environment, environment: req.query.environment,
projectId: req.query.workspaceId, projectId: req.query.workspaceId,
path: req.query.secretPath, path: req.query.secretPath,
@ -646,6 +653,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,
actorOrgId: req.permission.orgId,
secretPath, secretPath,
environment, environment,
projectId, projectId,
@ -688,6 +696,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,
actorOrgId: req.permission.orgId,
path: secretPath, path: secretPath,
type, type,
environment: req.body.environment, environment: req.body.environment,
@ -811,6 +820,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,
actorOrgId: req.permission.orgId,
secretPath, secretPath,
environment, environment,
projectId projectId
@ -819,6 +829,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,
actorOrgId: req.permission.orgId,
secretPath, secretPath,
environment, environment,
projectId, projectId,
@ -863,6 +874,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,
actorOrgId: req.permission.orgId,
path: secretPath, path: secretPath,
type, type,
environment, environment,
@ -952,6 +964,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,
actorOrgId: req.permission.orgId,
secretPath, secretPath,
environment, environment,
projectId projectId
@ -960,6 +973,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,
actorOrgId: req.permission.orgId,
secretPath, secretPath,
environment, environment,
projectId, projectId,
@ -992,6 +1006,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,
actorOrgId: req.permission.orgId,
path: secretPath, path: secretPath,
type, type,
environment, environment,
@ -1074,6 +1089,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,
actorOrgId: req.permission.orgId,
secretPath, secretPath,
environment, environment,
projectId projectId
@ -1082,6 +1098,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,
actorOrgId: req.permission.orgId,
secretPath, secretPath,
environment, environment,
projectId, projectId,
@ -1110,6 +1127,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,
actorOrgId: req.permission.orgId,
path: secretPath, path: secretPath,
environment, environment,
projectId, projectId,
@ -1192,6 +1210,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,
actorOrgId: req.permission.orgId,
secretPath, secretPath,
environment, environment,
projectId projectId
@ -1200,6 +1219,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,
actorOrgId: req.permission.orgId,
secretPath, secretPath,
environment, environment,
projectId, projectId,
@ -1227,6 +1247,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,
actorOrgId: req.permission.orgId,
path: secretPath, path: secretPath,
environment, environment,
projectId, projectId,
@ -1298,6 +1319,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,
actorOrgId: req.permission.orgId,
secretPath, secretPath,
environment, environment,
projectId projectId
@ -1306,6 +1328,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,
actorOrgId: req.permission.orgId,
secretPath, secretPath,
environment, environment,
projectId, projectId,
@ -1332,6 +1355,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,
actorOrgId: req.permission.orgId,
path: req.body.secretPath, path: req.body.secretPath,
environment, environment,
projectId, projectId,

View File

@ -141,7 +141,7 @@ export const tokenServiceFactory = ({ tokenDAL, userDAL }: TAuthTokenServiceFact
const user = await userDAL.findById(session.userId); const user = await userDAL.findById(session.userId);
if (!user || !user.isAccepted) throw new UnauthorizedError({ name: "Token user not found" }); if (!user || !user.isAccepted) throw new UnauthorizedError({ name: "Token user not found" });
return { user, tokenVersionId: token.tokenVersionId }; return { user, tokenVersionId: token.tokenVersionId, orgId: token.organizationId };
}; };
return { return {

View File

@ -12,6 +12,12 @@ export const validateProviderAuthToken = (providerToken: string, email: string)
if (decodedToken.authTokenType !== AuthTokenType.PROVIDER_TOKEN) throw new UnauthorizedError(); if (decodedToken.authTokenType !== AuthTokenType.PROVIDER_TOKEN) throw new UnauthorizedError();
if (decodedToken.email !== email) throw new Error("Invalid auth credentials"); if (decodedToken.email !== email) throw new Error("Invalid auth credentials");
if (decodedToken.organizationId) {
return { orgId: decodedToken.organizationId };
}
return {};
}; };
export const validateSignUpAuthorization = (token: string, userId: string, validate = true) => { export const validateSignUpAuthorization = (token: string, userId: string, validate = true) => {

View File

@ -56,7 +56,7 @@ export const authLoginServiceFactory = ({ userDAL, tokenService, smtpService }:
* Private * Private
* Send mfa code via email * Send mfa code via email
* */ * */
const sendUserMfaCode = async (userId: string, email: string) => { const sendUserMfaCode = async ({ userId, email }: { userId: string; email: string }) => {
const code = await tokenService.createTokenForUser({ const code = await tokenService.createTokenForUser({
type: TokenType.TOKEN_EMAIL_MFA, type: TokenType.TOKEN_EMAIL_MFA,
userId userId
@ -76,7 +76,17 @@ export const authLoginServiceFactory = ({ userDAL, tokenService, smtpService }:
* Check user device and send mail if new device * Check user device and send mail if new device
* generate the auth and refresh token. fn shared by mfa verification and login verification with mfa disabled * generate the auth and refresh token. fn shared by mfa verification and login verification with mfa disabled
*/ */
const generateUserTokens = async (user: TUsers, ip: string, userAgent: string) => { const generateUserTokens = async ({
user,
ip,
userAgent,
organizationId
}: {
user: TUsers;
ip: string;
userAgent: string;
organizationId?: string;
}) => {
const cfg = getConfig(); const cfg = getConfig();
await updateUserDeviceSession(user, ip, userAgent); await updateUserDeviceSession(user, ip, userAgent);
const tokenSession = await tokenService.getUserTokenSession({ const tokenSession = await tokenService.getUserTokenSession({
@ -90,7 +100,8 @@ export const authLoginServiceFactory = ({ userDAL, tokenService, smtpService }:
authTokenType: AuthTokenType.ACCESS_TOKEN, authTokenType: AuthTokenType.ACCESS_TOKEN,
userId: user.id, userId: user.id,
tokenVersionId: tokenSession.id, tokenVersionId: tokenSession.id,
accessVersion: tokenSession.accessVersion accessVersion: tokenSession.accessVersion,
organizationId
}, },
cfg.AUTH_SECRET, cfg.AUTH_SECRET,
{ expiresIn: cfg.JWT_AUTH_LIFETIME } { expiresIn: cfg.JWT_AUTH_LIFETIME }
@ -101,7 +112,8 @@ export const authLoginServiceFactory = ({ userDAL, tokenService, smtpService }:
authTokenType: AuthTokenType.REFRESH_TOKEN, authTokenType: AuthTokenType.REFRESH_TOKEN,
userId: user.id, userId: user.id,
tokenVersionId: tokenSession.id, tokenVersionId: tokenSession.id,
refreshVersion: tokenSession.refreshVersion refreshVersion: tokenSession.refreshVersion,
organizationId
}, },
cfg.AUTH_SECRET, cfg.AUTH_SECRET,
{ expiresIn: cfg.JWT_REFRESH_LIFETIME } { expiresIn: cfg.JWT_REFRESH_LIFETIME }
@ -149,8 +161,14 @@ 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;
if (!userEnc.authMethods?.includes(AuthMethod.EMAIL)) { if (!userEnc.authMethods?.includes(AuthMethod.EMAIL)) {
validateProviderAuthToken(providerAuthToken as string, email); const { orgId } = validateProviderAuthToken(providerAuthToken as string, email);
organizationId = orgId;
} else if (providerAuthToken) {
// SAML SSO
const { orgId } = validateProviderAuthToken(providerAuthToken, email);
organizationId = 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?");
@ -169,15 +187,36 @@ export const authLoginServiceFactory = ({ userDAL, tokenService, smtpService }:
}); });
// send multi factor auth token if they it enabled // send multi factor auth token if they it enabled
if (userEnc.isMfaEnabled) { if (userEnc.isMfaEnabled) {
const mfaToken = jwt.sign({ authTokenType: AuthTokenType.MFA_TOKEN, userId: userEnc.userId }, cfg.AUTH_SECRET, { const mfaToken = jwt.sign(
expiresIn: cfg.JWT_MFA_LIFETIME {
authTokenType: AuthTokenType.MFA_TOKEN,
userId: userEnc.userId,
organizationId
},
cfg.AUTH_SECRET,
{
expiresIn: cfg.JWT_MFA_LIFETIME
}
);
await sendUserMfaCode({
userId: userEnc.userId,
email: userEnc.email
}); });
await sendUserMfaCode(userEnc.userId, userEnc.email);
return { isMfaEnabled: true, token: mfaToken } as const; return { isMfaEnabled: true, token: mfaToken } as const;
} }
const token = await generateUserTokens({ ...userEnc, id: userEnc.userId }, ip, userAgent); const token = await generateUserTokens({
user: {
...userEnc,
id: userEnc.userId
},
ip,
userAgent,
organizationId
});
return { token, isMfaEnabled: false, user: userEnc } as const; return { token, isMfaEnabled: false, user: userEnc } as const;
}; };
@ -188,14 +227,17 @@ export const authLoginServiceFactory = ({ userDAL, tokenService, smtpService }:
const resendMfaToken = async (userId: string) => { const resendMfaToken = async (userId: string) => {
const user = await userDAL.findById(userId); const user = await userDAL.findById(userId);
if (!user) return; if (!user) return;
await sendUserMfaCode(user.id, user.email); await sendUserMfaCode({
userId: user.id,
email: user.email
});
}; };
/* /*
* 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 }: TVerifyMfaTokenDTO) => { const verifyMfaToken = async ({ userId, mfaToken, ip, userAgent, orgId }: TVerifyMfaTokenDTO) => {
await tokenService.validateTokenForUser({ await tokenService.validateTokenForUser({
type: TokenType.TOKEN_EMAIL_MFA, type: TokenType.TOKEN_EMAIL_MFA,
userId, userId,
@ -204,7 +246,16 @@ export const authLoginServiceFactory = ({ userDAL, tokenService, smtpService }:
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");
const token = await generateUserTokens({ ...userEnc, id: userEnc.userId }, ip, userAgent); const token = await generateUserTokens({
user: {
...userEnc,
id: userEnc.userId
},
ip,
userAgent,
organizationId: orgId
});
return { token, user: userEnc }; return { token, user: userEnc };
}; };
/* /*

View File

@ -19,6 +19,7 @@ export type TVerifyMfaTokenDTO = {
mfaToken: string; mfaToken: string;
ip: string; ip: string;
userAgent: string; userAgent: string;
orgId?: string;
}; };
export type TOauthLoginDTO = { export type TOauthLoginDTO = {

View File

@ -120,8 +120,10 @@ export const authSignupServiceFactory = ({
throw new Error("Failed to complete account for complete user"); throw new Error("Failed to complete account for complete user");
} }
let organizationId;
if (providerAuthToken) { if (providerAuthToken) {
validateProviderAuthToken(providerAuthToken, user.email); const { orgId } = validateProviderAuthToken(providerAuthToken, user.email);
organizationId = orgId;
} else { } else {
validateSignUpAuthorization(authorization, user.id); validateSignUpAuthorization(authorization, user.id);
} }
@ -147,11 +149,7 @@ export const authSignupServiceFactory = ({
return { info: us, key: userEncKey }; return { info: us, key: userEncKey };
}); });
const hasSamlEnabled = user?.authMethods?.some((authMethod) => if (!organizationId) {
[AuthMethod.OKTA_SAML, AuthMethod.AZURE_SAML, AuthMethod.JUMPCLOUD_SAML].includes(authMethod as AuthMethod)
);
if (!hasSamlEnabled) {
await orgService.createOrganization(user.id, user.email, organizationName); await orgService.createOrganization(user.id, user.email, organizationName);
} }
@ -175,7 +173,8 @@ export const authSignupServiceFactory = ({
authTokenType: AuthTokenType.ACCESS_TOKEN, authTokenType: AuthTokenType.ACCESS_TOKEN,
userId: updateduser.info.id, userId: updateduser.info.id,
tokenVersionId: tokenSession.id, tokenVersionId: tokenSession.id,
accessVersion: tokenSession.accessVersion accessVersion: tokenSession.accessVersion,
organizationId
}, },
appCfg.AUTH_SECRET, appCfg.AUTH_SECRET,
{ expiresIn: appCfg.JWT_AUTH_LIFETIME } { expiresIn: appCfg.JWT_AUTH_LIFETIME }
@ -186,7 +185,8 @@ export const authSignupServiceFactory = ({
authTokenType: AuthTokenType.REFRESH_TOKEN, authTokenType: AuthTokenType.REFRESH_TOKEN,
userId: updateduser.info.id, userId: updateduser.info.id,
tokenVersionId: tokenSession.id, tokenVersionId: tokenSession.id,
refreshVersion: tokenSession.refreshVersion refreshVersion: tokenSession.refreshVersion,
organizationId
}, },
appCfg.AUTH_SECRET, appCfg.AUTH_SECRET,
{ expiresIn: appCfg.JWT_REFRESH_LIFETIME } { expiresIn: appCfg.JWT_REFRESH_LIFETIME }

View File

@ -39,11 +39,13 @@ export type AuthModeJwtTokenPayload = {
userId: string; userId: string;
tokenVersionId: string; tokenVersionId: string;
accessVersion: number; accessVersion: number;
organizationId?: string;
}; };
export type AuthModeMfaJwtTokenPayload = { export type AuthModeMfaJwtTokenPayload = {
authTokenType: AuthTokenType.MFA_TOKEN; authTokenType: AuthTokenType.MFA_TOKEN;
userId: string; userId: string;
organizationId?: string;
}; };
export type AuthModeRefreshJwtTokenPayload = { export type AuthModeRefreshJwtTokenPayload = {
@ -51,11 +53,13 @@ export type AuthModeRefreshJwtTokenPayload = {
userId: string; userId: string;
tokenVersionId: string; tokenVersionId: string;
refreshVersion: number; refreshVersion: number;
organizationId?: string;
}; };
export type AuthModeProviderJwtTokenPayload = { export type AuthModeProviderJwtTokenPayload = {
authTokenType: AuthTokenType.PROVIDER_TOKEN; authTokenType: AuthTokenType.PROVIDER_TOKEN;
email: string; email: string;
organizationId?: string;
}; };
export type AuthModeProviderSignUpTokenPayload = { export type AuthModeProviderSignUpTokenPayload = {

View File

@ -32,8 +32,15 @@ export const identityProjectServiceFactory = ({
identityOrgMembershipDAL, identityOrgMembershipDAL,
projectDAL projectDAL
}: TIdentityProjectServiceFactoryDep) => { }: TIdentityProjectServiceFactoryDep) => {
const createProjectIdentity = async ({ identityId, actor, actorId, projectId, role }: TCreateProjectIdentityDTO) => { const createProjectIdentity = async ({
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); identityId,
actor,
actorId,
actorOrgId,
projectId,
role
}: TCreateProjectIdentityDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, 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 });
@ -72,8 +79,15 @@ export const identityProjectServiceFactory = ({
return projectIdentity; return projectIdentity;
}; };
const updateProjectIdentity = async ({ projectId, identityId, role, actor, actorId }: TUpdateProjectIdentityDTO) => { const updateProjectIdentity = async ({
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); projectId,
identityId,
role,
actor,
actorId,
actorOrgId
}: TUpdateProjectIdentityDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, 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 });
@ -85,7 +99,8 @@ export const identityProjectServiceFactory = ({
const { permission: identityRolePermission } = await permissionService.getProjectPermission( const { permission: identityRolePermission } = await permissionService.getProjectPermission(
ActorType.IDENTITY, ActorType.IDENTITY,
projectIdentity.identityId, projectIdentity.identityId,
projectIdentity.projectId projectIdentity.projectId,
actorOrgId
); );
const hasRequiredPriviledges = isAtLeastAsPrivileged(permission, identityRolePermission); const hasRequiredPriviledges = isAtLeastAsPrivileged(permission, identityRolePermission);
if (!hasRequiredPriviledges) if (!hasRequiredPriviledges)
@ -115,7 +130,13 @@ export const identityProjectServiceFactory = ({
return updatedProjectIdentity; return updatedProjectIdentity;
}; };
const deleteProjectIdentity = async ({ identityId, actorId, actor, projectId }: TDeleteProjectIdentityDTO) => { const deleteProjectIdentity = async ({
identityId,
actorId,
actor,
actorOrgId,
projectId
}: TDeleteProjectIdentityDTO) => {
const identityProjectMembership = await identityProjectDAL.findOne({ identityId, projectId }); const identityProjectMembership = await identityProjectDAL.findOne({ identityId, projectId });
if (!identityProjectMembership) if (!identityProjectMembership)
throw new BadRequestError({ message: `Failed to find identity with id ${identityId}` }); throw new BadRequestError({ message: `Failed to find identity with id ${identityId}` });
@ -123,13 +144,15 @@ export const identityProjectServiceFactory = ({
const { permission } = await permissionService.getProjectPermission( const { permission } = await permissionService.getProjectPermission(
actor, actor,
actorId, actorId,
identityProjectMembership.projectId identityProjectMembership.projectId,
actorOrgId
); );
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Delete, ProjectPermissionSub.Identity); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Delete, ProjectPermissionSub.Identity);
const { permission: identityRolePermission } = await permissionService.getProjectPermission( const { permission: identityRolePermission } = await permissionService.getProjectPermission(
ActorType.IDENTITY, ActorType.IDENTITY,
identityId, identityId,
identityProjectMembership.projectId identityProjectMembership.projectId,
actorOrgId
); );
const hasRequiredPriviledges = isAtLeastAsPrivileged(permission, identityRolePermission); const hasRequiredPriviledges = isAtLeastAsPrivileged(permission, identityRolePermission);
if (!hasRequiredPriviledges) if (!hasRequiredPriviledges)
@ -139,8 +162,8 @@ export const identityProjectServiceFactory = ({
return deletedIdentity; return deletedIdentity;
}; };
const listProjectIdentities = async ({ projectId, actor, actorId }: TListProjectIdentityDTO) => { const listProjectIdentities = async ({ projectId, actor, actorId, actorOrgId }: TListProjectIdentityDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, 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);

View File

@ -127,6 +127,7 @@ export const identityUaServiceFactory = ({
expiresIn: identityAccessToken.accessTokenMaxTTL === 0 ? undefined : identityAccessToken.accessTokenMaxTTL expiresIn: identityAccessToken.accessTokenMaxTTL === 0 ? undefined : identityAccessToken.accessTokenMaxTTL
} }
); );
return { accessToken, identityUa, validClientSecretInfo, identityAccessToken }; return { accessToken, identityUa, validClientSecretInfo, identityAccessToken };
}; };
@ -138,7 +139,8 @@ export const identityUaServiceFactory = ({
accessTokenTrustedIps, accessTokenTrustedIps,
clientSecretTrustedIps, clientSecretTrustedIps,
actorId, actorId,
actor actor,
actorOrgId
}: TAttachUaDTO) => { }: TAttachUaDTO) => {
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" });
@ -151,7 +153,12 @@ export const identityUaServiceFactory = ({
throw new BadRequestError({ message: "Access token TTL cannot be greater than max TTL" }); throw new BadRequestError({ message: "Access token TTL cannot be greater than max TTL" });
} }
const { permission } = await permissionService.getOrgPermission(actor, actorId, identityMembershipOrg.orgId); const { permission } = await permissionService.getOrgPermission(
actor,
actorId,
identityMembershipOrg.orgId,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Create, OrgPermissionSubjects.Identity); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Create, OrgPermissionSubjects.Identity);
const plan = await licenseService.getPlan(identityMembershipOrg.orgId); const plan = await licenseService.getPlan(identityMembershipOrg.orgId);
@ -221,7 +228,8 @@ export const identityUaServiceFactory = ({
accessTokenTrustedIps, accessTokenTrustedIps,
clientSecretTrustedIps, clientSecretTrustedIps,
actorId, actorId,
actor actor,
actorOrgId
}: TUpdateUaDTO) => { }: TUpdateUaDTO) => {
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" });
@ -239,7 +247,12 @@ export const identityUaServiceFactory = ({
throw new BadRequestError({ message: "Access token TTL cannot be greater than max TTL" }); throw new BadRequestError({ message: "Access token TTL cannot be greater than max TTL" });
} }
const { permission } = await permissionService.getOrgPermission(actor, actorId, identityMembershipOrg.orgId); const { permission } = await permissionService.getOrgPermission(
actor,
actorId,
identityMembershipOrg.orgId,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Edit, OrgPermissionSubjects.Identity); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Edit, OrgPermissionSubjects.Identity);
const plan = await licenseService.getPlan(identityMembershipOrg.orgId); const plan = await licenseService.getPlan(identityMembershipOrg.orgId);
@ -290,7 +303,7 @@ export const identityUaServiceFactory = ({
return { ...updatedUaAuth, orgId: identityMembershipOrg.orgId }; return { ...updatedUaAuth, orgId: identityMembershipOrg.orgId };
}; };
const getIdentityUa = async ({ identityId, actorId, actor }: TGetUaDTO) => { const getIdentityUa = async ({ identityId, actorId, actor, 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)
@ -300,7 +313,12 @@ export const identityUaServiceFactory = ({
const uaIdentityAuth = await identityUaDAL.findOne({ identityId }); const uaIdentityAuth = await identityUaDAL.findOne({ identityId });
const { permission } = await permissionService.getOrgPermission(actor, actorId, identityMembershipOrg.orgId); const { permission } = await permissionService.getOrgPermission(
actor,
actorId,
identityMembershipOrg.orgId,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Identity); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Identity);
return { ...uaIdentityAuth, orgId: identityMembershipOrg.orgId }; return { ...uaIdentityAuth, orgId: identityMembershipOrg.orgId };
}; };
@ -308,6 +326,7 @@ export const identityUaServiceFactory = ({
const createUaClientSecret = async ({ const createUaClientSecret = async ({
actor, actor,
actorId, actorId,
actorOrgId,
identityId, identityId,
ttl, ttl,
description, description,
@ -319,13 +338,19 @@ export const identityUaServiceFactory = ({
throw new BadRequestError({ throw new BadRequestError({
message: "The identity does not have universal auth" message: "The identity does not have universal auth"
}); });
const { permission } = await permissionService.getOrgPermission(actor, actorId, identityMembershipOrg.orgId); const { permission } = await permissionService.getOrgPermission(
actor,
actorId,
identityMembershipOrg.orgId,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Create, OrgPermissionSubjects.Identity); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Create, OrgPermissionSubjects.Identity);
const { permission: rolePermission } = await permissionService.getOrgPermission( const { permission: rolePermission } = await permissionService.getOrgPermission(
ActorType.IDENTITY, ActorType.IDENTITY,
identityMembershipOrg.identityId, identityMembershipOrg.identityId,
identityMembershipOrg.orgId identityMembershipOrg.orgId,
actorOrgId
); );
const hasPriviledge = isAtLeastAsPrivileged(permission, rolePermission); const hasPriviledge = isAtLeastAsPrivileged(permission, rolePermission);
if (!hasPriviledge) if (!hasPriviledge)
@ -358,20 +383,26 @@ export const identityUaServiceFactory = ({
}; };
}; };
const getUaClientSecrets = async ({ actor, actorId, identityId }: TGetUaClientSecretsDTO) => { const getUaClientSecrets = async ({ actor, actorId, actorOrgId, 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)
throw new BadRequestError({ throw new BadRequestError({
message: "The identity does not have universal auth" message: "The identity does not have universal auth"
}); });
const { permission } = await permissionService.getOrgPermission(actor, actorId, identityMembershipOrg.orgId); const { permission } = await permissionService.getOrgPermission(
actor,
actorId,
identityMembershipOrg.orgId,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Identity); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Identity);
const { permission: rolePermission } = await permissionService.getOrgPermission( const { permission: rolePermission } = await permissionService.getOrgPermission(
ActorType.IDENTITY, ActorType.IDENTITY,
identityMembershipOrg.identityId, identityMembershipOrg.identityId,
identityMembershipOrg.orgId identityMembershipOrg.orgId,
actorOrgId
); );
const hasPriviledge = isAtLeastAsPrivileged(permission, rolePermission); const hasPriviledge = isAtLeastAsPrivileged(permission, rolePermission);
if (!hasPriviledge) if (!hasPriviledge)
@ -390,20 +421,32 @@ export const identityUaServiceFactory = ({
return { clientSecrets, orgId: identityMembershipOrg.orgId }; return { clientSecrets, orgId: identityMembershipOrg.orgId };
}; };
const revokeUaClientSecret = async ({ identityId, actorId, actor, clientSecretId }: TRevokeUaClientSecretDTO) => { const revokeUaClientSecret = async ({
identityId,
actorId,
actor,
actorOrgId,
clientSecretId
}: TRevokeUaClientSecretDTO) => {
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)
throw new BadRequestError({ throw new BadRequestError({
message: "The identity does not have universal auth" message: "The identity does not have universal auth"
}); });
const { permission } = await permissionService.getOrgPermission(actor, actorId, identityMembershipOrg.orgId); const { permission } = await permissionService.getOrgPermission(
actor,
actorId,
identityMembershipOrg.orgId,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Delete, OrgPermissionSubjects.Identity); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Delete, OrgPermissionSubjects.Identity);
const { permission: rolePermission } = await permissionService.getOrgPermission( const { permission: rolePermission } = await permissionService.getOrgPermission(
ActorType.IDENTITY, ActorType.IDENTITY,
identityMembershipOrg.identityId, identityMembershipOrg.identityId,
identityMembershipOrg.orgId identityMembershipOrg.orgId,
actorOrgId
); );
const hasPriviledge = isAtLeastAsPrivileged(permission, rolePermission); const hasPriviledge = isAtLeastAsPrivileged(permission, rolePermission);
if (!hasPriviledge) if (!hasPriviledge)

View File

@ -25,8 +25,8 @@ export const identityServiceFactory = ({
identityOrgMembershipDAL, identityOrgMembershipDAL,
permissionService permissionService
}: TIdentityServiceFactoryDep) => { }: TIdentityServiceFactoryDep) => {
const createIdentity = async ({ name, role, actor, orgId, actorId }: TCreateIdentityDTO) => { const createIdentity = async ({ name, role, actor, orgId, actorId, actorOrgId }: TCreateIdentityDTO) => {
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId); const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, 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,17 +54,23 @@ export const identityServiceFactory = ({
return identity; return identity;
}; };
const updateIdentity = async ({ id, role, name, actor, actorId }: TUpdateIdentityDTO) => { const updateIdentity = async ({ id, role, name, actor, actorId, 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}` });
const { permission } = await permissionService.getOrgPermission(actor, actorId, identityOrgMembership.orgId); const { permission } = await permissionService.getOrgPermission(
actor,
actorId,
identityOrgMembership.orgId,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Edit, OrgPermissionSubjects.Identity); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Edit, OrgPermissionSubjects.Identity);
const { permission: identityRolePermission } = await permissionService.getOrgPermission( const { permission: identityRolePermission } = await permissionService.getOrgPermission(
ActorType.IDENTITY, ActorType.IDENTITY,
id, id,
identityOrgMembership.orgId identityOrgMembership.orgId,
actorOrgId
); );
const hasRequiredPriviledges = isAtLeastAsPrivileged(permission, identityRolePermission); const hasRequiredPriviledges = isAtLeastAsPrivileged(permission, identityRolePermission);
if (!hasRequiredPriviledges) if (!hasRequiredPriviledges)
@ -102,11 +108,16 @@ export const identityServiceFactory = ({
return { ...identity, orgId: identityOrgMembership.orgId }; return { ...identity, orgId: identityOrgMembership.orgId };
}; };
const deleteIdentity = async ({ actorId, actor, id }: TDeleteIdentityDTO) => { const deleteIdentity = async ({ actorId, actor, actorOrgId, 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}` });
const { permission } = await permissionService.getOrgPermission(actor, actorId, identityOrgMembership.orgId); const { permission } = await permissionService.getOrgPermission(
actor,
actorId,
identityOrgMembership.orgId,
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,
@ -121,8 +132,8 @@ export const identityServiceFactory = ({
return { ...deletedIdentity, orgId: identityOrgMembership.orgId }; return { ...deletedIdentity, orgId: identityOrgMembership.orgId };
}; };
const listOrgIdentities = async ({ orgId, actor, actorId }: TOrgPermission) => { const listOrgIdentities = async ({ orgId, actor, actorId, actorOrgId }: TOrgPermission) => {
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId); const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, 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);

View File

@ -59,27 +59,40 @@ export const integrationAuthServiceFactory = ({
projectBotDAL, projectBotDAL,
projectBotService projectBotService
}: TIntegrationAuthServiceFactoryDep) => { }: TIntegrationAuthServiceFactoryDep) => {
const listIntegrationAuthByProjectId = async ({ actorId, actor, projectId }: TProjectPermission) => { const listIntegrationAuthByProjectId = async ({ actorId, actor, actorOrgId, projectId }: TProjectPermission) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, 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 }: TGetIntegrationAuthDTO) => { const getIntegrationAuth = async ({ actor, id, actorId, 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" });
const { permission } = await permissionService.getProjectPermission(actor, actorId, integrationAuth.projectId); const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
integrationAuth.projectId,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations);
return integrationAuth; return integrationAuth;
}; };
const oauthExchange = async ({ projectId, actorId, actor, integration, url, code }: TOauthExchangeDTO) => { const oauthExchange = async ({
projectId,
actorId,
actor,
actorOrgId,
integration,
url,
code
}: TOauthExchangeDTO) => {
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); const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, 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 });
@ -134,6 +147,7 @@ export const integrationAuthServiceFactory = ({
integration, integration,
url, url,
actor, actor,
actorOrgId,
accessId, accessId,
namespace, namespace,
accessToken accessToken
@ -141,7 +155,7 @@ 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); const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, 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 });
@ -254,11 +268,23 @@ export const integrationAuthServiceFactory = ({
return { accessId, accessToken }; return { accessId, accessToken };
}; };
const getIntegrationApps = async ({ actor, actorId, teamId, id, workspaceSlug }: TIntegrationAuthAppsDTO) => { const getIntegrationApps = async ({
actor,
actorId,
actorOrgId,
teamId,
id,
workspaceSlug
}: TIntegrationAuthAppsDTO) => {
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" });
const { permission } = await permissionService.getProjectPermission(actor, actorId, integrationAuth.projectId); const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
integrationAuth.projectId,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations);
const botKey = await projectBotService.getBotKey(integrationAuth.projectId); const botKey = await projectBotService.getBotKey(integrationAuth.projectId);
@ -274,11 +300,16 @@ export const integrationAuthServiceFactory = ({
return apps; return apps;
}; };
const getIntegrationAuthTeams = async ({ actor, actorId, id }: TIntegrationAuthTeamsDTO) => { const getIntegrationAuthTeams = async ({ actor, actorId, 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" });
const { permission } = await permissionService.getProjectPermission(actor, actorId, integrationAuth.projectId); const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
integrationAuth.projectId,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations);
const botKey = await projectBotService.getBotKey(integrationAuth.projectId); const botKey = await projectBotService.getBotKey(integrationAuth.projectId);
@ -291,11 +322,16 @@ export const integrationAuthServiceFactory = ({
return teams; return teams;
}; };
const getVercelBranches = async ({ appId, id, actor, actorId }: TIntegrationAuthVercelBranchesDTO) => { const getVercelBranches = async ({ appId, id, actor, actorId, 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" });
const { permission } = await permissionService.getProjectPermission(actor, actorId, integrationAuth.projectId); const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
integrationAuth.projectId,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations);
const botKey = await projectBotService.getBotKey(integrationAuth.projectId); const botKey = await projectBotService.getBotKey(integrationAuth.projectId);
const { accessToken } = await getIntegrationAccessToken(integrationAuth, botKey); const { accessToken } = await getIntegrationAccessToken(integrationAuth, botKey);
@ -319,11 +355,16 @@ export const integrationAuthServiceFactory = ({
return []; return [];
}; };
const getChecklyGroups = async ({ actorId, actor, id, accountId }: TIntegrationAuthChecklyGroupsDTO) => { const getChecklyGroups = async ({ actorId, actor, actorOrgId, 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" });
const { permission } = await permissionService.getProjectPermission(actor, actorId, integrationAuth.projectId); const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
integrationAuth.projectId,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations);
const botKey = await projectBotService.getBotKey(integrationAuth.projectId); const botKey = await projectBotService.getBotKey(integrationAuth.projectId);
const { accessToken } = await getIntegrationAccessToken(integrationAuth, botKey); const { accessToken } = await getIntegrationAccessToken(integrationAuth, botKey);
@ -340,11 +381,16 @@ export const integrationAuthServiceFactory = ({
return []; return [];
}; };
const getQoveryOrgs = async ({ actorId, actor, id }: TIntegrationAuthQoveryOrgsDTO) => { const getQoveryOrgs = async ({ actorId, actor, actorOrgId, 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" });
const { permission } = await permissionService.getProjectPermission(actor, actorId, integrationAuth.projectId); const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
integrationAuth.projectId,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations);
const botKey = await projectBotService.getBotKey(integrationAuth.projectId); const botKey = await projectBotService.getBotKey(integrationAuth.projectId);
const { accessToken } = await getIntegrationAccessToken(integrationAuth, botKey); const { accessToken } = await getIntegrationAccessToken(integrationAuth, botKey);
@ -361,11 +407,16 @@ 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, id, orgId }: TIntegrationAuthQoveryProjectDTO) => { const getQoveryProjects = async ({ actorId, actor, actorOrgId, 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" });
const { permission } = await permissionService.getProjectPermission(actor, actorId, integrationAuth.projectId); const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
integrationAuth.projectId,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations);
const botKey = await projectBotService.getBotKey(integrationAuth.projectId); const botKey = await projectBotService.getBotKey(integrationAuth.projectId);
const { accessToken } = await getIntegrationAccessToken(integrationAuth, botKey); const { accessToken } = await getIntegrationAccessToken(integrationAuth, botKey);
@ -384,11 +435,22 @@ export const integrationAuthServiceFactory = ({
return []; return [];
}; };
const getQoveryEnvs = async ({ projectId, id, actor, actorId }: TIntegrationAuthQoveryEnvironmentsDTO) => { const getQoveryEnvs = async ({
projectId,
id,
actor,
actorId,
actorOrgId
}: TIntegrationAuthQoveryEnvironmentsDTO) => {
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" });
const { permission } = await permissionService.getProjectPermission(actor, actorId, integrationAuth.projectId); const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
integrationAuth.projectId,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations);
const botKey = await projectBotService.getBotKey(integrationAuth.projectId); const botKey = await projectBotService.getBotKey(integrationAuth.projectId);
const { accessToken } = await getIntegrationAccessToken(integrationAuth, botKey); const { accessToken } = await getIntegrationAccessToken(integrationAuth, botKey);
@ -412,11 +474,16 @@ export const integrationAuthServiceFactory = ({
return []; return [];
}; };
const getQoveryApps = async ({ id, actor, actorId, environmentId }: TIntegrationAuthQoveryScopesDTO) => { const getQoveryApps = async ({ id, actor, actorId, actorOrgId, 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" });
const { permission } = await permissionService.getProjectPermission(actor, actorId, integrationAuth.projectId); const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
integrationAuth.projectId,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations);
const botKey = await projectBotService.getBotKey(integrationAuth.projectId); const botKey = await projectBotService.getBotKey(integrationAuth.projectId);
const { accessToken } = await getIntegrationAccessToken(integrationAuth, botKey); const { accessToken } = await getIntegrationAccessToken(integrationAuth, botKey);
@ -439,11 +506,22 @@ export const integrationAuthServiceFactory = ({
return []; return [];
}; };
const getQoveryContainers = async ({ id, actor, actorId, environmentId }: TIntegrationAuthQoveryScopesDTO) => { const getQoveryContainers = async ({
id,
actor,
actorId,
actorOrgId,
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" });
const { permission } = await permissionService.getProjectPermission(actor, actorId, integrationAuth.projectId); const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
integrationAuth.projectId,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations);
const botKey = await projectBotService.getBotKey(integrationAuth.projectId); const botKey = await projectBotService.getBotKey(integrationAuth.projectId);
const { accessToken } = await getIntegrationAccessToken(integrationAuth, botKey); const { accessToken } = await getIntegrationAccessToken(integrationAuth, botKey);
@ -466,11 +544,16 @@ export const integrationAuthServiceFactory = ({
return []; return [];
}; };
const getQoveryJobs = async ({ id, actor, actorId, environmentId }: TIntegrationAuthQoveryScopesDTO) => { const getQoveryJobs = async ({ id, actor, actorId, actorOrgId, 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" });
const { permission } = await permissionService.getProjectPermission(actor, actorId, integrationAuth.projectId); const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
integrationAuth.projectId,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations);
const botKey = await projectBotService.getBotKey(integrationAuth.projectId); const botKey = await projectBotService.getBotKey(integrationAuth.projectId);
const { accessToken } = await getIntegrationAccessToken(integrationAuth, botKey); const { accessToken } = await getIntegrationAccessToken(integrationAuth, botKey);
@ -493,11 +576,16 @@ export const integrationAuthServiceFactory = ({
return []; return [];
}; };
const getRailwayEnvironments = async ({ id, actor, actorId, appId }: TIntegrationAuthRailwayEnvDTO) => { const getRailwayEnvironments = async ({ id, actor, actorId, actorOrgId, 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" });
const { permission } = await permissionService.getProjectPermission(actor, actorId, integrationAuth.projectId); const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
integrationAuth.projectId,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations);
const botKey = await projectBotService.getBotKey(integrationAuth.projectId); const botKey = await projectBotService.getBotKey(integrationAuth.projectId);
const { accessToken } = await getIntegrationAccessToken(integrationAuth, botKey); const { accessToken } = await getIntegrationAccessToken(integrationAuth, botKey);
@ -547,11 +635,17 @@ export const integrationAuthServiceFactory = ({
} }
return []; return [];
}; };
const getRailwayServices = async ({ id, actor, actorId, appId }: TIntegrationAuthRailwayServicesDTO) => {
const getRailwayServices = async ({ id, actor, actorId, actorOrgId, 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" });
const { permission } = await permissionService.getProjectPermission(actor, actorId, integrationAuth.projectId); const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
integrationAuth.projectId,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations);
const botKey = await projectBotService.getBotKey(integrationAuth.projectId); const botKey = await projectBotService.getBotKey(integrationAuth.projectId);
const { accessToken } = await getIntegrationAccessToken(integrationAuth, botKey); const { accessToken } = await getIntegrationAccessToken(integrationAuth, botKey);
@ -620,11 +714,16 @@ export const integrationAuthServiceFactory = ({
return []; return [];
}; };
const getBitbucketWorkspaces = async ({ actorId, actor, id }: TIntegrationAuthBitbucketWorkspaceDTO) => { const getBitbucketWorkspaces = async ({ actorId, actor, actorOrgId, 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" });
const { permission } = await permissionService.getProjectPermission(actor, actorId, integrationAuth.projectId); const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
integrationAuth.projectId,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations);
const botKey = await projectBotService.getBotKey(integrationAuth.projectId); const botKey = await projectBotService.getBotKey(integrationAuth.projectId);
const { accessToken } = await getIntegrationAccessToken(integrationAuth, botKey); const { accessToken } = await getIntegrationAccessToken(integrationAuth, botKey);
@ -658,11 +757,22 @@ export const integrationAuthServiceFactory = ({
return workspaces; return workspaces;
}; };
const getNorthFlankSecretGroups = async ({ id, actor, actorId, appId }: TIntegrationAuthNorthflankSecretGroupDTO) => { const getNorthFlankSecretGroups = async ({
id,
actor,
actorId,
actorOrgId,
appId
}: TIntegrationAuthNorthflankSecretGroupDTO) => {
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" });
const { permission } = await permissionService.getProjectPermission(actor, actorId, integrationAuth.projectId); const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
integrationAuth.projectId,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations);
const botKey = await projectBotService.getBotKey(integrationAuth.projectId); const botKey = await projectBotService.getBotKey(integrationAuth.projectId);
const { accessToken } = await getIntegrationAccessToken(integrationAuth, botKey); const { accessToken } = await getIntegrationAccessToken(integrationAuth, botKey);
@ -713,11 +823,22 @@ export const integrationAuthServiceFactory = ({
return secretGroups; return secretGroups;
}; };
const getTeamcityBuildConfigs = async ({ appId, id, actorId, actor }: TGetIntegrationAuthTeamCityBuildConfigDTO) => { const getTeamcityBuildConfigs = async ({
appId,
id,
actorId,
actorOrgId,
actor
}: TGetIntegrationAuthTeamCityBuildConfigDTO) => {
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" });
const { permission } = await permissionService.getProjectPermission(actor, actorId, integrationAuth.projectId); const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
integrationAuth.projectId,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations);
const botKey = await projectBotService.getBotKey(integrationAuth.projectId); const botKey = await projectBotService.getBotKey(integrationAuth.projectId);
const { accessToken } = await getIntegrationAccessToken(integrationAuth, botKey); const { accessToken } = await getIntegrationAccessToken(integrationAuth, botKey);
@ -742,19 +863,30 @@ export const integrationAuthServiceFactory = ({
return []; return [];
}; };
const deleteIntegrationAuths = async ({ projectId, integration, actor, actorId }: TDeleteIntegrationAuthsDTO) => { const deleteIntegrationAuths = async ({
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); projectId,
integration,
actor,
actorId,
actorOrgId
}: TDeleteIntegrationAuthsDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, 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 }: TDeleteIntegrationAuthByIdDTO) => { const deleteIntegrationAuthById = async ({ id, actorId, actor, 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" });
const { permission } = await permissionService.getProjectPermission(actor, actorId, integrationAuth.projectId); const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
integrationAuth.projectId,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Delete, ProjectPermissionSub.Integrations); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Delete, ProjectPermissionSub.Integrations);
const delIntegrationAuth = await integrationAuthDAL.transaction(async (tx) => { const delIntegrationAuth = await integrationAuthDAL.transaction(async (tx) => {

View File

@ -31,6 +31,7 @@ export const integrationServiceFactory = ({
const createIntegration = async ({ const createIntegration = async ({
app, app,
actor, actor,
actorOrgId,
path, path,
appId, appId,
owner, owner,
@ -50,7 +51,12 @@ export const integrationServiceFactory = ({
const integrationAuth = await integrationAuthDAL.findById(integrationAuthId); const integrationAuth = await integrationAuthDAL.findById(integrationAuthId);
if (!integrationAuth) throw new BadRequestError({ message: "Integration auth not found" }); if (!integrationAuth) throw new BadRequestError({ message: "Integration auth not found" });
const { permission } = await permissionService.getProjectPermission(actor, actorId, integrationAuth.projectId); const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
integrationAuth.projectId,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Create, ProjectPermissionSub.Integrations); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Create, ProjectPermissionSub.Integrations);
const folder = await folderDAL.findBySecretPath(integrationAuth.projectId, sourceEnvironment, secretPath); const folder = await folderDAL.findBySecretPath(integrationAuth.projectId, sourceEnvironment, secretPath);
@ -86,6 +92,7 @@ export const integrationServiceFactory = ({
const updateIntegration = async ({ const updateIntegration = async ({
actorId, actorId,
actor, actor,
actorOrgId,
targetEnvironment, targetEnvironment,
app, app,
id, id,
@ -98,7 +105,12 @@ export const integrationServiceFactory = ({
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" });
const { permission } = await permissionService.getProjectPermission(actor, actorId, integration.projectId); const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
integration.projectId,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.Integrations); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.Integrations);
const folder = await folderDAL.findBySecretPath(integration.projectId, environment, secretPath); const folder = await folderDAL.findBySecretPath(integration.projectId, environment, secretPath);
@ -117,19 +129,24 @@ export const integrationServiceFactory = ({
return updatedIntegration; return updatedIntegration;
}; };
const deleteIntegration = async ({ actorId, id, actor }: TDeleteIntegrationDTO) => { const deleteIntegration = async ({ actorId, id, actor, 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" });
const { permission } = await permissionService.getProjectPermission(actor, actorId, integration.projectId); const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
integration.projectId,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Delete, ProjectPermissionSub.Integrations); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Delete, ProjectPermissionSub.Integrations);
const deletedIntegration = await integrationDAL.deleteById(id); const deletedIntegration = await integrationDAL.deleteById(id);
return { ...integration, ...deletedIntegration }; return { ...integration, ...deletedIntegration };
}; };
const listIntegrationByProject = async ({ actor, actorId, projectId }: TProjectPermission) => { const listIntegrationByProject = async ({ actor, actorId, actorOrgId, projectId }: TProjectPermission) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, 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);

View File

@ -11,11 +11,13 @@ import {
TUserEncryptionKeys TUserEncryptionKeys
} from "@app/db/schemas"; } from "@app/db/schemas";
import { DatabaseError } from "@app/lib/errors"; import { DatabaseError } from "@app/lib/errors";
import { buildFindFilter, selectAllTableCols, TFindFilter, TFindOpt, withTransaction } from "@app/lib/knex"; import { buildFindFilter, ormify, selectAllTableCols, TFindFilter, TFindOpt, withTransaction } from "@app/lib/knex";
export type TOrgDALFactory = ReturnType<typeof orgDALFactory>; export type TOrgDALFactory = ReturnType<typeof orgDALFactory>;
export const orgDALFactory = (db: TDbClient) => { export const orgDALFactory = (db: TDbClient) => {
const orgOrm = ormify(db, TableName.Organization);
const findOrgById = async (orgId: string) => { const findOrgById = async (orgId: string) => {
try { try {
const org = await db(TableName.Organization).where({ id: orgId }).first(); const org = await db(TableName.Organization).where({ id: orgId }).first();
@ -177,6 +179,7 @@ export const orgDALFactory = (db: TDbClient) => {
}; };
return withTransaction(db, { return withTransaction(db, {
...orgOrm,
findOrgByProjectId, findOrgByProjectId,
findAllOrgMembers, findAllOrgMembers,
findOrgById, findOrgById,

View File

@ -22,8 +22,13 @@ type TOrgRoleServiceFactoryDep = {
export type TOrgRoleServiceFactory = ReturnType<typeof orgRoleServiceFactory>; export type TOrgRoleServiceFactory = ReturnType<typeof orgRoleServiceFactory>;
export const orgRoleServiceFactory = ({ orgRoleDAL, permissionService }: TOrgRoleServiceFactoryDep) => { export const orgRoleServiceFactory = ({ orgRoleDAL, permissionService }: TOrgRoleServiceFactoryDep) => {
const createRole = async (userId: string, orgId: string, data: Omit<TOrgRolesInsert, "orgId">) => { const createRole = async (
const { permission } = await permissionService.getUserOrgPermission(userId, orgId); userId: string,
orgId: string,
data: Omit<TOrgRolesInsert, "orgId">,
actorOrgId?: string
) => {
const { permission } = await permissionService.getUserOrgPermission(userId, orgId, 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" });
@ -35,8 +40,14 @@ export const orgRoleServiceFactory = ({ orgRoleDAL, permissionService }: TOrgRol
return role; return role;
}; };
const updateRole = async (userId: string, orgId: string, roleId: string, data: Omit<TOrgRolesUpdate, "orgId">) => { const updateRole = async (
const { permission } = await permissionService.getUserOrgPermission(userId, orgId); userId: string,
orgId: string,
roleId: string,
data: Omit<TOrgRolesUpdate, "orgId">,
actorOrgId?: string
) => {
const { permission } = await permissionService.getUserOrgPermission(userId, orgId, 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 });
@ -51,8 +62,8 @@ export const orgRoleServiceFactory = ({ orgRoleDAL, permissionService }: TOrgRol
return updatedRole; return updatedRole;
}; };
const deleteRole = async (userId: string, orgId: string, roleId: string) => { const deleteRole = async (userId: string, orgId: string, roleId: string, actorOrgId?: string) => {
const { permission } = await permissionService.getUserOrgPermission(userId, orgId); const { permission } = await permissionService.getUserOrgPermission(userId, orgId, 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 (!deleteRole) throw new BadRequestError({ message: "Role not found", name: "Update role" }); if (!deleteRole) throw new BadRequestError({ message: "Role not found", name: "Update role" });
@ -60,8 +71,8 @@ export const orgRoleServiceFactory = ({ orgRoleDAL, permissionService }: TOrgRol
return deletedRole; return deletedRole;
}; };
const listRoles = async (userId: string, orgId: string) => { const listRoles = async (userId: string, orgId: string, actorOrgId?: string) => {
const { permission } = await permissionService.getUserOrgPermission(userId, orgId); const { permission } = await permissionService.getUserOrgPermission(userId, orgId, 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 = [
@ -104,8 +115,8 @@ export const orgRoleServiceFactory = ({ orgRoleDAL, permissionService }: TOrgRol
return roles; return roles;
}; };
const getUserPermission = async (userId: string, orgId: string) => { const getUserPermission = async (userId: string, orgId: string, actorOrgId?: string) => {
const { permission, membership } = await permissionService.getUserOrgPermission(userId, orgId); const { permission, membership } = await permissionService.getUserOrgPermission(userId, orgId, actorOrgId);
return { permissions: packRules(permission.rules), membership }; return { permissions: packRules(permission.rules), membership };
}; };

View File

@ -29,6 +29,7 @@ import {
TDeleteOrgMembershipDTO, TDeleteOrgMembershipDTO,
TFindAllWorkspacesDTO, TFindAllWorkspacesDTO,
TInviteUserToOrgDTO, TInviteUserToOrgDTO,
TUpdateOrgDTO,
TUpdateOrgMembershipDTO, TUpdateOrgMembershipDTO,
TVerifyUserToOrgDTO TVerifyUserToOrgDTO
} from "./org-types"; } from "./org-types";
@ -40,7 +41,7 @@ type TOrgServiceFactoryDep = {
userDAL: TUserDALFactory; userDAL: TUserDALFactory;
projectDAL: TProjectDALFactory; projectDAL: TProjectDALFactory;
incidentContactDAL: TIncidentContactsDALFactory; incidentContactDAL: TIncidentContactsDALFactory;
samlConfigDAL: Pick<TSamlConfigDALFactory, "findOne">; samlConfigDAL: Pick<TSamlConfigDALFactory, "findOne" | "findEnforceableSamlCfg">;
smtpService: TSmtpService; smtpService: TSmtpService;
tokenService: TAuthTokenServiceFactory; tokenService: TAuthTokenServiceFactory;
permissionService: TPermissionServiceFactory; permissionService: TPermissionServiceFactory;
@ -68,8 +69,8 @@ export const orgServiceFactory = ({
/* /*
* Get organization details by the organization id * Get organization details by the organization id
* */ * */
const findOrganizationById = async (userId: string, orgId: string) => { const findOrganizationById = async (userId: string, orgId: string, actorOrgId?: string) => {
await permissionService.getUserOrgPermission(userId, orgId); await permissionService.getUserOrgPermission(userId, orgId, 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;
@ -84,16 +85,16 @@ export const orgServiceFactory = ({
/* /*
* Get all workspace members * Get all workspace members
* */ * */
const findAllOrgMembers = async (userId: string, orgId: string) => { const findAllOrgMembers = async (userId: string, orgId: string, actorOrgId?: string) => {
const { permission } = await permissionService.getUserOrgPermission(userId, orgId); const { permission } = await permissionService.getUserOrgPermission(userId, orgId, 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 findAllWorkspaces = async ({ actor, actorId, orgId }: TFindAllWorkspacesDTO) => { const findAllWorkspaces = async ({ actor, actorId, actorOrgId, orgId }: TFindAllWorkspacesDTO) => {
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId); const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, 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));
@ -118,12 +119,36 @@ export const orgServiceFactory = ({
}; };
/* /*
* Update organization settings * Update organization details
* */ * */
const updateOrgName = async (userId: string, orgId: string, name: string) => { const updateOrg = async ({
const { permission } = await permissionService.getUserOrgPermission(userId, orgId); actor,
actorId,
actorOrgId,
orgId,
data: { name, slug, authEnforced }
}: TUpdateOrgDTO) => {
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, actorOrgId);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Edit, OrgPermissionSubjects.Settings); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Edit, OrgPermissionSubjects.Settings);
const org = await orgDAL.updateById(orgId, { name });
if (authEnforced !== undefined) {
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Edit, OrgPermissionSubjects.Sso);
}
if (authEnforced) {
const samlCfg = await samlConfigDAL.findEnforceableSamlCfg(orgId);
if (!samlCfg)
throw new BadRequestError({
name: "No enforceable SAML config found",
message: "No enforceable SAML config found"
});
}
const org = await orgDAL.updateById(orgId, {
name,
slug: slug ? slugify(slug) : undefined,
authEnforced
});
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;
}; };
@ -191,8 +216,8 @@ export const orgServiceFactory = ({
/* /*
* Delete organization by id * Delete organization by id
* */ * */
const deleteOrganizationById = async (userId: string, orgId: string) => { const deleteOrganizationById = async (userId: string, orgId: string, actorOrgId?: string) => {
const { membership } = await permissionService.getUserOrgPermission(userId, orgId); const { membership } = await permissionService.getUserOrgPermission(userId, orgId, 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" });
@ -206,8 +231,8 @@ 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 }: TUpdateOrgMembershipDTO) => { const updateOrgMembership = async ({ role, orgId, userId, membershipId, actorOrgId }: TUpdateOrgMembershipDTO) => {
const { permission } = await permissionService.getUserOrgPermission(userId, orgId); const { permission } = await permissionService.getUserOrgPermission(userId, orgId, 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);
@ -237,16 +262,18 @@ export const orgServiceFactory = ({
/* /*
* Invite user to organization * Invite user to organization
*/ */
const inviteUserToOrganization = async ({ orgId, userId, inviteeEmail }: TInviteUserToOrgDTO) => { const inviteUserToOrganization = async ({ orgId, userId, inviteeEmail, actorOrgId }: TInviteUserToOrgDTO) => {
const { permission } = await permissionService.getUserOrgPermission(userId, orgId); const { permission } = await permissionService.getUserOrgPermission(userId, orgId, actorOrgId);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Create, OrgPermissionSubjects.Member); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Create, OrgPermissionSubjects.Member);
const samlCfg = await samlConfigDAL.findOne({ orgId }); const org = await orgDAL.findOrgById(orgId);
if (samlCfg && samlCfg.isActive) {
if (org?.authEnforced) {
throw new BadRequestError({ throw new BadRequestError({
message: "Failed to invite member due to SAML SSO configured for organization" message: "Failed to invite user due to org-level auth enforced for organization"
}); });
} }
const plan = await licenseService.getPlan(orgId); const plan = await licenseService.getPlan(orgId);
if (plan.memberLimit !== null && plan.membersUsed >= plan.memberLimit) { if (plan.memberLimit !== null && plan.membersUsed >= plan.memberLimit) {
// case: limit imposed on number of members allowed // case: limit imposed on number of members allowed
@ -317,7 +344,6 @@ export const orgServiceFactory = ({
orgId orgId
}); });
const org = await orgDAL.findOrgById(orgId);
const user = await userDAL.findById(userId); const user = await userDAL.findById(userId);
const appCfg = getConfig(); const appCfg = getConfig();
await smtpService.sendMail({ await smtpService.sendMail({
@ -394,8 +420,8 @@ export const orgServiceFactory = ({
return { token, user }; return { token, user };
}; };
const deleteOrgMembership = async ({ orgId, userId, membershipId }: TDeleteOrgMembershipDTO) => { const deleteOrgMembership = async ({ orgId, userId, membershipId, actorOrgId }: TDeleteOrgMembershipDTO) => {
const { permission } = await permissionService.getUserOrgPermission(userId, orgId); const { permission } = await permissionService.getUserOrgPermission(userId, orgId, actorOrgId);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Delete, OrgPermissionSubjects.Member); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Delete, OrgPermissionSubjects.Member);
const membership = await orgDAL.deleteMembershipById(membershipId, orgId); const membership = await orgDAL.deleteMembershipById(membershipId, orgId);
@ -407,15 +433,15 @@ export const orgServiceFactory = ({
/* /*
* CRUD operations of incident contacts * CRUD operations of incident contacts
* */ * */
const findIncidentContacts = async (userId: string, orgId: string) => { const findIncidentContacts = async (userId: string, orgId: string, actorOrgId?: string) => {
const { permission } = await permissionService.getUserOrgPermission(userId, orgId); const { permission } = await permissionService.getUserOrgPermission(userId, orgId, 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) => { const createIncidentContact = async (userId: string, orgId: string, email: string, actorOrgId?: string) => {
const { permission } = await permissionService.getUserOrgPermission(userId, orgId); const { permission } = await permissionService.getUserOrgPermission(userId, orgId, 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) {
@ -429,8 +455,8 @@ export const orgServiceFactory = ({
return incidentContact; return incidentContact;
}; };
const deleteIncidentContact = async (userId: string, orgId: string, id: string) => { const deleteIncidentContact = async (userId: string, orgId: string, id: string, actorOrgId?: string) => {
const { permission } = await permissionService.getUserOrgPermission(userId, orgId); const { permission } = await permissionService.getUserOrgPermission(userId, orgId, 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);
@ -443,7 +469,7 @@ export const orgServiceFactory = ({
findAllOrganizationOfUser, findAllOrganizationOfUser,
inviteUserToOrganization, inviteUserToOrganization,
verifyUserToOrg, verifyUserToOrg,
updateOrgName, updateOrg,
createOrganization, createOrganization,
deleteOrganizationById, deleteOrganizationById,
deleteOrgMembership, deleteOrgMembership,

View File

@ -1,3 +1,5 @@
import { TOrgPermission } from "@app/lib/types";
import { ActorType } from "../auth/auth-type"; import { ActorType } from "../auth/auth-type";
export type TUpdateOrgMembershipDTO = { export type TUpdateOrgMembershipDTO = {
@ -5,17 +7,20 @@ export type TUpdateOrgMembershipDTO = {
orgId: string; orgId: string;
membershipId: string; membershipId: string;
role: string; role: string;
actorOrgId?: string;
}; };
export type TDeleteOrgMembershipDTO = { export type TDeleteOrgMembershipDTO = {
userId: string; userId: string;
orgId: string; orgId: string;
membershipId: string; membershipId: string;
actorOrgId?: string;
}; };
export type TInviteUserToOrgDTO = { export type TInviteUserToOrgDTO = {
userId: string; userId: string;
orgId: string; orgId: string;
actorOrgId?: string;
inviteeEmail: string; inviteeEmail: string;
}; };
@ -28,5 +33,10 @@ export type TVerifyUserToOrgDTO = {
export type TFindAllWorkspacesDTO = { export type TFindAllWorkspacesDTO = {
actor: ActorType; actor: ActorType;
actorId: string; actorId: string;
actorOrgId?: string;
orgId: string; orgId: string;
}; };
export type TUpdateOrgDTO = {
data: Partial<{ name: string; slug: string; authEnforced: boolean }>;
} & TOrgPermission;

View File

@ -71,8 +71,8 @@ export const projectBotServiceFactory = ({ projectBotDAL, permissionService }: T
}); });
}; };
const findBotByProjectId = async ({ actorId, actor, projectId }: TProjectPermission) => { const findBotByProjectId = async ({ actorId, actor, actorOrgId, projectId }: TProjectPermission) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations);
const appCfg = getConfig(); const appCfg = getConfig();
@ -120,11 +120,11 @@ export const projectBotServiceFactory = ({ projectBotDAL, permissionService }: T
return bot; return bot;
}; };
const setBotActiveState = async ({ actor, botId, botKey, actorId, isActive }: TSetActiveStateDTO) => { const setBotActiveState = async ({ actor, botId, botKey, actorId, actorOrgId, 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); const { permission } = await permissionService.getProjectPermission(actor, actorId, bot.projectId, actorOrgId);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.Integrations); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.Integrations);
if (isActive) { if (isActive) {

View File

@ -27,8 +27,8 @@ export const projectEnvServiceFactory = ({
projectDAL, projectDAL,
folderDAL folderDAL
}: TProjectEnvServiceFactoryDep) => { }: TProjectEnvServiceFactoryDep) => {
const createEnvironment = async ({ projectId, actorId, actor, name, slug }: TCreateEnvDTO) => { const createEnvironment = async ({ projectId, actorId, actor, actorOrgId, name, slug }: TCreateEnvDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, 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 });
@ -59,8 +59,17 @@ export const projectEnvServiceFactory = ({
return env; return env;
}; };
const updateEnvironment = async ({ projectId, slug, actor, actorId, name, id, position }: TUpdateEnvDTO) => { const updateEnvironment = async ({
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); projectId,
slug,
actor,
actorId,
actorOrgId,
name,
id,
position
}: TUpdateEnvDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, 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 });
@ -85,8 +94,8 @@ export const projectEnvServiceFactory = ({
return { environment: env, old: oldEnv }; return { environment: env, old: oldEnv };
}; };
const deleteEnvironment = async ({ projectId, actor, actorId, id }: TDeleteEnvDTO) => { const deleteEnvironment = async ({ projectId, actor, actorId, actorOrgId, id }: TDeleteEnvDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, 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) => {

View File

@ -25,11 +25,12 @@ export const projectKeyServiceFactory = ({
receiverId, receiverId,
actor, actor,
actorId, actorId,
actorOrgId,
projectId, projectId,
nonce, nonce,
encryptedKey encryptedKey
}: TUploadProjectKeyDTO) => { }: TUploadProjectKeyDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, 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({
@ -45,14 +46,14 @@ 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 }: TGetLatestProjectKeyDTO) => { const getLatestProjectKey = async ({ actorId, projectId, actor, actorOrgId }: TGetLatestProjectKeyDTO) => {
await permissionService.getProjectPermission(actor, actorId, projectId); await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId);
const latestKey = await projectKeyDAL.findLatestProjectKey(actorId, projectId); const latestKey = await projectKeyDAL.findLatestProjectKey(actorId, projectId);
return latestKey; return latestKey;
}; };
const getProjectPublicKeys = async ({ actor, actorId, projectId }: TGetLatestProjectKeyDTO) => { const getProjectPublicKeys = async ({ actor, actorId, actorOrgId, projectId }: TGetLatestProjectKeyDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, 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);
}; };

View File

@ -48,15 +48,15 @@ export const projectMembershipServiceFactory = ({
projectKeyDAL, projectKeyDAL,
licenseService licenseService
}: TProjectMembershipServiceFactoryDep) => { }: TProjectMembershipServiceFactoryDep) => {
const getProjectMemberships = async ({ actorId, actor, projectId }: TGetProjectMembershipDTO) => { const getProjectMemberships = async ({ actorId, actor, actorOrgId, projectId }: TGetProjectMembershipDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, 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);
}; };
const inviteUserToProject = async ({ actorId, actor, projectId, email }: TInviteUserToProjectDTO) => { const inviteUserToProject = async ({ actorId, actor, actorOrgId, projectId, email }: TInviteUserToProjectDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Create, ProjectPermissionSub.Member); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Create, ProjectPermissionSub.Member);
const invitee = await userDAL.findOne({ email }); const invitee = await userDAL.findOne({ email });
@ -112,11 +112,11 @@ export const projectMembershipServiceFactory = ({
return { invitee, latestKey }; return { invitee, latestKey };
}; };
const addUsersToProject = async ({ projectId, actorId, actor, members }: TAddUsersToWorkspaceDTO) => { const addUsersToProject = async ({ projectId, actorId, actor, actorOrgId, members }: 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); const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, 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,
@ -172,11 +172,12 @@ export const projectMembershipServiceFactory = ({
const updateProjectMembership = async ({ const updateProjectMembership = async ({
actorId, actorId,
actor, actor,
actorOrgId,
projectId, projectId,
membershipId, membershipId,
role role
}: TUpdateProjectMembershipDTO) => { }: TUpdateProjectMembershipDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.Member); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.Member);
const isCustomRole = !Object.values(ProjectMembershipRole).includes(role as ProjectMembershipRole); const isCustomRole = !Object.values(ProjectMembershipRole).includes(role as ProjectMembershipRole);
@ -204,8 +205,14 @@ export const projectMembershipServiceFactory = ({
return membership; return membership;
}; };
const deleteProjectMembership = async ({ actorId, actor, projectId, membershipId }: TDeleteProjectMembershipDTO) => { const deleteProjectMembership = async ({
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); actorId,
actor,
actorOrgId,
projectId,
membershipId
}: TDeleteProjectMembershipDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Delete, ProjectPermissionSub.Member); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Delete, ProjectPermissionSub.Member);
const membership = await projectMembershipDAL.transaction(async (tx) => { const membership = await projectMembershipDAL.transaction(async (tx) => {

View File

@ -28,9 +28,10 @@ export const projectRoleServiceFactory = ({ projectRoleDAL, permissionService }:
actor: ActorType, actor: ActorType,
actorId: string, actorId: string,
projectId: string, projectId: string,
data: Omit<TProjectRolesInsert, "projectId"> data: Omit<TProjectRolesInsert, "projectId">,
actorOrgId?: string
) => { ) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, 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" });
@ -47,9 +48,10 @@ export const projectRoleServiceFactory = ({ projectRoleDAL, permissionService }:
actorId: string, actorId: string,
projectId: string, projectId: string,
roleId: string, roleId: string,
data: Omit<TOrgRolesUpdate, "orgId"> data: Omit<TOrgRolesUpdate, "orgId">,
actorOrgId?: string
) => { ) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, 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 });
@ -64,8 +66,14 @@ export const projectRoleServiceFactory = ({ projectRoleDAL, permissionService }:
return updatedRole; return updatedRole;
}; };
const deleteRole = async (actor: ActorType, actorId: string, projectId: string, roleId: string) => { const deleteRole = async (
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); actor: ActorType,
actorId: string,
projectId: string,
roleId: string,
actorOrgId?: string
) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, 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 (!deleteRole) throw new BadRequestError({ message: "Role not found", name: "Update role" }); if (!deleteRole) throw new BadRequestError({ message: "Role not found", name: "Update role" });
@ -73,8 +81,8 @@ export const projectRoleServiceFactory = ({ projectRoleDAL, permissionService }:
return deletedRole; return deletedRole;
}; };
const listRoles = async (actor: ActorType, actorId: string, projectId: string) => { const listRoles = async (actor: ActorType, actorId: string, projectId: string, actorOrgId?: string) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, 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 = [
@ -127,8 +135,8 @@ export const projectRoleServiceFactory = ({ projectRoleDAL, permissionService }:
return roles; return roles;
}; };
const getUserPermission = async (userId: string, projectId: string) => { const getUserPermission = async (userId: string, projectId: string, actorOrgId?: string) => {
const { permission, membership } = await permissionService.getUserProjectPermission(userId, projectId); const { permission, membership } = await permissionService.getUserProjectPermission(userId, projectId, actorOrgId);
return { permissions: packRules(permission.rules), membership }; return { permissions: packRules(permission.rules), membership };
}; };

View File

@ -48,8 +48,8 @@ export const projectServiceFactory = ({
/* /*
* Create workspace. Make user the admin * Create workspace. Make user the admin
* */ * */
const createProject = async ({ orgId, actor, actorId, workspaceName }: TCreateProjectDTO) => { const createProject = async ({ orgId, actor, actorId, actorOrgId, workspaceName }: TCreateProjectDTO) => {
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId); const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, actorOrgId);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Create, OrgPermissionSubjects.Workspace); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Create, OrgPermissionSubjects.Workspace);
const appCfg = getConfig(); const appCfg = getConfig();
@ -106,8 +106,8 @@ export const projectServiceFactory = ({
return newProject; return newProject;
}; };
const deleteProject = async ({ actor, actorId, projectId }: TDeleteProjectDTO) => { const deleteProject = async ({ actor, actorId, actorOrgId, projectId }: TDeleteProjectDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Delete, ProjectPermissionSub.Project); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Delete, ProjectPermissionSub.Project);
const deletedProject = await projectDAL.deleteById(projectId); const deletedProject = await projectDAL.deleteById(projectId);
@ -119,8 +119,8 @@ export const projectServiceFactory = ({
return workspaces; return workspaces;
}; };
const getAProject = async ({ actorId, projectId, actor }: TGetProjectDTO) => { const getAProject = async ({ actorId, actorOrgId, projectId, actor }: TGetProjectDTO) => {
await permissionService.getProjectPermission(actor, actorId, projectId); await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId);
return projectDAL.findProjectById(projectId); return projectDAL.findProjectById(projectId);
}; };
@ -128,17 +128,18 @@ export const projectServiceFactory = ({
projectId, projectId,
actor, actor,
actorId, actorId,
actorOrgId,
autoCapitalization autoCapitalization
}: TGetProjectDTO & { autoCapitalization: boolean }) => { }: TGetProjectDTO & { autoCapitalization: boolean }) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, 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, name }: TGetProjectDTO & { name: string }) => { const updateName = async ({ projectId, actor, actorId, actorOrgId, name }: TGetProjectDTO & { name: string }) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, 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 });

View File

@ -3,6 +3,7 @@ import { ActorType } from "../auth/auth-type";
export type TCreateProjectDTO = { export type TCreateProjectDTO = {
actor: ActorType; actor: ActorType;
actorId: string; actorId: string;
actorOrgId?: string;
orgId: string; orgId: string;
workspaceName: string; workspaceName: string;
}; };
@ -10,11 +11,13 @@ export type TCreateProjectDTO = {
export type TDeleteProjectDTO = { export type TDeleteProjectDTO = {
actor: ActorType; actor: ActorType;
actorId: string; actorId: string;
actorOrgId?: string;
projectId: string; projectId: string;
}; };
export type TGetProjectDTO = { export type TGetProjectDTO = {
actor: ActorType; actor: ActorType;
actorId: string; actorId: string;
actorOrgId?: string;
projectId: string; projectId: string;
}; };

View File

@ -24,8 +24,13 @@ export const secretBlindIndexServiceFactory = ({
permissionService, permissionService,
secretDAL secretDAL
}: TSecretBlindIndexServiceFactoryDep) => { }: TSecretBlindIndexServiceFactoryDep) => {
const getSecretBlindIndexStatus = async ({ actor, projectId, actorId }: TGetProjectBlindIndexStatusDTO) => { const getSecretBlindIndexStatus = async ({
await permissionService.getProjectPermission(actor, actorId, projectId); actor,
projectId,
actorId,
actorOrgId
}: TGetProjectBlindIndexStatusDTO) => {
await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId);
const secretCount = await secretBlindIndexDAL.countOfSecretsWithNullSecretBlindIndex(projectId); const secretCount = await secretBlindIndexDAL.countOfSecretsWithNullSecretBlindIndex(projectId);
return Number(secretCount); return Number(secretCount);
@ -45,9 +50,10 @@ export const secretBlindIndexServiceFactory = ({
projectId, projectId,
actor, actor,
actorId, actorId,
actorOrgId,
secretsToUpdate secretsToUpdate
}: TUpdateProjectSecretNameDTO) => { }: TUpdateProjectSecretNameDTO) => {
const { membership } = await permissionService.getProjectPermission(actor, actorId, projectId); const { membership } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId);
if (membership?.role !== ProjectMembershipRole.Admin) { if (membership?.role !== ProjectMembershipRole.Admin) {
throw new UnauthorizedError({ message: "User must be admin" }); throw new UnauthorizedError({ message: "User must be admin" });
} }

View File

@ -30,8 +30,16 @@ export const secretFolderServiceFactory = ({
projectEnvDAL, projectEnvDAL,
folderVersionDAL folderVersionDAL
}: TSecretFolderServiceFactoryDep) => { }: TSecretFolderServiceFactoryDep) => {
const createFolder = async ({ projectId, actor, actorId, name, environment, path: secretPath }: TCreateFolderDTO) => { const createFolder = async ({
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); projectId,
actor,
actorId,
actorOrgId,
name,
environment,
path: secretPath
}: TCreateFolderDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId);
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Create, ProjectPermissionActions.Create,
subject(ProjectPermissionSub.Secrets, { environment, secretPath }) subject(ProjectPermissionSub.Secrets, { environment, secretPath })
@ -105,12 +113,13 @@ export const secretFolderServiceFactory = ({
projectId, projectId,
actor, actor,
actorId, actorId,
actorOrgId,
name, name,
environment, environment,
path: secretPath, path: secretPath,
id id
}: TUpdateFolderDTO) => { }: TUpdateFolderDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId);
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Edit, ProjectPermissionActions.Edit,
subject(ProjectPermissionSub.Secrets, { environment, secretPath }) subject(ProjectPermissionSub.Secrets, { environment, secretPath })
@ -148,8 +157,16 @@ export const secretFolderServiceFactory = ({
return { folder: newFolder, old: folder }; return { folder: newFolder, old: folder };
}; };
const deleteFolder = async ({ projectId, actor, actorId, environment, path: secretPath, id }: TDeleteFolderDTO) => { const deleteFolder = async ({
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); projectId,
actor,
actorId,
actorOrgId,
environment,
path: secretPath,
id
}: TDeleteFolderDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId);
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Delete, ProjectPermissionActions.Delete,
subject(ProjectPermissionSub.Secrets, { environment, secretPath }) subject(ProjectPermissionSub.Secrets, { environment, secretPath })
@ -171,10 +188,17 @@ export const secretFolderServiceFactory = ({
return folder; return folder;
}; };
const getFolders = async ({ projectId, actor, actorId, environment, path: secretPath }: TGetFolderDTO) => { const getFolders = async ({
projectId,
actor,
actorId,
actorOrgId,
environment,
path: secretPath
}: 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); await permissionService.getProjectPermission(actor, actorId, projectId, 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" });

View File

@ -36,8 +36,16 @@ export const secretImportServiceFactory = ({
folderDAL, folderDAL,
secretDAL secretDAL
}: TSecretImportServiceFactoryDep) => { }: TSecretImportServiceFactoryDep) => {
const createImport = async ({ environment, data, actor, actorId, projectId, path }: TCreateSecretImportDTO) => { const createImport = async ({
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); environment,
data,
actor,
actorId,
actorOrgId,
projectId,
path
}: TCreateSecretImportDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, 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(
@ -77,8 +85,17 @@ export const secretImportServiceFactory = ({
return { ...secImport, importEnv }; return { ...secImport, importEnv };
}; };
const updateImport = async ({ path, environment, projectId, actor, actorId, data, id }: TUpdateSecretImportDTO) => { const updateImport = async ({
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); path,
environment,
projectId,
actor,
actorId,
actorOrgId,
data,
id
}: TUpdateSecretImportDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, 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 })
@ -115,8 +132,16 @@ export const secretImportServiceFactory = ({
return { ...updatedSecImport, importEnv: importedEnv }; return { ...updatedSecImport, importEnv: importedEnv };
}; };
const deleteImport = async ({ path, environment, projectId, actor, actorId, id }: TDeleteSecretImportDTO) => { const deleteImport = async ({
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); path,
environment,
projectId,
actor,
actorId,
actorOrgId,
id
}: TDeleteSecretImportDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, 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 })
@ -137,8 +162,8 @@ export const secretImportServiceFactory = ({
return secImport; return secImport;
}; };
const getImports = async ({ path, environment, projectId, actor, actorId }: TGetSecretImportsDTO) => { const getImports = async ({ path, environment, projectId, actor, actorId, actorOrgId }: TGetSecretImportsDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, 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 })
@ -151,8 +176,15 @@ export const secretImportServiceFactory = ({
return secImports; return secImports;
}; };
const getSecretsFromImports = async ({ path, environment, projectId, actor, actorId }: TGetSecretsFromImportDTO) => { const getSecretsFromImports = async ({
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); path,
environment,
projectId,
actor,
actorId,
actorOrgId
}: TGetSecretsFromImportDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, 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 })

View File

@ -15,8 +15,8 @@ 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, projectId }: TCreateTagDTO) => { const createTag = async ({ name, slug, actor, color, actorId, actorOrgId, projectId }: TCreateTagDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Create, ProjectPermissionSub.Tags); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Create, ProjectPermissionSub.Tags);
const existingTag = await secretTagDAL.findOne({ slug }); const existingTag = await secretTagDAL.findOne({ slug });
@ -32,19 +32,19 @@ export const secretTagServiceFactory = ({ secretTagDAL, permissionService }: TSe
return newTag; return newTag;
}; };
const deleteTag = async ({ actorId, actor, id }: TDeleteTagDTO) => { const deleteTag = async ({ actorId, actor, actorOrgId, 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); const { permission } = await permissionService.getProjectPermission(actor, actorId, tag.projectId, 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, projectId }: TListProjectTagsDTO) => { const getProjectTags = async ({ actor, actorId, actorOrgId, projectId }: TListProjectTagsDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, 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"]] });

View File

@ -37,7 +37,6 @@ import {
TGetSecretsDTO, TGetSecretsDTO,
TGetSecretsRawDTO, TGetSecretsRawDTO,
TGetSecretVersionsDTO, TGetSecretVersionsDTO,
TListSecretVersionDTO,
TUpdateBulkSecretDTO, TUpdateBulkSecretDTO,
TUpdateSecretDTO, TUpdateSecretDTO,
TUpdateSecretRawDTO TUpdateSecretRawDTO
@ -267,8 +266,16 @@ export const secretServiceFactory = ({
return { secsGroupedByBlindIndex, secrets }; return { secsGroupedByBlindIndex, secrets };
}; };
const createSecret = async ({ path, actor, actorId, environment, projectId, ...inputSecret }: TCreateSecretDTO) => { const createSecret = async ({
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); path,
actor,
actorId,
actorOrgId,
environment,
projectId,
...inputSecret
}: TCreateSecretDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, 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 })
@ -337,8 +344,16 @@ export const secretServiceFactory = ({
return { ...secret[0], environment, workspace: projectId, tags }; return { ...secret[0], environment, workspace: projectId, tags };
}; };
const updateSecret = async ({ path, actor, actorId, environment, projectId, ...inputSecret }: TUpdateSecretDTO) => { const updateSecret = async ({
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); path,
actor,
actorId,
actorOrgId,
environment,
projectId,
...inputSecret
}: TUpdateSecretDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, 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 })
@ -429,8 +444,16 @@ export const secretServiceFactory = ({
return { ...updatedSecret[0], workspace: projectId, environment }; return { ...updatedSecret[0], workspace: projectId, environment };
}; };
const deleteSecret = async ({ path, actor, actorId, environment, projectId, ...inputSecret }: TDeleteSecretDTO) => { const deleteSecret = async ({
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); path,
actor,
actorId,
actorOrgId,
environment,
projectId,
...inputSecret
}: TDeleteSecretDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, 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 })
@ -476,8 +499,16 @@ export const secretServiceFactory = ({
return { ...deletedSecret[0], _id: deletedSecret[0].id, workspace: projectId, environment }; return { ...deletedSecret[0], _id: deletedSecret[0].id, workspace: projectId, environment };
}; };
const getSecrets = async ({ actorId, path, environment, projectId, actor, includeImports }: TGetSecretsDTO) => { const getSecrets = async ({
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); actorId,
path,
environment,
projectId,
actor,
actorOrgId,
includeImports
}: TGetSecretsDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, 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 })
@ -518,6 +549,7 @@ export const secretServiceFactory = ({
const getSecretByName = async ({ const getSecretByName = async ({
actorId, actorId,
actor, actor,
actorOrgId,
projectId, projectId,
environment, environment,
path, path,
@ -526,7 +558,7 @@ export const secretServiceFactory = ({
version, version,
includeImports includeImports
}: TGetASecretDTO) => { }: TGetASecretDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, 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 })
@ -549,7 +581,7 @@ export const secretServiceFactory = ({
secretType = SecretType.Shared; secretType = SecretType.Shared;
} }
const secret = await (typeof version === undefined const secret = await (version === undefined
? secretDAL.findOne({ ? secretDAL.findOne({
folderId, folderId,
type: secretType, type: secretType,
@ -607,11 +639,12 @@ export const secretServiceFactory = ({
path, path,
actor, actor,
actorId, actorId,
actorOrgId,
environment, environment,
projectId, projectId,
secrets: inputSecrets secrets: inputSecrets
}: TCreateBulkSecretDTO) => { }: TCreateBulkSecretDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, 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 })
@ -661,11 +694,12 @@ export const secretServiceFactory = ({
path, path,
actor, actor,
actorId, actorId,
actorOrgId,
environment, environment,
projectId, projectId,
secrets: inputSecrets secrets: inputSecrets
}: TUpdateBulkSecretDTO) => { }: TUpdateBulkSecretDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, 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 })
@ -733,9 +767,10 @@ export const secretServiceFactory = ({
environment, environment,
projectId, projectId,
actor, actor,
actorId actorId,
actorOrgId
}: TDeleteBulkSecretDTO) => { }: TDeleteBulkSecretDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, 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 })
@ -774,20 +809,15 @@ export const secretServiceFactory = ({
return secretsDeleted; return secretsDeleted;
}; };
const listSecretVersionsBySecretId = async ({ actorId, actor, limit, offset, secretId }: TListSecretVersionDTO) => { const getSecretsRaw = async ({
const secret = await secretDAL.findById(secretId); projectId,
if (!secret) throw new BadRequestError({ message: "Failed to find secret" }); path,
actor,
const folder = await folderDAL.findById(secret.folderId); actorId,
if (!folder) throw new BadRequestError({ message: "Folder not found" }); actorOrgId,
const { permission } = await permissionService.getProjectPermission(actor, actorId, folder.projectId); environment,
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.SecretRollback); includeImports
}: TGetSecretsRawDTO) => {
const secretVersions = await secretVersionDAL.find({ secretId }, { limit, offset, sort: [["createdAt", "desc"]] });
return secretVersions;
};
const getSecretsRaw = async ({ projectId, path, actor, actorId, environment, includeImports }: TGetSecretsRawDTO) => {
const botKey = await projectBotService.getBotKey(projectId); const botKey = await projectBotService.getBotKey(projectId);
if (!botKey) throw new BadRequestError({ message: "Project bot not found", name: "bot_not_found_error" }); if (!botKey) throw new BadRequestError({ message: "Project bot not found", name: "bot_not_found_error" });
@ -796,6 +826,7 @@ export const secretServiceFactory = ({
projectId, projectId,
environment, environment,
actor, actor,
actorOrgId,
path, path,
includeImports includeImports
}); });
@ -818,6 +849,7 @@ export const secretServiceFactory = ({
environment, environment,
projectId, projectId,
actorId, actorId,
actorOrgId,
secretName, secretName,
includeImports, includeImports,
version version
@ -830,6 +862,7 @@ export const secretServiceFactory = ({
projectId, projectId,
environment, environment,
actor, actor,
actorOrgId,
path, path,
secretName, secretName,
type, type,
@ -845,6 +878,7 @@ export const secretServiceFactory = ({
projectId, projectId,
environment, environment,
actor, actor,
actorOrgId,
type, type,
secretPath, secretPath,
secretValue, secretValue,
@ -866,6 +900,7 @@ export const secretServiceFactory = ({
path: secretPath, path: secretPath,
actor, actor,
actorId, actorId,
actorOrgId,
secretKeyCiphertext: secretKeyEncrypted.ciphertext, secretKeyCiphertext: secretKeyEncrypted.ciphertext,
secretKeyIV: secretKeyEncrypted.iv, secretKeyIV: secretKeyEncrypted.iv,
secretKeyTag: secretKeyEncrypted.tag, secretKeyTag: secretKeyEncrypted.tag,
@ -890,6 +925,7 @@ export const secretServiceFactory = ({
projectId, projectId,
environment, environment,
actor, actor,
actorOrgId,
type, type,
secretPath, secretPath,
secretValue, secretValue,
@ -908,6 +944,7 @@ export const secretServiceFactory = ({
path: secretPath, path: secretPath,
actor, actor,
actorId, actorId,
actorOrgId,
secretValueCiphertext: secretValueEncrypted.ciphertext, secretValueCiphertext: secretValueEncrypted.ciphertext,
secretValueIV: secretValueEncrypted.iv, secretValueIV: secretValueEncrypted.iv,
secretValueTag: secretValueEncrypted.tag, secretValueTag: secretValueEncrypted.tag,
@ -926,6 +963,7 @@ export const secretServiceFactory = ({
projectId, projectId,
environment, environment,
actor, actor,
actorOrgId,
type, type,
secretPath secretPath
}: TDeleteSecretRawDTO) => { }: TDeleteSecretRawDTO) => {
@ -939,7 +977,8 @@ export const secretServiceFactory = ({
type, type,
path: secretPath, path: secretPath,
actor, actor,
actorId actorId,
actorOrgId
}); });
await snapshotService.performSnapshot(secret.folderId); await snapshotService.performSnapshot(secret.folderId);
@ -948,14 +987,21 @@ export const secretServiceFactory = ({
return decryptSecretRaw(secret, botKey); return decryptSecretRaw(secret, botKey);
}; };
const getSecretVersions = async ({ actorId, actor, limit = 20, offset = 0, secretId }: TGetSecretVersionsDTO) => { const getSecretVersions = async ({
actorId,
actor,
actorOrgId,
limit = 20,
offset = 0,
secretId
}: TGetSecretVersionsDTO) => {
const secret = await secretDAL.findById(secretId); const secret = await secretDAL.findById(secretId);
if (!secret) throw new BadRequestError({ message: "Failed to find secret" }); if (!secret) throw new BadRequestError({ message: "Failed to find secret" });
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); const { permission } = await permissionService.getProjectPermission(actor, actorId, folder.projectId, 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"]] });
@ -976,7 +1022,6 @@ export const secretServiceFactory = ({
createSecretRaw, createSecretRaw,
updateSecretRaw, updateSecretRaw,
deleteSecretRaw, deleteSecretRaw,
listSecretVersionsBySecretId,
getSecretVersions, getSecretVersions,
// external services function // external services function
fnSecretBulkDelete, fnSecretBulkDelete,

View File

@ -128,12 +128,6 @@ export type TDeleteBulkSecretDTO = {
}>; }>;
} & TProjectPermission; } & TProjectPermission;
export type TListSecretVersionDTO = {
secretId: string;
offset?: number;
limit?: number;
} & Omit<TProjectPermission, "projectId">;
export type TGetSecretsRawDTO = { export type TGetSecretsRawDTO = {
path: string; path: string;
environment: string; environment: string;

View File

@ -39,6 +39,7 @@ export const serviceTokenServiceFactory = ({
tag, tag,
name, name,
actor, actor,
actorOrgId,
scopes, scopes,
actorId, actorId,
projectId, projectId,
@ -46,7 +47,7 @@ export const serviceTokenServiceFactory = ({
permissions, permissions,
encryptedKey encryptedKey
}: TCreateServiceTokenDTO) => { }: TCreateServiceTokenDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, 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 }) => {
@ -90,11 +91,16 @@ export const serviceTokenServiceFactory = ({
return { token, serviceToken }; return { token, serviceToken };
}; };
const deleteServiceToken = async ({ actorId, actor, id }: TDeleteServiceTokenDTO) => { const deleteServiceToken = async ({ actorId, actor, actorOrgId, 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" });
const { permission } = await permissionService.getProjectPermission(actor, actorId, serviceToken.projectId); const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
serviceToken.projectId,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Delete, ProjectPermissionSub.ServiceTokens); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Delete, ProjectPermissionSub.ServiceTokens);
const deletedServiceToken = await serviceTokenDAL.deleteById(id); const deletedServiceToken = await serviceTokenDAL.deleteById(id);
@ -113,8 +119,8 @@ export const serviceTokenServiceFactory = ({
return { serviceToken, user: serviceTokenUser }; return { serviceToken, user: serviceTokenUser };
}; };
const getProjectServiceTokens = async ({ actorId, actor, projectId }: TProjectServiceTokensDTO) => { const getProjectServiceTokens = async ({ actorId, actor, actorOrgId, projectId }: TProjectServiceTokensDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, 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"]] });

View File

@ -99,7 +99,12 @@ export const superAdminServiceFactory = ({
await orgService.createOrganization(userInfo.user.id, userInfo.user.email, initialOrganizationName); await orgService.createOrganization(userInfo.user.id, userInfo.user.email, initialOrganizationName);
await updateServerCfg({ initialized: true }); await updateServerCfg({ initialized: true });
const token = await authService.generateUserTokens(userInfo.user, ip, userAgent); const token = await authService.generateUserTokens({
user: userInfo.user,
ip,
userAgent,
organizationId: undefined
});
// TODO(akhilmhdh-pg): telemetry service // TODO(akhilmhdh-pg): telemetry service
return { token, user: userInfo }; return { token, user: userInfo };
}; };

View File

@ -30,15 +30,6 @@ export const userServiceFactory = ({ userDAL }: TUserServiceFactoryDep) => {
const user = await userDAL.findById(userId); const user = await userDAL.findById(userId);
if (!user) throw new BadRequestError({ name: "Update auth methods" }); if (!user) throw new BadRequestError({ name: "Update auth methods" });
const hasSamlEnabled = user?.authMethods?.some((method) =>
[AuthMethod.OKTA_SAML, AuthMethod.AZURE_SAML, AuthMethod.JUMPCLOUD_SAML].includes(method as AuthMethod)
);
if (hasSamlEnabled)
throw new BadRequestError({
name: "Update auth method",
message: "Failed to update auth methods due to SAML SSO "
});
const updatedUser = await userDAL.updateById(userId, { authMethods }); const updatedUser = await userDAL.updateById(userId, { authMethods });
return updatedUser; return updatedUser;
}; };

View File

@ -30,13 +30,14 @@ export const webhookServiceFactory = ({ webhookDAL, projectEnvDAL, permissionSer
const createWebhook = async ({ const createWebhook = async ({
actor, actor,
actorId, actorId,
actorOrgId,
projectId, projectId,
webhookUrl, webhookUrl,
environment, environment,
secretPath, secretPath,
webhookSecretKey webhookSecretKey
}: TCreateWebhookDTO) => { }: TCreateWebhookDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, 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" });
@ -72,33 +73,33 @@ export const webhookServiceFactory = ({ webhookDAL, projectEnvDAL, permissionSer
return { ...webhook, projectId, environment: env }; return { ...webhook, projectId, environment: env };
}; };
const updateWebhook = async ({ actorId, actor, id, isDisabled }: TUpdateWebhookDTO) => { const updateWebhook = async ({ actorId, actor, actorOrgId, 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); const { permission } = await permissionService.getProjectPermission(actor, actorId, webhook.projectId, 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 }: TDeleteWebhookDTO) => { const deleteWebhook = async ({ id, actor, actorId, 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); const { permission } = await permissionService.getProjectPermission(actor, actorId, webhook.projectId, 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 }: TTestWebhookDTO) => { const testWebhook = async ({ id, actor, actorId, 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); const { permission } = await permissionService.getProjectPermission(actor, actorId, webhook.projectId, 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;
@ -118,8 +119,8 @@ export const webhookServiceFactory = ({ webhookDAL, projectEnvDAL, permissionSer
return { ...webhook, ...updatedWebhook }; return { ...webhook, ...updatedWebhook };
}; };
const listWebhooks = async ({ actorId, actor, projectId, secretPath, environment }: TListWebhookDTO) => { const listWebhooks = async ({ actorId, actor, actorOrgId, projectId, secretPath, environment }: TListWebhookDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, 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);

View File

@ -62,8 +62,11 @@ services:
dockerfile: Dockerfile.dev dockerfile: Dockerfile.dev
depends_on: depends_on:
- db - db
- redis
env_file: env_file:
- .env - .env
ports:
- 4000:4000
environment: environment:
- NODE_ENV=development - NODE_ENV=development
- DB_CONNECTION_URI=postgres://infisical:infisical@db/infisical?sslmode=disable - DB_CONNECTION_URI=postgres://infisical:infisical@db/infisical?sslmode=disable

View File

@ -91,10 +91,17 @@ description: "Configure Azure SAML for Infisical SSO"
![Azure SAML assignment](../../../images/sso/azure/assignment.png) ![Azure SAML assignment](../../../images/sso/azure/assignment.png)
</Step> </Step>
<Step title="Enable SAML SSO in Infisical"> <Step title="Enable SAML SSO in Infisical">
Enabling SAML SSO enforces all members in your organization to only be able to log into Infisical via Azure. Enabling SAML SSO allows members in your organization to log into Infisical via Azure.
![Azure SAML assignment](../../../images/sso/azure/enable-saml.png) ![Azure SAML assignment](../../../images/sso/azure/enable-saml.png)
</Step> </Step>
<Step title="Enforce SAML SSO in Infisical">
Enforcing SAML SSO ensures that members in your organization can only access Infisical
by logging into the organization via Azure.
To enforce SAML SSO, you're required to test out the SAML connection by successfully authenticating at least one Azure user with Infisical;
Once you've completed this requirement, you can toggle the **Enforce SAML SSO** button to enforce SAML SSO.
</Step>
</Steps> </Steps>
<Note> <Note>

View File

@ -71,10 +71,17 @@ description: "Configure JumpCloud SAML for Infisical SSO"
![JumpCloud SAML assignment](../../../images/sso/jumpcloud/assignment.png) ![JumpCloud SAML assignment](../../../images/sso/jumpcloud/assignment.png)
</Step> </Step>
<Step title="Enable SAML SSO in Infisical"> <Step title="Enable SAML SSO in Infisical">
Enabling SAML SSO enforces all members in your organization to only be able to log into Infisical via JumpCloud. Enabling SAML SSO allows members in your organization to log into Infisical via JumpCloud.
![JumpCloud SAML assignment](../../../images/sso/jumpcloud/enable-saml.png) ![JumpCloud SAML assignment](../../../images/sso/jumpcloud/enable-saml.png)
</Step> </Step>
<Step title="Enforce SAML SSO in Infisical">
Enforcing SAML SSO ensures that members in your organization can only access Infisical
by logging into the organization via JumpCloud.
To enforce SAML SSO, you're required to test out the SAML connection by successfully authenticating at least one JumpCloud user with Infisical;
Once you've completed this requirement, you can toggle the **Enforce SAML SSO** button to enforce SAML SSO.
</Step>
</Steps> </Steps>
<Note> <Note>

View File

@ -74,9 +74,16 @@ description: "Configure Okta SAML 2.0 for Infisical SSO"
At this point, you have configured everything you need within the context of the Okta Admin Portal. At this point, you have configured everything you need within the context of the Okta Admin Portal.
</Step> </Step>
<Step title="Enable SAML SSO in Infisical"> <Step title="Enable SAML SSO in Infisical">
Enabling SAML SSO enforces all members in your organization to only be able to log into Infisical via Okta. Enabling SAML SSO allows members in your organization to log into Infisical via Okta.
![SAML Okta assignment](../../../images/sso/okta/enable-saml.png) ![SAML Okta enable SAML](../../../images/sso/okta/enable-saml.png)
</Step>
<Step title="Enforce SAML SSO in Infisical">
Enforcing SAML SSO ensures that members in your organization can only access Infisical
by logging into the organization via Okta.
To enforce SAML SSO, you're required to test out the SAML connection by successfully authenticating at least one Okta user with Infisical;
Once you've completed this requirement, you can toggle the **Enforce SAML SSO** button to enforce SAML SSO.
</Step> </Step>
</Steps> </Steps>

Binary file not shown.

After

Width:  |  Height:  |  Size: 134 KiB

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