team-3/src/c3nav/api/api.py

64 lines
2.1 KiB
Python
Raw Normal View History

2023-11-14 17:54:56 +01:00
from django.conf import settings
2023-12-04 13:55:24 +01:00
from ninja import Field as APIField
from ninja import Router as APIRouter
2023-11-14 17:54:56 +01:00
from ninja import Schema
2023-12-04 13:04:35 +01:00
from c3nav.api.auth import APIKeyType, auth_responses
from c3nav.api.utils import NonEmptyStr
2023-12-02 01:31:58 +01:00
from c3nav.control.models import UserPermissions
2023-11-14 17:54:56 +01:00
auth_api_router = APIRouter(tags=["auth"])
2023-12-02 01:31:58 +01:00
class AuthStatusSchema(Schema):
"""
Current auth state and permissions
"""
2023-12-04 13:04:35 +01:00
key_type: APIKeyType = APIField(
title="api key type",
2023-12-04 19:32:11 +01:00
description="the type of api key that is being used"
2023-12-04 13:04:35 +01:00
)
readonly: bool = APIField(
title="read only",
description="if true, no API operations that modify data can be called"
)
scopes: list[str] = APIField(
title="authorized scopes",
description="scopes available with the current authorization",
)
2023-12-02 01:31:58 +01:00
2023-12-03 19:04:23 +01:00
@auth_api_router.get('/status/', summary="get status",
description="Returns details about the current authentication",
2023-12-02 01:31:58 +01:00
response={200: AuthStatusSchema, **auth_responses})
def get_status(request):
permissions = UserPermissions.get_for_user(request.user)
scopes = [
*(p for p in ("editor_access", "grant_permissions", "mesh_control") if getattr(permissions, p)),
*([] if request.auth.readonly else ["write"]),
]
return AuthStatusSchema(
method=request.auth.method,
readonly=request.auth.readonly,
scopes=scopes,
)
2023-11-14 17:54:56 +01:00
class APITokenSchema(Schema):
token: NonEmptyStr = APIField(
title="API token",
description="API token to be directly used with `Authorization: Bearer <token>` HTTP header."
)
2023-11-14 17:54:56 +01:00
2023-11-14 18:29:21 +01:00
@auth_api_router.get('/session/', response=APITokenSchema, auth=None,
2023-12-03 19:04:23 +01:00
summary="get session-bound token")
2023-11-14 17:54:56 +01:00
def session_token(request):
"""
Get an API token that is bound to the transmitted session cookie.
Keep in mind that this API token will be invalid if the session gets signed out or similar.
"""
2023-11-14 18:29:21 +01:00
session_id = request.COOKIES.get(settings.SESSION_COOKIE_NAME, None)
return {"token": "anonymous" if session_id is None else f"session:{session_id}"}