Task #352: Make logo upload always visible for admin users

Previously, the logo upload field in Font Settings was hidden behind two
conditions: canEditGlobal AND scope === "global". Admin users had to
first switch the scope dropdown to "Global" before the logo upload
appeared, making it very hard to discover.

Changes:
- Frontend (executive-meetings.tsx): Removed `scope === "global"`
  condition from logo upload rendering — now shows whenever
  `canEditGlobal` is true (admin/executive_office_manager).
- Frontend: Save function now always sends `logoObjectPath` when
  `canEditGlobal` is true, regardless of selected scope.
- Backend (executive-meetings.ts): When an admin saves with user scope
  and includes logoObjectPath, the logo is written to the global row
  (upsert) in the same transaction. This preserves the global-only
  semantics while allowing admins to update the logo from any scope.
- When no global row exists, new row uses safe defaults (system font,
  14px, regular, start, #000000) instead of copying the user's prefs.
- Removed the 400 rejection for logoObjectPath on user-scope saves.
- Authorization preserved: only EM_ADMIN_ROLES can trigger logo writes.

Tested:
- API: PATCH with scope=user + logoObjectPath correctly updates global row
- E2E: Logo upload field visible for admin in user scope (confirmed)
- Code review: APPROVED (addressed comment about safe defaults)
- Pre-existing test failures unchanged (PDF font assertion, notification tests)
This commit is contained in:
riyadhafraa
2026-05-04 06:44:02 +00:00
parent bd939e6f6e
commit 7473e6f2ea
2 changed files with 5 additions and 9 deletions
@@ -2880,17 +2880,13 @@ const upsertFontSettingsHandler = async (
const userId = req.session.userId!;
const data = parseBody(res, fontSettingsSchema, req.body);
if (!data) return;
if (data.scope === "global") {
const names = await getRoleNamesForUser(userId);
const ok = EM_ADMIN_ROLES.some((r) => names.has(r));
if (!ok) {
res.status(403).json({ error: "Forbidden", code: "forbidden" });
return;
}
}
const targetUserId = data.scope === "global" ? null : userId;
const userRoleNames = await getRoleNamesForUser(userId);
const isAdmin = EM_ADMIN_ROLES.some((r) => userRoleNames.has(r));
if (data.scope === "global" && !isAdmin) {
res.status(403).json({ error: "Forbidden", code: "forbidden" });
return;
}
const targetUserId = data.scope === "global" ? null : userId;
const logoSentByAdmin =
isAdmin && data.logoObjectPath !== undefined;
const logoForFontRow =
Binary file not shown.

After

Width:  |  Height:  |  Size: 152 KiB