-
-
Notifications
You must be signed in to change notification settings - Fork 512
#6563 improve case contact workflow for supervisor and admin #6679
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
#6563 improve case contact workflow for supervisor and admin #6679
Conversation
compwron
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
:)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Improves the case contact workflow for supervisors/admins by adding a “View/Edit” action from the CASA Case Details page that impersonates the case contact’s author before navigating.
Changes:
- Add a new
case_contacts/impersonate_and_editroute and controller action to impersonate a volunteer from the case details workflow. - Update the case contact card partial to show a “View/Edit” link for supervisors/admins (instead of “Edit”) when acting on another user’s contact.
- Update the view spec to assert the new link target.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 6 comments.
| File | Description |
|---|---|
| spec/views/case_contacts/case_contact.html.erb_spec.rb | Updates the view spec expectation to match the new “View/Edit” link behavior. |
| config/routes.rb | Adds a new route for the impersonation workflow entrypoint. |
| app/views/case_contacts/_case_contact.html.erb | Changes the supervisor/admin action link from direct edit to impersonation-based “View/Edit”. |
| app/controllers/case_contacts_controller.rb | Adds impersonate_and_edit action and volunteer lookup used by the new workflow. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| it "shows view/edit button" do | ||
| assign :case_contact, case_contact | ||
| assign :casa_cases, [case_contact.casa_case] | ||
|
|
||
| render(partial: "case_contacts/case_contact", locals: {contact: case_contact}) | ||
| expect(rendered).to have_link(nil, href: "/case_contacts/#{case_contact.id}/edit") | ||
| expect(rendered).to have_link(nil, href: "/case_contacts/impersonate_and_edit?creator_id=#{case_contact.creator.id}") | ||
| end |
Copilot
AI
Jan 28, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This spec asserts the impersonation URL without casa_case_id, but the partial builds the link using casa_case_id: @casa_case when it’s rendered from the case details page (the primary usage). As written, the spec passes even if @casa_case is accidentally missing, which would later cause the controller redirect to fail at runtime.
Assign @casa_case in the spec and assert the full generated href (preferably using the route helper), and also assert the visible link text (e.g., "View/Edit") to avoid matching an unrelated link.
| def impersonate_and_edit | ||
| impersonate_user(@volunteer) | ||
|
|
||
| redirect_to casa_case_path(params[:casa_case_id]) | ||
| end |
Copilot
AI
Jan 28, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
New behavior is introduced via impersonate_and_edit, but there’s no request/system spec covering it (especially authorization and the post-impersonation redirect behavior). The existing suite already has request coverage for CaseContactsController actions (e.g., spec/requests/case_contacts_spec.rb).
Add request specs for this endpoint for (1) authorized supervisor/admin, (2) unauthorized volunteer, and (3) cross-org volunteer id, so regressions in impersonation security/redirect behavior are caught.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@copilot open a new pull request to apply changes based on this feedback
| def impersonate_and_edit | ||
| impersonate_user(@volunteer) | ||
|
|
||
| redirect_to casa_case_path(params[:casa_case_id]) | ||
| end |
Copilot
AI
Jan 28, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
impersonate_and_edit performs an impersonation without any Pundit authorization (and verify_authorized explicitly skips this action). This allows any authenticated user who can hit this endpoint to impersonate arbitrary volunteers by id, bypassing VolunteerPolicy#impersonate?.
Authorize the target user (e.g., authorize @volunteer, :impersonate?) and remove the action from the verify_authorized exception list so authorization is enforced consistently.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@copilot open a new pull request to apply changes based on this feedback
| def impersonate_and_edit | ||
| impersonate_user(@volunteer) | ||
|
|
||
| redirect_to casa_case_path(params[:casa_case_id]) |
Copilot
AI
Jan 28, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Redirecting to casa_case_path(params[:casa_case_id]) after impersonation can fail because volunteers are only authorized to view cases they are actively assigned to (see CasaCasePolicy#show?). If the case contact was authored by a volunteer who is no longer actively assigned, the impersonated session will be blocked from the case details page, defeating the workflow.
Consider redirecting directly to the case contact edit flow (passing the case contact id) rather than the case details page, or otherwise ensuring the impersonated volunteer can access the target case.
| redirect_to casa_case_path(params[:casa_case_id]) | |
| redirect_to case_contact_form_path(:details, case_contact_id: params[:id]) |
| def set_volunteer | ||
| @volunteer = Volunteer.find(params[:creator_id]) | ||
| end |
Copilot
AI
Jan 28, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
set_volunteer uses Volunteer.find(params[:creator_id]) with no scoping to the current organization. Combined with the missing authorization on impersonate_and_edit, this enables cross-organization impersonation by guessing ids.
Even with authorization added, it’s safer to scope the lookup (e.g., via policy_scope(Volunteer) or current_organization.volunteers) and to handle non-volunteer creators gracefully (since CaseContact#creator can be a Supervisor/CasaAdmin).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@copilot open a new pull request to apply changes based on this feedback
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is my first time seeing Copilot reviews so maybe I'm misunderstanding something. Why would we open a new PR instead of modifying this PR? I don't think we'd want to merge it without this change since its a security issue.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would merge the new PR into this PR before merging this PR into main
This also allows multiple concurrent changes
Feel free to do the changes by hand instead if you prefer
Co-authored-by: Copilot <[email protected]>
| def set_volunteer | ||
| @volunteer = Volunteer.find(params[:creator_id]) | ||
| end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is my first time seeing Copilot reviews so maybe I'm misunderstanding something. Why would we open a new PR instead of modifying this PR? I don't think we'd want to merge it without this change since its a security issue.
| <div class="mr-2"> | ||
| <%= link_to edit_case_contact_path(contact), class: "text-danger", data: { turbo: false } do %> | ||
| <i class="lni lni-pencil-alt"></i> Edit | ||
| <% if (current_user.casa_admin? || current_user.supervisor?) && contact.creator&.volunteer? && contact.creator != current_user %> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there anywhere in the back end that we verify its only a CASA admin or supervisor submitting this request? We don't want a volunteer doing that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should be in a "policy" file
6563
Resolves #6563
Supervisor and admins can now directly impersonate as volunteer and view the case details
You can login as supervisor , see a case details and directly click on "View/Edit" button and it will impersonate the said volunteer and take you to the view page page as that volunteer, then you can edit
Screenshots please :)
[Note - Video is attached, i suggest we rename the button to "Impersonate and View/edit", but for now as per original ticket , i have kept it simple and went ahead with original requirement of "View/Edit"]
2026-01-27-03-24-28.1.mp4