feat(federation): POST /api/dm accepts homeUserId+homeInstance for federated DM creation
This commit is contained in:
@@ -344,24 +344,31 @@ export async function dmRoutes(app: FastifyInstance): Promise<void> {
|
|||||||
app.post<{ Body: CreateDmRequest }>('/api/dm', {
|
app.post<{ Body: CreateDmRequest }>('/api/dm', {
|
||||||
preHandler: authenticate,
|
preHandler: authenticate,
|
||||||
}, async (request, reply) => {
|
}, async (request, reply) => {
|
||||||
const { userId } = request.body;
|
const { userId, homeUserId, homeInstance } = request.body;
|
||||||
|
|
||||||
if (!userId || typeof userId !== 'string') {
|
|
||||||
return reply.code(400).send({ error: 'userId is required', statusCode: 400 });
|
|
||||||
}
|
|
||||||
|
|
||||||
if (userId === request.userId) {
|
|
||||||
return reply.code(400).send({ error: 'Cannot create DM with yourself', statusCode: 400 });
|
|
||||||
}
|
|
||||||
|
|
||||||
const db = getDb();
|
const db = getDb();
|
||||||
|
let targetUser: typeof schema.users.$inferSelect | undefined;
|
||||||
|
|
||||||
|
if (homeUserId && homeInstance) {
|
||||||
|
// Federated identity: resolve or create a replicated user stub
|
||||||
|
targetUser = resolveOrCreateReplicatedUser(homeUserId, homeInstance, db);
|
||||||
|
} else if (userId && typeof userId === 'string') {
|
||||||
|
// Local ID: direct lookup (existing behavior)
|
||||||
|
targetUser = db.select().from(schema.users).where(eq(schema.users.id, userId)).get();
|
||||||
|
} else {
|
||||||
|
return reply.code(400).send({ error: 'userId or (homeUserId + homeInstance) is required', statusCode: 400 });
|
||||||
|
}
|
||||||
|
|
||||||
// Check if target user exists
|
|
||||||
const targetUser = db.select().from(schema.users).where(eq(schema.users.id, userId)).get();
|
|
||||||
if (!targetUser) {
|
if (!targetUser) {
|
||||||
return reply.code(404).send({ error: 'User not found', statusCode: 404 });
|
return reply.code(404).send({ error: 'User not found', statusCode: 404 });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const targetUserId = targetUser.id;
|
||||||
|
|
||||||
|
if (targetUserId === request.userId) {
|
||||||
|
return reply.code(400).send({ error: 'Cannot create DM with yourself', statusCode: 400 });
|
||||||
|
}
|
||||||
|
|
||||||
// Check if DM channel already exists between these two users
|
// Check if DM channel already exists between these two users
|
||||||
// (both have membership rows, regardless of closed state)
|
// (both have membership rows, regardless of closed state)
|
||||||
const myDms = db.select()
|
const myDms = db.select()
|
||||||
@@ -374,7 +381,7 @@ export async function dmRoutes(app: FastifyInstance): Promise<void> {
|
|||||||
.from(schema.dmMembers)
|
.from(schema.dmMembers)
|
||||||
.where(and(
|
.where(and(
|
||||||
eq(schema.dmMembers.dmChannelId, myDm.dmChannelId),
|
eq(schema.dmMembers.dmChannelId, myDm.dmChannelId),
|
||||||
eq(schema.dmMembers.userId, userId),
|
eq(schema.dmMembers.userId, targetUserId),
|
||||||
))
|
))
|
||||||
.get();
|
.get();
|
||||||
|
|
||||||
@@ -477,7 +484,7 @@ export async function dmRoutes(app: FastifyInstance): Promise<void> {
|
|||||||
|
|
||||||
tx.insert(schema.dmMembers).values({
|
tx.insert(schema.dmMembers).values({
|
||||||
dmChannelId,
|
dmChannelId,
|
||||||
userId,
|
userId: targetUserId,
|
||||||
}).run();
|
}).run();
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -495,7 +502,7 @@ export async function dmRoutes(app: FastifyInstance): Promise<void> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Broadcast dm_channel_created to the other user so their sidebar updates
|
// Broadcast dm_channel_created to the other user so their sidebar updates
|
||||||
connectionManager.sendToUser(userId, {
|
connectionManager.sendToUser(targetUserId, {
|
||||||
type: 'dm_channel_created',
|
type: 'dm_channel_created',
|
||||||
dmChannel: result,
|
dmChannel: result,
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user