From 141ab7489ee41aaac726f20f32cdf64463259382 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Laura=20Kl=C3=BCnder?= Date: Sun, 19 Nov 2023 16:48:40 +0100 Subject: [PATCH] add more mapdata endpoints, completing the mapdata API tag --- src/c3nav/mapdata/newapi/mapdata.py | 47 +++++++++++++++++++++++-- src/c3nav/mapdata/schemas/model_base.py | 16 ++++----- src/c3nav/mapdata/schemas/models.py | 29 ++++++++++++--- 3 files changed, 76 insertions(+), 16 deletions(-) diff --git a/src/c3nav/mapdata/newapi/mapdata.py b/src/c3nav/mapdata/newapi/mapdata.py index 1ba062a2..023c1c96 100644 --- a/src/c3nav/mapdata/newapi/mapdata.py +++ b/src/c3nav/mapdata/newapi/mapdata.py @@ -9,13 +9,14 @@ from c3nav.api.exceptions import API404 from c3nav.mapdata.api import optimize_query from c3nav.mapdata.models import (Area, Building, Door, Hole, Level, LocationGroup, LocationGroupCategory, Source, Space, Stair) -from c3nav.mapdata.models.access import AccessPermission +from c3nav.mapdata.models.access import AccessPermission, AccessRestriction, AccessRestrictionGroup from c3nav.mapdata.models.geometry.space import (POI, Column, CrossDescription, LeaveDescription, LineObstacle, Obstacle, Ramp) from c3nav.mapdata.schemas.filters import (ByCategoryFilter, ByGroupFilter, ByLevelFilter, ByOnTopOfFilter, BySpaceFilter, FilterSchema) -from c3nav.mapdata.schemas.models import (AreaSchema, BuildingSchema, ColumnSchema, CrossDescriptionSchema, DoorSchema, - HoleSchema, LeaveDescriptionSchema, LevelSchema, LineObstacleSchema, +from c3nav.mapdata.schemas.models import (AccessRestrictionGroupSchema, AccessRestrictionSchema, AreaSchema, + BuildingSchema, ColumnSchema, CrossDescriptionSchema, DoorSchema, HoleSchema, + LeaveDescriptionSchema, LevelSchema, LineObstacleSchema, LocationGroupCategorySchema, LocationGroupSchema, ObstacleSchema, POISchema, RampSchema, SourceSchema, SpaceSchema, StairSchema) @@ -420,3 +421,43 @@ def source_list(request): def source_detail(request, source_id: int): # todo: access, caching, filtering, etc return mapdata_retrieve_endpoint(request, Source, pk=source_id) + + +""" +AccessRestrictions +""" + + +@mapdata_api_router.get('/accessrestrictions/', response=list[AccessRestrictionSchema], + summary="Get access restriction list") +@paginate +def accessrestriction_list(request): + # todo cache? + return mapdata_list_endpoint(request, model=AccessRestriction) + + +@mapdata_api_router.get('/accessrestrictions/{accessrestriction_id}/', response=AccessRestrictionSchema, + summary="Get access restriction by ID") +def accessrestriction_detail(request, accessrestriction_id: int): + # todo: access, caching, filtering, etc + return mapdata_retrieve_endpoint(request, AccessRestriction, pk=accessrestriction_id) + + +""" +AccessRestrictionGroups +""" + + +@mapdata_api_router.get('/accessrestrictiongroups/', response=list[AccessRestrictionGroupSchema], + summary="Get access restriction group list") +@paginate +def accessrestrictiongroup_list(request): + # todo cache? + return mapdata_list_endpoint(request, model=AccessRestrictionGroup) + + +@mapdata_api_router.get('/accessrestrictiongroups/{group_id}/', response=AccessRestrictionGroupSchema, + summary="Get access restriction group by ID") +def accessrestrictiongroups_detail(request, group_id: int): + # todo: access, caching, filtering, etc + return mapdata_retrieve_endpoint(request, AccessRestrictionGroup, pk=group_id) diff --git a/src/c3nav/mapdata/schemas/model_base.py b/src/c3nav/mapdata/schemas/model_base.py index 242d7e01..9b216ddb 100644 --- a/src/c3nav/mapdata/schemas/model_base.py +++ b/src/c3nav/mapdata/schemas/model_base.py @@ -10,12 +10,6 @@ from c3nav.api.schema import LineStringSchema, PointSchema, PolygonSchema from c3nav.api.utils import NonEmptyStr -class DjangoModelSchema(Schema): - id: PositiveInt = APIField( - title="ID", - ) - - class SerializableSchema(Schema): @model_validator(mode="wrap") # noqa @classmethod @@ -25,6 +19,12 @@ class SerializableSchema(Schema): return handler(values) +class DjangoModelSchema(SerializableSchema): + id: PositiveInt = APIField( + title="ID", + ) + + class LocationSlugSchema(Schema): slug: NonEmptyStr = APIField( title="location slug", @@ -36,7 +36,7 @@ class LocationSlugSchema(Schema): ) -class AccessRestrictionSchema(Schema): +class WithAccessRestrictionSchema(Schema): access_restriction: Optional[PositiveInt] = APIField( default=None, title="access restriction ID", @@ -58,7 +58,7 @@ class TitledSchema(Schema): ) -class LocationSchema(AccessRestrictionSchema, TitledSchema, LocationSlugSchema, SerializableSchema): +class LocationSchema(WithAccessRestrictionSchema, TitledSchema, LocationSlugSchema): subtitle: NonEmptyStr = APIField( title="subtitle (preferred language)", description="an automatically generated short description for this location. " diff --git a/src/c3nav/mapdata/schemas/models.py b/src/c3nav/mapdata/schemas/models.py index dab69bbf..078d7e04 100644 --- a/src/c3nav/mapdata/schemas/models.py +++ b/src/c3nav/mapdata/schemas/models.py @@ -4,8 +4,8 @@ from pydantic import Field as APIField from pydantic import NonNegativeFloat, PositiveFloat, PositiveInt from c3nav.api.utils import NonEmptyStr -from c3nav.mapdata.schemas.model_base import (AccessRestrictionSchema, DjangoModelSchema, LabelSettingsSchema, - LocationSchema, SerializableSchema, SpecificLocationSchema, TitledSchema, +from c3nav.mapdata.schemas.model_base import (DjangoModelSchema, LabelSettingsSchema, LocationSchema, + SpecificLocationSchema, TitledSchema, WithAccessRestrictionSchema, WithLevelSchema, WithLineStringGeometrySchema, WithPointGeometrySchema, WithPolygonGeometrySchema, WithSpaceSchema) @@ -58,7 +58,7 @@ class SpaceSchema(WithPolygonGeometrySchema, SpecificLocationSchema, WithLevelSc ) -class DoorSchema(WithPolygonGeometrySchema, AccessRestrictionSchema, WithLevelSchema, DjangoModelSchema): +class DoorSchema(WithPolygonGeometrySchema, WithAccessRestrictionSchema, WithLevelSchema, DjangoModelSchema): """ A link between two spaces """ @@ -221,7 +221,7 @@ class LocationGroupSchema(LocationSchema, DjangoModelSchema): ) -class LocationGroupCategorySchema(TitledSchema, SerializableSchema, DjangoModelSchema): +class LocationGroupCategorySchema(TitledSchema, DjangoModelSchema): """ A location group category can hold either one or multiple location groups. @@ -277,7 +277,7 @@ class LocationGroupCategorySchema(TitledSchema, SerializableSchema, DjangoModelS priority: int = APIField() # todo: ??? -class SourceSchema(AccessRestrictionSchema, DjangoModelSchema): +class SourceSchema(WithAccessRestrictionSchema, DjangoModelSchema): """ A source image that can be traced in the editor. """ @@ -289,3 +289,22 @@ class SourceSchema(AccessRestrictionSchema, DjangoModelSchema): left: float top: float right: float + + +class AccessRestrictionSchema(TitledSchema, DjangoModelSchema): + """ + A category that some objects can belong to. + + If they do, you can only see them if you have a permission to see objects with this access retriction. + """ + open: bool + groups: list[PositiveInt] = APIField( + title="access restriction groups" + ) + + +class AccessRestrictionGroupSchema(WithAccessRestrictionSchema, DjangoModelSchema): + """ + For simplicity's sake, access restrictions can belong to groups, and you can grant permissions for the entire group. + """ + pass