This commit is contained in:
Bryan1029384756
2026-04-18 15:41:51 -05:00
parent 938df217f4
commit 593eaba82e
47 changed files with 3539 additions and 212 deletions

View File

@@ -2,6 +2,7 @@ import { query, mutation, internalQuery, internalMutation } from "./_generated/s
import { v } from "convex/values";
import { getPublicStorageUrl } from "./storageUrl";
import { getRolesForUser } from "./roles";
import { isBanned } from "./bans";
async function sha256Hex(input: string): Promise<string> {
const buffer = await crypto.subtle.digest(
@@ -62,6 +63,9 @@ export const verifyUser = mutation({
const hashedDAK = await sha256Hex(args.dak);
if (hashedDAK === user.hashedAuthKey) {
if (await isBanned(ctx, user._id)) {
return { error: "You've been banned from this server." };
}
return {
success: true,
userId: user._id,
@@ -166,6 +170,7 @@ export const createUserWithProfile = mutation({
create_invite: true,
embed_links: true,
attach_files: true,
ban_members: true,
},
isHoist: true,
});
@@ -205,6 +210,7 @@ export const getPublicKeys = query({
customStatus: v.optional(v.string()),
joinSoundUrl: v.optional(v.union(v.string(), v.null())),
accentColor: v.optional(v.string()),
bannerUrl: v.optional(v.union(v.string(), v.null())),
})
),
handler: async (ctx) => {
@@ -219,6 +225,10 @@ export const getPublicKeys = query({
if (u.joinSoundStorageId) {
joinSoundUrl = await getPublicStorageUrl(ctx, u.joinSoundStorageId);
}
let bannerUrl: string | null = null;
if (u.bannerStorageId) {
bannerUrl = await getPublicStorageUrl(ctx, u.bannerStorageId);
}
results.push({
id: u._id,
username: u.username,
@@ -230,6 +240,7 @@ export const getPublicKeys = query({
customStatus: u.customStatus,
joinSoundUrl,
accentColor: u.accentColor,
bannerUrl,
});
}
return results;
@@ -251,6 +262,8 @@ export const updateProfileInternal = internalMutation({
joinSoundStorageId: v.optional(v.id("_storage")),
removeJoinSound: v.optional(v.boolean()),
accentColor: v.optional(v.string()),
bannerStorageId: v.optional(v.id("_storage")),
removeBanner: v.optional(v.boolean()),
},
returns: v.null(),
handler: async (ctx, args) => {
@@ -262,6 +275,17 @@ export const updateProfileInternal = internalMutation({
if (args.joinSoundStorageId !== undefined) patch.joinSoundStorageId = args.joinSoundStorageId;
if (args.removeJoinSound) patch.joinSoundStorageId = undefined;
if (args.accentColor !== undefined) patch.accentColor = args.accentColor;
if (args.bannerStorageId !== undefined) patch.bannerStorageId = args.bannerStorageId;
if (args.removeBanner) {
// Drop the blob from storage too so orphaned banners don't
// accumulate. Matches how the rest of this file treats one-off
// user uploads.
const existing = await ctx.db.get(args.userId);
if (existing?.bannerStorageId) {
try { await ctx.storage.delete(existing.bannerStorageId); } catch {}
}
patch.bannerStorageId = undefined;
}
await ctx.db.patch(args.userId, patch);
return null;
},