feat: switched up all dal except policy ones

This commit is contained in:
=
2025-10-10 00:09:45 +05:30
parent 4d68d48d89
commit 0ddf98ec15
37 changed files with 1022 additions and 895 deletions
+114 -127
View File
@@ -2,14 +2,15 @@ import { Knex } from "knex";
import { TDbClient } from "@app/db";
import {
AccessScope,
OrganizationsSchema,
OrgMembershipRole,
TableName,
TMemberships,
TMembershipsInsert,
TMembershipsUpdate,
TOrganizations,
TOrganizationsInsert,
TOrgMemberships,
TOrgMembershipsInsert,
TOrgMembershipsUpdate,
TUserEncryptionKeys
} from "@app/db/schemas";
import { DatabaseError } from "@app/lib/errors";
@@ -64,9 +65,12 @@ export const orgDALFactory = (db: TDbClient) => {
.replicaNode()(TableName.Organization)
.whereIn(`${TableName.Organization}.id`, orgIdSubquery)
.leftJoin(TableName.Project, `${TableName.Organization}.id`, `${TableName.Project}.orgId`)
.leftJoin(TableName.OrgMembership, `${TableName.Organization}.id`, `${TableName.OrgMembership}.orgId`)
.leftJoin(TableName.Users, `${TableName.OrgMembership}.userId`, `${TableName.Users}.id`)
.leftJoin(TableName.OrgRoles, `${TableName.OrgMembership}.roleId`, `${TableName.OrgRoles}.id`)
.leftJoin(TableName.Membership, `${TableName.Organization}.id`, `${TableName.Membership}.scopeOrgId`)
.where(`${TableName.Membership}.scope`, AccessScope.Organization)
.whereNotNull(`${TableName.Membership}.actorUserId`)
.leftJoin(TableName.Users, `${TableName.Membership}.actorUserId`, `${TableName.Users}.id`)
.leftJoin(TableName.MembershipRole, `${TableName.Membership}.id`, `${TableName.MembershipRole}.membershipId`)
.leftJoin(TableName.Role, `${TableName.MembershipRole}.customRoleId`, `${TableName.Role}.id`)
.where((qb) => {
void qb.where(`${TableName.Users}.isGhost`, false).orWhereNull(`${TableName.Users}.id`);
});
@@ -84,11 +88,11 @@ export const orgDALFactory = (db: TDbClient) => {
.select(db.ref("firstName").withSchema(TableName.Users).as("firstName"))
.select(db.ref("lastName").withSchema(TableName.Users).as("lastName"))
.select(db.ref("id").withSchema(TableName.Users).as("userId"))
.select(db.ref("id").withSchema(TableName.OrgMembership).as("orgMembershipId"))
.select(db.ref("role").withSchema(TableName.OrgMembership).as("orgMembershipRole"))
.select(db.ref("roleId").withSchema(TableName.OrgMembership).as("orgMembershipRoleId"))
.select(db.ref("status").withSchema(TableName.OrgMembership).as("orgMembershipStatus"))
.select(db.ref("name").withSchema(TableName.OrgRoles).as("orgMembershipRoleName")),
.select(db.ref("id").withSchema(TableName.Membership).as("orgMembershipId"))
.select(db.ref("status").withSchema(TableName.Membership).as("orgMembershipStatus"))
.select(db.ref("role").withSchema(TableName.MembershipRole).as("orgMembershipRole"))
.select(db.ref("customRoleId").withSchema(TableName.MembershipRole).as("orgMembershipRoleId"))
.select(db.ref("name").withSchema(TableName.Role).as("orgMembershipRoleName")),
buildBaseQuery(countQuery).countDistinct(`${TableName.Organization}.id`, { as: "count" }).first()
]);
@@ -229,9 +233,12 @@ export const orgDALFactory = (db: TDbClient) => {
): Promise<(TOrganizations & { orgAuthMethod: string; userRole: string; userStatus: string })[]> => {
try {
const org = (await db
.replicaNode()(TableName.OrgMembership)
.where({ userId })
.join(TableName.Organization, `${TableName.OrgMembership}.orgId`, `${TableName.Organization}.id`)
.replicaNode()(TableName.Membership)
.where(`${TableName.Membership}.actorUserId`, userId)
.where(`${TableName.Membership}.scope`, AccessScope.Organization)
.whereNotNull(`${TableName.Membership}.actorUserId`)
.join(TableName.MembershipRole, `${TableName.Membership}.id`, `${TableName.MembershipRole}.membershipId`)
.join(TableName.Organization, `${TableName.Membership}.scopeOrgId`, `${TableName.Organization}.id`)
.leftJoin(TableName.SamlConfig, (qb) => {
qb.on(`${TableName.SamlConfig}.orgId`, "=", `${TableName.Organization}.id`).andOn(
`${TableName.SamlConfig}.isActive`,
@@ -247,8 +254,8 @@ export const orgDALFactory = (db: TDbClient) => {
);
})
.select(selectAllTableCols(TableName.Organization))
.select(db.ref("role").withSchema(TableName.OrgMembership).as("userRole"))
.select(db.ref("status").withSchema(TableName.OrgMembership).as("userStatus"))
.select(db.ref("role").withSchema(TableName.MembershipRole).as("userRole"))
.select(db.ref("status").withSchema(TableName.Membership).as("userStatus"))
.select(
db.raw(`
CASE
@@ -283,24 +290,28 @@ export const orgDALFactory = (db: TDbClient) => {
const findAllOrgMembers = async (orgId: string) => {
try {
const members = await db
.replicaNode()(TableName.OrgMembership)
.where(`${TableName.OrgMembership}.orgId`, orgId)
.join(TableName.Users, `${TableName.OrgMembership}.userId`, `${TableName.Users}.id`)
.replicaNode()(TableName.Membership)
.where(`${TableName.Membership}.scopeOrgId`, orgId)
.where(`${TableName.Membership}.scope`, AccessScope.Organization)
.whereNotNull(`${TableName.Membership}.actorUserId`)
.join(TableName.Users, `${TableName.Membership}.actorUserId`, `${TableName.Users}.id`)
.join(TableName.MembershipRole, `${TableName.Membership}.id`, `${TableName.MembershipRole}.membershipId`)
.leftJoin(TableName.Role, `${TableName.MembershipRole}.customRoleId`, `${TableName.Role}.id`)
.leftJoin<TUserEncryptionKeys>(
TableName.UserEncryptionKey,
`${TableName.UserEncryptionKey}.userId`,
`${TableName.Users}.id`
)
.select(
db.ref("id").withSchema(TableName.OrgMembership),
db.ref("inviteEmail").withSchema(TableName.OrgMembership),
db.ref("orgId").withSchema(TableName.OrgMembership),
db.ref("role").withSchema(TableName.OrgMembership),
db.ref("roleId").withSchema(TableName.OrgMembership),
db.ref("status").withSchema(TableName.OrgMembership),
db.ref("isActive").withSchema(TableName.OrgMembership),
db.ref("lastLoginAuthMethod").withSchema(TableName.OrgMembership),
db.ref("lastLoginTime").withSchema(TableName.OrgMembership),
db.ref("id").withSchema(TableName.Membership),
db.ref("inviteEmail").withSchema(TableName.Membership),
db.ref("actorOrgId").withSchema(TableName.Membership).as("orgId"),
db.ref("role").withSchema(TableName.MembershipRole),
db.ref("customRoleId").withSchema(TableName.MembershipRole).as("roleId"),
db.ref("status").withSchema(TableName.Membership),
db.ref("isActive").withSchema(TableName.Membership),
db.ref("lastLoginAuthMethod").withSchema(TableName.Membership),
db.ref("lastLoginTime").withSchema(TableName.Membership),
db.ref("email").withSchema(TableName.Users),
db.ref("isEmailVerified").withSchema(TableName.Users),
db.ref("username").withSchema(TableName.Users),
@@ -332,11 +343,13 @@ export const orgDALFactory = (db: TDbClient) => {
}
const count = await db
.replicaNode()(TableName.OrgMembership)
.where(`${TableName.OrgMembership}.orgId`, orgId)
.replicaNode()(TableName.Membership)
.where(`${TableName.Membership}.orgId`, orgId)
.where(`${TableName.Membership}.scope`, AccessScope.Organization)
.whereNotNull(`${TableName.Membership}.actorUserId`)
.count("*")
.join(TableName.Users, `${TableName.OrgMembership}.userId`, `${TableName.Users}.id`)
.where({ isGhost: false, [`${TableName.OrgMembership}.isActive` as "isActive"]: true })
.join(TableName.Users, `${TableName.Membership}.actorUserId`, `${TableName.Users}.id`)
.where({ isGhost: false, [`${TableName.Membership}.isActive` as "isActive"]: true })
.first();
return parseInt((count as unknown as CountResult).count || "0", 10);
@@ -348,21 +361,25 @@ export const orgDALFactory = (db: TDbClient) => {
const findOrgMembersByUsername = async (orgId: string, usernames: string[], tx?: Knex) => {
try {
const conn = tx || db.replicaNode();
const members = await conn(TableName.OrgMembership)
.where(`${TableName.OrgMembership}.orgId`, orgId)
.join(TableName.Users, `${TableName.OrgMembership}.userId`, `${TableName.Users}.id`)
const members = await conn(TableName.Membership)
.where(`${TableName.Membership}.scopeOrgId`, orgId)
.where(`${TableName.Membership}.scope`, AccessScope.Organization)
.whereNotNull(`${TableName.Membership}.actorUserId`)
.join(TableName.Users, `${TableName.Membership}.actorUserId`, `${TableName.Users}.id`)
.join(TableName.MembershipRole, `${TableName.Membership}.id`, `${TableName.MembershipRole}.membershipId`)
.leftJoin(TableName.Role, `${TableName.MembershipRole}.customRoleId`, `${TableName.Role}.id`)
.leftJoin<TUserEncryptionKeys>(
TableName.UserEncryptionKey,
`${TableName.UserEncryptionKey}.userId`,
`${TableName.Users}.id`
)
.select(
conn.ref("id").withSchema(TableName.OrgMembership),
conn.ref("inviteEmail").withSchema(TableName.OrgMembership),
conn.ref("orgId").withSchema(TableName.OrgMembership),
conn.ref("role").withSchema(TableName.OrgMembership),
conn.ref("roleId").withSchema(TableName.OrgMembership),
conn.ref("status").withSchema(TableName.OrgMembership),
conn.ref("id").withSchema(TableName.Membership),
conn.ref("inviteEmail").withSchema(TableName.Membership),
conn.ref("orgId").withSchema(TableName.Membership),
db.ref("role").withSchema(TableName.MembershipRole),
db.ref("customRoleId").withSchema(TableName.MembershipRole).as("roleId"),
conn.ref("status").withSchema(TableName.Membership),
conn.ref("username").withSchema(TableName.Users),
conn.ref("email").withSchema(TableName.Users),
conn.ref("firstName").withSchema(TableName.Users),
@@ -384,22 +401,25 @@ export const orgDALFactory = (db: TDbClient) => {
const findOrgMembersByRole = async (orgId: string, role: OrgMembershipRole, tx?: Knex) => {
try {
const conn = tx || db.replicaNode();
const members = await conn(TableName.OrgMembership)
.where(`${TableName.OrgMembership}.orgId`, orgId)
.where(`${TableName.OrgMembership}.role`, role)
.join(TableName.Users, `${TableName.OrgMembership}.userId`, `${TableName.Users}.id`)
const members = await conn(TableName.Membership)
.where(`${TableName.Membership}.scopeOrgId`, orgId)
.where(`${TableName.Membership}.scope`, AccessScope.Organization)
.whereNotNull(`${TableName.Membership}.actorUserId`)
.join(TableName.MembershipRole, `${TableName.Membership}.id`, `${TableName.MembershipRole}.membershipId`)
.where(`${TableName.MembershipRole}.role`, role)
.join(TableName.Users, `${TableName.Membership}.actorUserId`, `${TableName.Users}.id`)
.leftJoin<TUserEncryptionKeys>(
TableName.UserEncryptionKey,
`${TableName.UserEncryptionKey}.userId`,
`${TableName.Users}.id`
)
.select(
conn.ref("id").withSchema(TableName.OrgMembership),
conn.ref("inviteEmail").withSchema(TableName.OrgMembership),
conn.ref("orgId").withSchema(TableName.OrgMembership),
conn.ref("role").withSchema(TableName.OrgMembership),
conn.ref("roleId").withSchema(TableName.OrgMembership),
conn.ref("status").withSchema(TableName.OrgMembership),
conn.ref("id").withSchema(TableName.Membership),
conn.ref("inviteEmail").withSchema(TableName.Membership),
conn.ref("orgId").withSchema(TableName.Membership),
conn.ref("role").withSchema(TableName.MembershipRole),
conn.ref("customRoleId").withSchema(TableName.MembershipRole).as("roleId"),
conn.ref("status").withSchema(TableName.Membership),
conn.ref("username").withSchema(TableName.Users),
conn.ref("email").withSchema(TableName.Users),
conn.ref("firstName").withSchema(TableName.Users),
@@ -418,47 +438,6 @@ export const orgDALFactory = (db: TDbClient) => {
}
};
const findOrgGhostUser = async (orgId: string) => {
try {
const member = await db
.replicaNode()(TableName.OrgMembership)
.where({ orgId })
.join(TableName.Users, `${TableName.OrgMembership}.userId`, `${TableName.Users}.id`)
.leftJoin(TableName.UserEncryptionKey, `${TableName.UserEncryptionKey}.userId`, `${TableName.Users}.id`)
.select(
db.ref("id").withSchema(TableName.OrgMembership),
db.ref("orgId").withSchema(TableName.OrgMembership),
db.ref("role").withSchema(TableName.OrgMembership),
db.ref("roleId").withSchema(TableName.OrgMembership),
db.ref("status").withSchema(TableName.OrgMembership),
db.ref("email").withSchema(TableName.Users),
db.ref("id").withSchema(TableName.Users).as("userId"),
db.ref("publicKey").withSchema(TableName.UserEncryptionKey)
)
.where({ isGhost: true })
.first();
return member;
} catch (error) {
return null;
}
};
const ghostUserExists = async (orgId: string) => {
try {
const member = await db
.replicaNode()(TableName.OrgMembership)
.where({ orgId })
.join(TableName.Users, `${TableName.OrgMembership}.userId`, `${TableName.Users}.id`)
.leftJoin(TableName.UserEncryptionKey, `${TableName.UserEncryptionKey}.userId`, `${TableName.Users}.id`)
.select(db.ref("id").withSchema(TableName.Users).as("userId"))
.where({ isGhost: true })
.first();
return Boolean(member);
} catch (error) {
return false;
}
};
const create = async (dto: TOrganizationsInsert, tx?: Knex) => {
try {
const [organization] = await (tx || db)(TableName.Organization).insert(dto).returning("*");
@@ -491,38 +470,37 @@ export const orgDALFactory = (db: TDbClient) => {
// MEMBERSHIP OPERATIONS
// --------------------
// const orgMembershipOrm = ormify(db, TableName.OrgMembership);
const createMembership = async (data: TOrgMembershipsInsert, tx?: Knex) => {
const createMembership = async (data: TMembershipsInsert, tx?: Knex) => {
try {
const [membership] = await (tx || db)(TableName.OrgMembership).insert(data).returning("*");
const [membership] = await (tx || db)(TableName.Membership).insert(data).returning("*");
return membership;
} catch (error) {
throw new DatabaseError({ error, name: "Create org membership" });
}
};
const bulkCreateMemberships = async (data: TOrgMembershipsInsert[], tx?: Knex) => {
const bulkCreateMemberships = async (data: TMembershipsInsert[], tx?: Knex) => {
try {
const memberships = await (tx || db)(TableName.OrgMembership).insert(data).returning("*");
const memberships = await (tx || db)(TableName.Membership).insert(data).returning("*");
return memberships;
} catch (error) {
throw new DatabaseError({ error, name: "Create org memberships" });
}
};
const updateMembershipById = async (id: string, data: TOrgMembershipsUpdate, tx?: Knex) => {
const updateMembershipById = async (id: string, data: TMembershipsUpdate, tx?: Knex) => {
try {
const [membership] = await (tx || db)(TableName.OrgMembership).where({ id }).update(data).returning("*");
const [membership] = await (tx || db)(TableName.Membership).where({ id }).update(data).returning("*");
return membership;
} catch (error) {
throw new DatabaseError({ error, name: "Update org membership" });
}
};
const updateMembership = async (filter: Partial<TOrgMemberships>, data: TOrgMembershipsUpdate, tx?: Knex) => {
const updateMembership = async (filter: Partial<TMemberships>, data: TMembershipsUpdate, tx?: Knex) => {
try {
const membership = await (tx || db)(TableName.OrgMembership).where(filter).update(data).returning("*");
const membership = await (tx || db)(TableName.Membership).where(filter).update(data).returning("*");
return membership;
} catch (error) {
throw new DatabaseError({ error, name: "Update org memberships" });
@@ -531,7 +509,10 @@ export const orgDALFactory = (db: TDbClient) => {
const deleteMembershipById = async (id: string, orgId: string, tx?: Knex) => {
try {
const [membership] = await (tx || db)(TableName.OrgMembership).where({ id, orgId }).delete().returning("*");
const [membership] = await (tx || db)(TableName.Membership)
.where({ id, scopeOrgId: orgId, scope: AccessScope.Organization })
.delete()
.returning("*");
return membership;
} catch (error) {
throw new DatabaseError({ error, name: "Delete org membership" });
@@ -540,9 +521,10 @@ export const orgDALFactory = (db: TDbClient) => {
const deleteMembershipsById = async (ids: string[], orgId: string, tx?: Knex) => {
try {
const memberships = await (tx || db)(TableName.OrgMembership)
const memberships = await (tx || db)(TableName.Membership)
.where({
orgId
scopeOrgId: orgId,
scope: AccessScope.Organization
})
.whereIn("id", ids)
.delete()
@@ -554,22 +536,23 @@ export const orgDALFactory = (db: TDbClient) => {
};
const findMembership = async (
filter: TFindFilter<TOrgMemberships>,
{ offset, limit, sort, tx }: TFindOpt<TOrgMemberships> = {}
filter: TFindFilter<TMemberships>,
{ offset, limit, sort, tx }: TFindOpt<TMemberships> = {}
) => {
try {
const query = (tx || db.replicaNode())(TableName.OrgMembership)
const query = (tx || db.replicaNode())(TableName.Membership)
// eslint-disable-next-line
.where(buildFindFilter(filter))
.join(TableName.Users, `${TableName.Users}.id`, `${TableName.OrgMembership}.userId`)
.join(TableName.Organization, `${TableName.Organization}.id`, `${TableName.OrgMembership}.orgId`)
.where("scope", AccessScope.Organization)
.join(TableName.Users, `${TableName.Users}.id`, `${TableName.Membership}.actorUserId`)
.join(TableName.Organization, `${TableName.Organization}.id`, `${TableName.Membership}.scopeOrgId`)
.leftJoin(TableName.UserAliases, function joinUserAlias() {
this.on(`${TableName.UserAliases}.userId`, "=", `${TableName.OrgMembership}.userId`)
.andOn(`${TableName.UserAliases}.orgId`, "=", `${TableName.OrgMembership}.orgId`)
this.on(`${TableName.UserAliases}.userId`, "=", `${TableName.Membership}.actorUserId`)
.andOn(`${TableName.UserAliases}.orgId`, "=", `${TableName.Membership}.scopeOrgId`)
.andOn(`${TableName.UserAliases}.aliasType`, "=", (tx || db).raw("?", ["saml"]));
})
.select(
selectAllTableCols(TableName.OrgMembership),
selectAllTableCols(TableName.Membership),
db.ref("email").withSchema(TableName.Users),
db.ref("isEmailVerified").withSchema(TableName.Users),
db.ref("username").withSchema(TableName.Users),
@@ -595,18 +578,20 @@ export const orgDALFactory = (db: TDbClient) => {
const findMembershipWithScimFilter = async (
orgId: string,
scimFilter: string | undefined,
{ offset, limit, sort, tx }: TFindOpt<TOrgMemberships> = {}
{ offset, limit, sort, tx }: TFindOpt<TMemberships> = {}
) => {
try {
const query = (tx || db.replicaNode())(TableName.OrgMembership)
const query = (tx || db.replicaNode())(TableName.Membership)
// eslint-disable-next-line
.where(`${TableName.OrgMembership}.orgId`, orgId)
.where(`${TableName.Membership}.scopeOrgId`, orgId)
.where(`${TableName.Membership}.scope`, AccessScope.Organization)
.whereNotNull(`${TableName.Membership}.actorUserId`)
.where((qb) => {
if (scimFilter) {
void generateKnexQueryFromScim(qb, scimFilter, (attrPath) => {
switch (attrPath) {
case "active":
return `${TableName.OrgMembership}.isActive`;
return `${TableName.Membership}.isActive`;
case "userName":
return `${TableName.UserAliases}.externalId`;
case "name.givenName":
@@ -621,15 +606,15 @@ export const orgDALFactory = (db: TDbClient) => {
});
}
})
.join(TableName.Users, `${TableName.Users}.id`, `${TableName.OrgMembership}.userId`)
.join(TableName.Organization, `${TableName.Organization}.id`, `${TableName.OrgMembership}.orgId`)
.join(TableName.Users, `${TableName.Users}.id`, `${TableName.Membership}.actorUserId`)
.join(TableName.Organization, `${TableName.Organization}.id`, `${TableName.Membership}.scopeOrgId`)
.leftJoin(TableName.UserAliases, function joinUserAlias() {
this.on(`${TableName.UserAliases}.userId`, "=", `${TableName.OrgMembership}.userId`)
.andOn(`${TableName.UserAliases}.orgId`, "=", `${TableName.OrgMembership}.orgId`)
this.on(`${TableName.UserAliases}.userId`, "=", `${TableName.Membership}.actorUserId`)
.andOn(`${TableName.UserAliases}.orgId`, "=", `${TableName.Membership}.scopeOrgId`)
.andOn(`${TableName.UserAliases}.aliasType`, "=", (tx || db).raw("?", ["saml"]));
})
.select(
selectAllTableCols(TableName.OrgMembership),
selectAllTableCols(TableName.Membership),
db.ref("email").withSchema(TableName.Users),
db.ref("isEmailVerified").withSchema(TableName.Users),
db.ref("username").withSchema(TableName.Users),
@@ -653,18 +638,22 @@ export const orgDALFactory = (db: TDbClient) => {
}
};
// TODO(simp): resolve this role field later
const findIdentityOrganization = async (
identityId: string
): Promise<{ id: string; name: string; slug: string; role: string }> => {
try {
const org = await db
.replicaNode()(TableName.IdentityOrgMembership)
.where({ identityId })
.join(TableName.Organization, `${TableName.IdentityOrgMembership}.orgId`, `${TableName.Organization}.id`)
.replicaNode()(TableName.Membership)
.where({ actorIdentityId: identityId })
.where(`${TableName.Membership}.scope`, AccessScope.Organization)
.whereNotNull(`${TableName.Membership}.actorUserId`)
.join(TableName.MembershipRole, `${TableName.Membership}.id`, `${TableName.MembershipRole}.membershipId`)
.join(TableName.Organization, `${TableName.Membership}.scopeOrgId`, `${TableName.Organization}.id`)
.select(db.ref("id").withSchema(TableName.Organization).as("id"))
.select(db.ref("name").withSchema(TableName.Organization).as("name"))
.select(db.ref("slug").withSchema(TableName.Organization).as("slug"))
.select(db.ref("role").withSchema(TableName.IdentityOrgMembership).as("role"));
.select(db.ref("role").withSchema(TableName.MembershipRole).as("role"));
return org?.[0];
} catch (error) {
@@ -681,10 +670,8 @@ export const orgDALFactory = (db: TDbClient) => {
findOrgBySlug,
findAllOrgsByUserId,
findOrganizationsByFilter,
ghostUserExists,
findOrgMembersByUsername,
findOrgMembersByRole,
findOrgGhostUser,
create,
updateById,
deleteById,
-7
View File
@@ -1,7 +0,0 @@
import { TDbClient } from "@app/db";
import { TableName } from "@app/db/schemas";
import { ormify } from "@app/lib/knex";
export type TOrgRoleDALFactory = ReturnType<typeof orgRoleDALFactory>;
export const orgRoleDALFactory = (db: TDbClient) => ormify(db, TableName.OrgRoles);
+5 -4
View File
@@ -1,7 +1,8 @@
import { OrgMembershipRole } from "@app/db/schemas";
import { TFeatureSet } from "@app/ee/services/license/license-types";
import { BadRequestError, NotFoundError } from "@app/lib/errors";
import { TOrgRoleDALFactory } from "@app/services/org/org-role-dal";
import { TRoleDALFactory } from "../role/role-dal";
const RESERVED_ORG_ROLE_SLUGS = Object.values(OrgMembershipRole).filter((role) => role !== "custom");
@@ -10,13 +11,13 @@ export const isCustomOrgRole = (roleSlug: string) => !RESERVED_ORG_ROLE_SLUGS.fi
// this is only for updating an org
export const getDefaultOrgMembershipRoleForUpdateOrg = async ({
membershipRoleSlug,
orgRoleDAL,
roleDAL,
plan,
orgId
}: {
orgId: string;
membershipRoleSlug: string;
orgRoleDAL: TOrgRoleDALFactory;
roleDAL: TRoleDALFactory;
plan: TFeatureSet;
}) => {
if (isCustomOrgRole(membershipRoleSlug)) {
@@ -26,7 +27,7 @@ export const getDefaultOrgMembershipRoleForUpdateOrg = async ({
"Failed to set custom default role due to plan RBAC restriction. Upgrade plan to set custom default org membership role."
});
const customRole = await orgRoleDAL.findOne({ slug: membershipRoleSlug, orgId });
const customRole = await roleDAL.findOne({ slug: membershipRoleSlug, orgId });
if (!customRole) {
throw new NotFoundError({
name: "UpdateOrg",
+4 -3
View File
@@ -14,7 +14,7 @@ import { BadRequestError, NotFoundError } from "@app/lib/errors";
import { TExternalGroupOrgRoleMappingDALFactory } from "@app/services/external-group-org-role-mapping/external-group-org-role-mapping-dal";
import { TOrgDALFactory } from "@app/services/org/org-dal";
import { ActorAuthMethod } from "../auth/auth-type";
import { ActorAuthMethod, ActorType } from "../auth/auth-type";
import { TOrgRoleDALFactory } from "./org-role-dal";
type TOrgRoleServiceFactoryDep = {
@@ -224,13 +224,14 @@ export const orgRoleServiceFactory = ({
actorAuthMethod: ActorAuthMethod,
actorOrgId: string | undefined
) => {
const { permission, membership } = await permissionService.getUserOrgPermission(
const { permission, memberships } = await permissionService.getOrgPermission(
ActorType.USER,
userId,
orgId,
actorAuthMethod,
actorOrgId
);
return { permissions: packRules(permission.rules), membership };
return { permissions: packRules(permission.rules), memberships };
};
return { createRole, getRole, updateRole, deleteRole, listRoles, getUserPermission };
+39 -15
View File
@@ -76,7 +76,6 @@ import { TIncidentContactsDALFactory } from "./incident-contacts-dal";
import { TOrgBotDALFactory } from "./org-bot-dal";
import { TOrgDALFactory } from "./org-dal";
import { deleteOrgMembershipFn, deleteOrgMembershipsFn } from "./org-fns";
import { TOrgRoleDALFactory } from "./org-role-dal";
import {
TDeleteOrgMembershipDTO,
TDeleteOrgMembershipsDTO,
@@ -92,6 +91,7 @@ import {
TUpgradePrivilegeSystemDTO,
TVerifyUserToOrgDTO
} from "./org-types";
import { TRoleDALFactory } from "../role/role-dal";
type TOrgServiceFactoryDep = {
userAliasDAL: Pick<TUserAliasDALFactory, "delete">;
@@ -100,7 +100,7 @@ type TOrgServiceFactoryDep = {
folderDAL: Pick<TSecretFolderDALFactory, "findByProjectId">;
orgDAL: TOrgDALFactory;
orgBotDAL: TOrgBotDALFactory;
orgRoleDAL: TOrgRoleDALFactory;
roleDAL: TRoleDALFactory;
userDAL: TUserDALFactory;
groupDAL: TGroupDALFactory;
projectDAL: TProjectDALFactory;
@@ -154,7 +154,7 @@ export const orgServiceFactory = ({
folderDAL,
userDAL,
groupDAL,
orgRoleDAL,
roleDAL,
incidentContactDAL,
permissionService,
smtpService,
@@ -185,7 +185,7 @@ export const orgServiceFactory = ({
actorAuthMethod: ActorAuthMethod,
actorOrgId: string | undefined
) => {
await permissionService.getUserOrgPermission(userId, orgId, actorAuthMethod, actorOrgId);
await permissionService.getOrgPermission(ActorType.USER, userId, orgId, actorAuthMethod, actorOrgId);
const appCfg = getConfig();
const org = await orgDAL.findOrgById(orgId);
if (!org) throw new NotFoundError({ message: `Organization with ID '${orgId}' not found` });
@@ -221,7 +221,13 @@ export const orgServiceFactory = ({
actorAuthMethod: ActorAuthMethod,
actorOrgId: string | undefined
) => {
const { permission } = await permissionService.getUserOrgPermission(userId, orgId, actorAuthMethod, actorOrgId);
const { permission } = await permissionService.getOrgPermission(
ActorType.USER,
userId,
orgId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Member);
const members = await orgDAL.findAllOrgMembers(orgId);
@@ -323,9 +329,15 @@ export const orgServiceFactory = ({
actorAuthMethod,
orgId
}: TUpgradePrivilegeSystemDTO) => {
const { membership } = await permissionService.getUserOrgPermission(actorId, orgId, actorAuthMethod, actorOrgId);
const { hasRole } = await permissionService.getOrgPermission(
ActorType.USER,
actorId,
orgId,
actorAuthMethod,
actorOrgId
);
if (membership.role !== OrgMembershipRole.Admin) {
if (!hasRole(OrgMembershipRole.Admin)) {
throw new ForbiddenRequestError({
message: "Insufficient privileges - only the organization admin can upgrade the privilege system."
});
@@ -531,7 +543,7 @@ export const orgServiceFactory = ({
defaultMembershipRole = await getDefaultOrgMembershipRoleForUpdateOrg({
membershipRoleSlug: defaultMembershipRoleSlug,
orgId,
orgRoleDAL,
roleDAL,
plan
});
}
@@ -659,8 +671,14 @@ export const orgServiceFactory = ({
actorAuthMethod: ActorAuthMethod;
actorOrgId: string | undefined;
}) => {
const { membership } = await permissionService.getUserOrgPermission(userId, orgId, actorAuthMethod, actorOrgId);
if ((membership.role as OrgMembershipRole) !== OrgMembershipRole.Admin) {
const { hasRole } = await permissionService.getOrgPermission(
ActorType.USER,
userId,
orgId,
actorAuthMethod,
actorOrgId
);
if (!hasRole(OrgMembershipRole.Admin)) {
throw new ForbiddenRequestError({
name: "DeleteOrganizationById",
message: "Insufficient privileges"
@@ -739,7 +757,13 @@ export const orgServiceFactory = ({
actorOrgId,
metadata
}: TUpdateOrgMembershipDTO) => {
const { permission } = await permissionService.getUserOrgPermission(userId, orgId, actorAuthMethod, actorOrgId);
const { permission } = await permissionService.getOrgPermission(
ActorType.USER,
userId,
orgId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Edit, OrgPermissionSubjects.Member);
const foundMembership = await orgMembershipDAL.findById(membershipId);
@@ -754,7 +778,7 @@ export const orgServiceFactory = ({
let userRole = role;
let userRoleId: string | null = null;
if (role && isCustomRole) {
const customRole = await orgRoleDAL.findOne({ slug: role, orgId });
const customRole = await roleDAL.findOne({ slug: role, orgId });
if (!customRole) throw new BadRequestError({ name: "UpdateMembership", message: "Organization role not found" });
const plan = await licenseService.getPlan(orgId);
@@ -768,16 +792,16 @@ export const orgServiceFactory = ({
}
const membership = await orgDAL.transaction(async (tx) => {
const [updatedOrgMembership] = await orgDAL.updateMembership(
{ id: membershipId, orgId },
{ id: membershipId, scopeOrgId: orgId },
{ role: userRole, roleId: userRoleId, isActive }
);
if (metadata) {
await identityMetadataDAL.delete({ userId: updatedOrgMembership.userId, orgId }, tx);
await identityMetadataDAL.delete({ userId: updatedOrgMembership.actorUserId, orgId }, tx);
if (metadata.length) {
await identityMetadataDAL.insertMany(
metadata.map(({ key, value }) => ({
userId: updatedOrgMembership.userId,
userId: updatedOrgMembership.actorUserId as string,
orgId,
key,
value