fix(server): canonicalize spaceInstanceOrigin before storing payload
Empty-string (local) origin is now stored as the absolute home origin so relayed DM space-invite cards carry the correct value to remote recipients instead of resolving against the wrong instance.
This commit is contained in:
@@ -248,6 +248,11 @@ describe('POST /api/dm/space-invite', () => {
|
|||||||
expect(parsed.snapshot.avatarColor).toBe('mint');
|
expect(parsed.snapshot.avatarColor).toBe('mint');
|
||||||
expect(parsed.snapshot.description).toBe('desc');
|
expect(parsed.snapshot.description).toBe('desc');
|
||||||
expect(parsed.snapshot.instanceName).toBe('Backspace');
|
expect(parsed.snapshot.instanceName).toBe('Backspace');
|
||||||
|
|
||||||
|
// Canonicalization: empty origin (local) must be stored as the absolute home
|
||||||
|
// origin so relayed messages carry the correct value to remote recipients.
|
||||||
|
expect(parsed.spaceInstanceOrigin).toBe('https://local.test');
|
||||||
|
expect(parsed.spaceInstanceOrigin).not.toBe('');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('reuses an existing 1-on-1 DM rather than creating a new one', async () => {
|
it('reuses an existing 1-on-1 DM rather than creating a new one', async () => {
|
||||||
@@ -386,4 +391,35 @@ describe('POST /api/dm/space-invite', () => {
|
|||||||
expect(fetchSpaceInviteSnapshot).toHaveBeenCalledWith('https://remote.example', 'abc');
|
expect(fetchSpaceInviteSnapshot).toHaveBeenCalledWith('https://remote.example', 'abc');
|
||||||
expect(getLocalInviteSnapshot).not.toHaveBeenCalled();
|
expect(getLocalInviteSnapshot).not.toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('preserves explicit remote spaceInstanceOrigin in stored payload', async () => {
|
||||||
|
(fetchSpaceInviteSnapshot as unknown as ReturnType<typeof vi.fn>).mockResolvedValueOnce({
|
||||||
|
spaceId: 'S1',
|
||||||
|
spaceName: 'Remote',
|
||||||
|
description: null,
|
||||||
|
icon: null,
|
||||||
|
avatarColor: null,
|
||||||
|
memberCount: 5,
|
||||||
|
instanceName: 'OtherHost',
|
||||||
|
});
|
||||||
|
|
||||||
|
const res = await app.inject({
|
||||||
|
method: 'POST',
|
||||||
|
url: '/api/dm/space-invite',
|
||||||
|
payload: {
|
||||||
|
target: { userId: 'bob' },
|
||||||
|
spaceId: 'S1',
|
||||||
|
spaceInstanceOrigin: 'https://other.example',
|
||||||
|
inviteCode: 'abc',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
expect(res.statusCode).toBe(200);
|
||||||
|
const body = JSON.parse(res.body) as { messageId: string };
|
||||||
|
const stored = testDb.select()
|
||||||
|
.from(schema.dmMessages)
|
||||||
|
.where(eq(schema.dmMessages.id, body.messageId))
|
||||||
|
.get();
|
||||||
|
const parsed = JSON.parse(stored!.content!);
|
||||||
|
expect(parsed.spaceInstanceOrigin).toBe('https://other.example');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1757,7 +1757,7 @@ export async function dmRoutes(app: FastifyInstance): Promise<void> {
|
|||||||
const payload: SpaceInviteSystemPayload = {
|
const payload: SpaceInviteSystemPayload = {
|
||||||
event: 'space_invite',
|
event: 'space_invite',
|
||||||
spaceId: body.spaceId,
|
spaceId: body.spaceId,
|
||||||
spaceInstanceOrigin: body.spaceInstanceOrigin,
|
spaceInstanceOrigin: spaceOrigin,
|
||||||
inviteCode: body.inviteCode,
|
inviteCode: body.inviteCode,
|
||||||
snapshot: {
|
snapshot: {
|
||||||
spaceName: snapshot.spaceName,
|
spaceName: snapshot.spaceName,
|
||||||
|
|||||||
Reference in New Issue
Block a user