force uppercase usernames

This commit is contained in:
Face 2025-05-31 17:39:30 +03:00
parent ccd4126953
commit 82d8e34560
6 changed files with 1595 additions and 5 deletions

View file

@ -0,0 +1,16 @@
ALTER TABLE "transaction" DROP CONSTRAINT "transaction_recipient_user_id_user_id_fk";
--> statement-breakpoint
ALTER TABLE "transaction" DROP CONSTRAINT "transaction_sender_user_id_user_id_fk";
--> statement-breakpoint
ALTER TABLE "coin" ALTER COLUMN "change_24h" SET DATA TYPE numeric(30, 4);--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "transaction" ADD CONSTRAINT "transaction_recipient_user_id_user_id_fk" FOREIGN KEY ("recipient_user_id") REFERENCES "public"."user"("id") ON DELETE set null ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "transaction" ADD CONSTRAINT "transaction_sender_user_id_user_id_fk" FOREIGN KEY ("sender_user_id") REFERENCES "public"."user"("id") ON DELETE set null ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;

File diff suppressed because it is too large Load diff

View file

@ -15,6 +15,13 @@
"when": 1748690470287, "when": 1748690470287,
"tag": "0001_yummy_meggan", "tag": "0001_yummy_meggan",
"breakpoints": true "breakpoints": true
},
{
"idx": 2,
"version": "7",
"when": 1748700252762,
"tag": "0002_lush_guardian",
"breakpoints": true
} }
] ]
} }

View file

@ -80,7 +80,7 @@ export const coin = pgTable("coin", {
currentPrice: decimal("current_price", { precision: 20, scale: 8 }).notNull(), // Price in base currency currentPrice: decimal("current_price", { precision: 20, scale: 8 }).notNull(), // Price in base currency
marketCap: decimal("market_cap", { precision: 30, scale: 2 }).notNull(), marketCap: decimal("market_cap", { precision: 30, scale: 2 }).notNull(),
volume24h: decimal("volume_24h", { precision: 30, scale: 2 }).default("0.00"), volume24h: decimal("volume_24h", { precision: 30, scale: 2 }).default("0.00"),
change24h: decimal("change_24h", { precision: 10, scale: 4 }).default("0.0000"), // Percentage change24h: decimal("change_24h", { precision: 30, scale: 4 }).default("0.0000"), // Percentage
poolCoinAmount: decimal("pool_coin_amount", { precision: 30, scale: 8 }).notNull().default("0.00000000"), poolCoinAmount: decimal("pool_coin_amount", { precision: 30, scale: 8 }).notNull().default("0.00000000"),
poolBaseCurrencyAmount: decimal("pool_base_currency_amount", { precision: 30, scale: 8, }).notNull().default("0.00000000"), poolBaseCurrencyAmount: decimal("pool_base_currency_amount", { precision: 30, scale: 8, }).notNull().default("0.00000000"),
createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(), createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),

View file

@ -25,9 +25,9 @@ async function validateInputs(name: string, bio: string, username: string, avata
} }
if (username) { if (username) {
const alphanumericRegex = /^[a-zA-Z0-9]+$/; const alphanumericRegex = /^[a-z0-9_]+$/;
if (!alphanumericRegex.test(username)) { if (!alphanumericRegex.test(username)) {
throw error(400, 'Username must contain only letters and numbers'); throw error(400, 'Username must contain only lowercase letters, numbers, and underscores');
} }
} }
@ -56,7 +56,7 @@ export async function POST({ request }) {
const formData = await request.formData(); const formData = await request.formData();
const name = formData.get('name') as string; const name = formData.get('name') as string;
const bio = formData.get('bio') as string; const bio = formData.get('bio') as string;
const username = formData.get('username') as string; const username = (formData.get('username') as string)?.toLowerCase();
const avatarFile = formData.get('avatar') as File | null; const avatarFile = formData.get('avatar') as File | null;
await validateInputs(name, bio, username, avatarFile); await validateInputs(name, bio, username, avatarFile);

View file

@ -5,11 +5,19 @@ import { eq } from 'drizzle-orm';
import { isNameAppropriate } from '$lib/server/moderation'; import { isNameAppropriate } from '$lib/server/moderation';
export async function GET({ url }) { export async function GET({ url }) {
const username = url.searchParams.get('username'); const username = url.searchParams.get('username')?.toLowerCase();
if (!username) { if (!username) {
return json({ available: false }); return json({ available: false });
} }
const alphanumericRegex = /^[a-z0-9_]+$/;
if (!alphanumericRegex.test(username)) {
return json({
available: false,
reason: 'Username must contain only lowercase letters, numbers, and underscores'
});
}
if (!(await isNameAppropriate(username))) { if (!(await isNameAppropriate(username))) {
return json({ available: false, reason: 'Inappropriate content' }); return json({ available: false, reason: 'Inappropriate content' });
} }