Restructure api

Fixes in geo api, registry
Cleanups
This commit is contained in:
phil 2024-02-27 05:05:33 +05:30
parent c84dd61f6a
commit 8c299f0041
17 changed files with 212 additions and 162 deletions

View file

@ -1,6 +1,6 @@
import logging
from fastapi import Depends, FastAPI, HTTPException, status, responses
from fastapi import Depends, APIRouter, HTTPException, status, responses
from gisaf.models.admin import AdminBasket, BasketNameOnly
from gisaf.models.authentication import User
@ -9,8 +9,10 @@ from gisaf.admin import manager
logger = logging.getLogger(__name__)
api = FastAPI(
default_response_class=responses.ORJSONResponse,
api = APIRouter(
tags=["admin"],
# dependencies=[Depends(get_token_header)],
responses={404: {"description": "Not found"}},
)
@api.get('/basket')

View file

@ -2,7 +2,7 @@ import logging
from pathlib import Path
from json import dumps
from fastapi import Depends, FastAPI, HTTPException, status, responses
from fastapi import Depends, APIRouter, HTTPException, status, responses
from sqlalchemy.orm import selectinload
from sqlmodel import select
import pandas as pd
@ -34,8 +34,10 @@ Gisaf is free, open source software for geomatics and GIS:
<a href="http://redmine.auroville.org.in/projects/gisaf">Gisaf</a>.
'''
api = FastAPI(
default_response_class=responses.ORJSONResponse,
api = APIRouter(
tags=["dashboard"],
# dependencies=[Depends(get_token_header)],
responses={404: {"description": "Not found"}},
)
@api.get('/groups')

View file

@ -7,7 +7,7 @@ import logging
from typing import Annotated
from asyncio import CancelledError
from fastapi import (Depends, FastAPI, HTTPException, Response, Header,
from fastapi import (Depends, APIRouter, HTTPException, Response, Header,
WebSocket, WebSocketDisconnect,
status, responses)
@ -20,8 +20,10 @@ from gisaf.security import get_current_active_user
logger = logging.getLogger(__name__)
api = FastAPI(
default_response_class=responses.ORJSONResponse,
api = APIRouter(
tags=["geoapi"],
# dependencies=[Depends(get_token_header)],
responses={404: {"description": "Not found"}},
)
class ConnectionManager:
@ -103,11 +105,10 @@ async def get_geojson(store_name,
if model.cache_enabled:
ttag = await redis_store.get_ttag(store_name)
if ttag and If_None_Match == ttag:
return status.HTTP_304_NOT_MODIFIED
raise HTTPException(status.HTTP_304_NOT_MODIFIED)
if hasattr(model, 'get_geojson'):
geojson = await model.get_geojson(simplify_tolerance=simplify,
preserve_topology=preserveTopology,
registry=registry)
preserve_topology=preserveTopology)
## Store to redis for caching
if use_cache:
await redis_store.store_json(model, geojson)

View file

@ -2,7 +2,7 @@ import logging
from datetime import timedelta
from typing import Annotated
from fastapi import Depends, FastAPI, HTTPException, status, responses
from fastapi import Depends, APIRouter, HTTPException, status, responses
from sqlalchemy.orm import selectinload
from fastapi.security import OAuth2PasswordRequestForm
from sqlmodel import select
@ -12,7 +12,6 @@ from gisaf.models.authentication import (
Role, RoleRead,
)
from gisaf.models.category import Category, CategoryRead
from gisaf.models.geo_models_base import LineWorkSurveyModel
from gisaf.models.to_migrate import DataProvider
from gisaf.models.survey import Equipment, SurveyMeta, Surveyor
from gisaf.config import Survey, conf
@ -31,19 +30,16 @@ from gisaf.models.to_migrate import (
FeatureInfo, InfoItem, Attachment, InfoCategory
)
from gisaf.live_utils import get_live_feature_info
from gisaf.api.dashboard import api as dashboard_api
from gisaf.api.map import api as map_api
logger = logging.getLogger(__name__)
api = FastAPI(
default_response_class=responses.ORJSONResponse,
api = APIRouter(
tags=["api"],
# dependencies=[Depends(get_token_header)],
responses={404: {"description": "Not found"}},
)
#api.add_middleware(SessionMiddleware, secret_key=conf.crypto.secret)
api.mount('/dashboard', dashboard_api)
api.mount('/map', map_api)
@api.get('/bootstrap')
async def bootstrap(

View file

@ -2,21 +2,26 @@ from collections import OrderedDict, defaultdict
import logging
from json import dumps
from fastapi import FastAPI, Request, HTTPException, status, responses
from fastapi import (APIRouter, Request, HTTPException,
Response, status)
from sqlalchemy.orm import selectinload
from sqlalchemy.exc import NoResultFound
from sqlmodel import select
from gisaf.models.map_bases import BaseMap, BaseMapLayer, BaseStyle, MapInitData
from gisaf.models.map_bases import (BaseMap, BaseMapLayer, BaseMapWithStores,
BaseStyle, MapInitData, MaplibreStyle)
from gisaf.models.misc import Qml
from gisaf.registry import registry
from gisaf.database import db_session
from gisaf.database import fastapi_db_session
from gisaf.database import db_session, fastapi_db_session
from gisaf.tiles import registry as tiles_registry
from gisaf.redis_tools import store as redis_store
logger = logging.getLogger(__name__)
api = FastAPI(
default_response_class=responses.ORJSONResponse,
api = APIRouter(
tags=["map"],
# dependencies=[Depends(get_token_header)],
# responses={404: {"description": "Not found"}},
)
async def get_base_styles():
@ -31,23 +36,21 @@ async def get_base_styles():
# base_styles.extend(tiles_registry.mbtiles.values())
return [BaseStyle(name=bs) for bs in base_styles] # type: ignore
async def get_base_maps() -> list[BaseMap]:
async def get_base_maps() -> list[BaseMapWithStores]:
async with db_session() as session:
query1 = select(BaseMap).options(selectinload(BaseMap.layers)) # type: ignore
query1 = select(BaseMap) #.options(selectinload(BaseMap.layers)) # type: ignore
data1 = await session.exec(query1)
base_maps = data1.all()
return base_maps # type: ignore
base_map_dict = {bm.id: bm.name for bm in base_maps}
query2 = select(BaseMapLayer).options(selectinload(BaseMapLayer.base_map))
query2 = select(BaseMapLayer).options(selectinload(BaseMapLayer.base_map)) # type: ignore
data2 = await session.exec(query2)
base_map_layers = data2.all()
bms = defaultdict(list)
bms: dict[str, list] = defaultdict(list)
for bml in base_map_layers:
breakpoint()
if bml.store:
bms[base_map_dict[bml.base_map_id]].append(name=bml.store)
bms[base_map_dict[bml.base_map_id]].append(bml.store)
return [
BaseMap(name=bm, stores=bmls)
BaseMapWithStores(name=bm, stores=bmls)
for bm, bmls in OrderedDict(sorted(bms.items())).items()
]
@ -84,3 +87,29 @@ async def get_base_style(request: Request, name: str,
else:
style = base_style.style # type: ignore
return BaseStyle(name=name, style=style) # type: ignore
@api.get('/layer_style/{store}')
async def get_layer_style(request: Request, store: str,
response: Response,
) -> MaplibreStyle | None:
store_record = registry.stores.loc[store]
if store_record.is_live:
## No ttag for live layers' style (could be added?)
## Get layer_defs from live redis and give symbol
return await redis_store.get_maplibre_style(store)
## Set the etag based on the last modification of the model's style.
#if store in info.schema.app['registry'].geom_auto:
if store_record.custom:
## The style is in Qml
ttag_channel = 'gisaf_map.qml'
else:
## The style is in Category
ttag_channel = 'gisaf_survey.category'
## Check if the request was etagged:
ttag = await redis_store.get_ttag(ttag_channel)
if ttag and request.headers.get('If-None-Match') == ttag:
raise HTTPException(status_code=status.HTTP_304_NOT_MODIFIED)
# request.not_modified = True
# return MaplibreStyle()
response.headers['ETag'] = ttag
return await store_record.model.get_maplibre_style()