add perms mixin for healthcare service and facility location#3561
add perms mixin for healthcare service and facility location#3561Jacobjeevan wants to merge 1 commit intoohcnetwork:developfrom
Conversation
📝 WalkthroughWalkthroughThis change introduces permissions mixins for healthcare service and facility location resources, consistently following established architectural patterns. New access methods enable role determination for users within these resource contexts, and spec classes are updated to leverage the new permission-handling mixins. Changes
Estimated code review effort🎯 2 (Simple) | ⏱️ ~12 minutes 🚥 Pre-merge checks | ✅ 1 | ❌ 2❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (1 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (3)
care/security/authorization/facility_location.py (1)
14-18: Guardfacility_organization_cachebefore using it in__in.This is fine for happy-path data, but it’ll fail noisily if the cache is ever
None. A small guard keeps this method robust.Suggested patch
def find_roles_on_facility_location(self, user, facility_location): - roles = FacilityOrganizationUser.objects.filter( - organization_id__in=facility_location.facility_organization_cache, user=user + org_ids = facility_location.facility_organization_cache or [] + roles = FacilityOrganizationUser.objects.filter( + organization_id__in=org_ids, user=user ).values_list("role_id", flat=True) return set(roles)🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@care/security/authorization/facility_location.py` around lines 14 - 18, The method find_roles_on_facility_location uses facility_location.facility_organization_cache directly in a filter __in which will raise if the cache is None; guard the cache first (in find_roles_on_facility_location) by checking facility_location.facility_organization_cache is truthy/iterable and if not return an empty set, otherwise perform the FacilityOrganizationUser.objects.filter(..., organization_id__in=facility_location.facility_organization_cache, user=user).values_list("role_id", flat=True) and return set(roles).care/security/authorization/healthcare_service.py (1)
10-21: Handle nullableparent_cachedefensively in role resolution.Current logic works as long as
parent_cacheis always iterable; if not, this blows up quickly in production.Suggested patch
def find_roles_on_healthcare_service(self, user, healthcare_service): - roles = set() - if healthcare_service.managing_organization: - orgs = [ - *healthcare_service.managing_organization.parent_cache, - healthcare_service.managing_organization.id, - ] - roles = FacilityOrganizationUser.objects.filter( - organization_id__in=orgs, - user=user, - ).values_list("role_id", flat=True) - return set(roles) + if not healthcare_service.managing_organization: + return set() + + parent_cache = healthcare_service.managing_organization.parent_cache or [] + orgs = [*parent_cache, healthcare_service.managing_organization.id] + roles = FacilityOrganizationUser.objects.filter( + organization_id__in=orgs, + user=user, + ).values_list("role_id", flat=True) + return set(roles)🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@care/security/authorization/healthcare_service.py` around lines 10 - 21, The method find_roles_on_healthcare_service can raise if healthcare_service.managing_organization.parent_cache is None or not iterable; defensively handle this by treating parent_cache as an empty iterable when absent. Update the logic in find_roles_on_healthcare_service to access parent_cache via a safe fallback (e.g., parent_cache = getattr(healthcare_service.managing_organization, "parent_cache", []) or check for None) and build orgs = [*parent_cache, healthcare_service.managing_organization.id] only after ensuring parent_cache is iterable, then call FacilityOrganizationUser.objects.filter(...).values_list("role_id", flat=True) as before.care/emr/resources/permissions.py (1)
77-81: De-duplicate permission slugs before serializing.Right now users with overlapping roles can get repeated permission strings. Not fatal, just unnecessarily noisy.
Suggested patch
mapping["permissions"] = list( RolePermission.objects.filter( role_id__in=roles, permission__context__in=["FACILITY"] - ).values_list("permission__slug", flat=True) + ).values_list("permission__slug", flat=True).distinct() ) @@ mapping["permissions"] = list( RolePermission.objects.filter( role_id__in=roles, permission__context__in=["FACILITY"] - ).values_list("permission__slug", flat=True) + ).values_list("permission__slug", flat=True).distinct() )Also applies to: 91-95
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@care/emr/resources/permissions.py` around lines 77 - 81, The permission slug list constructed via mapping["permissions"] is not deduplicated; change the query to return unique slugs by appending .distinct() to RolePermission.objects.filter(...).values_list("permission__slug", flat=True).distinct() and convert that to a list, and apply the same fix to the other occurrence that builds permissions (the similar RolePermission.objects.filter(...) block around lines 91-95) so serialized permission strings are unique.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@care/emr/resources/permissions.py`:
- Around line 77-81: The permission slug list constructed via
mapping["permissions"] is not deduplicated; change the query to return unique
slugs by appending .distinct() to
RolePermission.objects.filter(...).values_list("permission__slug",
flat=True).distinct() and convert that to a list, and apply the same fix to the
other occurrence that builds permissions (the similar
RolePermission.objects.filter(...) block around lines 91-95) so serialized
permission strings are unique.
In `@care/security/authorization/facility_location.py`:
- Around line 14-18: The method find_roles_on_facility_location uses
facility_location.facility_organization_cache directly in a filter __in which
will raise if the cache is None; guard the cache first (in
find_roles_on_facility_location) by checking
facility_location.facility_organization_cache is truthy/iterable and if not
return an empty set, otherwise perform the
FacilityOrganizationUser.objects.filter(...,
organization_id__in=facility_location.facility_organization_cache,
user=user).values_list("role_id", flat=True) and return set(roles).
In `@care/security/authorization/healthcare_service.py`:
- Around line 10-21: The method find_roles_on_healthcare_service can raise if
healthcare_service.managing_organization.parent_cache is None or not iterable;
defensively handle this by treating parent_cache as an empty iterable when
absent. Update the logic in find_roles_on_healthcare_service to access
parent_cache via a safe fallback (e.g., parent_cache =
getattr(healthcare_service.managing_organization, "parent_cache", []) or check
for None) and build orgs = [*parent_cache,
healthcare_service.managing_organization.id] only after ensuring parent_cache is
iterable, then call
FacilityOrganizationUser.objects.filter(...).values_list("role_id", flat=True)
as before.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 511231b8-1be6-4ab7-8ef4-b86e6b199bf3
📒 Files selected for processing (5)
care/emr/resources/healthcare_service/spec.pycare/emr/resources/location/spec.pycare/emr/resources/permissions.pycare/security/authorization/facility_location.pycare/security/authorization/healthcare_service.py
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## develop #3561 +/- ##
===========================================
+ Coverage 76.22% 76.24% +0.01%
===========================================
Files 474 474
Lines 22261 22287 +26
Branches 2324 2325 +1
===========================================
+ Hits 16969 16992 +23
- Misses 4764 4766 +2
- Partials 528 529 +1 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
Proposed Changes
Architecture changes
Merge Checklist
/docsOnly PR's with test cases included and passing lint and test pipelines will be reviewed
@ohcnetwork/care-backend-maintainers @ohcnetwork/care-backend-admins
Summary by CodeRabbit
Release Notes