feat: banning
This commit is contained in:
parent
bc1687e40a
commit
d9f2836fb9
11 changed files with 576 additions and 21 deletions
|
|
@ -3,6 +3,10 @@ import { resolveExpiredQuestions, processAccountDeletions } from "$lib/server/jo
|
|||
import { svelteKitHandler } from "better-auth/svelte-kit";
|
||||
import { redis } from "$lib/server/redis";
|
||||
import { building } from '$app/environment';
|
||||
import { redirect, type Handle } from '@sveltejs/kit';
|
||||
import { db } from '$lib/server/db';
|
||||
import { user } from '$lib/server/db/schema';
|
||||
import { eq } from 'drizzle-orm';
|
||||
|
||||
async function initializeScheduler() {
|
||||
if (building) return;
|
||||
|
|
@ -68,14 +72,109 @@ async function initializeScheduler() {
|
|||
|
||||
initializeScheduler();
|
||||
|
||||
export async function handle({ event, resolve }) {
|
||||
// event.setHeaders({
|
||||
// 'Cache-Control': 'private, no-cache, no-store, must-revalidate'
|
||||
// });
|
||||
const sessionCache = new Map<string, {
|
||||
userData: any;
|
||||
timestamp: number;
|
||||
ttl: number;
|
||||
}>();
|
||||
|
||||
const CACHE_TTL = 5 * 60 * 1000; // 5 minutes
|
||||
const CACHE_CLEANUP_INTERVAL = 10 * 60 * 1000; // 10 minutes
|
||||
|
||||
setInterval(() => {
|
||||
const now = Date.now();
|
||||
for (const [key, value] of sessionCache.entries()) {
|
||||
if (now - value.timestamp > value.ttl) {
|
||||
sessionCache.delete(key);
|
||||
}
|
||||
}
|
||||
}, CACHE_CLEANUP_INTERVAL);
|
||||
|
||||
export const handle: Handle = async ({ event, resolve }) => {
|
||||
if (event.url.pathname.startsWith('/.well-known/appspecific/com.chrome.devtools')) {
|
||||
return new Response(null, { status: 204 });
|
||||
}
|
||||
|
||||
// Get session from auth
|
||||
const session = await auth.api.getSession({
|
||||
headers: event.request.headers
|
||||
});
|
||||
|
||||
let userData = null;
|
||||
|
||||
if (session?.user) {
|
||||
const userId = session.user.id;
|
||||
const cacheKey = `user:${userId}`;
|
||||
const now = Date.now();
|
||||
|
||||
const cached = sessionCache.get(cacheKey);
|
||||
if (cached && (now - cached.timestamp) < cached.ttl) {
|
||||
userData = cached.userData;
|
||||
} else {
|
||||
const [userRecord] = await db
|
||||
.select({
|
||||
id: user.id,
|
||||
name: user.name,
|
||||
username: user.username,
|
||||
email: user.email,
|
||||
isAdmin: user.isAdmin,
|
||||
image: user.image,
|
||||
isBanned: user.isBanned,
|
||||
banReason: user.banReason,
|
||||
baseCurrencyBalance: user.baseCurrencyBalance,
|
||||
bio: user.bio,
|
||||
volumeMaster: user.volumeMaster,
|
||||
volumeMuted: user.volumeMuted
|
||||
})
|
||||
.from(user)
|
||||
.where(eq(user.id, Number(userId)))
|
||||
.limit(1);
|
||||
|
||||
if (userRecord?.isBanned) {
|
||||
try {
|
||||
await auth.api.signOut({
|
||||
headers: event.request.headers
|
||||
});
|
||||
} catch (e) {
|
||||
console.error('Failed to sign out banned user:', e);
|
||||
}
|
||||
|
||||
if (event.url.pathname !== '/banned') {
|
||||
const banReason = encodeURIComponent(userRecord.banReason || 'Account suspended');
|
||||
throw redirect(302, `/banned?reason=${banReason}`);
|
||||
}
|
||||
} else if (userRecord) {
|
||||
userData = {
|
||||
id: userRecord.id.toString(),
|
||||
name: userRecord.name,
|
||||
username: userRecord.username,
|
||||
email: userRecord.email,
|
||||
isAdmin: userRecord.isAdmin || false,
|
||||
image: userRecord.image || '',
|
||||
isBanned: userRecord.isBanned || false,
|
||||
banReason: userRecord.banReason,
|
||||
avatarUrl: userRecord.image,
|
||||
baseCurrencyBalance: parseFloat(userRecord.baseCurrencyBalance || '0'),
|
||||
bio: userRecord.bio || '',
|
||||
volumeMaster: parseFloat(userRecord.volumeMaster || '0.7'),
|
||||
volumeMuted: userRecord.volumeMuted || false
|
||||
};
|
||||
|
||||
const cacheTTL = userRecord.isAdmin ? CACHE_TTL * 2 : CACHE_TTL;
|
||||
sessionCache.set(cacheKey, {
|
||||
userData,
|
||||
timestamp: now,
|
||||
ttl: cacheTTL
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
event.locals.userSession = userData;
|
||||
|
||||
return svelteKitHandler({ event, resolve, auth });
|
||||
};
|
||||
|
||||
export function clearUserCache(userId: string) {
|
||||
sessionCache.delete(`user:${userId}`);
|
||||
}
|
||||
Reference in a new issue