Skip to content

Instantly share code, notes, and snippets.

@ckozus
Created April 1, 2026 19:30
Show Gist options
  • Select an option

  • Save ckozus/24d3630315b665911d4cd3601ce22e80 to your computer and use it in GitHub Desktop.

Select an option

Save ckozus/24d3630315b665911d4cd3601ce22e80 to your computer and use it in GitHub Desktop.
IDEA-330: Expand College System User Access - Implementation Plan

IDEA-330: Expand College System User Access

Context

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:

  1. Courses & Instructors pages: load_college in application_controller.rb:171-174 can't resolve @college for system users (their college_id is nil), so require_college (line 209) blocks access before CanCan even runs.
  2. Instructors page: Additionally missing CanCan permissions in ability.rb.
  3. Admin sidebar: _college_system_profile_nav.html.erb only has 2 items vs ~30 in the college version.

Part 1: Fix college loading for system users

File: app/controllers/application_controller.rb

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.

Part 2: Add Instructor permissions

File: app/models/ability.rb (lines 837-941, college_system? block)

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_cond

Instructor reviews:

can :create, InstructorReview, instructor: instr_cond
can :manage, InstructorReview, college: coll_cond

Documents:

can [:read, :create, :update, :destroy, :approve], InstructorDocument, college: coll_cond
can [:read, :create, :update, :destroy, :approve], CourseReviewerDocument, college: coll_cond

Upgrade 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)
end

Course reviewers and deans:

can :manage, CourseReviewer, college: coll_cond
can :manage, Dean, college: coll_cond

Instructor 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, ActiveFlow

Part 3: Expand Admin sidebar navigation

File: app/views/shared/_college_system_profile_nav.html.erb

Currently 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.

File: app/models/ability.rb — Additional admin permissions

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_cond

File: app/views/colleges/college_systems/edit.html.erb

Bug 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.

Verification

  1. Log in as kctcs_system on dev for any KCTCS college subdomain
  2. Courses page: Navigate to Courses tab — should load without Access Denied, CRUD works
  3. Instructors page: Navigate to Instructors tab — should load, CRUD on instructors/documents/reviews/deans/course reviewers
  4. Admin sidebar: Navigate to Admin tab — right-side nav should show Academic Terms, High Schools, College Users, Campuses, etc.
  5. Admin profile form: System name and common branded host fields should be editable (not disabled)
  6. Switch to a different KCTCS college subdomain and verify the same access
  7. Run bundle exec rspec for ability specs, instructor controller specs, and colleges controller specs
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment