Repository navigation
Task Issue 935 Assign Roles Read Route Rights Check
Issue: #935
Status: IMPLEMENTED & VERIFIED (2026-09-19) — branch task/issue-935
Legacy lib/usermanagement/usersAssign.php:201-240 (checkRights) denies the whole
page unless the caller holds ANY of role_management,
testplan_user_role_assignment (on the current project, falling back to the target
test plan), user_role_assignment (global) or — for a testproject context —
testproject_user_role_assignment on the target project. Denial goes through
testlinkInitPage($db,false,false,"checkRights") → localised "Not Enough Rights To
Access The Feature" (locale/en_GB/strings.txt:4100 $TLS_not_enough_rights) and an
audit_security_user_right_missing AUTH event is written.
When the issue was filed, the modern BFF api/roles/index.php served the read routes
GET meta/tplan-roles (:684-753) and GET meta/tproject-roles (:560-623) with NO
rights check — any authenticated user (e.g. guest1 with global role guest) received
HTTP 200 plus the full user list / role ids / plan+project role assignments.
Commit 7f4553712 (Refs #924) added route-aware enforcement to
api/roles/index.php:
-
userCanAssignRoles()(:67-82) — a faithful port of legacycheckRights()with the same union (role_managementORtestplan_user_role_assignmenton tproject ctx with tplan fallback OR globaluser_role_assignmentORtestproject_user_role_assignmenton the target project for the testproject feature); - gate block
:188-223that runs it on BOTH GET meta routes and the corresponding PUT update check (userCanUpdateAssignments,checkRightsForUpdateparity); -
denyAssignRights()(:96-104) → HTTP 403{"status":"error","message": "no_permissions_for_action","right":...}+audit_security_user_right_missingAUTH event.
The BFF already 403'd, but the modern screens swallowed it: usersAssignPlan.html
had no .fail handler at all (a denied user was left staring at a silently frozen
empty grid), and usersAssignProject.html conflated the 403 with its
"no assignable projects" notice. Both now mirror the legacy denial screen:
-
gui/templates/usermanagement/usersAssignPlan.html:#denyBoxmarkup +showNoAccess()(hides demo banner / tabs / toolbar / table / footer, shows the notice) and.fail(xhr.status === 403 → showNoAccess)handlers onloadProjects(:158),loadPlans(:181) andloadUsers(:200). -
gui/templates/usermanagement/usersAssignProject.html: same#denyBox+showNoAccess(), clearly separated fromshowDisabled()(the legacytestproject_roles_assign_disabledcase), re-routing the two 403.failpaths (:207,:275) to it. -
i18n: new
assign.noRights("You do not have enough rights to access this feature." — the$TLS_not_enough_rightsequivalent) added to all 10 locale bundles (gui/templates/i18n/{en,de,es,fr,it,ja,pt,ro,ru,zh}.json).

Before the client-side port: a guest with no assign rights saw a silently frozen, empty screen (the BFF already 403'd server-side).

After: the legacy "Not Enough Rights To Access The Feature" screen is reproduced — management chrome hidden, localized notice shown.

The project screen routes 403 to the same localized box (distinct from the "no assignable projects" notice).
-
guest1 (global role
guest):GET meta/tplan-roles?tproject_id=1&tplan_id=2,?tproject_id=0&tplan_id=0,meta/tproject-roles?tproject_id=1→ all HTTP 403no_permissions_for_action, no user dump;eventsgained rowsaudit_security_user_right_missing(AUTH, log_level 16); both screens render the localized deny box. -
leader935 (global role
leader=testplan_user_role_assignment+user_role_assignment, NOrole_management): all three read routes → HTTP 200 full data — the legacycheckRightsunion is preserved (permissive path, #924). -
admin (
role_management): both screens render the full grid (ASSIGN / RPlan, rows admin + guest1), deny box hidden — regression clean. - Event Viewer /
events: only log_level 16 audit rows; 0 Error/Warning rows. Browser console: only the expected 403 resource log, no JS exceptions. Inline JSnode --checkclean; all 10 bundlespython3 -m json.toolvalid. - Full manual pass:
tmp/TLU_Test_Cases.md— "Suite 935" — all PASS.
Fixture: tmp/fixtures_935.php (project ASSIGN id 1, test plan RPlan id 2, guest1
global role guest; leader935 global role leader added via SQL).
Refs #935.