This commit is contained in:
109
convex/authActions.ts
Normal file
109
convex/authActions.ts
Normal file
@@ -0,0 +1,109 @@
|
||||
"use node";
|
||||
|
||||
import { action } from "./_generated/server";
|
||||
import { internal } from "./_generated/api";
|
||||
import { v } from "convex/values";
|
||||
import { requireAuth } from "./authGuard";
|
||||
|
||||
/**
|
||||
* Signed profile update. The canonical message binds userId + timestamp;
|
||||
* the 5-minute replay window limits damage if a signature leaks. See
|
||||
* `authGuard.requireAuth` for the full verification flow.
|
||||
*/
|
||||
export const updateProfile = action({
|
||||
args: {
|
||||
userId: v.id("userProfiles"),
|
||||
displayName: v.optional(v.string()),
|
||||
aboutMe: v.optional(v.string()),
|
||||
avatarStorageId: v.optional(v.id("_storage")),
|
||||
customStatus: v.optional(v.string()),
|
||||
joinSoundStorageId: v.optional(v.id("_storage")),
|
||||
removeJoinSound: v.optional(v.boolean()),
|
||||
accentColor: v.optional(v.string()),
|
||||
authTimestamp: v.number(),
|
||||
authSignature: v.string(),
|
||||
},
|
||||
returns: v.null(),
|
||||
handler: async (ctx, args): Promise<null> => {
|
||||
const canonical = `updateProfile:${args.userId}:${args.authTimestamp}`;
|
||||
await requireAuth(ctx, args.userId, args.authTimestamp, args.authSignature, canonical);
|
||||
await ctx.runMutation(internal.auth.updateProfileInternal, {
|
||||
userId: args.userId,
|
||||
displayName: args.displayName,
|
||||
aboutMe: args.aboutMe,
|
||||
avatarStorageId: args.avatarStorageId,
|
||||
customStatus: args.customStatus,
|
||||
joinSoundStorageId: args.joinSoundStorageId,
|
||||
removeJoinSound: args.removeJoinSound,
|
||||
accentColor: args.accentColor,
|
||||
});
|
||||
return null;
|
||||
},
|
||||
});
|
||||
|
||||
export const updateStatus = action({
|
||||
args: {
|
||||
userId: v.id("userProfiles"),
|
||||
status: v.string(),
|
||||
authTimestamp: v.number(),
|
||||
authSignature: v.string(),
|
||||
},
|
||||
returns: v.null(),
|
||||
handler: async (ctx, args): Promise<null> => {
|
||||
const canonical = `updateStatus:${args.userId}:${args.status}:${args.authTimestamp}`;
|
||||
await requireAuth(ctx, args.userId, args.authTimestamp, args.authSignature, canonical);
|
||||
await ctx.runMutation(internal.auth.updateStatusInternal, {
|
||||
userId: args.userId,
|
||||
status: args.status,
|
||||
});
|
||||
return null;
|
||||
},
|
||||
});
|
||||
|
||||
export const setNickname = action({
|
||||
args: {
|
||||
actorUserId: v.id("userProfiles"),
|
||||
targetUserId: v.id("userProfiles"),
|
||||
displayName: v.string(),
|
||||
authTimestamp: v.number(),
|
||||
authSignature: v.string(),
|
||||
},
|
||||
returns: v.null(),
|
||||
handler: async (ctx, args): Promise<null> => {
|
||||
const canonical = `setNickname:${args.actorUserId}:${args.targetUserId}:${args.authTimestamp}`;
|
||||
await requireAuth(ctx, args.actorUserId, args.authTimestamp, args.authSignature, canonical);
|
||||
await ctx.runMutation(internal.auth.setNicknameInternal, {
|
||||
actorUserId: args.actorUserId,
|
||||
targetUserId: args.targetUserId,
|
||||
displayName: args.displayName,
|
||||
});
|
||||
return null;
|
||||
},
|
||||
});
|
||||
|
||||
export const deleteUser = action({
|
||||
args: {
|
||||
requestingUserId: v.id("userProfiles"),
|
||||
targetUserId: v.id("userProfiles"),
|
||||
authTimestamp: v.number(),
|
||||
authSignature: v.string(),
|
||||
},
|
||||
returns: v.object({ success: v.boolean(), error: v.optional(v.string()) }),
|
||||
handler: async (
|
||||
ctx,
|
||||
args,
|
||||
): Promise<{ success: boolean; error?: string }> => {
|
||||
const canonical = `deleteUser:${args.requestingUserId}:${args.targetUserId}:${args.authTimestamp}`;
|
||||
await requireAuth(
|
||||
ctx,
|
||||
args.requestingUserId,
|
||||
args.authTimestamp,
|
||||
args.authSignature,
|
||||
canonical,
|
||||
);
|
||||
return await ctx.runMutation(internal.auth.deleteUserInternal, {
|
||||
requestingUserId: args.requestingUserId,
|
||||
targetUserId: args.targetUserId,
|
||||
});
|
||||
},
|
||||
});
|
||||
Reference in New Issue
Block a user