Skip to content

Use HMIS Project Policy for enrollment detail visibility checks - #6779

Merged
gigxz merged 9 commits into
mainfrom
gig/9442-project-policy-enrollment-check
Jul 31, 2026
Merged

Use HMIS Project Policy for enrollment detail visibility checks#6779
gigxz merged 9 commits into
mainfrom
gig/9442-project-policy-enrollment-check

Conversation

@gigxz

@gigxz gigxz commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

Merging this PR

  • use the squash-merge strategy for PRs targeting main
  • use a merge-commit or rebase strategy for PRs targeting staging and production

Description

Related Issues (Does not close):

Adds project/client policy methods for enrollment-detail visibility, and migrates GraphQL callers (and warehouse “Open in HMIS” links) off raw permission helpers so permission dependencies apply consistently.

  • Add can_view_enrollment_details? / can_edit_enrollments? on project policy
  • Add can_view_some_enrollment_details? on client policy
  • Resolve selected Project/Client access fields and auth gates via policies
  • Add shared scope Project#with_enrollment_detail_visibility_for(user), to remove repeated usage of with_access(user, :can_view_enrollment_details, :can_view_project, mode: :all) across enrollment and household visibility scopes
  • Update warehouse HMIS URL resolution to use policy checks rather than raw permission checks

Why now:

  • Resolving https://github.com/open-path/Green-River/issues/9442 will include adding can_view_clients as a required permission for enrollment visibility. Enrollment visibility permission checks are sprinkled throughout the codebase; this PR consolidates so we can make the change in fewer places.

Type of change

Code clean-up

Checklist before requesting review

  • I performed a self-review of my code
  • I ran the OP review skill
  • I ran the code that is being changed under ideal conditions, and it doesn't fail
  • If adding a new endpoint / exposing data in a new way, I have:
    • ensured the API can't leak data from other data sources
    • ensured this does not introduce N+1s
    • ensured permissions and visibility checks are performed in the right places
  • Any major architectural changes are supported by an approved ADR (Architectural Decision Record)
  • I updated the documentation (or not applicable)
  • I added spec tests (or not applicable)
  • I provided testing instructions in this PR or the related issue (or not applicable)

@gigxz
gigxz requested a review from martha July 29, 2026 19:28
return true if source_project_permissions.include?(:can_manage_outgoing_referrals)

# Users who can view the target enrollment. Bakes in the assumption that the target enrollment is in the referral's project, which is validated on the referral
# TODO(8549) - encapsulate this check requiring both can_view_enrollment_details and can_view_project in the Enrollment Policy

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is already baked in from permission requirements, just updating the comment to reflect that

@martha martha left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me! Thanks for the cleanup 🙏

hmis_user.policy_for(hmis_entity, policy_type: :hmis_client).can_view?
when Hmis::Hud::Enrollment
hmis_user.policy_for(hmis_entity, policy_type: :hmis_enrollment).can_view_details?
when Hmis::Hud::CustomAssessment, Hmis::Hud::CustomService

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could instead gate on hmis_entity.respond_to?(:enrollment) and then we would check permissions on a broader range of enrollment-related records, instead of just Hmis::Hud::CustomAssessment, Hmis::Hud::CustomService.

I don't know the full context of when this is called, so maybe this is irrelevant.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm good question. It feels like an unsafe pattern to check authorization on a record where we don't know explicitly what it is, that would be my hesitation. I'll leave it as-is for now which has parity with the old behavior

'Hmis::Hud::Project' => [:can_view_project],
# 'Hmis::Hud::Organization' => [:can_view_organization],
'Hmis::Hud::Client' => [:can_view_clients],
'Hmis::Hud::Enrollment' => [:can_view_projects, :can_view_enrollment_details],

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note from AI review:

[warning] app/models/grda_warehouse/data_source.rb:824 — This is a larger behavior change than the description implies. The old known_permissions map required :can_view_projects (plural) for Hmis::Hud::Enrollment and Hmis::Hud::CustomAssessment. can_view_projects is a warehouse Role permission, not an Hmis::Role permission, and Hmis::User is not a subclass of ::User — so Hmis::User#permission_for? hit its respond_to? guard and returned false. With mode: :all, that made the check unconditionally false, meaning the "Open in HMIS" link was always suppressed for enrollments and assessments. The new code will start rendering those links wherever hmis_external_link is used. That is almost certainly the desired outcome, but it should be called out in the PR description and confirmed with someone who knows the intended warehouse UX, since it is a user-visible change rather than a refactor.

This surprised me, but I think it does seem to be true. I checked by viewing an enrollment in my local warehouse that I do have permission to see in HMIS (https://hmis-warehouse.dev.test/source_data/xxxx?type=Enrollment). On main I don't see a link to HMIS, but on your branch, I do.

Image

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes this looks like a bug in the old code that is now fixed. "can_view_projects" on lines 825-826 are a typo, it should be "can_view_project" like on line 822. These were always checking HMIS permissions (line 822 hmis_user.permissions_for?(hmis_entity, *perms, mode: :all)) it was just incorrectly returning false because of the typos.

can :delete_project
can :edit_project_details
can :view_enrollment_details
define_method(:policy) { @policy ||= policy_for(object, policy_type: :hmis_project) }

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe, add a project_access_field_spec.rb mirroring client_access_field_spec.rb. It looks like the underlying policy methods themselves are well tested though, so I think this is optional.

Comment thread drivers/hmis/app/graphql/types/hmis_schema/project.rb Outdated
Comment thread drivers/hmis/app/graphql/types/hmis_schema/query_type.rb Outdated
Comment thread drivers/hmis/app/models/hmis/hud/project.rb Outdated
@gigxz
gigxz merged commit f67d16e into main Jul 31, 2026
25 of 26 checks passed
@gigxz
gigxz deleted the gig/9442-project-policy-enrollment-check branch July 31, 2026 13:08
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.

2 participants