Public Access
fix(settings): keep Steam ID as string and store the new token
Number("76561198005679788") is 76561198005679790 in JavaScript, so the wrong
Steam ID was saved. The Steam ID now stays a 17-digit string. Theme and
language saves no longer send steamId 0. After a save the new token from Auth
replaces the old one.
Add Vitest and run it in CI.
This commit is contained in:
1 parent
2c1f22f4b4
commit
44e23de6d6
6 files changed
+343
-22
No files matched your search
@@ -82,7 +82,7 @@ export default function SettingsPage() {
|
||||
reset({
|
||||
useDarkTheme: !!data.settings?.useDarkTheme,
|
||||
language: data.settings?.language || 'en',
|
||||
steamId: data.steamId ? String(data.steamId) : '',
|
||||
steamId: data.steamId ?? '',
|
||||
});
|
||||
} catch (err) {
|
||||
console.error('Settings load error:', err);
|
||||
@@ -128,6 +128,8 @@ export default function SettingsPage() {
|
||||
return {ok: false};
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
localStorage.setItem('tbp_jwt', data.token); // Core reads the steamId from the token
|
||||
setFeedback({message: t('SETTINGS.SAVED'), isError: false});
|
||||
return {ok: true};
|
||||
} catch (err) {
|
||||
@@ -143,7 +145,7 @@ export default function SettingsPage() {
|
||||
await persistSettings({
|
||||
useDarkTheme: next,
|
||||
language: i18n.language,
|
||||
steamId: profile?.steamId ?? 0,
|
||||
steamId: profile?.steamId ?? null,
|
||||
});
|
||||
};
|
||||
|
||||
@@ -153,7 +155,7 @@ export default function SettingsPage() {
|
||||
await persistSettings({
|
||||
useDarkTheme: isDarkMode,
|
||||
language: next,
|
||||
steamId: profile?.steamId ?? 0,
|
||||
steamId: profile?.steamId ?? null,
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
@@ -15,14 +15,12 @@ const inviteCodeField = z
|
||||
.string()
|
||||
.min(1, 'VALIDATION.INVITE_CODE_REQUIRED');
|
||||
|
||||
// Backend stores steamId as a primitive long; Steam IDs are positive 64-bit integers.
|
||||
// A SteamID64 has 17 digits. Keep it a string: a JS number loses precision above 2^53.
|
||||
const steamIdField = z
|
||||
.union([z.string(), z.number()])
|
||||
.transform((v) => (typeof v === 'string' ? v.trim() : String(v)))
|
||||
.refine((v) => v.length > 0, {message: 'VALIDATION.STEAM_ID_REQUIRED'})
|
||||
.refine((v) => /^\d+$/.test(v), {message: 'VALIDATION.STEAM_ID_INVALID'})
|
||||
.transform((v) => Number(v))
|
||||
.refine((n) => Number.isFinite(n) && n > 0, {message: 'VALIDATION.STEAM_ID_INVALID'});
|
||||
.string()
|
||||
.trim()
|
||||
.min(1, 'VALIDATION.STEAM_ID_REQUIRED')
|
||||
.regex(/^\d{17}$/, 'VALIDATION.STEAM_ID_INVALID');
|
||||
|
||||
export const registrationSchema = z
|
||||
.object({
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
import {describe, expect, it} from 'vitest';
|
||||
import {registrationSchema, settingsSchema} from './validation.js';
|
||||
|
||||
const settings = (steamId) => ({useDarkTheme: true, language: 'de', steamId});
|
||||
|
||||
describe('steamId validation', () => {
|
||||
it('keeps a SteamID64 as the exact string', () => {
|
||||
// Number('76561198005679788') is 76561198005679790
|
||||
expect(settingsSchema.parse(settings('76561198005679788')).steamId).toBe('76561198005679788');
|
||||
});
|
||||
|
||||
it('trims whitespace', () => {
|
||||
expect(settingsSchema.parse(settings(' 76561198005679788 ')).steamId).toBe('76561198005679788');
|
||||
});
|
||||
|
||||
it.each(['', '12345', '7656119800567978x', '765611980056797880'])('rejects %j', (steamId) => {
|
||||
expect(settingsSchema.safeParse(settings(steamId)).success).toBe(false);
|
||||
});
|
||||
|
||||
it('keeps the exact string on registration', () => {
|
||||
const result = registrationSchema.parse({
|
||||
email: 'a@b.de',
|
||||
password: 'password1',
|
||||
passwordConfirmation: 'password1',
|
||||
inviteCode: 'code',
|
||||
steamId: '76561198005679788',
|
||||
});
|
||||
expect(result.steamId).toBe('76561198005679788');
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user