@7365admin1/core 3.138.0 → 3.139.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -3200,6 +3200,53 @@ function sameAppType(a, b) {
3200
3200
  return !!a && !!b && serviceAppType(a) === serviceAppType(b);
3201
3201
  }
3202
3202
 
3203
+ // src/utils/member-lookup.util.ts
3204
+ var idOf = (v) => v == null ? "" : String(v?._id ?? v).toLowerCase();
3205
+ function isLiveMembership(m) {
3206
+ return m.status !== "deleted" && !m.deletedAt;
3207
+ }
3208
+ function pickSiteMembership(rows, type, site, org = "") {
3209
+ site = site.toLowerCase();
3210
+ org = org.toLowerCase();
3211
+ if (!site)
3212
+ return null;
3213
+ const live2 = rows.filter(
3214
+ (m) => sameAppType(m.type, type) && isLiveMembership(m) && (!org || idOf(m.org) === org)
3215
+ );
3216
+ const atSite = live2.find((m) => idOf(m.siteId) === site);
3217
+ if (atSite)
3218
+ return atSite;
3219
+ if (!org)
3220
+ return null;
3221
+ return live2.find((m) => !idOf(m.siteId)) ?? live2[0] ?? null;
3222
+ }
3223
+ function pickLookupMembership(rows, type, site = "", org = "") {
3224
+ const list = Array.isArray(rows) ? rows : [];
3225
+ const atSite = site ? pickSiteMembership(list, type, site, org) : null;
3226
+ if (atSite)
3227
+ return atSite;
3228
+ const inOrg = org ? list.find((m) => sameAppType(m.type, type) && idOf(m.org) === org.toLowerCase()) : void 0;
3229
+ if (inOrg && isLiveMembership(inOrg))
3230
+ return inOrg;
3231
+ return preferWorkingMembership(list.filter((m) => sameAppType(m.type, type)));
3232
+ }
3233
+ var WORKING = /* @__PURE__ */ new Set(["active", "approved"]);
3234
+ function preferWorkingMembership(rows, defaultOrg = "") {
3235
+ const list = Array.isArray(rows) ? rows : [];
3236
+ const working = list.filter((m) => WORKING.has(String(m.status ?? "")) && !m.deletedAt);
3237
+ const home = idOf(defaultOrg);
3238
+ return (home ? working.find((m) => idOf(m.org) === home) : void 0) ?? working[0] ?? list.find(isLiveMembership) ?? list[0] ?? null;
3239
+ }
3240
+ function memberListSiteScope(memberships, org) {
3241
+ const inOrg = (memberships ?? []).filter((m) => idOf(m.org) === idOf(org));
3242
+ const here = inOrg.filter((m) => m.type !== "resident");
3243
+ if (!inOrg.length)
3244
+ return null;
3245
+ if (here.some((m) => !idOf(m.siteId) || m.orgLevelRole))
3246
+ return null;
3247
+ return [...new Set(here.map((m) => idOf(m.siteId)))];
3248
+ }
3249
+
3203
3250
  // src/repositories/member.repo.ts
3204
3251
  import {
3205
3252
  AppError as AppError2,
@@ -3332,10 +3379,10 @@ import { ObjectId as ObjectId13 } from "mongodb";
3332
3379
  function crossSiteRoleMode() {
3333
3380
  return (process.env.CROSS_SITE_ROLE_MODE ?? "").trim().toLowerCase() === "enforce" ? "enforce" : "log";
3334
3381
  }
3335
- var idOf = (value) => value === null || value === void 0 ? "" : String(value?.toString?.() ?? value);
3382
+ var idOf2 = (value) => value === null || value === void 0 ? "" : String(value?.toString?.() ?? value);
3336
3383
  function isCrossSiteRole(role, memberSite) {
3337
- const roleSite = idOf(role?.site);
3338
- return !!roleSite && roleSite !== idOf(memberSite);
3384
+ const roleSite = idOf2(role?.site);
3385
+ return !!roleSite && roleSite !== idOf2(memberSite);
3339
3386
  }
3340
3387
  var THROTTLE_MS = 10 * 60 * 1e3;
3341
3388
  var lastLogged = /* @__PURE__ */ new Map();
@@ -3344,7 +3391,7 @@ function crossSiteRoleGrants(input) {
3344
3391
  return true;
3345
3392
  const mode = crossSiteRoleMode();
3346
3393
  const granted = mode !== "enforce";
3347
- const key = [mode, idOf(input.member) || idOf(input.user), idOf(input.role?._id), input.where].join("|");
3394
+ const key = [mode, idOf2(input.member) || idOf2(input.user), idOf2(input.role?._id), input.where].join("|");
3348
3395
  const now = Date.now();
3349
3396
  if ((lastLogged.get(key) ?? 0) + THROTTLE_MS <= now) {
3350
3397
  lastLogged.set(key, now);
@@ -3352,7 +3399,7 @@ function crossSiteRoleGrants(input) {
3352
3399
  lastLogged.clear();
3353
3400
  logger7.log({
3354
3401
  level: "warn",
3355
- message: `cross-site-role mode=${mode} ${granted ? "granted" : "refused"} where=${input.where} member=${idOf(input.member) || "-"} user=${idOf(input.user) || "-"} site=${idOf(input.memberSite) || "-"} role=${idOf(input.role?._id) || "-"} roleSite=${idOf(input.role?.site)}`
3402
+ message: `cross-site-role mode=${mode} ${granted ? "granted" : "refused"} where=${input.where} member=${idOf2(input.member) || "-"} user=${idOf2(input.user) || "-"} site=${idOf2(input.memberSite) || "-"} role=${idOf2(input.role?._id) || "-"} roleSite=${idOf2(input.role?.site)}`
3356
3403
  });
3357
3404
  }
3358
3405
  return granted;
@@ -3363,7 +3410,7 @@ function crossSiteRoleRefusal(roleName, roleSiteName) {
3363
3410
  return `${role} belongs to ${site}. Choose a role for this site, or an org-wide role.`;
3364
3411
  }
3365
3412
  async function requireRoleFitsSite(roleId, siteId) {
3366
- const id = idOf(roleId);
3413
+ const id = idOf2(roleId);
3367
3414
  if (!id || !ObjectId13.isValid(id))
3368
3415
  return;
3369
3416
  const db2 = useAtlas7.getDb();
@@ -3372,7 +3419,7 @@ async function requireRoleFitsSite(roleId, siteId) {
3372
3419
  const role = await db2.collection("roles").findOne({ _id: new ObjectId13(id) }, { projection: { name: 1, site: 1 } });
3373
3420
  if (!isCrossSiteRole(role, siteId))
3374
3421
  return;
3375
- const site = ObjectId13.isValid(idOf(role?.site)) ? await db2.collection("sites").findOne({ _id: new ObjectId13(idOf(role?.site)) }, { projection: { name: 1 } }) : null;
3422
+ const site = ObjectId13.isValid(idOf2(role?.site)) ? await db2.collection("sites").findOne({ _id: new ObjectId13(idOf2(role?.site)) }, { projection: { name: 1 } }) : null;
3376
3423
  throw new BadRequestError13(crossSiteRoleRefusal(role?.name, site?.name));
3377
3424
  }
3378
3425
  async function otherSiteRoleClauses(roles, org) {
@@ -3380,7 +3427,7 @@ async function otherSiteRoleClauses(roles, org) {
3380
3427
  { ...org ? { org } : { org: { $nin: ["", null] } }, site: { $nin: ["", null] }, status: "active" },
3381
3428
  { projection: { site: 1, org: 1 } }
3382
3429
  ).toArray();
3383
- const both3 = (v) => ObjectId13.isValid(idOf(v)) ? [new ObjectId13(idOf(v)), idOf(v)] : [v];
3430
+ const both3 = (v) => ObjectId13.isValid(idOf2(v)) ? [new ObjectId13(idOf2(v)), idOf2(v)] : [v];
3384
3431
  const clauses = (list ?? []).map((r) => ({
3385
3432
  role: r._id,
3386
3433
  org: { $in: both3(r.org) },
@@ -3563,9 +3610,12 @@ function useMemberRepo() {
3563
3610
  } catch (error) {
3564
3611
  throw new BadRequestError14("Invalid user ID format.");
3565
3612
  }
3613
+ const account = await db2?.collection("users").findOne({ _id: user }, { projection: { defaultOrg: 1 } }).catch(() => null);
3614
+ const defaultOrg = String(account?.defaultOrg ?? "");
3566
3615
  const cacheKey = makeCacheKey5(namespace_collection3, {
3567
3616
  user: user.toString(),
3568
- type
3617
+ type,
3618
+ defaultOrg
3569
3619
  });
3570
3620
  const cachedData = await getCache(cacheKey);
3571
3621
  if (cachedData) {
@@ -3573,7 +3623,10 @@ function useMemberRepo() {
3573
3623
  return cachedData;
3574
3624
  }
3575
3625
  try {
3576
- const data = await collection.findOne({ user, type: appTypeQuery(type) });
3626
+ const data = preferWorkingMembership(
3627
+ await collection.find({ user, type: appTypeQuery(type) }).toArray(),
3628
+ defaultOrg
3629
+ );
3577
3630
  if (!data) {
3578
3631
  throw new NotFoundError5("Member not found.");
3579
3632
  }
@@ -4036,7 +4089,12 @@ function useMemberRepo() {
4036
4089
  const query2 = {
4037
4090
  user,
4038
4091
  org: { $nin: [null, ""] },
4039
- type: appTypeQuery(type)
4092
+ type: appTypeQuery(type),
4093
+ // The organisation switcher. A membership that was taken away (Repair
4094
+ // sets it inactive, removal deletes it) must not keep the organisation
4095
+ // on the person's list: latitude.sec@ still saw JLL Singapore beside its
4096
+ // own company after the repair (owner report 2026-09-30).
4097
+ status: { $nin: ["inactive", "deleted"] }
4040
4098
  };
4041
4099
  const cacheOptions = {
4042
4100
  page: page2,
@@ -10541,7 +10599,7 @@ function enforcedModuleList(stored, save) {
10541
10599
  return NO_LIST;
10542
10600
  return { list, since: typeof save?.createdAt === "string" ? save.createdAt : "" };
10543
10601
  }
10544
- var idOf2 = (v) => v == null ? "" : String(v?._id ?? v).toLowerCase();
10602
+ var idOf3 = (v) => v == null ? "" : String(v?._id ?? v).toLowerCase();
10545
10603
  function deniedForMembership({
10546
10604
  membership,
10547
10605
  org,
@@ -10549,12 +10607,12 @@ function deniedForMembership({
10549
10607
  site,
10550
10608
  siteSave
10551
10609
  }) {
10552
- const memberOrg = idOf2(membership?.org);
10610
+ const memberOrg = idOf3(membership?.org);
10553
10611
  if (!membership || membership.type === "resident" || !memberOrg) {
10554
10612
  return { denied: [], since: "" };
10555
10613
  }
10556
10614
  const orgTier = enforcedModuleList(org?.modules, orgSave);
10557
- const siteTier = site && idOf2(site.orgId) === memberOrg ? enforcedModuleList(site.metadata?.modules, siteSave) : NO_LIST;
10615
+ const siteTier = site && idOf3(site.orgId) === memberOrg ? enforcedModuleList(site.metadata?.modules, siteSave) : NO_LIST;
10558
10616
  const denied = deniedModules(orgTier.list, siteTier.list);
10559
10617
  if (!denied.length)
10560
10618
  return { denied: [], since: "" };
@@ -11128,46 +11186,6 @@ function staffMayBypass(actor, grant = CROSS_CLIENT_GRANT) {
11128
11186
  return consoleRoleAllows(actor.staffPermissions, grant.resource, grant.action);
11129
11187
  }
11130
11188
 
11131
- // src/utils/member-lookup.util.ts
11132
- var idOf3 = (v) => v == null ? "" : String(v?._id ?? v).toLowerCase();
11133
- function isLiveMembership(m) {
11134
- return m.status !== "deleted" && !m.deletedAt;
11135
- }
11136
- function pickSiteMembership(rows, type, site, org = "") {
11137
- site = site.toLowerCase();
11138
- org = org.toLowerCase();
11139
- if (!site)
11140
- return null;
11141
- const live2 = rows.filter(
11142
- (m) => sameAppType(m.type, type) && isLiveMembership(m) && (!org || idOf3(m.org) === org)
11143
- );
11144
- const atSite = live2.find((m) => idOf3(m.siteId) === site);
11145
- if (atSite)
11146
- return atSite;
11147
- if (!org)
11148
- return null;
11149
- return live2.find((m) => !idOf3(m.siteId)) ?? live2[0] ?? null;
11150
- }
11151
- function pickLookupMembership(rows, type, site = "", org = "") {
11152
- const list = Array.isArray(rows) ? rows : [];
11153
- const atSite = site ? pickSiteMembership(list, type, site, org) : null;
11154
- if (atSite)
11155
- return atSite;
11156
- const inOrg = org ? list.find((m) => sameAppType(m.type, type) && idOf3(m.org) === org.toLowerCase()) : void 0;
11157
- if (inOrg && isLiveMembership(inOrg))
11158
- return inOrg;
11159
- return list.find((m) => sameAppType(m.type, type)) ?? null;
11160
- }
11161
- function memberListSiteScope(memberships, org) {
11162
- const inOrg = (memberships ?? []).filter((m) => idOf3(m.org) === idOf3(org));
11163
- const here = inOrg.filter((m) => m.type !== "resident");
11164
- if (!inOrg.length)
11165
- return null;
11166
- if (here.some((m) => !idOf3(m.siteId) || m.orgLevelRole))
11167
- return null;
11168
- return [...new Set(here.map((m) => idOf3(m.siteId)))];
11169
- }
11170
-
11171
11189
  // src/services/module-gate.service.ts
11172
11190
  var idOf4 = (v) => v == null ? "" : String(v?._id ?? v).toLowerCase();
11173
11191
  var isId = (v) => /^[0-9a-f]{24}$/i.test(v);
@@ -24560,7 +24578,7 @@ function useServiceProviderInviteService() {
24560
24578
  );
24561
24579
  }
24562
24580
  const existing = await getByCreatorAndNature(actor.id, nature).catch(() => null);
24563
- if (existing) {
24581
+ if (existing && String(existing.invitedFrom ?? "") !== String(invite._id)) {
24564
24582
  throw new BadRequestError47(
24565
24583
  `You already have a ${serviceTypeLabel(nature)} company on iService365 (${existing.name}). Accept the invitation from that company instead.`
24566
24584
  );
@@ -24591,12 +24609,21 @@ function useServiceProviderInviteService() {
24591
24609
  country
24592
24610
  }) {
24593
24611
  const inviteeId = String(user?._id ?? "");
24594
- const name = sanitizeCompanyName(companyName) || sanitizeCompanyName(invite.metadata?.name) || sanitizeCompanyName(user?.name);
24612
+ let name = sanitizeCompanyName(companyName) || sanitizeCompanyName(invite.metadata?.name) || sanitizeCompanyName(user?.name);
24595
24613
  if (!name)
24596
24614
  throw new BadRequestError47("Enter your company's name.");
24597
24615
  const email = String(invite.email ?? "").trim().toLowerCase();
24598
24616
  const actor = { id: inviteeId };
24599
- const orgId = String(
24617
+ const db2 = useAtlas38.getDb();
24618
+ const actorIds = [actor.id, ...ObjectId56.isValid(actor.id) ? [new ObjectId56(actor.id)] : []];
24619
+ const made = db2 ? await db2.collection("organizations").findOne({
24620
+ invitedFrom: { $in: [String(invite._id), invite._id] },
24621
+ createdBy: { $in: actorIds },
24622
+ status: { $ne: "deleted" }
24623
+ }) : null;
24624
+ if (made)
24625
+ name = String(made.name ?? name);
24626
+ const orgId = made ? String(made._id) : String(
24600
24627
  await addOrg({
24601
24628
  name,
24602
24629
  type: nature,
@@ -24608,8 +24635,17 @@ function useServiceProviderInviteService() {
24608
24635
  invitedFrom: String(invite._id)
24609
24636
  })
24610
24637
  );
24611
- const roles = await seedDefaultOrgRoles(useRoleRepo().addRole, orgId, nature);
24612
24638
  const appType = serviceAppType(nature);
24639
+ const owners = made && db2 ? await db2.collection("roles").find({
24640
+ org: { $in: [new ObjectId56(orgId), orgId] },
24641
+ name: "owner",
24642
+ status: { $ne: "deleted" }
24643
+ }).toArray() : [];
24644
+ const ownerRole = (type) => {
24645
+ const r = owners.find((x) => x.type === type);
24646
+ return r ? { id: String(r._id), type, name: "owner" } : null;
24647
+ };
24648
+ const roles = ownerRole("organization") && ownerRole(appType) ? [ownerRole("organization"), ownerRole(appType)] : await seedDefaultOrgRoles(useRoleRepo().addRole, orgId, nature);
24613
24649
  const orgOwner = roles.find((r) => r.type === "organization" && r.name === "owner");
24614
24650
  const appOwner = roles.find((r) => r.type === appType && r.name === "owner");
24615
24651
  if (!orgOwner || !appOwner) {
@@ -24632,8 +24668,18 @@ function useServiceProviderInviteService() {
24632
24668
  siteName: "",
24633
24669
  onboardingRequired: false
24634
24670
  };
24635
- await addMember({ ...base, role: orgOwner.id, type: "organization" });
24636
- await addMember({ ...base, role: appOwner.id, type: appType });
24671
+ const hasOwnerRow = async (type) => !!made && !!await db2?.collection("members").findOne({
24672
+ user: { $in: actorIds },
24673
+ org: { $in: [new ObjectId56(orgId), orgId] },
24674
+ type,
24675
+ status: "active"
24676
+ });
24677
+ if (!await hasOwnerRow("organization")) {
24678
+ await addMember({ ...base, role: orgOwner.id, type: "organization" });
24679
+ }
24680
+ if (!await hasOwnerRow(appType)) {
24681
+ await addMember({ ...base, role: appOwner.id, type: appType });
24682
+ }
24637
24683
  await useUserRepo().updateUserFieldById({ _id: actor.id, field: "defaultOrg", value: orgId }).catch(() => void 0);
24638
24684
  logger36.log({
24639
24685
  level: "info",
@@ -24689,10 +24735,60 @@ function useServiceProviderInviteService() {
24689
24735
  const last = [...history].reverse().find((e) => ["wrong-join-repaired", "wrong-join-undone"].includes(e?.action));
24690
24736
  return last?.action === "wrong-join-repaired" ? last : null;
24691
24737
  }
24738
+ async function leftoverRoles(invite, senderOrg, user) {
24739
+ const db2 = useAtlas38.getDb();
24740
+ if (!db2 || !user?._id || !ObjectId56.isValid(senderOrg))
24741
+ return [];
24742
+ const since = new Date(String(invite.createdAt ?? 0)).getTime();
24743
+ const rows = await db2.collection("members").find({
24744
+ user: { $in: [user._id, String(user._id)] },
24745
+ org: { $in: [new ObjectId56(senderOrg), senderOrg] }
24746
+ }).project({ role: 1 }).toArray();
24747
+ const roleIds = [
24748
+ ...new Set(
24749
+ rows.map((m) => m.role?.toString?.() ?? "").filter((r) => ObjectId56.isValid(r))
24750
+ )
24751
+ ].map((r) => new ObjectId56(r));
24752
+ if (!roleIds.length)
24753
+ return [];
24754
+ const roles = await db2.collection("roles").find({
24755
+ _id: { $in: roleIds },
24756
+ org: { $in: [new ObjectId56(senderOrg), senderOrg] },
24757
+ status: { $ne: "deleted" }
24758
+ }).project({ name: 1, permissions: 1, createdAt: 1 }).toArray();
24759
+ const out = [];
24760
+ for (const role of roles) {
24761
+ if (!(Array.isArray(role.permissions) && role.permissions.includes("*")))
24762
+ continue;
24763
+ if (role.createdAt && Number.isFinite(since) && new Date(role.createdAt).getTime() < since)
24764
+ continue;
24765
+ const inUse = await db2.collection("members").countDocuments({
24766
+ role: { $in: [role._id, role._id.toString()] },
24767
+ status: "active"
24768
+ });
24769
+ if (inUse)
24770
+ continue;
24771
+ out.push({ _id: role._id.toString(), name: String(role.name ?? "") });
24772
+ }
24773
+ return out;
24774
+ }
24775
+ async function setRoleStatus(ids2, status) {
24776
+ const db2 = useAtlas38.getDb();
24777
+ const valid = ids2.filter((r) => ObjectId56.isValid(r)).map((r) => new ObjectId56(r));
24778
+ if (!db2 || !valid.length)
24779
+ return;
24780
+ const now = (/* @__PURE__ */ new Date()).toISOString();
24781
+ await db2.collection("roles").updateMany(
24782
+ { _id: { $in: valid } },
24783
+ { $set: { status, deletedAt: status === "deleted" ? now : "", updatedAt: now } }
24784
+ );
24785
+ await useCache21("roles").delNamespace().catch(() => void 0);
24786
+ }
24692
24787
  async function wrongJoinPreview({ id, userId }) {
24693
24788
  const { invite, senderOrg, user } = await wrongJoinContext(id, userId);
24694
24789
  const org = await getOrgById(senderOrg).catch(() => null);
24695
24790
  const memberships = await wrongJoinRows(invite, senderOrg, user);
24791
+ const roles = await leftoverRoles(invite, senderOrg, user);
24696
24792
  const repaired = lastRepair(invite);
24697
24793
  return {
24698
24794
  invitationId: id,
@@ -24701,6 +24797,8 @@ function useServiceProviderInviteService() {
24701
24797
  senderOrgId: senderOrg,
24702
24798
  senderOrgName: String(org?.name ?? ""),
24703
24799
  memberships,
24800
+ // Left in the sender's role list by the old sign-up; Repair retires them.
24801
+ leftoverRoles: roles,
24704
24802
  defaultOrgIsSender: String(user?.defaultOrg ?? "") === senderOrg,
24705
24803
  repaired: repaired ? { at: repaired.at, by: repaired.byName, memberIds: repaired.memberIds ?? [] } : null
24706
24804
  };
@@ -24709,15 +24807,17 @@ function useServiceProviderInviteService() {
24709
24807
  const { actor, invite, senderOrg, user } = await wrongJoinContext(id, userId);
24710
24808
  const rows = await wrongJoinRows(invite, senderOrg, user);
24711
24809
  const defaultOrgIsSender = !!user?._id && String(user?.defaultOrg ?? "") === senderOrg;
24712
- if (!rows.length && !defaultOrgIsSender) {
24810
+ const { updateMemberStatus } = useMemberRepo();
24811
+ for (const row of rows)
24812
+ await updateMemberStatus(row._id, { status: "inactive" });
24813
+ const roles = await leftoverRoles(invite, senderOrg, user);
24814
+ if (!rows.length && !defaultOrgIsSender && !roles.length) {
24713
24815
  return {
24714
24816
  message: "Nothing to repair: this account is not in the sender's organisation.",
24715
24817
  changed: 0
24716
24818
  };
24717
24819
  }
24718
- const { updateMemberStatus } = useMemberRepo();
24719
- for (const row of rows)
24720
- await updateMemberStatus(row._id, { status: "inactive" });
24820
+ await setRoleStatus(roles.map((r) => r._id), "deleted");
24721
24821
  if (defaultOrgIsSender)
24722
24822
  await setDefaultOrg(String(user._id), "");
24723
24823
  await _transition({
@@ -24726,6 +24826,7 @@ function useServiceProviderInviteService() {
24726
24826
  event: {
24727
24827
  ...event("wrong-join-repaired", actor),
24728
24828
  memberIds: rows.map((row) => row._id),
24829
+ roleIds: roles.map((r) => r._id),
24729
24830
  ...defaultOrgIsSender ? { defaultOrgWas: senderOrg } : {}
24730
24831
  }
24731
24832
  });
@@ -24734,8 +24835,8 @@ function useServiceProviderInviteService() {
24734
24835
  message: `[sp-invite] wrong-join repaired invite=${id} memberships=${rows.length} by=${actor.id}`
24735
24836
  });
24736
24837
  return {
24737
- message: `Repaired: ${rows.length} membership${rows.length === 1 ? "" : "s"} in the sender's organisation set inactive. Undo is available.`,
24738
- changed: rows.length
24838
+ message: `Repaired: ${rows.length} membership${rows.length === 1 ? "" : "s"} in the sender's organisation set inactive` + (roles.length ? `, ${roles.length} unused full-access role${roles.length === 1 ? "" : "s"} removed from its role list` : "") + ". Undo is available.",
24839
+ changed: rows.length + roles.length
24739
24840
  };
24740
24841
  }
24741
24842
  async function undoWrongJoin({ id, userId }) {
@@ -24747,6 +24848,7 @@ function useServiceProviderInviteService() {
24747
24848
  const ids2 = (repaired.memberIds ?? []).filter((m) => ObjectId56.isValid(m));
24748
24849
  for (const m of ids2)
24749
24850
  await updateMemberStatus(m, { status: "active" }).catch(() => 0);
24851
+ await setRoleStatus(repaired.roleIds ?? [], "active");
24750
24852
  const { user } = await wrongJoinContext(id, userId);
24751
24853
  if (repaired.defaultOrgWas && user?._id && !String(user.defaultOrg ?? "")) {
24752
24854
  await setDefaultOrg(String(user._id), String(repaired.defaultOrgWas));