99 lines
3.9 KiB
Python
99 lines
3.9 KiB
Python
from fastapi import APIRouter, Depends, HTTPException, Path, Query, Response, status
|
|
from typing import List, Optional
|
|
import json
|
|
import logging
|
|
|
|
from app.lib_general_v3 import AccountContext, get_account_context
|
|
from app.methods.lookup_methods import get_lookup_list_v3, resolve_lookup_v3
|
|
from app.methods.site_methods import load_site_obj
|
|
from app.models.response_models import Resp_Body_Base, mk_resp
|
|
from app.object_definitions.lookups import lu_obj_li
|
|
|
|
log = logging.getLogger(__name__)
|
|
|
|
router = APIRouter()
|
|
|
|
@router.get("/{lu_type}/list", response_model=Resp_Body_Base)
|
|
async def get_v3_lookup_list(
|
|
lu_type: str = Path(..., min_length=2, max_length=50),
|
|
for_type: Optional[str] = Query(None, min_length=2, max_length=50),
|
|
for_id: Optional[int] = Query(None),
|
|
site_id: Optional[str] = Query(None, min_length=8, max_length=22),
|
|
include_disabled: bool = Query(False),
|
|
only_priority: bool = Query(False),
|
|
account_ctx: AccountContext = Depends(get_account_context),
|
|
response: Response = Response
|
|
):
|
|
"""
|
|
Returns a hierarchical, ranked, and deduplicated list of lookup records.
|
|
Supports Object/Account overrides, negative shadowing, and Site Whitelist policies.
|
|
"""
|
|
v3_key = f"lu_v3_{lu_type}"
|
|
if v3_key not in lu_obj_li:
|
|
return mk_resp(data=False, status_code=400, response=response, status_message=f"Lookup type '{lu_type}' not supported in V3.")
|
|
|
|
# Phase 2: Whitelist Policy Injection
|
|
whitelist = None
|
|
if site_id:
|
|
if site_obj := load_site_obj(site_id=site_id, model_as_dict=True):
|
|
# Check if this site belongs to the current account context
|
|
# NOTE: site_obj.get('account_id') returns the RANDOM string ID in V3 models
|
|
if site_obj.get('account_id') == account_ctx.account_id_random:
|
|
cfg = site_obj.get('cfg_json')
|
|
if isinstance(cfg, str):
|
|
try: cfg = json.loads(cfg)
|
|
except: cfg = {}
|
|
|
|
if isinstance(cfg, dict):
|
|
policy = cfg.get('lookup_policy', {})
|
|
whitelist = policy.get(lu_type)
|
|
else:
|
|
return mk_resp(data=False, status_code=403, response=response, status_message="Site does not belong to the authorized account.")
|
|
|
|
results = get_lookup_list_v3(
|
|
lu_type=lu_type,
|
|
account_ctx=account_ctx,
|
|
for_type=for_type,
|
|
for_id=for_id,
|
|
include_disabled=include_disabled,
|
|
whitelist=whitelist,
|
|
only_priority=only_priority
|
|
)
|
|
|
|
if not results and not include_disabled:
|
|
return mk_resp(data=[], status_code=200, response=response, status_message="No active records found.")
|
|
|
|
return mk_resp(data=results)
|
|
|
|
@router.get("/{lu_type}/resolve", response_model=Resp_Body_Base)
|
|
async def resolve_v3_lookup(
|
|
lu_type: str = Path(..., min_length=2, max_length=50),
|
|
q: str = Query(..., min_length=1, description="The code, group, or identity to resolve."),
|
|
site_id: Optional[str] = Query(None, min_length=8, max_length=22),
|
|
account_ctx: AccountContext = Depends(get_account_context),
|
|
response: Response = Response
|
|
):
|
|
"""
|
|
Resolves an identity string to the highest-priority hierarchical match.
|
|
"""
|
|
v3_key = f"lu_v3_{lu_type}"
|
|
if v3_key not in lu_obj_li:
|
|
return mk_resp(data=False, status_code=400, response=response, status_message=f"Lookup type '{lu_type}' not supported in V3.")
|
|
|
|
# TODO: Add whitelist support for resolve if needed.
|
|
# For now, resolve uses the full ranked list.
|
|
|
|
identity_fields = lu_obj_li[v3_key].get("searchable_fields", ["group"])
|
|
|
|
result = resolve_lookup_v3(
|
|
lu_type=lu_type,
|
|
query=q,
|
|
account_ctx=account_ctx,
|
|
identity_fields=identity_fields
|
|
)
|
|
|
|
if not result:
|
|
return mk_resp(data=None, status_code=404, response=response, status_message=f"Could not resolve '{q}' for lookup '{lu_type}'.")
|
|
|
|
return mk_resp(data=result)
|