mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-09-07 21:15:41 +00:00
feat(chat): join users to rooms on sign-in
This commit is contained in:
@@ -67,7 +67,8 @@ export class ChatProvisioningService {
|
||||
}
|
||||
}
|
||||
|
||||
private async currentHolders(): Promise<PositionHolder[]> {
|
||||
/** Every current holder in the unit, or just one person's rows when `userId` is given. */
|
||||
private async currentHolders(userId?: string): Promise<PositionHolder[]> {
|
||||
return this.dataSource.query(
|
||||
`SELECT p.key AS "positionKey",
|
||||
COALESCE(p.name->>'en', p.key) AS "positionName",
|
||||
@@ -82,11 +83,53 @@ export class ChatProvisioningService {
|
||||
WHERE ep.is_current = true
|
||||
AND e.is_current = true
|
||||
AND o.key = $1
|
||||
AND u.key = $2`,
|
||||
[ORG_KEY, UNIT_KEY],
|
||||
AND u.key = $2
|
||||
${userId ? 'AND e.user_id = $3' : ''}`,
|
||||
userId ? [ORG_KEY, UNIT_KEY, userId] : [ORG_KEY, UNIT_KEY],
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Put one person in their rooms right now.
|
||||
*
|
||||
* {@link reconcile} is nightly, so without this a new employee's first
|
||||
* sign-in shows an empty client until 3AM — the SSO handoff creates their
|
||||
* account but joins them to nothing. Called on every /chat/sso, so it is
|
||||
* scoped to the one user (a full reconcile per click would be a room-count
|
||||
* multiple of Matrix calls) and every step is get-or-create.
|
||||
*
|
||||
* Someone holding no current position in the unit joins nothing, by the same
|
||||
* rule the reconcile uses — chat membership follows the org tree.
|
||||
*/
|
||||
async joinUserRooms(userId: string, displayName: string): Promise<number> {
|
||||
const positions = await this.currentHolders(userId);
|
||||
if (positions.length === 0) return 0;
|
||||
|
||||
const mxid = this.matrix.mxidFor(userId, displayName);
|
||||
// The JWT login auto-registers too, but that happens after this runs and
|
||||
// the admin join API 404s on an account that does not exist yet.
|
||||
await this.matrix.ensureUser(mxid, displayName);
|
||||
|
||||
const spaceId = await this.matrix.ensureRoom(SPACE_ALIAS, 'EDR Freight', {
|
||||
isSpace: true,
|
||||
});
|
||||
const generalRoomId = await this.matrix.ensureRoom(GENERAL_ALIAS, 'General', {
|
||||
parentSpaceId: spaceId,
|
||||
});
|
||||
await this.matrix.ensureJoined(generalRoomId, mxid);
|
||||
|
||||
for (const position of positions) {
|
||||
const roomId = await this.matrix.ensureRoom(
|
||||
`dept-${position.positionKey}`,
|
||||
position.positionName,
|
||||
{ parentSpaceId: spaceId },
|
||||
);
|
||||
await this.matrix.ensureJoined(roomId, mxid);
|
||||
}
|
||||
|
||||
return positions.length + 1;
|
||||
}
|
||||
|
||||
/** Force-joins additions, kicks+deactivates users no longer entitled anywhere. */
|
||||
private async syncMembership(
|
||||
roomId: string,
|
||||
@@ -99,7 +142,7 @@ export class ChatProvisioningService {
|
||||
let joined = 0;
|
||||
for (const userId of desiredUserIds) {
|
||||
if (!currentSet.has(userId)) {
|
||||
await this.matrix.forceJoin(roomId, userId);
|
||||
await this.matrix.ensureJoined(roomId, userId);
|
||||
joined += 1;
|
||||
}
|
||||
}
|
||||
@@ -126,14 +169,16 @@ export class ChatProvisioningService {
|
||||
parentSpaceId: spaceId,
|
||||
});
|
||||
|
||||
const allUserIds = new Set(holders.map((h) => this.matrix.mxid(h.userId)));
|
||||
const allUserIds = new Set(
|
||||
holders.map((h) => this.matrix.mxidFor(h.userId, h.userName)),
|
||||
);
|
||||
|
||||
// Accounts are otherwise only created lazily on first JWT login (see
|
||||
// ChatSsoService) — force-joining someone who has never clicked "Chat"
|
||||
// yet 404s ("User not found") without this.
|
||||
const seenUserIds = new Set<string>();
|
||||
for (const h of holders) {
|
||||
const mxid = this.matrix.mxid(h.userId);
|
||||
const mxid = this.matrix.mxidFor(h.userId, h.userName);
|
||||
if (seenUserIds.has(mxid)) continue;
|
||||
seenUserIds.add(mxid);
|
||||
await this.matrix.ensureUser(mxid, h.userName);
|
||||
@@ -158,7 +203,7 @@ export class ChatProvisioningService {
|
||||
name: h.positionName,
|
||||
userIds: new Set<string>(),
|
||||
};
|
||||
entry.userIds.add(this.matrix.mxid(h.userId));
|
||||
entry.userIds.add(this.matrix.mxidFor(h.userId, h.userName));
|
||||
byPosition.set(h.positionKey, entry);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user