feat: resolved all missing things

This commit is contained in:
=
2025-10-10 00:09:47 +05:30
parent 3fa63a033e
commit 879bc00eeb
14 changed files with 134 additions and 46 deletions
@@ -127,7 +127,8 @@ export async function down(knex: Knex): Promise<void> {
}); });
await knex.schema.alterTable(TableName.SecretApprovalPolicyApprover, (tb) => { await knex.schema.alterTable(TableName.SecretApprovalPolicyApprover, (tb) => {
tb.dropColumn("approverUserId"); tb.dropColumn("approverUserId");
tb.uuid("approverId").notNullable().alter(); // akhilmhdh: i had to comment this out and is not possible as membership is now changed in structure
// tb.uuid("approverId").notNullable().alter();
}); });
} }
} }
@@ -16,6 +16,9 @@ import { selectAllTableCols, sqlNestRelationships } from "@app/lib/knex";
import { ActorType } from "@app/services/auth/auth-type"; import { ActorType } from "@app/services/auth/auth-type";
interface TPermissionDataReturn extends TMemberships { interface TPermissionDataReturn extends TMemberships {
orgAuthEnforced?: boolean | null;
orgGoogleSsoAuthEnforced?: boolean | null;
bypassOrgAuthEnabled?: boolean | null;
roles: { roles: {
id: string; id: string;
createdAt: Date; createdAt: Date;
@@ -177,6 +180,7 @@ export const permissionDALFactory = (db: TDbClient): TPermissionDALFactory => {
const docs = await (tx || db) const docs = await (tx || db)
.replicaNode()(TableName.Membership) .replicaNode()(TableName.Membership)
.join(TableName.MembershipRole, `${TableName.Membership}.id`, `${TableName.MembershipRole}.membershipId`) .join(TableName.MembershipRole, `${TableName.Membership}.id`, `${TableName.MembershipRole}.membershipId`)
.join(TableName.Organization, `${TableName.Membership}.scopeOrgId`, `${TableName.Organization}.id`)
.leftJoin(TableName.Role, `${TableName.MembershipRole}.customRoleId`, `${TableName.Role}.id`) .leftJoin(TableName.Role, `${TableName.MembershipRole}.customRoleId`, `${TableName.Role}.id`)
.leftJoin(TableName.AdditionalPrivilege, (qb) => { .leftJoin(TableName.AdditionalPrivilege, (qb) => {
if (actorType === ActorType.IDENTITY) { if (actorType === ActorType.IDENTITY) {
@@ -264,13 +268,22 @@ export const permissionDALFactory = (db: TDbClient): TPermissionDALFactory => {
db.ref("updatedAt").withSchema(TableName.AdditionalPrivilege).as("additionalPrivilegeUpdatedAt"), db.ref("updatedAt").withSchema(TableName.AdditionalPrivilege).as("additionalPrivilegeUpdatedAt"),
db.ref("id").withSchema(TableName.IdentityMetadata).as("metadataId"), db.ref("id").withSchema(TableName.IdentityMetadata).as("metadataId"),
db.ref("key").withSchema(TableName.IdentityMetadata).as("metadataKey"), db.ref("key").withSchema(TableName.IdentityMetadata).as("metadataKey"),
db.ref("value").withSchema(TableName.IdentityMetadata).as("metadataValue") db.ref("value").withSchema(TableName.IdentityMetadata).as("metadataValue"),
db.ref("shouldUseNewPrivilegeSystem").withSchema(TableName.Organization),
db.ref("authEnforced").withSchema(TableName.Organization).as("orgAuthEnforced"),
db.ref("googleSsoAuthEnforced").withSchema(TableName.Organization).as("orgGoogleSsoAuthEnforced"),
db.ref("bypassOrgAuthEnabled").withSchema(TableName.Organization).as("bypassOrgAuthEnabled")
); );
const data = sqlNestRelationships({ const data = sqlNestRelationships({
data: docs, data: docs,
key: "id", key: "id",
parentMapper: (el) => MembershipsSchema.parse(el), parentMapper: (el) =>
MembershipsSchema.extend({
orgAuthEnforced: z.boolean().optional().nullable(),
orgGoogleSsoAuthEnforced: z.boolean(),
bypassOrgAuthEnabled: z.boolean()
}).parse(el),
childrenMapper: [ childrenMapper: [
{ {
key: "additionalPrivilegeId", key: "additionalPrivilegeId",
@@ -2,7 +2,7 @@
import { ForbiddenError, MongoAbility, PureAbility, subject } from "@casl/ability"; import { ForbiddenError, MongoAbility, PureAbility, subject } from "@casl/ability";
import { z } from "zod"; import { z } from "zod";
import { OrgMembershipRole, TOrganizations } from "@app/db/schemas"; import { TOrganizations } from "@app/db/schemas";
import { validatePermissionBoundary } from "@app/lib/casl/boundary"; import { validatePermissionBoundary } from "@app/lib/casl/boundary";
import { BadRequestError, ForbiddenRequestError, UnauthorizedError } from "@app/lib/errors"; import { BadRequestError, ForbiddenRequestError, UnauthorizedError } from "@app/lib/errors";
import { ActorAuthMethod, AuthMethod } from "@app/services/auth/auth-type"; import { ActorAuthMethod, AuthMethod } from "@app/services/auth/auth-type";
@@ -123,13 +123,13 @@ function validateOrgSSO(
isOrgSsoEnforced: TOrganizations["authEnforced"], isOrgSsoEnforced: TOrganizations["authEnforced"],
isOrgGoogleSsoEnforced: TOrganizations["googleSsoAuthEnforced"], isOrgGoogleSsoEnforced: TOrganizations["googleSsoAuthEnforced"],
isOrgSsoBypassEnabled: TOrganizations["bypassOrgAuthEnabled"], isOrgSsoBypassEnabled: TOrganizations["bypassOrgAuthEnabled"],
orgRole: OrgMembershipRole isAdmin: boolean
) { ) {
if (actorAuthMethod === undefined) { if (actorAuthMethod === undefined) {
throw new UnauthorizedError({ name: "No auth method defined" }); throw new UnauthorizedError({ name: "No auth method defined" });
} }
if ((isOrgSsoEnforced || isOrgGoogleSsoEnforced) && isOrgSsoBypassEnabled && orgRole === OrgMembershipRole.Admin) { if ((isOrgSsoEnforced || isOrgGoogleSsoEnforced) && isOrgSsoBypassEnabled && isAdmin) {
return; return;
} }
@@ -32,7 +32,7 @@ import { TUserDALFactory } from "@app/services/user/user-dal";
import { orgAdminPermissions, orgMemberPermissions, orgNoAccessPermissions, OrgPermissionSet } from "./org-permission"; import { orgAdminPermissions, orgMemberPermissions, orgNoAccessPermissions, OrgPermissionSet } from "./org-permission";
import { TPermissionDALFactory } from "./permission-dal"; import { TPermissionDALFactory } from "./permission-dal";
import { escapeHandlebarsMissingDict } from "./permission-fns"; import { escapeHandlebarsMissingDict, validateOrgSSO } from "./permission-fns";
import { import {
TBuildOrgPermissionDTO, TBuildOrgPermissionDTO,
TBuildProjectPermissionDTO, TBuildProjectPermissionDTO,
@@ -223,24 +223,25 @@ export const permissionServiceFactory = ({
return activeRoles.concat(activeAdditionalPrivileges); return activeRoles.concat(activeAdditionalPrivileges);
}); });
const hasRole = (role: string) =>
permissionData.some((memberships) => memberships.roles.some((el) => role === (el.customRoleSlug || el.role)));
validateOrgSSO(
authMethod,
permissionData?.[0].orgAuthEnforced,
Boolean(permissionData?.[0].orgGoogleSsoAuthEnforced),
Boolean(permissionData?.[0].bypassOrgAuthEnabled),
hasRole(OrgMembershipRole.Admin)
);
const permission = createMongoAbility<OrgPermissionSet>(buildOrgPermissionRules(permissionFromRoles), { const permission = createMongoAbility<OrgPermissionSet>(buildOrgPermissionRules(permissionFromRoles), {
conditionsMatcher conditionsMatcher
}); });
// TODO(simp): validate this
// validateOrgSSO(
// authMethod,
// membership.orgAuthEnforced,
// membership.orgGoogleSsoAuthEnforced,
// membership.bypassOrgAuthEnabled,
// membership.role as OrgMembershipRole
// );
return { return {
permission, permission,
memberships: permissionData, memberships: permissionData,
hasRole: (role: string) => hasRole
permissionData.some((memberships) => memberships.roles.some((el) => role === (el.customRoleSlug || el.role)))
}; };
}; };
@@ -367,13 +368,16 @@ export const permissionServiceFactory = ({
return activeRoles.concat(activeAdditionalPrivileges); return activeRoles.concat(activeAdditionalPrivileges);
}); });
// validateOrgSSO( const hasRole = (role: string) =>
// authMethod, permissionData.some((memberships) => memberships.roles.some((el) => role === (el.customRoleSlug || el.role)));
// userProjectPermission.orgAuthEnforced,
// userProjectPermission.orgGoogleSsoAuthEnforced, validateOrgSSO(
// userProjectPermission.bypassOrgAuthEnabled, actorAuthMethod,
// userProjectPermission.orgRole permissionData?.[0].orgAuthEnforced,
// ); Boolean(permissionData?.[0].orgGoogleSsoAuthEnforced),
Boolean(permissionData?.[0].bypassOrgAuthEnabled),
hasRole(ProjectMembershipRole.Admin)
);
const rules = buildProjectPermissionRules(permissionFromRoles); const rules = buildProjectPermissionRules(permissionFromRoles);
const templatedRules = handlebars.compile(JSON.stringify(rules), { data: false }); const templatedRules = handlebars.compile(JSON.stringify(rules), { data: false });
@@ -422,8 +426,7 @@ export const permissionServiceFactory = ({
return { return {
permission, permission,
memberships: permissionData, memberships: permissionData,
hasRole: (role: string) => hasRole
permissionData.some((memberships) => memberships.roles.some((el) => role === (el.customRoleSlug || el.role)))
}; };
}; };
+6 -2
View File
@@ -19,6 +19,7 @@ import { getConfig } from "@app/lib/config/env";
import { crypto } from "@app/lib/crypto"; import { crypto } from "@app/lib/crypto";
import { BadRequestError, NotFoundError, ScimRequestError, UnauthorizedError } from "@app/lib/errors"; import { BadRequestError, NotFoundError, ScimRequestError, UnauthorizedError } from "@app/lib/errors";
import { alphaNumericNanoId } from "@app/lib/nanoid"; import { alphaNumericNanoId } from "@app/lib/nanoid";
import { TAdditionalPrivilegeDALFactory } from "@app/services/additional-privilege/additional-privilege-dal";
import { AuthTokenType } from "@app/services/auth/auth-type"; import { AuthTokenType } from "@app/services/auth/auth-type";
import { TExternalGroupOrgRoleMappingDALFactory } from "@app/services/external-group-org-role-mapping/external-group-org-role-mapping-dal"; import { TExternalGroupOrgRoleMappingDALFactory } from "@app/services/external-group-org-role-mapping/external-group-org-role-mapping-dal";
import { TMembershipRoleDALFactory } from "@app/services/membership/membership-role-dal"; import { TMembershipRoleDALFactory } from "@app/services/membership/membership-role-dal";
@@ -93,6 +94,7 @@ type TScimServiceFactoryDep = {
permissionService: Pick<TPermissionServiceFactory, "getOrgPermission">; permissionService: Pick<TPermissionServiceFactory, "getOrgPermission">;
smtpService: Pick<TSmtpService, "sendMail">; smtpService: Pick<TSmtpService, "sendMail">;
externalGroupOrgRoleMappingDAL: TExternalGroupOrgRoleMappingDALFactory; externalGroupOrgRoleMappingDAL: TExternalGroupOrgRoleMappingDALFactory;
additionalPrivilegeDAL: TAdditionalPrivilegeDALFactory;
}; };
export const scimServiceFactory = ({ export const scimServiceFactory = ({
@@ -111,7 +113,8 @@ export const scimServiceFactory = ({
externalGroupOrgRoleMappingDAL, externalGroupOrgRoleMappingDAL,
membershipGroupDAL, membershipGroupDAL,
membershipUserDAL, membershipUserDAL,
membershipRoleDAL membershipRoleDAL,
additionalPrivilegeDAL
}: TScimServiceFactoryDep): TScimServiceFactory => { }: TScimServiceFactoryDep): TScimServiceFactory => {
const createScimToken: TScimServiceFactory["createScimToken"] = async ({ const createScimToken: TScimServiceFactory["createScimToken"] = async ({
actor, actor,
@@ -673,7 +676,8 @@ export const scimServiceFactory = ({
licenseService, licenseService,
membershipUserDAL, membershipUserDAL,
membershipRoleDAL, membershipRoleDAL,
userGroupMembershipDAL userGroupMembershipDAL,
additionalPrivilegeDAL
}); });
return {}; // intentionally return empty object upon success return {}; // intentionally return empty object upon success
+10 -5
View File
@@ -575,7 +575,8 @@ export const registerRoutes = async (
smtpService, smtpService,
tokenService, tokenService,
userAliasDAL, userAliasDAL,
userGroupMembershipDAL userGroupMembershipDAL,
additionalPrivilegeDAL
}); });
const membershipIdentityService = membershipIdentityServiceFactory({ const membershipIdentityService = membershipIdentityServiceFactory({
@@ -583,7 +584,8 @@ export const registerRoutes = async (
membershipRoleDAL, membershipRoleDAL,
orgDAL, orgDAL,
permissionService, permissionService,
roleDAL roleDAL,
additionalPrivilegeDAL
}); });
const membershipGroupService = membershipGroupServiceFactory({ const membershipGroupService = membershipGroupServiceFactory({
@@ -599,7 +601,8 @@ export const registerRoutes = async (
roleDAL, roleDAL,
projectDAL, projectDAL,
identityDAL, identityDAL,
userDAL userDAL,
externalGroupOrgRoleMappingDAL
}); });
const additionalPrivilegeService = additionalPrivilegeServiceFactory({ const additionalPrivilegeService = additionalPrivilegeServiceFactory({
additionalPrivilegeDAL, additionalPrivilegeDAL,
@@ -764,7 +767,8 @@ export const registerRoutes = async (
groupDAL, groupDAL,
membershipGroupDAL, membershipGroupDAL,
membershipRoleDAL, membershipRoleDAL,
membershipUserDAL membershipUserDAL,
additionalPrivilegeDAL
}); });
const githubOrgSyncConfigService = githubOrgSyncServiceFactory({ const githubOrgSyncConfigService = githubOrgSyncServiceFactory({
@@ -891,7 +895,8 @@ export const registerRoutes = async (
membershipRoleDAL, membershipRoleDAL,
membershipUserDAL, membershipUserDAL,
roleDAL, roleDAL,
userGroupMembershipDAL userGroupMembershipDAL,
additionalPrivilegeDAL
}); });
const signupService = authSignupServiceFactory({ const signupService = authSignupServiceFactory({
tokenService, tokenService,
@@ -161,7 +161,6 @@ export const registerProjectMembershipRouter = async (server: FastifyZodProvider
} }
}); });
// TODO(simp): look into multi deletion and this as well
server.route({ server.route({
method: "POST", method: "POST",
url: "/:projectId/memberships/details", url: "/:projectId/memberships/details",
@@ -273,7 +273,7 @@ export const identityServiceFactory = ({
); );
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionIdentityActions.Read, OrgPermissionSubjects.Identity); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionIdentityActions.Read, OrgPermissionSubjects.Identity);
// TODO(simp): check this in identity service // TODO(namespace): check this in identity service
const activeLockouts = await keyStore.getKeysByPattern(`lockout:identity:${id}:*`); const activeLockouts = await keyStore.getKeysByPattern(`lockout:identity:${id}:*`);
const activeLockoutAuthMethods = new Set<string>(); const activeLockoutAuthMethods = new Set<string>();
@@ -5,6 +5,7 @@ import { groupBy } from "@app/lib/fn";
import { ms } from "@app/lib/ms"; import { ms } from "@app/lib/ms";
import { SearchResourceOperators } from "@app/lib/search-resource/search"; import { SearchResourceOperators } from "@app/lib/search-resource/search";
import { TAdditionalPrivilegeDALFactory } from "../additional-privilege/additional-privilege-dal";
import { TMembershipRoleDALFactory } from "../membership/membership-role-dal"; import { TMembershipRoleDALFactory } from "../membership/membership-role-dal";
import { TOrgDALFactory } from "../org/org-dal"; import { TOrgDALFactory } from "../org/org-dal";
import { TRoleDALFactory } from "../role/role-dal"; import { TRoleDALFactory } from "../role/role-dal";
@@ -29,6 +30,7 @@ type TMembershipIdentityServiceFactoryDep = {
"getOrgPermission" | "getProjectPermission" | "getProjectPermissionByRoles" | "getOrgPermissionByRoles" "getOrgPermission" | "getProjectPermission" | "getProjectPermissionByRoles" | "getOrgPermissionByRoles"
>; >;
orgDAL: Pick<TOrgDALFactory, "findById">; orgDAL: Pick<TOrgDALFactory, "findById">;
additionalPrivilegeDAL: Pick<TAdditionalPrivilegeDALFactory, "delete">;
}; };
export type TMembershipIdentityServiceFactory = ReturnType<typeof membershipIdentityServiceFactory>; export type TMembershipIdentityServiceFactory = ReturnType<typeof membershipIdentityServiceFactory>;
@@ -38,7 +40,8 @@ export const membershipIdentityServiceFactory = ({
roleDAL, roleDAL,
membershipRoleDAL, membershipRoleDAL,
permissionService, permissionService,
orgDAL orgDAL,
additionalPrivilegeDAL
}: TMembershipIdentityServiceFactoryDep) => { }: TMembershipIdentityServiceFactoryDep) => {
const scopeFactory = { const scopeFactory = {
[AccessScope.Organization]: newOrgMembershipIdentityFactory({ [AccessScope.Organization]: newOrgMembershipIdentityFactory({
@@ -255,6 +258,7 @@ export const membershipIdentityServiceFactory = ({
await factory.onDeleteMembershipIdentityGuard(dto); await factory.onDeleteMembershipIdentityGuard(dto);
const scopeField = factory.getScopeField(scopeData);
const scopeDatabaseFields = factory.getScopeDatabaseFields(dto.scopeData); const scopeDatabaseFields = factory.getScopeDatabaseFields(dto.scopeData);
const existingMembership = await membershipIdentityDAL.findOne({ const existingMembership = await membershipIdentityDAL.findOne({
scope: scopeData.scope, scope: scopeData.scope,
@@ -272,6 +276,13 @@ export const membershipIdentityServiceFactory = ({
}); });
const membershipDoc = await membershipIdentityDAL.transaction(async (tx) => { const membershipDoc = await membershipIdentityDAL.transaction(async (tx) => {
await additionalPrivilegeDAL.delete(
{
actorIdentityId: dto.selector.identityId,
[scopeField.key]: scopeField.value
},
tx
);
await membershipRoleDAL.delete({ membershipId: existingMembership.id }, tx); await membershipRoleDAL.delete({ membershipId: existingMembership.id }, tx);
const doc = await membershipIdentityDAL.deleteById(existingMembership.id, tx); const doc = await membershipIdentityDAL.deleteById(existingMembership.id, tx);
return doc; return doc;
@@ -13,6 +13,7 @@ import { groupBy } from "@app/lib/fn";
import { ms } from "@app/lib/ms"; import { ms } from "@app/lib/ms";
import { SearchResourceOperators } from "@app/lib/search-resource/search"; import { SearchResourceOperators } from "@app/lib/search-resource/search";
import { TAdditionalPrivilegeDALFactory } from "../additional-privilege/additional-privilege-dal";
import { AuthMethod } from "../auth/auth-type"; import { AuthMethod } from "../auth/auth-type";
import { TAuthTokenServiceFactory } from "../auth-token/auth-token-service"; import { TAuthTokenServiceFactory } from "../auth-token/auth-token-service";
import { TMembershipRoleDALFactory } from "../membership/membership-role-dal"; import { TMembershipRoleDALFactory } from "../membership/membership-role-dal";
@@ -53,6 +54,7 @@ type TMembershipUserServiceFactoryDep = {
tokenService: TAuthTokenServiceFactory; tokenService: TAuthTokenServiceFactory;
userGroupMembershipDAL: TUserGroupMembershipDALFactory; userGroupMembershipDAL: TUserGroupMembershipDALFactory;
projectDAL: TProjectDALFactory; projectDAL: TProjectDALFactory;
additionalPrivilegeDAL: TAdditionalPrivilegeDALFactory;
}; };
export type TMembershipUserServiceFactory = ReturnType<typeof membershipUserServiceFactory>; export type TMembershipUserServiceFactory = ReturnType<typeof membershipUserServiceFactory>;
@@ -70,7 +72,8 @@ export const membershipUserServiceFactory = ({
smtpService, smtpService,
tokenService, tokenService,
userGroupMembershipDAL, userGroupMembershipDAL,
projectDAL projectDAL,
additionalPrivilegeDAL
}: TMembershipUserServiceFactoryDep) => { }: TMembershipUserServiceFactoryDep) => {
const scopeFactory = { const scopeFactory = {
[AccessScope.Organization]: newOrgMembershipUserFactory({ [AccessScope.Organization]: newOrgMembershipUserFactory({
@@ -410,11 +413,22 @@ export const membershipUserServiceFactory = ({
userId: dto.permission.id, userId: dto.permission.id,
membershipUserDAL, membershipUserDAL,
userGroupMembershipDAL, userGroupMembershipDAL,
membershipRoleDAL membershipRoleDAL,
additionalPrivilegeDAL
}); });
return doc; return doc;
} }
if (dto.scopeData.scope === AccessScope.Project) {
await additionalPrivilegeDAL.delete(
{
actorUserId: dto.selector.userId,
projectId: dto.scopeData.projectId
},
tx
);
}
await membershipRoleDAL.delete({ membershipId: existingMembership.id }, tx); await membershipRoleDAL.delete({ membershipId: existingMembership.id }, tx);
const doc = await membershipUserDAL.deleteById(existingMembership.id, tx); const doc = await membershipUserDAL.deleteById(existingMembership.id, tx);
return doc; return doc;
+14 -1
View File
@@ -6,6 +6,7 @@ import { TOrgDALFactory } from "@app/services/org/org-dal";
import { TProjectKeyDALFactory } from "@app/services/project-key/project-key-dal"; import { TProjectKeyDALFactory } from "@app/services/project-key/project-key-dal";
import { TUserAliasDALFactory } from "@app/services/user-alias/user-alias-dal"; import { TUserAliasDALFactory } from "@app/services/user-alias/user-alias-dal";
import { TAdditionalPrivilegeDALFactory } from "../additional-privilege/additional-privilege-dal";
import { TMembershipRoleDALFactory } from "../membership/membership-role-dal"; import { TMembershipRoleDALFactory } from "../membership/membership-role-dal";
import { TMembershipUserDALFactory } from "../membership-user/membership-user-dal"; import { TMembershipUserDALFactory } from "../membership-user/membership-user-dal";
@@ -20,6 +21,7 @@ type TDeleteOrgMemberships = {
userAliasDAL: Pick<TUserAliasDALFactory, "delete">; userAliasDAL: Pick<TUserAliasDALFactory, "delete">;
licenseService: Pick<TLicenseServiceFactory, "updateSubscriptionOrgMemberCount">; licenseService: Pick<TLicenseServiceFactory, "updateSubscriptionOrgMemberCount">;
userId?: string; userId?: string;
additionalPrivilegeDAL: Pick<TAdditionalPrivilegeDALFactory, "delete">;
}; };
export const deleteOrgMembershipsFn = async ({ export const deleteOrgMembershipsFn = async ({
@@ -32,7 +34,8 @@ export const deleteOrgMembershipsFn = async ({
userId, userId,
membershipUserDAL, membershipUserDAL,
userGroupMembershipDAL, userGroupMembershipDAL,
membershipRoleDAL membershipRoleDAL,
additionalPrivilegeDAL
}: TDeleteOrgMemberships) => { }: TDeleteOrgMemberships) => {
const deletedMemberships = await orgDAL.transaction(async (tx) => { const deletedMemberships = await orgDAL.transaction(async (tx) => {
await membershipRoleDAL.delete( await membershipRoleDAL.delete(
@@ -112,6 +115,16 @@ export const deleteOrgMembershipsFn = async ({
.filter((el) => el.scope === AccessScope.Project && el.scopeProjectId) .filter((el) => el.scope === AccessScope.Project && el.scopeProjectId)
.map((el) => el.scopeProjectId as string); .map((el) => el.scopeProjectId as string);
await additionalPrivilegeDAL.delete(
{
$in: {
projectId: projectIds,
actorUserId: membershipUserIds
}
},
tx
);
// Delete all the project keys of the user in the organization // Delete all the project keys of the user in the organization
await projectKeyDAL.delete( await projectKeyDAL.delete(
{ {
+8 -3
View File
@@ -36,6 +36,7 @@ import { getDefaultOrgMembershipRoleForUpdateOrg } from "@app/services/org/org-r
import { TOrgMembershipDALFactory } from "@app/services/org-membership/org-membership-dal"; import { TOrgMembershipDALFactory } from "@app/services/org-membership/org-membership-dal";
import { TUserAliasDALFactory } from "@app/services/user-alias/user-alias-dal"; import { TUserAliasDALFactory } from "@app/services/user-alias/user-alias-dal";
import { TAdditionalPrivilegeDALFactory } from "../additional-privilege/additional-privilege-dal";
import { TAuthLoginFactory } from "../auth/auth-login-service"; import { TAuthLoginFactory } from "../auth/auth-login-service";
import { ActorAuthMethod, ActorType, AuthMethod, AuthModeJwtTokenPayload, AuthTokenType } from "../auth/auth-type"; import { ActorAuthMethod, ActorType, AuthMethod, AuthModeJwtTokenPayload, AuthTokenType } from "../auth/auth-type";
import { TAuthTokenServiceFactory } from "../auth-token/auth-token-service"; import { TAuthTokenServiceFactory } from "../auth-token/auth-token-service";
@@ -112,6 +113,7 @@ type TOrgServiceFactoryDep = {
loginService: Pick<TAuthLoginFactory, "generateUserTokens">; loginService: Pick<TAuthLoginFactory, "generateUserTokens">;
reminderService: Pick<TReminderServiceFactory, "deleteReminderBySecretId">; reminderService: Pick<TReminderServiceFactory, "deleteReminderBySecretId">;
userGroupMembershipDAL: TUserGroupMembershipDALFactory; userGroupMembershipDAL: TUserGroupMembershipDALFactory;
additionalPrivilegeDAL: TAdditionalPrivilegeDALFactory;
}; };
export type TOrgServiceFactory = ReturnType<typeof orgServiceFactory>; export type TOrgServiceFactory = ReturnType<typeof orgServiceFactory>;
@@ -144,7 +146,8 @@ export const orgServiceFactory = ({
reminderService, reminderService,
membershipRoleDAL, membershipRoleDAL,
membershipUserDAL, membershipUserDAL,
userGroupMembershipDAL userGroupMembershipDAL,
additionalPrivilegeDAL
}: TOrgServiceFactoryDep) => { }: TOrgServiceFactoryDep) => {
/* /*
* Get organization details by the organization id * Get organization details by the organization id
@@ -1004,7 +1007,8 @@ export const orgServiceFactory = ({
userId, userId,
membershipUserDAL, membershipUserDAL,
membershipRoleDAL, membershipRoleDAL,
userGroupMembershipDAL userGroupMembershipDAL,
additionalPrivilegeDAL
}); });
return deletedMembership; return deletedMembership;
@@ -1040,7 +1044,8 @@ export const orgServiceFactory = ({
userId, userId,
membershipUserDAL, membershipUserDAL,
membershipRoleDAL, membershipRoleDAL,
userGroupMembershipDAL userGroupMembershipDAL,
additionalPrivilegeDAL
}); });
return deletedMemberships; return deletedMemberships;
@@ -10,6 +10,7 @@ import {
} from "@app/ee/services/permission/org-permission"; } from "@app/ee/services/permission/org-permission";
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service-types"; import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service-types";
import { BadRequestError } from "@app/lib/errors"; import { BadRequestError } from "@app/lib/errors";
import { TExternalGroupOrgRoleMappingDALFactory } from "@app/services/external-group-org-role-mapping/external-group-org-role-mapping-dal";
import { isCustomOrgRole } from "@app/services/org/org-role-fns"; import { isCustomOrgRole } from "@app/services/org/org-role-fns";
import { TRoleScopeFactory } from "../role-types"; import { TRoleScopeFactory } from "../role-types";
@@ -17,9 +18,13 @@ import { TRoleScopeFactory } from "../role-types";
// TODO(simp): missing external group checking // TODO(simp): missing external group checking
type TOrgRoleScopeFactoryDep = { type TOrgRoleScopeFactoryDep = {
permissionService: Pick<TPermissionServiceFactory, "getOrgPermission">; permissionService: Pick<TPermissionServiceFactory, "getOrgPermission">;
externalGroupOrgRoleMappingDAL: Pick<TExternalGroupOrgRoleMappingDALFactory, "findOne">;
}; };
export const newOrgRoleFactory = ({ permissionService }: TOrgRoleScopeFactoryDep): TRoleScopeFactory => { export const newOrgRoleFactory = ({
permissionService,
externalGroupOrgRoleMappingDAL
}: TOrgRoleScopeFactoryDep): TRoleScopeFactory => {
const getScopeField: TRoleScopeFactory["getScopeField"] = (dto) => { const getScopeField: TRoleScopeFactory["getScopeField"] = (dto) => {
if (dto.scope === AccessScope.Organization) { if (dto.scope === AccessScope.Organization) {
return { key: "orgId" as const, value: dto.orgId }; return { key: "orgId" as const, value: dto.orgId };
@@ -60,6 +65,17 @@ export const newOrgRoleFactory = ({ permissionService }: TOrgRoleScopeFactoryDep
dto.permission.orgId dto.permission.orgId
); );
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Delete, OrgPermissionSubjects.Role); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Delete, OrgPermissionSubjects.Role);
const externalGroupMapping = await externalGroupOrgRoleMappingDAL.findOne({
orgId: dto.permission.orgId,
roleId: dto.selector.id
});
if (externalGroupMapping)
throw new BadRequestError({
message:
"Cannot delete role assigned to external group organization role mapping. Please re-assign external mapping and try again."
});
}; };
const onListRoleGuard: TRoleScopeFactory["onListRoleGuard"] = async (dto) => { const onListRoleGuard: TRoleScopeFactory["onListRoleGuard"] = async (dto) => {
+6 -2
View File
@@ -8,6 +8,7 @@ import { validateHandlebarTemplate } from "@app/lib/template/validate-handlebars
import { UnpackedPermissionSchema, unpackPermissions } from "@app/server/routes/sanitizedSchema/permission"; import { UnpackedPermissionSchema, unpackPermissions } from "@app/server/routes/sanitizedSchema/permission";
import { ActorType } from "../auth/auth-type"; import { ActorType } from "../auth/auth-type";
import { TExternalGroupOrgRoleMappingDALFactory } from "../external-group-org-role-mapping/external-group-org-role-mapping-dal";
import { TIdentityDALFactory } from "../identity/identity-dal"; import { TIdentityDALFactory } from "../identity/identity-dal";
import { TProjectDALFactory } from "../project/project-dal"; import { TProjectDALFactory } from "../project/project-dal";
import { TUserDALFactory } from "../user/user-dal"; import { TUserDALFactory } from "../user/user-dal";
@@ -31,6 +32,7 @@ type TRoleServiceFactoryDep = {
userDAL: Pick<TUserDALFactory, "findById">; userDAL: Pick<TUserDALFactory, "findById">;
permissionService: Pick<TPermissionServiceFactory, "getProjectPermission" | "getOrgPermission">; permissionService: Pick<TPermissionServiceFactory, "getProjectPermission" | "getOrgPermission">;
projectDAL: Pick<TProjectDALFactory, "findById">; projectDAL: Pick<TProjectDALFactory, "findById">;
externalGroupOrgRoleMappingDAL: Pick<TExternalGroupOrgRoleMappingDALFactory, "findOne">;
}; };
export type TRoleServiceFactory = ReturnType<typeof roleServiceFactory>; export type TRoleServiceFactory = ReturnType<typeof roleServiceFactory>;
@@ -40,10 +42,12 @@ export const roleServiceFactory = ({
permissionService, permissionService,
projectDAL, projectDAL,
identityDAL, identityDAL,
userDAL userDAL,
externalGroupOrgRoleMappingDAL
}: TRoleServiceFactoryDep) => { }: TRoleServiceFactoryDep) => {
const orgRoleFactory = newOrgRoleFactory({ const orgRoleFactory = newOrgRoleFactory({
permissionService permissionService,
externalGroupOrgRoleMappingDAL
}); });
const projectRoleFactory = newProjectRoleFactory({ const projectRoleFactory = newProjectRoleFactory({
permissionService, permissionService,