1.1.00
All checks were successful
Build and Release / build-and-release (push) Successful in 20m36s

This commit is contained in:
Bryan1029384756
2026-04-16 20:14:27 -05:00
parent 56a12fdf3e
commit 6813bb40dc
40 changed files with 2228 additions and 387 deletions

View File

@@ -123,11 +123,7 @@ export const createUserWithProfile = mutation({
return { error: "Invite expired" };
}
if (
invite.maxUses !== undefined &&
invite.maxUses !== null &&
invite.uses >= invite.maxUses
) {
if (invite.maxUses !== undefined && invite.uses >= invite.maxUses) {
return { error: "Invite max uses reached" };
}
@@ -240,8 +236,12 @@ export const getPublicKeys = query({
},
});
// Update user profile (aboutMe, avatar, customStatus)
export const updateProfile = mutation({
// Internal writer. Public entry point: `authActions.updateProfile`. The
// action layer verifies the caller controls `userId` via Ed25519
// signature before this runs; calling this from another mutation
// without that check would reintroduce the "anyone can change anyone's
// profile" vulnerability.
export const updateProfileInternal = internalMutation({
args: {
userId: v.id("userProfiles"),
displayName: v.optional(v.string()),
@@ -278,8 +278,8 @@ export const getMyJoinSoundUrl = query({
},
});
// Update user status
export const updateStatus = mutation({
// Internal writer. Public entry point: `authActions.updateStatus`.
export const updateStatusInternal = internalMutation({
args: {
userId: v.id("userProfiles"),
status: v.string(),
@@ -343,8 +343,51 @@ export const getUserForRecovery = internalQuery({
},
});
// Set nickname (displayName) for a user
export const setNickname = mutation({
// Internal: resolve a userId to the fields needed by the voice-token action
// (server-side signature verification + LiveKit identity).
export const getUserForVoiceToken = internalQuery({
args: { userId: v.id("userProfiles") },
returns: v.union(
v.object({
userId: v.id("userProfiles"),
username: v.string(),
publicSigningKey: v.string(),
}),
v.null()
),
handler: async (ctx, args) => {
const user = await ctx.db.get(args.userId);
if (!user) return null;
return {
userId: user._id,
username: user.username,
publicSigningKey: user.publicSigningKey,
};
},
});
// Internal: fetch a channel for the voice-token action so it can confirm the
// target channel exists and is actually a voice/dm room.
export const getChannelForVoiceToken = internalQuery({
args: { channelId: v.id("channels") },
returns: v.union(
v.object({
channelId: v.id("channels"),
type: v.string(),
}),
v.null()
),
handler: async (ctx, args) => {
const channel = await ctx.db.get(args.channelId);
if (!channel) return null;
return { channelId: channel._id, type: channel.type };
},
});
// Internal writer. Public entry point: `authActions.setNickname`. The
// action layer verifies the caller controls `actorUserId` via
// signature; the existing self-or-manage_nicknames gate stays here.
export const setNicknameInternal = internalMutation({
args: {
actorUserId: v.id("userProfiles"),
targetUserId: v.id("userProfiles"),
@@ -371,8 +414,10 @@ export const setNickname = mutation({
},
});
// Delete a user and all their associated data (admin only)
export const deleteUser = mutation({
// Internal writer. Public entry point: `authActions.deleteUser`. Both
// the isAdmin check and the destructive delete live here; the action
// layer verifies the caller controls `requestingUserId`.
export const deleteUserInternal = internalMutation({
args: {
requestingUserId: v.id("userProfiles"),
targetUserId: v.id("userProfiles"),