feat: add Activity type system, DB migration, and self-only showActivity in sanitizeUser
- Add Activity, ActivityType, ActivityTimestamps, ActivityAssets types to shared types - Add activity_update client event and activities field on presence_update server event - Add userActivities to ready payload and showActivity to User/UpdateUserRequest - Create shared activities.ts with ACTIVITY_LIMITS, ACTIVITY_PRIORITY, getPrimaryActivity - Add show_activity column to users table (schema + migration) - Update sanitizeUser with isSelf parameter; only include showActivity for self - Fix .map(sanitizeUser) calls to use arrow wrapper to prevent index-as-boolean bug - Mark auth routes (register/login) as isSelf=true since they return own user data
This commit is contained in:
@@ -122,7 +122,7 @@ export async function authRoutes(app: FastifyInstance): Promise<void> {
|
||||
|
||||
const response: AuthResponse = {
|
||||
token,
|
||||
user: sanitizeUser(user),
|
||||
user: sanitizeUser(user, true),
|
||||
};
|
||||
|
||||
return reply.code(201).send(response);
|
||||
@@ -207,7 +207,7 @@ export async function authRoutes(app: FastifyInstance): Promise<void> {
|
||||
|
||||
const response: AuthResponse = {
|
||||
token,
|
||||
user: sanitizeUser({ ...user, status: 'online' }),
|
||||
user: sanitizeUser({ ...user, status: 'online' }, true),
|
||||
};
|
||||
|
||||
return reply.code(200).send(response);
|
||||
|
||||
@@ -192,7 +192,7 @@ export function broadcastDmMessage(dmChannelId: string, message: DmMessageWithUs
|
||||
id: dmChannel.id,
|
||||
ownerId: dmChannel.ownerId ?? null,
|
||||
createdAt: dmChannel.createdAt,
|
||||
members: users.map(sanitizeUser),
|
||||
members: users.map(u => sanitizeUser(u)),
|
||||
lastMessage: message,
|
||||
},
|
||||
});
|
||||
@@ -290,7 +290,7 @@ export async function dmRoutes(app: FastifyInstance): Promise<void> {
|
||||
const members = memberIds
|
||||
.map(id => userMap.get(id))
|
||||
.filter((u): u is NonNullable<typeof u> => u !== undefined)
|
||||
.map(sanitizeUser);
|
||||
.map(u => sanitizeUser(u));
|
||||
|
||||
const lastMsg = lastMessageMap.get(channelId) ?? null;
|
||||
|
||||
@@ -407,7 +407,7 @@ export async function dmRoutes(app: FastifyInstance): Promise<void> {
|
||||
id: dmChannel.id,
|
||||
ownerId: dmChannel.ownerId ?? null,
|
||||
createdAt: dmChannel.createdAt,
|
||||
members: users.map(sanitizeUser),
|
||||
members: users.map(u => sanitizeUser(u)),
|
||||
lastMessage: lastMsg ? {
|
||||
id: lastMsg.id,
|
||||
dmChannelId: lastMsg.dmChannelId,
|
||||
@@ -446,7 +446,7 @@ export async function dmRoutes(app: FastifyInstance): Promise<void> {
|
||||
const currentUserRow = db.select().from(schema.users).where(eq(schema.users.id, request.userId)).get();
|
||||
const members = [currentUserRow, targetUser]
|
||||
.filter((u): u is NonNullable<typeof u> => u !== undefined)
|
||||
.map(sanitizeUser);
|
||||
.map(u => sanitizeUser(u));
|
||||
|
||||
const result: DmChannel = {
|
||||
id: dmChannelId,
|
||||
@@ -600,7 +600,7 @@ export async function dmRoutes(app: FastifyInstance): Promise<void> {
|
||||
id: dmChannel.id,
|
||||
ownerId: dmChannel.ownerId ?? null,
|
||||
createdAt: dmChannel.createdAt,
|
||||
members: users.map(sanitizeUser),
|
||||
members: users.map(u => sanitizeUser(u)),
|
||||
lastMessage: lastMsg ? {
|
||||
id: lastMsg.id,
|
||||
dmChannelId: lastMsg.dmChannelId,
|
||||
|
||||
@@ -502,6 +502,6 @@ export async function socialRoutes(app: FastifyInstance): Promise<void> {
|
||||
.limit(10)
|
||||
.all();
|
||||
|
||||
return reply.code(200).send(users.map(sanitizeUser));
|
||||
return reply.code(200).send(users.map(u => sanitizeUser(u)));
|
||||
});
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ export async function userRoutes(app: FastifyInstance): Promise<void> {
|
||||
return reply.code(401).send({ error: 'This account has been deleted', statusCode: 401 });
|
||||
}
|
||||
|
||||
return reply.code(200).send(sanitizeUser(user));
|
||||
return reply.code(200).send(sanitizeUser(user, true));
|
||||
});
|
||||
|
||||
// POST /api/users/@me/verify-password — verify password matches current account
|
||||
@@ -328,7 +328,7 @@ export async function userRoutes(app: FastifyInstance): Promise<void> {
|
||||
const storedTs = currentUser.profileUpdatedAt ?? currentUser.createdAt;
|
||||
if (profileUpdatedAt < storedTs) {
|
||||
// Incoming data is older — return current state without updating
|
||||
return reply.code(200).send(sanitizeUser(currentUser));
|
||||
return reply.code(200).send(sanitizeUser(currentUser, true));
|
||||
}
|
||||
}
|
||||
(updateData as Record<string, unknown>).profileUpdatedAt = profileUpdatedAt;
|
||||
@@ -373,7 +373,7 @@ export async function userRoutes(app: FastifyInstance): Promise<void> {
|
||||
return reply.code(404).send({ error: 'User not found', statusCode: 404 });
|
||||
}
|
||||
|
||||
const sanitized = sanitizeUser(updatedUser);
|
||||
const sanitized = sanitizeUser(updatedUser, true);
|
||||
|
||||
// Broadcast presence update if status changed
|
||||
if (status !== undefined) {
|
||||
@@ -681,7 +681,7 @@ export async function userRoutes(app: FastifyInstance): Promise<void> {
|
||||
const mutualFriendIds = [...myFriendIds].filter((id) => targetFriendIds.has(id));
|
||||
|
||||
const mutualFriends = mutualFriendIds.length > 0
|
||||
? db.select().from(schema.users).where(inArray(schema.users.id, mutualFriendIds)).all().map(sanitizeUser)
|
||||
? db.select().from(schema.users).where(inArray(schema.users.id, mutualFriendIds)).all().map(u => sanitizeUser(u))
|
||||
: [];
|
||||
|
||||
// Mutual spaces: spaces both me and the target are members of
|
||||
|
||||
Reference in New Issue
Block a user