Update groups CRUD SCIM to use orgMembershipId

This commit is contained in:
Tuan Dang
2024-04-28 21:58:24 -07:00
parent a7af3a48d9
commit b2a976f3d4
9 changed files with 120 additions and 131 deletions
+3 -15
View File
@@ -152,7 +152,6 @@ export const registerScimRouter = async (server: FastifyZodProvider) => {
}, },
onRequest: verifyAuth([AuthMode.SCIM_TOKEN]), onRequest: verifyAuth([AuthMode.SCIM_TOKEN]),
handler: async (req) => { handler: async (req) => {
console.log("GET /Users req.query: ", req.query);
const users = await req.server.services.scim.listScimUsers({ const users = await req.server.services.scim.listScimUsers({
startIndex: req.query.startIndex, startIndex: req.query.startIndex,
limit: req.query.count, limit: req.query.count,
@@ -193,7 +192,6 @@ export const registerScimRouter = async (server: FastifyZodProvider) => {
}, },
onRequest: verifyAuth([AuthMode.SCIM_TOKEN]), onRequest: verifyAuth([AuthMode.SCIM_TOKEN]),
handler: async (req) => { handler: async (req) => {
console.log(`GET /Users/${req.params.orgMembershipId}`);
const user = await req.server.services.scim.getScimUser({ const user = await req.server.services.scim.getScimUser({
orgMembershipId: req.params.orgMembershipId, orgMembershipId: req.params.orgMembershipId,
orgId: req.permission.orgId orgId: req.permission.orgId
@@ -248,8 +246,6 @@ export const registerScimRouter = async (server: FastifyZodProvider) => {
}, },
onRequest: verifyAuth([AuthMode.SCIM_TOKEN]), onRequest: verifyAuth([AuthMode.SCIM_TOKEN]),
handler: async (req) => { handler: async (req) => {
console.log("POST /Users req.body: ", req.body);
const primaryEmail = req.body.emails?.find((email) => email.primary)?.value; const primaryEmail = req.body.emails?.find((email) => email.primary)?.value;
const user = await req.server.services.scim.createScimUser({ const user = await req.server.services.scim.createScimUser({
@@ -277,7 +273,6 @@ export const registerScimRouter = async (server: FastifyZodProvider) => {
}, },
onRequest: verifyAuth([AuthMode.SCIM_TOKEN]), onRequest: verifyAuth([AuthMode.SCIM_TOKEN]),
handler: async (req) => { handler: async (req) => {
console.log(`DELETE /Users/${req.params.orgMembershipId}`);
const user = await req.server.services.scim.deleteScimUser({ const user = await req.server.services.scim.deleteScimUser({
orgMembershipId: req.params.orgMembershipId, orgMembershipId: req.params.orgMembershipId,
orgId: req.permission.orgId orgId: req.permission.orgId
@@ -324,7 +319,6 @@ export const registerScimRouter = async (server: FastifyZodProvider) => {
}, },
onRequest: verifyAuth([AuthMode.SCIM_TOKEN]), onRequest: verifyAuth([AuthMode.SCIM_TOKEN]),
handler: async (req) => { handler: async (req) => {
console.log("POST /Groups req.body: ", req.body);
const group = await req.server.services.scim.createScimGroup({ const group = await req.server.services.scim.createScimGroup({
orgId: req.permission.orgId, orgId: req.permission.orgId,
...req.body ...req.body
@@ -365,10 +359,9 @@ export const registerScimRouter = async (server: FastifyZodProvider) => {
}, },
onRequest: verifyAuth([AuthMode.SCIM_TOKEN]), onRequest: verifyAuth([AuthMode.SCIM_TOKEN]),
handler: async (req) => { handler: async (req) => {
console.log("GET /Groups req.query: ", req.query);
const groups = await req.server.services.scim.listScimGroups({ const groups = await req.server.services.scim.listScimGroups({
orgId: req.permission.orgId, orgId: req.permission.orgId,
offset: req.query.startIndex, startIndex: req.query.startIndex,
limit: req.query.count limit: req.query.count
}); });
@@ -402,7 +395,6 @@ export const registerScimRouter = async (server: FastifyZodProvider) => {
}, },
onRequest: verifyAuth([AuthMode.SCIM_TOKEN]), onRequest: verifyAuth([AuthMode.SCIM_TOKEN]),
handler: async (req) => { handler: async (req) => {
console.log(`GET /Groups/${req.params.groupId}`);
const group = await req.server.services.scim.getScimGroup({ const group = await req.server.services.scim.getScimGroup({
groupId: req.params.groupId, groupId: req.params.groupId,
orgId: req.permission.orgId orgId: req.permission.orgId
@@ -424,10 +416,10 @@ export const registerScimRouter = async (server: FastifyZodProvider) => {
displayName: z.string().trim(), displayName: z.string().trim(),
members: z.array( members: z.array(
z.object({ z.object({
value: z.string(), // infisical userId value: z.string(), // infisical orgMembershipId
display: z.string() display: z.string()
}) })
) // note: is this where members are added to group? )
}), }),
response: { response: {
200: z.object({ 200: z.object({
@@ -448,7 +440,6 @@ export const registerScimRouter = async (server: FastifyZodProvider) => {
}, },
onRequest: verifyAuth([AuthMode.SCIM_TOKEN]), onRequest: verifyAuth([AuthMode.SCIM_TOKEN]),
handler: async (req) => { handler: async (req) => {
console.log(`PUT /Groups/${req.params.groupId} req.body: `, req.body);
const group = await req.server.services.scim.updateScimGroupNamePut({ const group = await req.server.services.scim.updateScimGroupNamePut({
groupId: req.params.groupId, groupId: req.params.groupId,
orgId: req.permission.orgId, orgId: req.permission.orgId,
@@ -510,7 +501,6 @@ export const registerScimRouter = async (server: FastifyZodProvider) => {
}, },
onRequest: verifyAuth([AuthMode.SCIM_TOKEN]), onRequest: verifyAuth([AuthMode.SCIM_TOKEN]),
handler: async (req) => { handler: async (req) => {
console.log(`PATCH /Groups/${req.params.groupId} req.body: `, req.body);
const group = await req.server.services.scim.updateScimGroupNamePatch({ const group = await req.server.services.scim.updateScimGroupNamePatch({
groupId: req.params.groupId, groupId: req.params.groupId,
orgId: req.permission.orgId, orgId: req.permission.orgId,
@@ -534,7 +524,6 @@ export const registerScimRouter = async (server: FastifyZodProvider) => {
}, },
onRequest: verifyAuth([AuthMode.SCIM_TOKEN]), onRequest: verifyAuth([AuthMode.SCIM_TOKEN]),
handler: async (req) => { handler: async (req) => {
console.log(`DELETE /Groups/${req.params.groupId}`);
const group = await req.server.services.scim.deleteScimGroup({ const group = await req.server.services.scim.deleteScimGroup({
groupId: req.params.groupId, groupId: req.params.groupId,
orgId: req.permission.orgId orgId: req.permission.orgId
@@ -585,7 +574,6 @@ export const registerScimRouter = async (server: FastifyZodProvider) => {
}, },
onRequest: verifyAuth([AuthMode.SCIM_TOKEN]), onRequest: verifyAuth([AuthMode.SCIM_TOKEN]),
handler: async (req) => { handler: async (req) => {
console.log(`PUT /Users/${req.params.orgMembershipId} req.body: `, req.body);
const user = await req.server.services.scim.replaceScimUser({ const user = await req.server.services.scim.replaceScimUser({
orgMembershipId: req.params.orgMembershipId, orgMembershipId: req.params.orgMembershipId,
orgId: req.permission.orgId, orgId: req.permission.orgId,
@@ -369,7 +369,7 @@ export const samlConfigServiceFactory = ({
}); });
} else { } else {
user = await userDAL.transaction(async (tx) => { user = await userDAL.transaction(async (tx) => {
const uniqueUsername = await normalizeUsername(externalId, userDAL); const uniqueUsername = await normalizeUsername(`${firstName ?? ""}-${lastName ?? ""}`, userDAL);
const newUser = await userDAL.create( const newUser = await userDAL.create(
{ {
username: uniqueUsername, username: uniqueUsername,
+3 -3
View File
@@ -65,18 +65,18 @@ export const buildScimUser = ({
export const buildScimGroupList = ({ export const buildScimGroupList = ({
scimGroups, scimGroups,
offset, startIndex,
limit limit
}: { }: {
scimGroups: TScimGroup[]; scimGroups: TScimGroup[];
offset: number; startIndex: number;
limit: number; limit: number;
}): TListScimGroups => { }): TListScimGroups => {
return { return {
Resources: scimGroups, Resources: scimGroups,
itemsPerPage: limit, itemsPerPage: limit,
schemas: ["urn:ietf:params:scim:api:messages:2.0:ListResponse"], schemas: ["urn:ietf:params:scim:api:messages:2.0:ListResponse"],
startIndex: offset, startIndex,
totalResults: scimGroups.length totalResults: scimGroups.length
}; };
}; };
+46 -52
View File
@@ -14,7 +14,7 @@ import { TOrgPermission } from "@app/lib/types";
import { AuthTokenType } from "@app/services/auth/auth-type"; import { AuthTokenType } from "@app/services/auth/auth-type";
import { TGroupProjectDALFactory } from "@app/services/group-project/group-project-dal"; import { TGroupProjectDALFactory } from "@app/services/group-project/group-project-dal";
import { TOrgDALFactory } from "@app/services/org/org-dal"; import { TOrgDALFactory } from "@app/services/org/org-dal";
import { deleteOrgMembership } from "@app/services/org/org-fns"; import { deleteOrgMembershipFn } from "@app/services/org/org-fns";
import { TOrgMembershipDALFactory } from "@app/services/org-membership/org-membership-dal"; import { TOrgMembershipDALFactory } from "@app/services/org-membership/org-membership-dal";
import { TProjectDALFactory } from "@app/services/project/project-dal"; import { TProjectDALFactory } from "@app/services/project/project-dal";
import { TProjectBotDALFactory } from "@app/services/project-bot/project-bot-dal"; import { TProjectBotDALFactory } from "@app/services/project-bot/project-bot-dal";
@@ -62,7 +62,7 @@ type TScimServiceFactoryDep = {
>; >;
orgMembershipDAL: TOrgMembershipDALFactory; // TODO: Pick orgMembershipDAL: TOrgMembershipDALFactory; // TODO: Pick
projectDAL: Pick<TProjectDALFactory, "find" | "findProjectGhostUser">; projectDAL: Pick<TProjectDALFactory, "find" | "findProjectGhostUser">;
projectMembershipDAL: Pick<TProjectMembershipDALFactory, "find" | "delete">; projectMembershipDAL: Pick<TProjectMembershipDALFactory, "find" | "delete" | "findProjectMembershipsByUserId">;
groupDAL: Pick< groupDAL: Pick<
TGroupDALFactory, TGroupDALFactory,
"create" | "findOne" | "findAllGroupMembers" | "update" | "delete" | "findGroups" | "transaction" "create" | "findOne" | "findAllGroupMembers" | "update" | "delete" | "findGroups" | "transaction"
@@ -71,7 +71,7 @@ type TScimServiceFactoryDep = {
userGroupMembershipDAL: TUserGroupMembershipDALFactory; // TODO: Pick userGroupMembershipDAL: TUserGroupMembershipDALFactory; // TODO: Pick
projectKeyDAL: Pick<TProjectKeyDALFactory, "find" | "findLatestProjectKey" | "insertMany" | "delete">; projectKeyDAL: Pick<TProjectKeyDALFactory, "find" | "findLatestProjectKey" | "insertMany" | "delete">;
projectBotDAL: Pick<TProjectBotDALFactory, "findOne">; projectBotDAL: Pick<TProjectBotDALFactory, "findOne">;
licenseService: Pick<TLicenseServiceFactory, "getPlan">; licenseService: Pick<TLicenseServiceFactory, "getPlan" | "updateSubscriptionOrgMemberCount">;
permissionService: Pick<TPermissionServiceFactory, "getOrgPermission">; permissionService: Pick<TPermissionServiceFactory, "getOrgPermission">;
smtpService: Pick<TSmtpService, "sendMail">; smtpService: Pick<TSmtpService, "sendMail">;
}; };
@@ -174,12 +174,6 @@ export const scimServiceFactory = ({
// SCIM server endpoints // SCIM server endpoints
const listScimUsers = async ({ startIndex, limit, filter, orgId }: TListScimUsersDTO): Promise<TListScimUsers> => { const listScimUsers = async ({ startIndex, limit, filter, orgId }: TListScimUsersDTO): Promise<TListScimUsers> => {
console.log("listScimUsers args: ", {
startIndex,
limit,
filter,
orgId
}); // done
const org = await orgDAL.findById(orgId); const org = await orgDAL.findById(orgId);
if (!org.scimEnabled) if (!org.scimEnabled)
@@ -232,10 +226,6 @@ export const scimServiceFactory = ({
}; };
const getScimUser = async ({ orgMembershipId, orgId }: TGetScimUserDTO) => { const getScimUser = async ({ orgMembershipId, orgId }: TGetScimUserDTO) => {
console.log("getScimUser args: ", {
orgMembershipId,
orgId
}); // done
const [membership] = await orgDAL const [membership] = await orgDAL
.findMembership({ .findMembership({
[`${TableName.OrgMembership}.id` as "id"]: orgMembershipId, [`${TableName.OrgMembership}.id` as "id"]: orgMembershipId,
@@ -260,8 +250,6 @@ export const scimServiceFactory = ({
status: 403 status: 403
}); });
console.log("getScimUser membership: ", membership);
return buildScimUser({ return buildScimUser({
orgMembershipId: membership.id, orgMembershipId: membership.id,
username: membership.username, username: membership.username,
@@ -273,14 +261,6 @@ export const scimServiceFactory = ({
}; };
const createScimUser = async ({ username, email, firstName, lastName, orgId }: TCreateScimUserDTO) => { const createScimUser = async ({ username, email, firstName, lastName, orgId }: TCreateScimUserDTO) => {
// do we get external ID or not?
console.log("createScimUser args: ", {
username,
email,
firstName,
lastName,
orgId
});
const org = await orgDAL.findById(orgId); const org = await orgDAL.findById(orgId);
if (!org) if (!org)
@@ -337,7 +317,7 @@ export const scimServiceFactory = ({
); );
} }
} else { } else {
const uniqueUsername = await normalizeUsername(username, userDAL); const uniqueUsername = await normalizeUsername(`${firstName}-${lastName}`, userDAL);
user = await userDAL.create( user = await userDAL.create(
{ {
username: uniqueUsername, username: uniqueUsername,
@@ -398,7 +378,6 @@ export const scimServiceFactory = ({
}; };
const updateScimUser = async ({ userId, orgId, operations }: TUpdateScimUserDTO) => { const updateScimUser = async ({ userId, orgId, operations }: TUpdateScimUserDTO) => {
console.log("updateScimUser"); // done
const [membership] = await orgDAL const [membership] = await orgDAL
.findMembership({ .findMembership({
userId, userId,
@@ -438,12 +417,14 @@ export const scimServiceFactory = ({
}); });
if (!active) { if (!active) {
await deleteOrgMembership({ await deleteOrgMembershipFn({
orgMembershipId: membership.id, orgMembershipId: membership.id,
orgId: membership.orgId, orgId: membership.orgId,
orgDAL, orgDAL,
projectDAL, projectMembershipDAL,
projectMembershipDAL projectKeyDAL,
userAliasDAL,
licenseService
}); });
} }
@@ -458,11 +439,6 @@ export const scimServiceFactory = ({
}; };
const replaceScimUser = async ({ orgMembershipId, active, orgId }: TReplaceScimUserDTO) => { const replaceScimUser = async ({ orgMembershipId, active, orgId }: TReplaceScimUserDTO) => {
console.log("replaceScimUser args: ", {
orgMembershipId,
orgId,
active
}); // done
const [membership] = await orgDAL const [membership] = await orgDAL
.findMembership({ .findMembership({
[`${TableName.OrgMembership}.id` as "id"]: orgMembershipId, [`${TableName.OrgMembership}.id` as "id"]: orgMembershipId,
@@ -489,12 +465,14 @@ export const scimServiceFactory = ({
if (!active) { if (!active) {
// tx // tx
await deleteOrgMembership({ await deleteOrgMembershipFn({
orgMembershipId: membership.id, orgMembershipId: membership.id,
orgId: membership.orgId, orgId: membership.orgId,
orgDAL, orgDAL,
projectDAL, projectMembershipDAL,
projectMembershipDAL projectKeyDAL,
userAliasDAL,
licenseService
}); });
} }
@@ -509,10 +487,6 @@ export const scimServiceFactory = ({
}; };
const deleteScimUser = async ({ orgMembershipId, orgId }: TDeleteScimUserDTO) => { const deleteScimUser = async ({ orgMembershipId, orgId }: TDeleteScimUserDTO) => {
console.log("deleteScimUser args: ", {
orgMembershipId,
orgId
}); // done
const [membership] = await orgDAL.findMembership({ const [membership] = await orgDAL.findMembership({
[`${TableName.OrgMembership}.id` as "id"]: orgMembershipId, [`${TableName.OrgMembership}.id` as "id"]: orgMembershipId,
[`${TableName.OrgMembership}.orgId` as "orgId"]: orgId [`${TableName.OrgMembership}.orgId` as "orgId"]: orgId
@@ -531,18 +505,20 @@ export const scimServiceFactory = ({
}); });
} }
await deleteOrgMembership({ await deleteOrgMembershipFn({
orgMembershipId: membership.id, orgMembershipId: membership.id,
orgId: membership.orgId, orgId: membership.orgId,
orgDAL, orgDAL,
projectDAL, projectMembershipDAL,
projectMembershipDAL projectKeyDAL,
userAliasDAL,
licenseService
}); });
return {}; // intentionally return empty object upon success return {}; // intentionally return empty object upon success
}; };
const listScimGroups = async ({ orgId, offset, limit }: TListScimGroupsDTO) => { const listScimGroups = async ({ orgId, startIndex, limit }: TListScimGroupsDTO) => {
const plan = await licenseService.getPlan(orgId); const plan = await licenseService.getPlan(orgId);
if (!plan.groups) if (!plan.groups)
throw new BadRequestError({ throw new BadRequestError({
@@ -563,9 +539,15 @@ export const scimServiceFactory = ({
status: 403 status: 403
}); });
const groups = await groupDAL.findGroups({ const groups = await groupDAL.findGroups(
orgId {
}); orgId
},
{
offset: startIndex - 1,
limit
}
);
const scimGroups = groups.map((group) => const scimGroups = groups.map((group) =>
buildScimGroup({ buildScimGroup({
@@ -577,7 +559,7 @@ export const scimServiceFactory = ({
return buildScimGroupList({ return buildScimGroupList({
scimGroups, scimGroups,
offset, startIndex,
limit limit
}); });
}; };
@@ -616,9 +598,15 @@ export const scimServiceFactory = ({
); );
if (members && members.length) { if (members && members.length) {
const orgMemberships = await orgMembershipDAL.find({
$in: {
id: members.map((member) => member.value)
}
});
const newMembers = await addUsersToGroupByUserIds({ const newMembers = await addUsersToGroupByUserIds({
group, group,
userIds: members.map((member) => member.value), userIds: orgMemberships.map((membership) => membership.userId as string),
userDAL, userDAL,
userGroupMembershipDAL, userGroupMembershipDAL,
orgDAL, orgDAL,
@@ -733,7 +721,13 @@ export const scimServiceFactory = ({
} }
if (members) { if (members) {
const membersIdsSet = new Set(members.map((member) => member.value)); const orgMemberships = await orgMembershipDAL.find({
$in: {
id: members.map((member) => member.value)
}
});
const membersIdsSet = new Set(orgMemberships.map((orgMembership) => orgMembership.userId));
const directMemberUserIds = ( const directMemberUserIds = (
await userGroupMembershipDAL.find({ await userGroupMembershipDAL.find({
@@ -752,13 +746,13 @@ export const scimServiceFactory = ({
const allMembersUserIds = directMemberUserIds.concat(pendingGroupAdditionsUserIds); const allMembersUserIds = directMemberUserIds.concat(pendingGroupAdditionsUserIds);
const allMembersUserIdsSet = new Set(allMembersUserIds); const allMembersUserIdsSet = new Set(allMembersUserIds);
const toAddUserIds = members.filter((member) => !allMembersUserIdsSet.has(member.value)); const toAddUserIds = orgMemberships.filter((member) => !allMembersUserIdsSet.has(member.userId as string));
const toRemoveUserIds = allMembersUserIds.filter((userId) => !membersIdsSet.has(userId)); const toRemoveUserIds = allMembersUserIds.filter((userId) => !membersIdsSet.has(userId));
if (toAddUserIds.length) { if (toAddUserIds.length) {
await addUsersToGroupByUserIds({ await addUsersToGroupByUserIds({
group, group,
userIds: toAddUserIds.map((member) => member.value), userIds: toAddUserIds.map((member) => member.userId as string),
userDAL, userDAL,
userGroupMembershipDAL, userGroupMembershipDAL,
orgDAL, orgDAL,
+1 -1
View File
@@ -65,7 +65,7 @@ export type TDeleteScimUserDTO = {
}; };
export type TListScimGroupsDTO = { export type TListScimGroupsDTO = {
offset: number; startIndex: number;
limit: number; limit: number;
orgId: string; orgId: string;
}; };
+1
View File
@@ -349,6 +349,7 @@ export const registerRoutes = async (
userDAL userDAL
}); });
const orgService = orgServiceFactory({ const orgService = orgServiceFactory({
userAliasDAL,
licenseService, licenseService,
samlConfigDAL, samlConfigDAL,
orgRoleDAL, orgRoleDAL,
+52 -17
View File
@@ -1,43 +1,78 @@
import { TLicenseServiceFactory } from "@app/ee/services/license/license-service";
import { TOrgDALFactory } from "@app/services/org/org-dal"; import { TOrgDALFactory } from "@app/services/org/org-dal";
import { TProjectDALFactory } from "@app/services/project/project-dal"; import { TProjectKeyDALFactory } from "@app/services/project-key/project-key-dal";
import { TProjectMembershipDALFactory } from "@app/services/project-membership/project-membership-dal"; import { TProjectMembershipDALFactory } from "@app/services/project-membership/project-membership-dal";
import { TUserAliasDALFactory } from "@app/services/user-alias/user-alias-dal";
type TDeleteOrgMembership = { type TDeleteOrgMembership = {
orgMembershipId: string; orgMembershipId: string;
orgId: string; orgId: string;
orgDAL: Pick<TOrgDALFactory, "findMembership" | "deleteMembershipById" | "transaction">; orgDAL: Pick<TOrgDALFactory, "findMembership" | "deleteMembershipById" | "transaction">;
projectDAL: Pick<TProjectDALFactory, "find">; projectMembershipDAL: Pick<TProjectMembershipDALFactory, "delete" | "findProjectMembershipsByUserId">;
projectMembershipDAL: Pick<TProjectMembershipDALFactory, "find" | "delete">; projectKeyDAL: Pick<TProjectKeyDALFactory, "find" | "delete">;
userAliasDAL: Pick<TUserAliasDALFactory, "delete">;
licenseService: Pick<TLicenseServiceFactory, "updateSubscriptionOrgMemberCount">;
}; };
export const deleteOrgMembership = async ({ export const deleteOrgMembershipFn = async ({
orgMembershipId, orgMembershipId,
orgId, orgId,
orgDAL, orgDAL,
projectDAL, projectMembershipDAL,
projectMembershipDAL projectKeyDAL,
userAliasDAL,
licenseService
}: TDeleteOrgMembership) => { }: TDeleteOrgMembership) => {
const membership = await orgDAL.transaction(async (tx) => { const deletedMembership = await orgDAL.transaction(async (tx) => {
// delete org membership
const orgMembership = await orgDAL.deleteMembershipById(orgMembershipId, orgId, tx); const orgMembership = await orgDAL.deleteMembershipById(orgMembershipId, orgId, tx);
const projects = await projectDAL.find({ orgId }, { tx }); if (!orgMembership.userId) {
await licenseService.updateSubscriptionOrgMemberCount(orgId);
return orgMembership;
}
// delete associated project memberships await userAliasDAL.delete(
await projectMembershipDAL.delete(
{ {
$in: { userId: orgMembership.userId,
projectId: projects.map((project) => project.id) orgId
},
userId: orgMembership.userId as string
}, },
tx tx
); );
// TODO: delete associated aliases // Get all the project memberships of the user in the organization
const projectMemberships = await projectMembershipDAL.findProjectMembershipsByUserId(orgId, orgMembership.userId);
// Delete all the project memberships of the user in the organization
await projectMembershipDAL.delete(
{
$in: {
id: projectMemberships.map((membership) => membership.id)
}
},
tx
);
// Get all the project keys of the user in the organization
const projectKeys = await projectKeyDAL.find({
$in: {
projectId: projectMemberships.map((membership) => membership.projectId)
},
receiverId: orgMembership.userId
});
// Delete all the project keys of the user in the organization
await projectKeyDAL.delete(
{
$in: {
id: projectKeys.map((key) => key.id)
}
},
tx
);
await licenseService.updateSubscriptionOrgMemberCount(orgId);
return orgMembership; return orgMembership;
}); });
return membership; return deletedMembership;
}; };
+12 -41
View File
@@ -18,6 +18,7 @@ import { generateUserSrpKeys } from "@app/lib/crypto/srp";
import { BadRequestError, UnauthorizedError } from "@app/lib/errors"; import { BadRequestError, UnauthorizedError } from "@app/lib/errors";
import { alphaNumericNanoId } from "@app/lib/nanoid"; import { alphaNumericNanoId } from "@app/lib/nanoid";
import { isDisposableEmail } from "@app/lib/validator"; import { isDisposableEmail } from "@app/lib/validator";
import { TUserAliasDALFactory } from "@app/services/user-alias/user-alias-dal";
import { ActorAuthMethod, ActorType, AuthMethod, AuthTokenType } from "../auth/auth-type"; import { ActorAuthMethod, ActorType, AuthMethod, AuthTokenType } from "../auth/auth-type";
import { TAuthTokenServiceFactory } from "../auth-token/auth-token-service"; import { TAuthTokenServiceFactory } from "../auth-token/auth-token-service";
@@ -30,6 +31,7 @@ import { TUserDALFactory } from "../user/user-dal";
import { TIncidentContactsDALFactory } from "./incident-contacts-dal"; import { TIncidentContactsDALFactory } from "./incident-contacts-dal";
import { TOrgBotDALFactory } from "./org-bot-dal"; import { TOrgBotDALFactory } from "./org-bot-dal";
import { TOrgDALFactory } from "./org-dal"; import { TOrgDALFactory } from "./org-dal";
import { deleteOrgMembershipFn } from "./org-fns";
import { TOrgRoleDALFactory } from "./org-role-dal"; import { TOrgRoleDALFactory } from "./org-role-dal";
import { import {
TDeleteOrgMembershipDTO, TDeleteOrgMembershipDTO,
@@ -43,6 +45,7 @@ import {
} from "./org-types"; } from "./org-types";
type TOrgServiceFactoryDep = { type TOrgServiceFactoryDep = {
userAliasDAL: Pick<TUserAliasDALFactory, "delete">;
orgDAL: TOrgDALFactory; orgDAL: TOrgDALFactory;
orgBotDAL: TOrgBotDALFactory; orgBotDAL: TOrgBotDALFactory;
orgRoleDAL: TOrgRoleDALFactory; orgRoleDAL: TOrgRoleDALFactory;
@@ -65,6 +68,7 @@ type TOrgServiceFactoryDep = {
export type TOrgServiceFactory = ReturnType<typeof orgServiceFactory>; export type TOrgServiceFactory = ReturnType<typeof orgServiceFactory>;
export const orgServiceFactory = ({ export const orgServiceFactory = ({
userAliasDAL,
orgDAL, orgDAL,
userDAL, userDAL,
groupDAL, groupDAL,
@@ -572,47 +576,14 @@ export const orgServiceFactory = ({
const { permission } = await permissionService.getUserOrgPermission(userId, orgId, actorAuthMethod, actorOrgId); const { permission } = await permissionService.getUserOrgPermission(userId, orgId, actorAuthMethod, actorOrgId);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Delete, OrgPermissionSubjects.Member); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Delete, OrgPermissionSubjects.Member);
const deletedMembership = await orgDAL.transaction(async (tx) => { const deletedMembership = await deleteOrgMembershipFn({
const orgMembership = await orgDAL.deleteMembershipById(membershipId, orgId, tx); orgMembershipId: membershipId,
orgId,
if (!orgMembership.userId) { orgDAL,
await licenseService.updateSubscriptionOrgMemberCount(orgId); projectMembershipDAL,
return orgMembership; projectKeyDAL,
} userAliasDAL,
licenseService
// Get all the project memberships of the user in the organization
const projectMemberships = await projectMembershipDAL.findProjectMembershipsByUserId(orgId, orgMembership.userId);
// Delete all the project memberships of the user in the organization
await projectMembershipDAL.delete(
{
$in: {
id: projectMemberships.map((membership) => membership.id)
}
},
tx
);
// Get all the project keys of the user in the organization
const projectKeys = await projectKeyDAL.find({
$in: {
projectId: projectMemberships.map((membership) => membership.projectId)
},
receiverId: orgMembership.userId
});
// Delete all the project keys of the user in the organization
await projectKeyDAL.delete(
{
$in: {
id: projectKeys.map((key) => key.id)
}
},
tx
);
await licenseService.updateSubscriptionOrgMemberCount(orgId);
return orgMembership;
}); });
return deletedMembership; return deletedMembership;
+1 -1
View File
@@ -4,7 +4,7 @@ import { alphaNumericNanoId } from "@app/lib/nanoid";
import { TUserDALFactory } from "@app/services/user/user-dal"; import { TUserDALFactory } from "@app/services/user/user-dal";
export const normalizeUsername = async (username: string, userDAL: Pick<TUserDALFactory, "findOne">) => { export const normalizeUsername = async (username: string, userDAL: Pick<TUserDALFactory, "findOne">) => {
let attempt = slugify(username); let attempt = slugify(`${username}-${alphaNumericNanoId(4)}`);
let user = await userDAL.findOne({ username: attempt }); let user = await userDAL.findOne({ username: attempt });
if (!user) return attempt; if (!user) return attempt;