fix(invites): show email invites in space settings pending list
listSpaceInvites now queries both space_invites and identity_invites tables, merging results so email-based invites (via /invite endpoint) appear in the Pending Invites section. revokeSpaceInvite also falls through to identity_invites if not found in space_invites. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
4a43ecdee0
commit
858457c056
|
|
@ -1067,12 +1067,28 @@ export async function getSpaceInviteByToken(token: string): Promise<StoredSpaceI
|
|||
}
|
||||
|
||||
export async function listSpaceInvites(spaceSlug: string): Promise<StoredSpaceInvite[]> {
|
||||
const rows = await sql`
|
||||
SELECT * FROM space_invites
|
||||
WHERE space_slug = ${spaceSlug}
|
||||
ORDER BY created_at DESC
|
||||
`;
|
||||
return Promise.all(rows.map(rowToInvite));
|
||||
const [spaceRows, identityRows] = await Promise.all([
|
||||
sql`SELECT * FROM space_invites WHERE space_slug = ${spaceSlug} ORDER BY created_at DESC`,
|
||||
sql`SELECT * FROM identity_invites WHERE space_slug = ${spaceSlug} ORDER BY created_at DESC`,
|
||||
]);
|
||||
const spaceInvites = await Promise.all(spaceRows.map(rowToInvite));
|
||||
const identityInvites = await Promise.all(identityRows.map(async (row: any) => {
|
||||
const emailDecrypted = await decryptField(row.email_enc);
|
||||
return {
|
||||
id: row.id,
|
||||
spaceSlug: row.space_slug,
|
||||
email: emailDecrypted ?? row.email ?? null,
|
||||
role: row.space_role || 'member',
|
||||
token: row.token,
|
||||
invitedBy: row.invited_by_user_id,
|
||||
status: row.status === 'claimed' ? 'accepted' : row.status,
|
||||
createdAt: new Date(row.created_at).getTime(),
|
||||
expiresAt: new Date(row.expires_at).getTime(),
|
||||
acceptedAt: row.claimed_at ? new Date(row.claimed_at).getTime() : null,
|
||||
acceptedByDid: row.claimed_by_user_id || null,
|
||||
} as StoredSpaceInvite;
|
||||
}));
|
||||
return [...spaceInvites, ...identityInvites].sort((a, b) => b.createdAt - a.createdAt);
|
||||
}
|
||||
|
||||
export async function acceptSpaceInvite(token: string, acceptedByDid: string): Promise<StoredSpaceInvite | null> {
|
||||
|
|
@ -1091,7 +1107,13 @@ export async function revokeSpaceInvite(id: string, spaceSlug: string): Promise<
|
|||
UPDATE space_invites SET status = 'revoked'
|
||||
WHERE id = ${id} AND space_slug = ${spaceSlug} AND status = 'pending'
|
||||
`;
|
||||
return result.count > 0;
|
||||
if (result.count > 0) return true;
|
||||
// Also check identity_invites (email invites with space_slug)
|
||||
const result2 = await sql`
|
||||
UPDATE identity_invites SET status = 'revoked'
|
||||
WHERE id = ${id} AND space_slug = ${spaceSlug} AND status = 'pending'
|
||||
`;
|
||||
return result2.count > 0;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
|
|
|
|||
Loading…
Reference in New Issue