openvibers/openvibe.live Commits

Projection: Network's display name is taken only when it re-cases the username, as Live's own profile route allows

OP OpenVibers committed 25 Sept 2026 · 31aa74b952 · 2 files, +8 −1


Changes

ddiff --git a/server/auth/subject-projection.js b/server/auth/subject-projection.js
iindex b76b1c26..6139f6fb 100644
---- a/server/auth/subject-projection.js
++++ b/server/auth/subject-projection.js
@@@ -86,7 +86,10 @@ function apply(p, { notify = () => {} } = {}) {
const user = localUser(subject, p.network_user_id);
if (!user) return 'updated';
const role = nextRole(user, p);
-- const next = { role, avatar_url: str(p.avatar_url, 500) || user.avatar_url, profile_color: str(p.profile_color, 32) || user.profile_color, display_name: str(p.display_name, 120) || user.display_name };
++ // Live's display name only re-cases the username (server/auth/routes.js): Network's is taken when it does.
++ const dn = str(p.display_name, 120);
++ const displayName = dn && dn.toLowerCase() === p.username.toLowerCase() ? dn : user.display_name;
++ const next = { role, avatar_url: str(p.avatar_url, 500) || user.avatar_url, profile_color: str(p.profile_color, 32) || user.profile_color, display_name: displayName };
const changed = Object.keys(next).filter((k) => next[k] !== user[k]);
if (changed.length) d.prepare(`UPDATE users SET ${changed.map((k) => `${k} = @${k}`).join(', ')} WHERE id = @id`).run({ ...Object.fromEntries(changed.map((k) => [k, next[k]])), id: user.id });
let renamed = false;
ddiff --git a/test/subject-projection.test.js b/test/subject-projection.test.js
iindex a3118e13..a675f727 100644
---- a/test/subject-projection.test.js
++++ b/test/subject-projection.test.js
@@@ -75,6 +75,10 @@ const envelope = (p) => ({ event_id: ids.newId('event'), event_type: 'network.us
assert.strictEqual(user(3).role, 'global_mod', 'Network makes them staff');
assert.strictEqual(await deliver(payload(CAM, 30, 3, { username: 'cam', role: 'user', changed: ['role'] })), 204);
assert.strictEqual(user(3).role, 'streamer', 'staff removed by Network: someone who has streamed keeps streamer');
++ assert.strictEqual(await deliver(payload(CAM, 30, 4, { username: 'cam', display_name: 'CAM', changed: ['display_name'] })), 204);
++ assert.strictEqual(user(3).display_name, 'CAM', 'a re-cased display name follows');
++ assert.strictEqual(await deliver(payload(CAM, 30, 5, { username: 'cam', display_name: 'Someone Else', changed: ['display_name'] })), 204);
++ assert.strictEqual(user(3).display_name, 'CAM', "a display name that is not the username keeps Live's (Live only re-cases)");
assert.strictEqual(await deliver(payload(ALEX, 7, 5, { username: 'alex_new', role: 'streamer', banned: true, changed: ['banned'] })), 204);
assert.strictEqual(projection.get(ALEX).banned, 1);