Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/workflows/frontend-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,8 @@ jobs:
- name: Run linter
working-directory: web
run: npm run lint
- name: Check translation keys
working-directory: web
run: npm run check-translations


32 changes: 32 additions & 0 deletions backend/api/decorators/filter_sort.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,43 @@
from database import models
from database.models.base import Base
from sqlalchemy import Select, and_, func, or_, select
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy.orm import aliased

T = TypeVar("T")


async def get_property_field_types(
db: AsyncSession,
filtering: list[FilterInput] | None,
sorting: list[SortInput] | None,
) -> dict[str, str]:
property_def_ids: set[str] = set()
if filtering:
for f in filtering:
if (
f.column_type == ColumnType.PROPERTY
and f.property_definition_id
):
property_def_ids.add(f.property_definition_id)
if sorting:
for s in sorting:
if (
s.column_type == ColumnType.PROPERTY
and s.property_definition_id
):
property_def_ids.add(s.property_definition_id)
if not property_def_ids:
return {}
result = await db.execute(
select(models.PropertyDefinition).where(
models.PropertyDefinition.id.in_(property_def_ids)
)
)
prop_defs = result.scalars().all()
return {str(p.id): p.field_type for p in prop_defs}


def detect_entity_type(model_class: type[Base]) -> str | None:
if model_class == models.Patient:
return "patient"
Expand Down
13 changes: 13 additions & 0 deletions backend/api/errors.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
from graphql import GraphQLError

FORBIDDEN_MESSAGE = (
"Insufficient permission. Please contact an administrator "
"if you believe this is an error."
)


def raise_forbidden(message: str | None = None) -> None:
raise GraphQLError(
message or FORBIDDEN_MESSAGE,
extensions={"code": "FORBIDDEN"},
)
51 changes: 11 additions & 40 deletions backend/api/resolvers/location.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from api.audit import audit_log
from api.context import Info
from api.decorators.pagination import apply_pagination
from api.errors import raise_forbidden
from api.inputs import CreateLocationNodeInput, LocationType, UpdateLocationNodeInput
from api.resolvers.base import BaseMutationResolver, BaseSubscriptionResolver
from api.services.authorization import AuthorizationService
Expand Down Expand Up @@ -52,10 +53,7 @@ async def location_node(
info.context.user, info.context
)
if location.id not in accessible_location_ids:
raise GraphQLError(
"Insufficient permission. Please contact an administrator if you believe this is an error.",
extensions={"code": "FORBIDDEN"},
)
raise_forbidden()

return location

Expand Down Expand Up @@ -83,10 +81,7 @@ async def location_nodes(

if recursive and parent_id:
if parent_id not in accessible_location_ids:
raise GraphQLError(
"Insufficient permission. Please contact an administrator if you believe this is an error.",
extensions={"code": "FORBIDDEN"},
)
raise_forbidden()

cte = (
select(models.LocationNode)
Expand All @@ -106,10 +101,7 @@ async def location_nodes(
)
if parent_id:
if parent_id not in accessible_location_ids:
raise GraphQLError(
"Insufficient permission. Please contact an administrator if you believe this is an error.",
extensions={"code": "FORBIDDEN"},
)
raise_forbidden()
query = query.where(models.LocationNode.parent_id == parent_id)

if kind:
Expand Down Expand Up @@ -143,16 +135,10 @@ async def create_location_node(
)

if not accessible_location_ids:
raise GraphQLError(
"Insufficient permission. Please contact an administrator if you believe this is an error.",
extensions={"code": "FORBIDDEN"},
)
raise_forbidden()

if data.parent_id and data.parent_id not in accessible_location_ids:
raise GraphQLError(
"Insufficient permission. Please contact an administrator if you believe this is an error.",
extensions={"code": "FORBIDDEN"},
)
raise_forbidden()

location = models.LocationNode(
title=data.title,
Expand Down Expand Up @@ -180,10 +166,7 @@ async def update_location_node(
)

if not accessible_location_ids:
raise GraphQLError(
"Insufficient permission. Please contact an administrator if you believe this is an error.",
extensions={"code": "FORBIDDEN"},
)
raise_forbidden()

result = await db.execute(
select(models.LocationNode).where(models.LocationNode.id == id)
Expand All @@ -197,16 +180,10 @@ async def update_location_node(
)

if location.id not in accessible_location_ids:
raise GraphQLError(
"Insufficient permission. Please contact an administrator if you believe this is an error.",
extensions={"code": "FORBIDDEN"},
)
raise_forbidden()

if data.parent_id is not None and data.parent_id not in accessible_location_ids:
raise GraphQLError(
"Insufficient permission. Please contact an administrator if you believe this is an error.",
extensions={"code": "FORBIDDEN"},
)
raise_forbidden()

if data.title is not None:
location.title = data.title
Expand All @@ -230,10 +207,7 @@ async def delete_location_node(self, info: Info, id: strawberry.ID) -> bool:
)

if not accessible_location_ids:
raise GraphQLError(
"Insufficient permission. Please contact an administrator if you believe this is an error.",
extensions={"code": "FORBIDDEN"},
)
raise_forbidden()

result = await db.execute(
select(models.LocationNode).where(models.LocationNode.id == id)
Expand All @@ -247,10 +221,7 @@ async def delete_location_node(self, info: Info, id: strawberry.ID) -> bool:
)

if location.id not in accessible_location_ids:
raise GraphQLError(
"Insufficient permission. Please contact an administrator if you believe this is an error.",
extensions={"code": "FORBIDDEN"},
)
raise_forbidden()

await BaseMutationResolver.delete_entity(
info, location, models.LocationNode, "location_node"
Expand Down
Loading
Loading