Skip to content

com_courses: let admins view course forms instead of 422ing them out - #1921

Open
denphi wants to merge 1 commit into
hubzero:2.4-mainfrom
denphi:fix/com-courses-form-admin-access
Open

com_courses: let admins view course forms instead of 422ing them out#1921
denphi wants to merge 1 commit into
hubzero:2.4-mainfrom
denphi:fix/com-courses-form-admin-access

Conversation

@denphi

@denphi denphi commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

Form::execute() resolved a #__courses_members row at section then offering scope and aborted 422 "No user found" when neither matched. Site admins and course managers who are not enrolled have no such row, so any form task -- including a read-only PDF layout view reached from the outline builder -- turned them away.

authorize() already exempts Super Administrators, and the manager check it performs is access('manage'), not membership. But authorize() runs inside the task and execute() gets there first, so that exemption was never reachable.

execute() now applies the same test: a user with no member row is let through when they are a super admin or can manage the course, with $this->member left null and $this->unenrolled set.

$this->member is only consumed by showDeployment, complete, startWork, saveProgress and submit, so those five now assert it themselves. An admin can lay out and read a form but still cannot deploy one or submit responses, which keeps respondent records tied to real members. The authoring tasks (layout, index, upload, saveLayout) never read it.

The layout view shows a warning when unenrolled. It has to render in the view rather than through Notify: this route is requested with tmpl=component, and neither the form views nor the component template render the notification queue, so a Notify call would silently surface on some later page.

Ticket: https://nanohub.org/support/ticket/510363

Form::execute() resolved a #__courses_members row at section then offering
scope and aborted 422 "No user found" when neither matched. Site admins and
course managers who are not enrolled have no such row, so any form task --
including a read-only PDF layout view reached from the outline builder --
turned them away.

authorize() already exempts Super Administrators, and the manager check it
performs is access('manage'), not membership. But authorize() runs inside the
task and execute() gets there first, so that exemption was never reachable.

execute() now applies the same test: a user with no member row is let through
when they are a super admin or can manage the course, with $this->member left
null and $this->unenrolled set.

$this->member is only consumed by showDeployment, complete, startWork,
saveProgress and submit, so those five now assert it themselves. An admin can
lay out and read a form but still cannot deploy one or submit responses, which
keeps respondent records tied to real members. The authoring tasks (layout,
index, upload, saveLayout) never read it.

The layout view shows a warning when unenrolled. It has to render in the view
rather than through Notify: this route is requested with tmpl=component, and
neither the form views nor the component template render the notification
queue, so a Notify call would silently surface on some later page.

Ticket: https://nanohub.org/support/ticket/510363

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@denphi
denphi requested a review from nkissebe as a code owner August 26, 2026 01:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant