kopia lustrzana https://github.com/bugout-dev/moonstream
306 wiersze
10 KiB
Python
306 wiersze
10 KiB
Python
![]() |
"""
|
||
|
The Moonstream users HTTP API
|
||
|
"""
|
||
|
import logging
|
||
![]() |
from typing import Any, Dict, Optional
|
||
![]() |
import uuid
|
||
|
|
||
![]() |
from bugout.data import BugoutToken, BugoutUser, BugoutResource, BugoutUserTokens
|
||
![]() |
from bugout.exceptions import BugoutResponseException
|
||
|
from fastapi import (
|
||
![]() |
APIRouter,
|
||
![]() |
Body,
|
||
![]() |
Form,
|
||
|
Request,
|
||
|
)
|
||
|
|
||
![]() |
from .. import data
|
||
![]() |
from ..middleware import MoonstreamHTTPException
|
||
![]() |
|
||
![]() |
from ..settings import (
|
||
|
MOONSTREAM_APPLICATION_ID,
|
||
|
bugout_client as bc,
|
||
![]() |
BUGOUT_REQUEST_TIMEOUT_SECONDS,
|
||
![]() |
)
|
||
![]() |
from ..actions import create_onboarding_resource
|
||
![]() |
|
||
|
logger = logging.getLogger(__name__)
|
||
|
|
||
![]() |
router = APIRouter(prefix="/users")
|
||
![]() |
|
||
|
|
||
![]() |
@router.post("/", tags=["users"], response_model=BugoutUser)
|
||
![]() |
async def create_user_handler(
|
||
|
username: str = Form(...), email: str = Form(...), password: str = Form(...)
|
||
|
) -> BugoutUser:
|
||
|
try:
|
||
|
user: BugoutUser = bc.create_user(
|
||
![]() |
username=username,
|
||
|
email=email,
|
||
|
password=password,
|
||
|
application_id=MOONSTREAM_APPLICATION_ID,
|
||
![]() |
)
|
||
|
except BugoutResponseException as e:
|
||
![]() |
raise MoonstreamHTTPException(status_code=e.status_code, detail=e.detail)
|
||
![]() |
except Exception as e:
|
||
![]() |
raise MoonstreamHTTPException(status_code=500, internal_error=e)
|
||
![]() |
return user
|
||
|
|
||
|
|
||
![]() |
@router.get("/", tags=["users"], response_model=BugoutUser)
|
||
![]() |
async def get_user_handler(request: Request) -> BugoutUser:
|
||
|
user: BugoutUser = request.state.user
|
||
![]() |
return user
|
||
|
|
||
|
|
||
![]() |
@router.post("/password/reset_initiate", tags=["users"], response_model=Dict[str, Any])
|
||
![]() |
async def restore_password_handler(email: str = Form(...)) -> Dict[str, Any]:
|
||
![]() |
try:
|
||
![]() |
response = bc.restore_password(email=email)
|
||
![]() |
except BugoutResponseException as e:
|
||
![]() |
raise MoonstreamHTTPException(status_code=e.status_code, detail=e.detail)
|
||
![]() |
except Exception as e:
|
||
![]() |
raise MoonstreamHTTPException(status_code=500, internal_error=e)
|
||
![]() |
return response
|
||
|
|
||
|
|
||
![]() |
@router.post("/password/reset_complete", tags=["users"], response_model=BugoutUser)
|
||
![]() |
async def reset_password_handler(
|
||
|
reset_id: str = Form(...), new_password: str = Form(...)
|
||
|
) -> BugoutUser:
|
||
|
try:
|
||
|
response = bc.reset_password(reset_id=reset_id, new_password=new_password)
|
||
|
except BugoutResponseException as e:
|
||
![]() |
raise MoonstreamHTTPException(status_code=e.status_code, detail=e.detail)
|
||
![]() |
except Exception as e:
|
||
![]() |
raise MoonstreamHTTPException(status_code=500, internal_error=e)
|
||
![]() |
return response
|
||
|
|
||
|
|
||
![]() |
@router.post("/password/change", tags=["users"], response_model=BugoutUser)
|
||
![]() |
async def change_password_handler(
|
||
|
request: Request, current_password: str = Form(...), new_password: str = Form(...)
|
||
|
) -> BugoutUser:
|
||
|
token = request.state.token
|
||
|
try:
|
||
|
user = bc.change_password(
|
||
|
token=token, current_password=current_password, new_password=new_password
|
||
![]() |
)
|
||
![]() |
except BugoutResponseException as e:
|
||
![]() |
raise MoonstreamHTTPException(status_code=e.status_code, detail=e.detail)
|
||
![]() |
except Exception as e:
|
||
![]() |
raise MoonstreamHTTPException(status_code=500, internal_error=e)
|
||
![]() |
return user
|
||
|
|
||
|
|
||
![]() |
@router.delete("/", tags=["users"], response_model=BugoutUser)
|
||
![]() |
async def delete_user_handler(
|
||
|
request: Request, password: str = Form(...)
|
||
|
) -> BugoutUser:
|
||
|
user = request.state.user
|
||
|
token = request.state.token
|
||
|
try:
|
||
|
user = bc.delete_user(token=token, user_id=user.id, password=password)
|
||
|
except BugoutResponseException as e:
|
||
![]() |
raise MoonstreamHTTPException(status_code=e.status_code, detail=e.detail)
|
||
![]() |
except Exception as e:
|
||
![]() |
raise MoonstreamHTTPException(status_code=500, internal_error=e)
|
||
![]() |
return user
|
||
|
|
||
|
|
||
![]() |
@router.post("/token", tags=["tokens"], response_model=BugoutToken)
|
||
![]() |
async def login_handler(
|
||
![]() |
username: str = Form(...),
|
||
|
password: str = Form(...),
|
||
|
token_note: Optional[str] = Form(None),
|
||
![]() |
) -> BugoutToken:
|
||
|
try:
|
||
|
token: BugoutToken = bc.create_token(
|
||
![]() |
username=username,
|
||
|
password=password,
|
||
|
application_id=MOONSTREAM_APPLICATION_ID,
|
||
![]() |
token_note=token_note,
|
||
![]() |
)
|
||
![]() |
|
||
![]() |
except BugoutResponseException as e:
|
||
![]() |
raise MoonstreamHTTPException(status_code=e.status_code, detail=e.detail)
|
||
![]() |
except Exception as e:
|
||
![]() |
raise MoonstreamHTTPException(status_code=500, internal_error=e)
|
||
![]() |
return token
|
||
|
|
||
|
|
||
![]() |
@router.get("/tokens", tags=["tokens"], response_model=BugoutUserTokens)
|
||
![]() |
async def tokens_handler(request: Request) -> BugoutUserTokens:
|
||
|
token = request.state.token
|
||
|
try:
|
||
|
response = bc.get_user_tokens(
|
||
|
token, timeout=BUGOUT_REQUEST_TIMEOUT_SECONDS, active=True
|
||
|
)
|
||
|
except BugoutResponseException as e:
|
||
![]() |
raise MoonstreamHTTPException(status_code=e.status_code, detail=e.detail)
|
||
![]() |
except Exception as e:
|
||
|
raise MoonstreamHTTPException(status_code=500, internal_error=e)
|
||
|
return response
|
||
|
|
||
|
|
||
![]() |
@router.put("/token", tags=["tokens"], response_model=BugoutToken)
|
||
![]() |
async def token_update_handler(
|
||
![]() |
token_note: str = Form(...), access_token: str = Form(...)
|
||
![]() |
) -> BugoutToken:
|
||
|
try:
|
||
![]() |
response = bc.update_token(token=access_token, token_note=token_note)
|
||
![]() |
except BugoutResponseException as e:
|
||
![]() |
raise MoonstreamHTTPException(status_code=e.status_code, detail=e.detail)
|
||
![]() |
except Exception as e:
|
||
|
raise MoonstreamHTTPException(status_code=500, internal_error=e)
|
||
|
return response
|
||
|
|
||
|
|
||
![]() |
@router.post("/revoke/{access_token}", tags=["tokens"], response_model=uuid.UUID)
|
||
![]() |
async def delete_token_by_id_handler(
|
||
|
request: Request, access_token: uuid.UUID
|
||
|
) -> uuid.UUID:
|
||
|
token = request.state.token
|
||
|
try:
|
||
|
response = bc.revoke_token(
|
||
|
token=token,
|
||
|
target_token=access_token,
|
||
|
timeout=BUGOUT_REQUEST_TIMEOUT_SECONDS,
|
||
|
)
|
||
|
except BugoutResponseException as e:
|
||
![]() |
raise MoonstreamHTTPException(status_code=e.status_code, detail=e.detail)
|
||
![]() |
except Exception as e:
|
||
|
raise MoonstreamHTTPException(status_code=500, internal_error=e)
|
||
|
return response
|
||
|
|
||
|
|
||
![]() |
@router.delete("/token", tags=["tokens"], response_model=uuid.UUID)
|
||
![]() |
async def logout_handler(request: Request) -> uuid.UUID:
|
||
|
token = request.state.token
|
||
|
try:
|
||
![]() |
token_id: uuid.UUID = bc.revoke_token(token=token)
|
||
![]() |
except BugoutResponseException as e:
|
||
![]() |
raise MoonstreamHTTPException(status_code=e.status_code, detail=e.detail)
|
||
![]() |
except Exception as e:
|
||
![]() |
raise MoonstreamHTTPException(status_code=500, internal_error=e)
|
||
![]() |
return token_id
|
||
![]() |
|
||
|
|
||
![]() |
@router.post("/onboarding", tags=["users"], response_model=data.OnboardingState)
|
||
![]() |
async def set_onboarding_state(
|
||
|
request: Request,
|
||
![]() |
onboarding_data: data.OnboardingState = Body(...),
|
||
![]() |
) -> data.OnboardingState:
|
||
|
|
||
|
token = request.state.token
|
||
|
try:
|
||
![]() |
response = bc.list_resources(
|
||
|
token=token,
|
||
|
params={"type": data.USER_ONBOARDING_STATE},
|
||
|
timeout=BUGOUT_REQUEST_TIMEOUT_SECONDS,
|
||
|
)
|
||
|
resource_data = {"type": data.USER_ONBOARDING_STATE, **onboarding_data.dict()}
|
||
![]() |
if response.resources:
|
||
![]() |
resource = bc.update_resource(
|
||
![]() |
token=token,
|
||
|
resource_id=str(response.resources[0].id),
|
||
|
resource_data={"update": resource_data, "drop_keys": []},
|
||
|
)
|
||
|
else:
|
||
![]() |
resource = create_onboarding_resource(
|
||
![]() |
token=token, resource_data=resource_data
|
||
|
)
|
||
|
|
||
|
except BugoutResponseException as e:
|
||
![]() |
raise MoonstreamHTTPException(status_code=e.status_code, detail=e.detail)
|
||
![]() |
except Exception as e:
|
||
![]() |
raise MoonstreamHTTPException(status_code=500)
|
||
![]() |
|
||
|
if (
|
||
|
resource.resource_data.get("is_complete") is None
|
||
|
or resource.resource_data.get("steps") is None
|
||
|
):
|
||
|
logger.error(
|
||
|
f"Resources did not return correct onboarding object. Resource id:{resource.id}"
|
||
|
)
|
||
![]() |
raise MoonstreamHTTPException(status_code=500)
|
||
![]() |
|
||
|
result = data.OnboardingState(
|
||
|
is_complete=resource.resource_data.get("is_complete", False),
|
||
|
steps=resource.resource_data.get("steps", {}),
|
||
|
)
|
||
|
return result
|
||
![]() |
|
||
|
|
||
![]() |
@router.get("/onboarding", tags=["users"], response_model=data.OnboardingState)
|
||
![]() |
async def get_onboarding_state(request: Request) -> data.OnboardingState:
|
||
|
token = request.state.token
|
||
|
try:
|
||
![]() |
response = bc.list_resources(
|
||
|
token=token,
|
||
|
params={"type": data.USER_ONBOARDING_STATE},
|
||
|
timeout=BUGOUT_REQUEST_TIMEOUT_SECONDS,
|
||
|
)
|
||
![]() |
|
||
![]() |
if response.resources:
|
||
![]() |
resource = response.resources[0]
|
||
![]() |
else:
|
||
![]() |
resource = create_onboarding_resource(token=token)
|
||
![]() |
except BugoutResponseException as e:
|
||
![]() |
raise MoonstreamHTTPException(status_code=e.status_code, detail=e.detail)
|
||
![]() |
except Exception as e:
|
||
![]() |
|
||
![]() |
raise MoonstreamHTTPException(status_code=500)
|
||
![]() |
|
||
|
if (
|
||
|
resource.resource_data.get("is_complete") is None
|
||
|
or resource.resource_data.get("steps") is None
|
||
|
):
|
||
|
logger.error(
|
||
|
f"Resources did not return correct onboarding object. Resource id:{resource.id}"
|
||
|
)
|
||
![]() |
raise MoonstreamHTTPException(status_code=500)
|
||
![]() |
result = data.OnboardingState(
|
||
|
is_complete=resource.resource_data.get("is_complete", False),
|
||
|
steps=resource.resource_data.get("steps", {}),
|
||
|
)
|
||
|
return result
|
||
![]() |
|
||
|
|
||
![]() |
@router.delete("/onboarding", tags=["users"], response_model=data.OnboardingState)
|
||
![]() |
async def delete_onboarding_state(request: Request) -> data.OnboardingState:
|
||
|
token = request.state.token
|
||
|
try:
|
||
![]() |
response = bc.list_resources(
|
||
|
token=token,
|
||
|
params={"type": data.USER_ONBOARDING_STATE},
|
||
|
timeout=BUGOUT_REQUEST_TIMEOUT_SECONDS,
|
||
|
)
|
||
|
if not response.resources:
|
||
![]() |
raise MoonstreamHTTPException(status_code=404, detail="not found")
|
||
![]() |
if response.resources:
|
||
|
resource: BugoutResource = bc.delete_resource(
|
||
|
token=token,
|
||
|
resource_id=response.resources[0].id,
|
||
|
timeout=BUGOUT_REQUEST_TIMEOUT_SECONDS,
|
||
|
)
|
||
|
|
||
|
except BugoutResponseException as e:
|
||
![]() |
raise MoonstreamHTTPException(status_code=e.status_code, detail=e.detail)
|
||
![]() |
except Exception as e:
|
||
![]() |
raise MoonstreamHTTPException(status_code=500)
|
||
![]() |
|
||
|
if (
|
||
|
resource.resource_data.get("is_complete") is None
|
||
|
or resource.resource_data.get("steps") is None
|
||
|
):
|
||
|
logger.error(
|
||
|
f"Resources did not return correct onboarding object. Resource id:{resource.id}"
|
||
|
)
|
||
![]() |
raise MoonstreamHTTPException(status_code=500)
|
||
![]() |
result = data.OnboardingState(
|
||
|
is_complete=resource.resource_data.get("is_complete", False),
|
||
|
steps=resource.resource_data.get("steps", {}),
|
||
|
)
|
||
|
return result
|