College system users (e.g., KCTCS kctcsreportingadmin) can access all colleges under their system and use the Registration Dashboard and workflow steps. However, they get "Access Denied" on the Courses page, Instructors page, and the Admin sidebar is nearly empty. Three distinct root causes:
- Courses & Instructors pages:
load_collegeinapplication_controller.rb:171-174can't resolve@collegefor system users (theircollege_idis nil), sorequire_college(line 209) blocks access before CanCan even runs. - Instructors page: Additionally missing CanCan permissions in
ability.rb. - Admin sidebar:
_college_system_profile_nav.html.erbonly has 2 items vs ~30 in the college version.
load_college (lines 171-175) — Add a fallback using branded_host_college for system users. This method already exists (line 508) and resolves a college from the URL subdomain, which is exactly how system users access specific colleges.
Add after line 174:
@college ||= branded_host_college if current_user&.college_system?This unblocks both the Courses and Instructors pages since require_college (line 209) will now find @college.
Note: require_college_or_college_system already exists at line 205 but isn't needed here — setting @college is better because downstream controllers and views already depend on @college being set.
instr_cond = { college: coll_cond } is already defined on line 847 but unused. Add after the existing InstructorCourseDocument read block (~line 857), mirroring college super admin permissions from lines 498-557:
Instructor core:
can :manage, Instructor, instr_cond
can :manage, InstructorEducation, instr_cond
can :manage, InstructorCourse, course: course_condInstructor reviews:
can :create, InstructorReview, instructor: instr_cond
can :manage, InstructorReview, college: coll_condDocuments:
can [:read, :create, :update, :destroy, :approve], InstructorDocument, college: coll_cond
can [:read, :create, :update, :destroy, :approve], CourseReviewerDocument, college: coll_condUpgrade InstructorCourseDocument from read-only to full CRUD+approve. Replace the existing read-only block (lines 854-857) with:
can [:create, :read, :approve, :select_course_review], InstructorCourseDocument do |icd|
!icd.instructor.archive && !icd.instructor.high_school.archive &&
icd.instructor.high_school.colleges.joins(:college_systems).exists?("college_systems.id = ?", id)
end
can [:update, :destroy], InstructorCourseDocument do |icd|
!icd.approved && !icd.instructor.archive && !icd.instructor.high_school.archive &&
icd.instructor.high_school.colleges.joins(:college_systems).exists?("college_systems.id = ?", id)
endCourse reviewers and deans:
can :manage, CourseReviewer, college: coll_cond
can :manage, Dean, college: coll_condInstructor review course actions:
can [:courses, :add_prospective_course_with_defaults, :remove_prospective_course,
:complete_af_step_and_redirect_back, :prospective_courses, :edit_prospective_course,
:batch_approve_prospective_courses, :update_prospective_course_and_launch_review], InstructorReviewCourse
can :deans_with_replacement_users, ActiveFlow
can :update_deans_with_replacement_users, ActiveFlow
can :change_term, ActiveFlow
can :update_change_term, ActiveFlow
can :change_participants, ActiveFlow
can :update_change_participants, ActiveFlowCurrently only shows 2 items (App Field Groups, App Fields). Replace with a version that mirrors _college_profile_nav.html.erb (the college version), using the same can? permission checks. The nav items will naturally show/hide based on CanCan permissions.
Key items to add (with their permission checks from the college version):
- Institution Profile (link to
college_path) - Academic Terms / HS Terms (
can? :read, Term) - Term Categories (
can?(:manage_term_categories, @college)) - No Registration Message (
can?(:no_registration_message, College)) - Local Options (
can? :manage, LocalOption) - Campuses (
can? :manage, Campus) - Disciplines (
can? :manage, Discipline) - Programs (
can? :manage, Program) - Documents (
can? :manage, CourseFee) - Course Fee Types (local option gated)
- Term Fee Types (local option gated)
- Course Reviewers (
can? :manage, CourseReviewer) - Deans (
can? :manage, Campus) - College Users (
can?(:manage_college_users, @college)) - High Schools (
can?(:manage_high_school_users, @college)) - High School Groups (
can?(:manage_high_school_groups, @college)) - District Users (
can?(:manage_district_users, @college)) - Course Categories, Section Categories, Delivery Formats
- Workflow Definitions (
can?(:read, ActiveFlowDefinition)) - Keep existing App Field Groups / App Fields
Important: The nav checks @college for some permission calls (e.g., can?(:manage_college_users, @college)). With Part 1 fixing load_college, @college will be available. The template should check @college presence: render items that need @college only when it's set, keeping @college_system-only items always visible.
The college super admin block (lines 556-558) grants custom actions that are missing from the college_system block. Add to the college_system? section:
can [:manage_college_users, :manage_high_school_users, :manage_high_school_groups,
:manage_district_users, :manage_term_categories, :manage_course_categories,
:manage_course_section_categories], College, coll_cond
can :manage, CollegeCourseSectionMeetingDeliveryFormat, college: coll_cond
can :manage_application_fields, College, coll_cond
can :manage, LocalOption, college: coll_condBug fix on line 13: can?(:update, @college) should be can?(:update, @college_system) — @college may be nil on this page, causing the form to always be disabled/read-only for system users.
- Log in as
kctcs_systemon dev for any KCTCS college subdomain - Courses page: Navigate to Courses tab — should load without Access Denied, CRUD works
- Instructors page: Navigate to Instructors tab — should load, CRUD on instructors/documents/reviews/deans/course reviewers
- Admin sidebar: Navigate to Admin tab — right-side nav should show Academic Terms, High Schools, College Users, Campuses, etc.
- Admin profile form: System name and common branded host fields should be editable (not disabled)
- Switch to a different KCTCS college subdomain and verify the same access
- Run
bundle exec rspecfor ability specs, instructor controller specs, and colleges controller specs