fix: exempt existing DM members from friend check in createGroup
When converting a 1-on-1 DM to a group, the existing DM partner was incorrectly required to be your friend. DMs don't require friendship, so this check was over-strict. Added fromDmChannelId parameter to createGroup — existing members of the source DM are exempt from the friendship validation.
This commit is contained in:
@@ -487,7 +487,7 @@ export async function dmRoutes(app: FastifyInstance): Promise<void> {
|
|||||||
app.post<{ Body: CreateGroupDmRequest }>('/api/dm/group', {
|
app.post<{ Body: CreateGroupDmRequest }>('/api/dm/group', {
|
||||||
preHandler: authenticate,
|
preHandler: authenticate,
|
||||||
}, async (request, reply) => {
|
}, async (request, reply) => {
|
||||||
const { users: userIdentities } = request.body;
|
const { users: userIdentities, fromDmChannelId } = request.body;
|
||||||
|
|
||||||
// Validate input is a non-empty array of at least 2 identity objects
|
// Validate input is a non-empty array of at least 2 identity objects
|
||||||
if (!Array.isArray(userIdentities) || userIdentities.length < 2) {
|
if (!Array.isArray(userIdentities) || userIdentities.length < 2) {
|
||||||
@@ -547,8 +547,29 @@ export async function dmRoutes(app: FastifyInstance): Promise<void> {
|
|||||||
return reply.code(400).send({ error: 'Do not include yourself — you are added automatically', statusCode: 400 });
|
return reply.code(400).send({ error: 'Do not include yourself — you are added automatically', statusCode: 400 });
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate all target users are friends with the caller
|
// When converting a 1-on-1 DM to a group, existing DM members are exempt
|
||||||
|
// from the friendship check (DMs don't require friendship).
|
||||||
|
const exemptUserIds = new Set<string>();
|
||||||
|
if (fromDmChannelId) {
|
||||||
|
const sourceDm = db.select().from(schema.dmChannels).where(
|
||||||
|
and(eq(schema.dmChannels.id, fromDmChannelId), isNull(schema.dmChannels.deletedAt)),
|
||||||
|
).get();
|
||||||
|
if (sourceDm && !sourceDm.ownerId) {
|
||||||
|
// Only exempt members from 1-on-1 DMs (ownerId is null)
|
||||||
|
if (isDmMember(fromDmChannelId, request.userId)) {
|
||||||
|
const members = db.select().from(schema.dmMembers)
|
||||||
|
.where(eq(schema.dmMembers.dmChannelId, fromDmChannelId)).all();
|
||||||
|
for (const m of members) {
|
||||||
|
exemptUserIds.add(m.userId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate all target users are friends with the caller (exempt existing DM members)
|
||||||
for (const targetUser of targetUsers) {
|
for (const targetUser of targetUsers) {
|
||||||
|
if (exemptUserIds.has(targetUser.id)) continue;
|
||||||
|
|
||||||
const friendship = db.select().from(schema.friends).where(
|
const friendship = db.select().from(schema.friends).where(
|
||||||
or(
|
or(
|
||||||
and(eq(schema.friends.userId, request.userId), eq(schema.friends.friendId, targetUser.id)),
|
and(eq(schema.friends.userId, request.userId), eq(schema.friends.friendId, targetUser.id)),
|
||||||
|
|||||||
@@ -524,6 +524,7 @@ export interface GroupDmUserIdentity {
|
|||||||
|
|
||||||
export interface CreateGroupDmRequest {
|
export interface CreateGroupDmRequest {
|
||||||
users: GroupDmUserIdentity[];
|
users: GroupDmUserIdentity[];
|
||||||
|
fromDmChannelId?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface CreateDmMessageRequest {
|
export interface CreateDmMessageRequest {
|
||||||
|
|||||||
@@ -107,7 +107,7 @@ export function AddDmMemberModal() {
|
|||||||
homeInstance: f.homeInstance,
|
homeInstance: f.homeInstance,
|
||||||
})),
|
})),
|
||||||
];
|
];
|
||||||
const newChannel = await api.dm.createGroup({ users });
|
const newChannel = await api.dm.createGroup({ users, fromDmChannelId: dmChannelId });
|
||||||
addDmChannel(newChannel);
|
addDmChannel(newChannel);
|
||||||
closeModal();
|
closeModal();
|
||||||
navigate(`/channels/@me/${newChannel.id}`);
|
navigate(`/channels/@me/${newChannel.id}`);
|
||||||
|
|||||||
Reference in New Issue
Block a user