feat: replace generated nicknames with filtered user input
This commit is contained in:
+16
-10
@@ -156,16 +156,17 @@ test('bot and friend wins never change ranked standings, profile stats or cosmet
|
||||
} finally { await f.close(); }
|
||||
});
|
||||
|
||||
test('profiles keep generated names and validate unlocked appearances, persistence and pairing snapshots', integration, async () => {
|
||||
test('profiles save filtered names and validate unlocked appearances, persistence and pairing snapshots', integration, async () => {
|
||||
const f = await fixture();
|
||||
try {
|
||||
const s = f.service;
|
||||
const original = await s.profile('player-a');
|
||||
assert.equal((await s.profile('player-a')).displayName, '');
|
||||
const original = await s.updateProfile('player-a', { displayName: '손오공' });
|
||||
assert.deepEqual(original.appearance, normalizeAppearance({ characterId: 0, colorId: 'white' }));
|
||||
assert.deepEqual(original.unlockedEquipment, []);
|
||||
assert.match(original.displayName, /^[가-힣]+-[0-9]{4}$/);
|
||||
for (const displayName of ['손오공', '광고사이트', '<img>', null, undefined]) {
|
||||
await assert.rejects(s.updateProfile('player-a', { displayName } as any), /PROFILE_NAME_READONLY/);
|
||||
assert.equal(original.displayName, '손오공');
|
||||
for (const displayName of ['씨 발', '병_신', '<img>', null, undefined]) {
|
||||
await assert.rejects(s.updateProfile('player-a', { displayName } as any), /PROFILE_NAME_PROFANITY|INVALID_PROFILE_NAME/);
|
||||
}
|
||||
for (const appearance of [{ characterId: 2, colorId: 'white' }, { characterId: 0, colorId: 'bogus' }, { characterId: 0, colorId: 'orange' }]) {
|
||||
await assert.rejects(s.updateProfile('player-a', { appearance: appearance as any }), /INVALID_APPEARANCE|COLOR_LOCKED/);
|
||||
@@ -186,7 +187,7 @@ test('profiles keep generated names and validate unlocked appearances, persisten
|
||||
} finally { await f.close(); }
|
||||
});
|
||||
|
||||
test('startup migrates old custom and default names including nonvisiting leaderboard players exactly once', integration, async () => {
|
||||
test('startup preserves old names and hides invalid leaderboard names without rewriting profiles', integration, async () => {
|
||||
const f = await fixture();
|
||||
try {
|
||||
await f.service.updateProfile('player-a', { appearance: { characterId: 1, colorId: 'white' } });
|
||||
@@ -206,13 +207,18 @@ test('startup migrates old custom and default names including nonvisiting leader
|
||||
const board = await restarted.leaderboard('new-viewer');
|
||||
names = board.entries.map(entry => entry.displayName);
|
||||
assert.equal(names.length, 2);
|
||||
for (const name of names) assert.match(name, /^[가-힣]+-[0-9]{4}$/);
|
||||
assert.deepEqual(names, ['플레이어', '무도가']);
|
||||
assert.equal(board.entries[0].wins, 1);
|
||||
const profile = await restarted.profile('player-a');
|
||||
assert.deepEqual(profile.stats, expectedStats);
|
||||
assert.deepEqual(profile.appearance, normalizeAppearance({ characterId: 1, colorId: 'white', skinTone: 'light', hairStyle: 'black' }));
|
||||
assert.deepEqual(await f.db.collection('ranked_matches').find().toArray(), records);
|
||||
assert.equal((await profiles.findOne({ _id: 'player-b' })).nameVersion, 1);
|
||||
assert.equal((await profiles.findOne({ _id: 'player-b' })).nameVersion, 0);
|
||||
assert.equal((await profiles.findOne({ _id: 'player-a' })).displayName, '광고.example');
|
||||
assert.equal(profile.displayName, '');
|
||||
await restarted.updateProfile('player-a', { displayName: '새이름' });
|
||||
names = (await restarted.leaderboard('new-viewer')).entries.map(entry => entry.displayName);
|
||||
assert.deepEqual(names, ['새이름', '무도가']);
|
||||
} finally { await restarted.close(); }
|
||||
const again = await createRankedService(f.db, f.clock, 'test');
|
||||
try { assert.deepEqual((await again.leaderboard('new-viewer')).entries.map(entry => entry.displayName), names!); }
|
||||
@@ -556,11 +562,11 @@ test('ranked HTTP authenticates identity and ignores client results for ranked a
|
||||
appearance: { characterId: 0, colorId: 'white', equipment: ['headband'] }, stats: { wins: 999, best: 999 },
|
||||
} });
|
||||
assert.equal(locked.statusCode, 403); assert.equal(locked.json().code, 'EQUIPMENT_LOCKED');
|
||||
for (const displayName of ['광고사이트', '<script>alert(1)</script>', '', null, { nameVersion: 1 }]) {
|
||||
for (const displayName of ['씨발', '<script>alert(1)</script>', '', null, { nameVersion: 1 }]) {
|
||||
const rejected = await app.inject({ method: 'POST', url: '/api/profile', headers, payload: {
|
||||
displayName, nameVersion: 1, appearance: { characterId: 1, colorId: 'white' },
|
||||
} });
|
||||
assert.equal(rejected.statusCode, 403); assert.equal(rejected.json().code, 'PROFILE_NAME_READONLY');
|
||||
assert.equal(rejected.statusCode, 400); assert.match(rejected.json().code, /PROFILE_NAME_PROFANITY|INVALID_PROFILE_NAME/);
|
||||
}
|
||||
assert.deepEqual(await f.service.profile('player-a'), original);
|
||||
const profile = await app.inject({ method: 'POST', url: '/api/profile', headers, payload: { playerId: 'player-b', stats: { wins: 500 } } });
|
||||
|
||||
Reference in New Issue
Block a user