diff --git a/src/backend_api/app/api/api.py b/src/backend_api/app/api/api.py index 4795926e..6df9942b 100644 --- a/src/backend_api/app/api/api.py +++ b/src/backend_api/app/api/api.py @@ -19,8 +19,6 @@ test_prefix, turnstile, turnstile_prefix, - user, - user_prefix, ) api_router = APIRouter() @@ -42,9 +40,6 @@ api_router.include_router( item.router, prefix=f"/{item_prefix}", tags=[f"{item_prefix}s"] ) -api_router.include_router( - login.router, prefix=f"/{login_prefix}", tags=[f"{login_prefix}s"] -) api_router.include_router( modifier.router, prefix=f"/{modifier_prefix}", tags=[f"{modifier_prefix}s"] ) @@ -55,8 +50,10 @@ turnstile.router, prefix=f"/{turnstile_prefix}", tags=[f"{turnstile_prefix}s"] ) api_router.include_router( - user.router, prefix=f"/{user_prefix}", tags=[f"{user_prefix}s"] + test.router, prefix=f"/{test_prefix}", tags=[f"{test_prefix}s"] ) api_router.include_router( - test.router, prefix=f"/{test_prefix}", tags=[f"{test_prefix}s"] + login.router, + prefix=f"/{login_prefix}", + tags=[f"{login_prefix}s"], ) diff --git a/src/backend_api/app/api/routes/item.py b/src/backend_api/app/api/routes/item.py index e0161722..cef6074a 100644 --- a/src/backend_api/app/api/routes/item.py +++ b/src/backend_api/app/api/routes/item.py @@ -5,16 +5,12 @@ from sqlalchemy.orm import Session import app.core.schemas as schemas -from app.api.api_message_util import ( - get_delete_return_msg, -) from app.api.deps import ( get_current_active_superuser, get_current_active_user, get_db, ) from app.api.params import FilterParams -from app.core.models.models import Item from app.core.rate_limit.rate_limit_config import rate_limit_settings from app.core.rate_limit.rate_limiters import apply_user_rate_limits from app.crud import CRUD_item diff --git a/src/backend_api/app/api/routes/item_base_type.py b/src/backend_api/app/api/routes/item_base_type.py index ce7782f9..cdd2c31a 100644 --- a/src/backend_api/app/api/routes/item_base_type.py +++ b/src/backend_api/app/api/routes/item_base_type.py @@ -16,6 +16,7 @@ from app.core.models.models import ItemBaseType from app.core.rate_limit.rate_limit_config import rate_limit_settings from app.core.rate_limit.rate_limiters import ( + apply_ip_rate_limits, apply_user_rate_limits, ) from app.crud import CRUD_itemBaseType @@ -58,9 +59,8 @@ async def get_item_base_type( @router.get( "/", response_model=schemas.ItemBaseType | list[schemas.ItemBaseType], - dependencies=[Depends(get_current_active_user)], ) -@apply_user_rate_limits( +@apply_ip_rate_limits( rate_limit_settings.DEFAULT_USER_RATE_LIMIT_SECOND, rate_limit_settings.DEFAULT_USER_RATE_LIMIT_MINUTE, rate_limit_settings.DEFAULT_USER_RATE_LIMIT_HOUR, diff --git a/src/backend_api/app/api/routes/login.py b/src/backend_api/app/api/routes/login.py index d6f6860f..9a666e69 100644 --- a/src/backend_api/app/api/routes/login.py +++ b/src/backend_api/app/api/routes/login.py @@ -1,45 +1,23 @@ # From FastAPI Fullstack Template https://github.com/fastapi/full-stack-fastapi-template/blob/master/backend/app/api/routes/login.py -from typing import Annotated, Any +from typing import Annotated from fastapi import APIRouter, Depends, Request, Response -from fastapi.responses import HTMLResponse from fastapi.security import OAuth2PasswordRequestForm -from pydantic import EmailStr from sqlalchemy.orm import Session -from app.api.api_message_util import ( - get_password_rec_email_sent_success_msg, - get_user_psw_change_msg, -) from app.api.deps import ( - UserCachePasswordResetSession, UserCacheSession, - get_current_active_superuser, get_db, ) from app.core.config import settings -from app.core.models.models import User from app.core.rate_limit.rate_limit_config import rate_limit_settings from app.core.rate_limit.rate_limiters import ( apply_ip_rate_limits, ) -from app.core.schemas import Message, NewPassword, Token -from app.core.schemas.token import RecoverPassword -from app.core.security import ( - get_password_hash, - verify_password, -) +from app.core.schemas import Token from app.crud import CRUD_user from app.exceptions import ( BadLoginCredentialsError, - DbObjectDoesNotExistError, - EmailOrUsernameRequiredError, - InvalidTokenError, - NewPasswordIsSameError, -) -from app.utils.user import ( - generate_reset_password_email, - send_email, ) router = APIRouter() @@ -81,137 +59,3 @@ async def login_access_session( return Token( access_token=access_token, ) - - -@router.post("/password-recovery/") -@apply_ip_rate_limits( - rate_limit_settings.RECOVERY_PASSWORD_RATE_LIMIT_SECOND, - rate_limit_settings.RECOVERY_PASSWORD_RATE_LIMIT_MINUTE, - rate_limit_settings.RECOVERY_PASSWORD_RATE_LIMIT_HOUR, - rate_limit_settings.RECOVERY_PASSWORD_RATE_LIMIT_DAY, -) -async def recover_password( - request: Request, # noqa: ARG001 - response: Response, # noqa: ARG001 - body: RecoverPassword, - user_cache_password_reset: UserCachePasswordResetSession, - db: Session = Depends(get_db), -) -> Message: - """ - Password Recovery - """ - if not body.email and not body.username: - raise EmailOrUsernameRequiredError( - function_name=recover_password.__name__, - ) - get_user_filter = {} - if body.email: - get_user_filter["email"] = body.email - if body.username: - get_user_filter["username"] = body.username - user = CRUD_user.get(db=db, filter=get_user_filter) - if not user: - raise DbObjectDoesNotExistError( - model_table_name=User.__tablename__, - filter=get_user_filter, - function_name=recover_password.__name__, - ) - - password_reset_token = await user_cache_password_reset.create_user_cache_instance( - user=user, expire_seconds=settings.EMAIL_RESET_TOKEN_EXPIRE_SECONDS - ) - - if not body.email: - email = CRUD_user.get_email_by_username(db=db, username=body.username) - else: - email = body.email - - email_data = generate_reset_password_email( - email_to=user.email, email=email, token=password_reset_token - ) - send_email( - email_to=user.email, - subject=email_data.subject, - html_content=email_data.html_content, - ) - return get_password_rec_email_sent_success_msg() - - -@router.post("/reset-password/") -@apply_ip_rate_limits( - rate_limit_settings.RESET_PASSWORD_RATE_LIMIT_SECOND, - rate_limit_settings.RESET_PASSWORD_RATE_LIMIT_MINUTE, - rate_limit_settings.RESET_PASSWORD_RATE_LIMIT_HOUR, - rate_limit_settings.RESET_PASSWORD_RATE_LIMIT_DAY, -) -async def reset_password( - request: Request, # noqa: ARG001 - response: Response, # noqa: ARG001 - body: NewPassword, - user_cache_password_reset: UserCachePasswordResetSession, - db: Session = Depends(get_db), -) -> Message: - """ - Reset password - """ - cached_user = await user_cache_password_reset.verify_token(token=body.token) - - email = cached_user.email - if not email: - raise InvalidTokenError( - token=body.token, - function_name=reset_password.__name__, - ) - get_user_filter = {"email": email} - user = CRUD_user.get(db=db, filter=get_user_filter) - if not user: - raise DbObjectDoesNotExistError( - model_table_name=User.__tablename__, - filter=get_user_filter, - function_name=reset_password.__name__, - ) - if verify_password(body.new_password, user.hashedPassword): - raise NewPasswordIsSameError( - function_name=reset_password.__name__, - ) - hashed_password = get_password_hash(password=body.new_password) - user.hashedPassword = hashed_password - db.add(user) - db.commit() - db.refresh(user) - return get_user_psw_change_msg(user.username) - - -@router.post( - "/password-recovery-html-content/{email}", - dependencies=[Depends(get_current_active_superuser)], - response_class=HTMLResponse, -) -async def recover_password_html_content( - email: EmailStr, - user_cache_password_reset: UserCachePasswordResetSession, - db: Session = Depends(get_db), -) -> Any: - """ - HTML Content for Password Recovery - """ - filter = {"email": email} - user = CRUD_user.get(db=db, filter=filter) - - if not user: - raise DbObjectDoesNotExistError( - model_table_name=User.__tablename__, - filter=filter, - function_name=recover_password_html_content.__name__, - ) - password_reset_token = await user_cache_password_reset.create_user_cache_instance( - user=user, expire_seconds=settings.EMAIL_RESET_TOKEN_EXPIRE_SECONDS - ) - - email_data = generate_reset_password_email( - email_to=user.email, email=email, token=password_reset_token - ) - - return HTMLResponse( - content=email_data.html_content, headers={"subject:": email_data.subject} - ) diff --git a/src/backend_api/app/api/routes/modifier.py b/src/backend_api/app/api/routes/modifier.py index d4500c43..2a55852e 100644 --- a/src/backend_api/app/api/routes/modifier.py +++ b/src/backend_api/app/api/routes/modifier.py @@ -15,7 +15,10 @@ from app.api.params import FilterParams from app.core.models.models import Modifier from app.core.rate_limit.rate_limit_config import rate_limit_settings -from app.core.rate_limit.rate_limiters import apply_user_rate_limits +from app.core.rate_limit.rate_limiters import ( + apply_ip_rate_limits, + apply_user_rate_limits, +) from app.crud import CRUD_modifier router = APIRouter() @@ -88,9 +91,8 @@ async def get_all_modifiers( "/grouped_modifiers_by_effect/", response_model=schemas.GroupedModifierByEffect | list[schemas.GroupedModifierByEffect], - dependencies=[Depends(get_current_active_user)], ) -@apply_user_rate_limits( +@apply_ip_rate_limits( rate_limit_settings.DEFAULT_USER_RATE_LIMIT_SECOND, rate_limit_settings.DEFAULT_USER_RATE_LIMIT_MINUTE, rate_limit_settings.DEFAULT_USER_RATE_LIMIT_HOUR, diff --git a/src/backend_api/app/api/routes/plot.py b/src/backend_api/app/api/routes/plot.py index 154defe9..06ec9885 100644 --- a/src/backend_api/app/api/routes/plot.py +++ b/src/backend_api/app/api/routes/plot.py @@ -2,12 +2,8 @@ from sqlalchemy.ext.asyncio import AsyncSession from app.api.deps import ( - UserCacheSession, - get_async_current_active_user, get_async_db, - get_rate_limit_tier_by_request, get_user_ip_from_header, - get_username_by_request, ) from app.core.rate_limit.custom_rate_limiter import RateSpec from app.core.rate_limit.rate_limit_config import rate_limit_settings @@ -23,12 +19,10 @@ @router.post( "/", response_model=PlotData, - dependencies=[Depends(get_async_current_active_user)], ) async def get_plot_data( request: Request, query: PlotQuery, - user_cache_session: UserCacheSession, db: AsyncSession = Depends(get_async_db), ): """ @@ -37,19 +31,15 @@ async def get_plot_data( The 'PlotQuery' schema allows for modifier restriction and item specifications. """ - rate_limit_tier = await get_rate_limit_tier_by_request(request, user_cache_session) + request_limit = rate_limit_settings.TIER_0_PLOT_RATE_LIMIT rate_spec = RateSpec( - requests=rate_limit_tier, + requests=request_limit, cooldown_seconds=rate_limit_settings.PLOT_RATE_LIMIT_COOLDOWN_SECONDS, ) client_ip = get_user_ip_from_header(request) async with apply_custom_rate_limit( - unique_key="plot_" + get_username_by_request(request), - rate_spec=rate_spec, - prefix=plot_prefix, - ), apply_custom_rate_limit( unique_key="plot_" + client_ip, rate_spec=rate_spec, prefix=plot_prefix, diff --git a/src/backend_api/app/core/schemas/currency.py b/src/backend_api/app/core/schemas/currency.py index b2eb5c50..95c6b744 100644 --- a/src/backend_api/app/core/schemas/currency.py +++ b/src/backend_api/app/core/schemas/currency.py @@ -1,5 +1,3 @@ -import datetime as _dt - import pydantic as _pydantic diff --git a/src/backend_api/app/core/schemas/item_modifier.py b/src/backend_api/app/core/schemas/item_modifier.py index b317f809..ca2d8630 100644 --- a/src/backend_api/app/core/schemas/item_modifier.py +++ b/src/backend_api/app/core/schemas/item_modifier.py @@ -1,5 +1,3 @@ -import datetime as _dt - import pydantic as _pydantic diff --git a/src/backend_api/app/tests/test_simulating_env/api/routes/test_currency.py b/src/backend_api/app/tests/test_simulating_env/api/routes/test_currency.py index c892168c..6a74b4d2 100644 --- a/src/backend_api/app/tests/test_simulating_env/api/routes/test_currency.py +++ b/src/backend_api/app/tests/test_simulating_env/api/routes/test_currency.py @@ -13,9 +13,6 @@ from app.core.models.models import Currency from app.crud import CRUD_currency from app.crud.base import CRUDBase, ModelType -from app.tests.test_simulating_env.api.api_routes_test_slowapi_rate_limit import ( - TestRateLimitSlowAPI as RateLimitSlowAPITestClass, -) from app.tests.utils.model_utils.currency import ( create_random_currency_dict, generate_random_currency, @@ -135,5 +132,5 @@ class TestCurrency(test_api.TestAPI): pass -class TestCurrencyRateLimit(RateLimitSlowAPITestClass): - pass +# class TestCurrencyRateLimit(RateLimitSlowAPITestClass): +# pass diff --git a/src/backend_api/app/tests/test_simulating_env/api/routes/test_item_base_type.py b/src/backend_api/app/tests/test_simulating_env/api/routes/test_item_base_type.py index e82dfb68..7adb4a17 100644 --- a/src/backend_api/app/tests/test_simulating_env/api/routes/test_item_base_type.py +++ b/src/backend_api/app/tests/test_simulating_env/api/routes/test_item_base_type.py @@ -13,9 +13,6 @@ from app.core.models.models import ItemBaseType as model_ItemBaseType from app.crud import CRUD_itemBaseType from app.crud.base import CRUDBase, ModelType -from app.tests.test_simulating_env.api.api_routes_test_slowapi_rate_limit import ( - TestRateLimitSlowAPI as RateLimitSlowAPITestClass, -) from app.tests.utils.model_utils.item_base_type import ( create_random_item_base_type_dict, generate_random_item_base_type, @@ -132,5 +129,5 @@ class TestItemBaseType(test_api.TestAPI): pass -class TestItemBaseTypeRateLimit(RateLimitSlowAPITestClass): - pass +# class TestItemBaseTypeRateLimit(RateLimitSlowAPITestClass): +# pass diff --git a/src/backend_api/app/tests/test_simulating_env/api/routes/test_login.py b/src/backend_api/app/tests/test_simulating_env/api/routes/test_login.py index 101c1fa1..34afc785 100644 --- a/src/backend_api/app/tests/test_simulating_env/api/routes/test_login.py +++ b/src/backend_api/app/tests/test_simulating_env/api/routes/test_login.py @@ -1,21 +1,11 @@ from collections.abc import Awaitable -from unittest.mock import patch import pytest from fastapi import Response from httpx import AsyncClient -from sqlalchemy.orm import Session -from app.api.api_message_util import ( - get_password_rec_email_sent_success_msg, - get_user_psw_change_msg, -) -from app.api.routes.login import login_access_session, login_prefix, reset_password -from app.core.cache.user_cache import UserCache +from app.api.routes.login import login_access_session, login_prefix from app.core.config import settings -from app.core.security import verify_password -from app.crud import CRUD_user -from app.exceptions import InvalidTokenError, NewPasswordIsSameError from app.tests.test_simulating_env.api.api_test_rate_limit_base import TestRateLimitBase from app.tests.test_simulating_env.base_test import BaseTest from app.tests.utils.rate_limit import ( @@ -79,164 +69,6 @@ async def test_get_access_token_incorrect_password_user( ) assert r.status_code == 401 - @pytest.mark.anyio - async def test_recovery_password( - self, async_client: AsyncClient, normal_user_token_headers: dict[str, str] - ) -> None: - """No test email yet. Checks internal errors without sending an email""" - with ( - patch("app.core.config.settings.SMTP_HOST", "smtp.example.com"), - patch("app.core.config.settings.SMTP_USER", "admin@example.com"), - ): - email_data = {"email": "test@example.com"} - r = await async_client.post( - f"{settings.API_V1_STR}/{login_prefix}/password-recovery/", - headers=normal_user_token_headers, - json=email_data, - ) - assert r.status_code == 200 - assert r.json() == { - "message": get_password_rec_email_sent_success_msg().message - } - - @pytest.mark.anyio - async def test_recovery_password_user_not_exists_email( - self, async_client: AsyncClient, normal_user_token_headers: dict[str, str] - ) -> None: - email = "jVgQr@example.com" - r = await async_client.post( - f"{settings.API_V1_STR}/password-recovery/", - headers=normal_user_token_headers, - json={"email": email}, - ) - assert r.status_code == 404 - - @pytest.mark.anyio - async def test_recovery_password_user_not_exists_username( - self, async_client: AsyncClient, normal_user_token_headers: dict[str, str] - ) -> None: - username_data = {"username": "jVgQr"} - r = await async_client.post( - f"{settings.API_V1_STR}/{login_prefix}/password-recovery/", - headers=normal_user_token_headers, - json=username_data, - ) - assert r.status_code == 404 - - @pytest.mark.anyio - async def test_reset_password( - self, - async_client: AsyncClient, - user_cache_password_reset: UserCache, - superuser_token_headers: dict[str, str], - db: Session, - ) -> None: - user = CRUD_user.get(db, filter={"email": settings.FIRST_SUPERUSER}) - assert user - assert verify_password(settings.FIRST_SUPERUSER_PASSWORD, user.hashedPassword) - - new_password = "the_new_password" - token = await user_cache_password_reset.create_user_cache_instance( - user=user, expire_seconds=settings.EMAIL_RESET_TOKEN_EXPIRE_SECONDS - ) - new_psw_data = {"new_password": new_password, "token": token} - r = await async_client.post( - f"{settings.API_V1_STR}/{login_prefix}/reset-password/", - headers=superuser_token_headers, - json=new_psw_data, - ) - assert r.status_code == 200 - assert r.json() == { - "message": get_user_psw_change_msg( - settings.FIRST_SUPERUSER_USERNAME - ).message - } - user = CRUD_user.get(db, filter={"email": settings.FIRST_SUPERUSER}) - db.refresh(user) - assert user - assert verify_password(new_password, user.hashedPassword) - - # Reset password back to original - reset_token = await user_cache_password_reset.create_user_cache_instance( - user=user, expire_seconds=settings.EMAIL_RESET_TOKEN_EXPIRE_SECONDS - ) - old_password = settings.FIRST_SUPERUSER_PASSWORD - old_psw_data = {"new_password": old_password, "token": reset_token} - r = await async_client.post( - f"{settings.API_V1_STR}/{login_prefix}/reset-password/", - headers=superuser_token_headers, - json=old_psw_data, - ) - assert r.status_code == 200 - assert r.json() == { - "message": get_user_psw_change_msg( - settings.FIRST_SUPERUSER_USERNAME - ).message - } - - user = CRUD_user.get(db, filter={"email": settings.FIRST_SUPERUSER}) - db.refresh(user) - assert user - assert verify_password(old_password, user.hashedPassword) - - @pytest.mark.anyio - async def test_reset_same_password( - self, - async_client: AsyncClient, - user_cache_password_reset: UserCache, - superuser_token_headers: dict[str, str], - db: Session, - ) -> None: - new_password = settings.FIRST_SUPERUSER_PASSWORD - user = CRUD_user.get(db, filter={"email": settings.FIRST_SUPERUSER}) - token = await user_cache_password_reset.create_user_cache_instance( - user=user, expire_seconds=settings.EMAIL_RESET_TOKEN_EXPIRE_SECONDS - ) - data = {"new_password": new_password, "token": token} - r = await async_client.post( - f"{settings.API_V1_STR}/{login_prefix}/reset-password/", - headers=superuser_token_headers, - json=data, - ) - assert r.status_code == 400 - assert ( - r.json()["detail"] - == NewPasswordIsSameError( - function_name=reset_password.__name__, - ).detail - ) - - user = CRUD_user.get(db, filter={"email": settings.FIRST_SUPERUSER}) - db.refresh(user) - assert user - assert verify_password(settings.FIRST_SUPERUSER_PASSWORD, user.hashedPassword) - - @pytest.mark.anyio - async def test_reset_password_invalid_token( - self, - async_client: AsyncClient, - user_cache_password_reset: UserCache, - superuser_token_headers: dict[str, str], - ) -> None: - invalid_token = "invalid" - data = {"new_password": "the_new_password", "token": invalid_token} - r = await async_client.post( - f"{settings.API_V1_STR}/{login_prefix}/reset-password/", - headers=superuser_token_headers, - json=data, - ) - response = r.json() - assert "detail" in response - assert r.status_code == 401 - assert ( - response["detail"] - == InvalidTokenError( - token=invalid_token, - function_name=user_cache_password_reset.verify_token.__name__, - class_name=user_cache_password_reset.__class__.__name__, - ).detail - ) - @pytest.mark.usefixtures("clear_db", autouse=True) @pytest.mark.skipif( diff --git a/src/backend_api/app/tests/test_simulating_env/api/routes/test_modifier.py b/src/backend_api/app/tests/test_simulating_env/api/routes/test_modifier.py index 5aec7ed7..c68e75b8 100644 --- a/src/backend_api/app/tests/test_simulating_env/api/routes/test_modifier.py +++ b/src/backend_api/app/tests/test_simulating_env/api/routes/test_modifier.py @@ -13,9 +13,6 @@ from app.core.models.models import Modifier from app.crud import CRUD_modifier from app.crud.base import CRUDBase, ModelType -from app.tests.test_simulating_env.api.api_routes_test_slowapi_rate_limit import ( - TestRateLimitSlowAPI as RateLimitSlowAPITestClass, -) from app.tests.utils.model_utils.modifier import ( create_random_modifier_dict, generate_random_modifier, @@ -132,5 +129,5 @@ class TestModifier(test_api.TestAPI): pass -class TestModifierRateLimit(RateLimitSlowAPITestClass): - pass +# class TestModifierRateLimit(RateLimitSlowAPITestClass): +# pass diff --git a/src/backend_api/app/tests/test_simulating_env/api/routes/test_plot.py b/src/backend_api/app/tests/test_simulating_env/api/routes/test_plot.py index a93188c8..b06f2243 100644 --- a/src/backend_api/app/tests/test_simulating_env/api/routes/test_plot.py +++ b/src/backend_api/app/tests/test_simulating_env/api/routes/test_plot.py @@ -67,7 +67,6 @@ async def test_post_plot_rate_limit( self, db: Session, async_client: AsyncClient, - superuser_token_headers: dict[str, str], ) -> None: """ Perform rate limit test for POST plot endpoint. @@ -75,22 +74,21 @@ async def test_post_plot_rate_limit( plot_query = await create_minimal_random_plot_query_dict(db) # Create API function for POST plot request - async def post_plot_query_from_api_super_user( + async def post_plot_query_from_api( query: dict[str, Any], ) -> Awaitable[Response]: return await async_client.post( f"{settings.API_V1_STR}/{plot_prefix}/", - headers=superuser_token_headers, json=query, ) # Get rate limit per time interval for POST plot request rate_limits_per_interval_format = RateLimitPerTimeInterval( - rate_per_interval=f"{rate_limit_settings.TIER_SUPERUSER_PLOT_RATE_LIMIT}/second" + rate_per_interval=f"{rate_limit_settings.TIER_0_PLOT_RATE_LIMIT}/second" ) await self.perform_time_interval_requests_with_api_function( - api_function=post_plot_query_from_api_super_user, + api_function=post_plot_query_from_api, all_rate_limits_per_interval=rate_limits_per_interval_format, query=plot_query, ) diff --git a/src/backend_api/app/tests/test_simulating_env/api/routes/test_user.py b/src/backend_api/app/tests/test_simulating_env/api/routes/test_user.py deleted file mode 100644 index e8373483..00000000 --- a/src/backend_api/app/tests/test_simulating_env/api/routes/test_user.py +++ /dev/null @@ -1,1181 +0,0 @@ -import asyncio -import uuid -from collections.abc import Awaitable -from unittest.mock import patch - -import pytest -from fastapi import Response -from httpx import AsyncClient -from redis.asyncio import Redis -from sqlalchemy.orm import Session - -from app.api.api_message_util import ( - get_delete_return_msg, - get_set_rate_limit_tier_success_msg, - get_user_active_change_msg, - get_user_psw_change_msg, - get_user_register_confirmation_sent_msg, - get_user_successfully_registered_msg, - get_user_update_me_confirmation_sent_msg, - get_user_update_me_success_msg, -) -from app.api.deps import get_current_active_superuser, get_current_user -from app.api.routes import user_prefix -from app.api.routes.user import ( - delete_user, - delete_user_me, - get_user_by_id, - register_user_send_confirmation, -) -from app.core.cache.user_cache import UserCache -from app.core.config import settings -from app.core.models.models import User -from app.core.schemas import UserCreate -from app.core.security import verify_password -from app.crud import CRUD_user -from app.exceptions import ( - DbObjectAlreadyExistsError, - DbObjectDoesNotExistError, - InvalidPasswordError, - InvalidTokenError, - NewPasswordIsSameError, - SuperUserNotAllowedToDeleteSelfError, - UserIsNotActiveError, - UserWithNotEnoughPrivilegesError, -) -from app.tests.test_simulating_env.api.api_test_rate_limit_base import TestRateLimitBase -from app.tests.test_simulating_env.base_test import BaseTest -from app.tests.utils.rate_limit import ( - get_function_decorator_rate_limit_per_time_interval, -) -from app.tests.utils.utils import random_email, random_lower_string - - -@pytest.mark.usefixtures("clear_db", autouse=True) -class TestUserAPI(BaseTest): - @pytest.mark.anyio - async def _get_current_normal_user( - self, - async_client: AsyncClient, - normal_user_token_headers: dict[str, str], - db: Session, - ) -> User: - get_normal_user_response = await async_client.get( - f"{settings.API_V1_STR}/{user_prefix}/me", - headers=normal_user_token_headers, - ) - normal_user_id = get_normal_user_response.json()["userId"] - normal_user = db.get(User, normal_user_id) - return normal_user - - @pytest.mark.anyio - async def test_get_users_superuser_me( - self, async_client: AsyncClient, superuser_token_headers: dict[str, str] - ) -> None: - r = await async_client.get( - f"{settings.API_V1_STR}/{user_prefix}/me", headers=superuser_token_headers - ) - current_user = r.json() - assert current_user - assert current_user["isActive"] - assert current_user["isSuperuser"] - assert current_user["email"] == settings.FIRST_SUPERUSER - assert current_user["username"] == settings.FIRST_SUPERUSER_USERNAME - - @pytest.mark.anyio - async def test_get_users_normal_user_me( - self, async_client: AsyncClient, normal_user_token_headers: dict[str, str] - ) -> None: - r = await async_client.get( - f"{settings.API_V1_STR}/{user_prefix}/me", headers=normal_user_token_headers - ) - current_user = r.json() - assert current_user - assert current_user["isActive"] - assert current_user["isSuperuser"] is False - assert current_user["email"] == settings.TEST_USER_EMAIL - assert current_user["username"] == settings.TEST_USER_USERNAME - - @pytest.mark.anyio - async def test_create_user_new_email( - self, - async_client: AsyncClient, - superuser_token_headers: dict[str, str], - db: Session, - ) -> None: - with ( - patch("app.utils.user.send_email", return_value=None), - patch("app.core.config.settings.SMTP_HOST", "smtp.example.com"), - patch("app.core.config.settings.SMTP_USER", "admin@example.com"), - ): - email = random_email() - password = random_lower_string() - username = random_lower_string(small_string=True) - data = {"email": email, "password": password, "username": username} - r = await async_client.post( - f"{settings.API_V1_STR}/{user_prefix}/", - headers=superuser_token_headers, - json=data, - ) - assert 200 <= r.status_code < 300 - created_user = r.json() - user = CRUD_user.get(db=db, filter={"email": email}) - assert user - assert user.email == created_user["email"] - assert user.username == created_user["username"] - - @pytest.mark.anyio - async def test_get_existing_user( - self, - async_client: AsyncClient, - superuser_token_headers: dict[str, str], - db: Session, - ) -> None: - email = random_email() - password = random_lower_string() - username = random_lower_string(small_string=True) - user_in = UserCreate(email=email, password=password, username=username) - user = CRUD_user.create(db=db, user_create=user_in) - user_id = user.userId - r = await async_client.get( - f"{settings.API_V1_STR}/{user_prefix}/{user_id}", - headers=superuser_token_headers, - ) - assert 200 <= r.status_code < 300 - api_user = r.json() - existing_user = CRUD_user.get(db=db, filter={"email": email}) - assert existing_user - assert existing_user.email == api_user["email"] - assert existing_user.username == api_user["username"] - - @pytest.mark.anyio - async def test_get_existing_user_current_user( - self, async_client: AsyncClient, db: Session - ) -> None: - email = random_email() - password = random_lower_string() - username = random_lower_string(small_string=True) - user_in = UserCreate(email=email, password=password, username=username) - user = CRUD_user.create(db=db, user_create=user_in) - user_id = user.userId - - login_data = { - "email": email, - "password": password, - "username": username, - } - r = await async_client.post( - f"{settings.API_V1_STR}/login/access-token", data=login_data - ) - tokens = r.json() - a_token = tokens["access_token"] - headers = {"Authorization": f"Bearer {a_token}"} - - r = await async_client.get( - f"{settings.API_V1_STR}/{user_prefix}/{user_id}", - headers=headers, - ) - assert 200 <= r.status_code < 300 - api_user = r.json() - existing_user = CRUD_user.get(db=db, filter={"email": email}) - assert existing_user - assert existing_user.email == api_user["email"] - assert existing_user.username == api_user["username"] - - @pytest.mark.anyio - async def test_get_existing_user_permissions_error( - self, - async_client: AsyncClient, - normal_user_token_headers: dict[str, str], - db: Session, - ) -> None: - # Create a user - email = random_email() - password = random_lower_string() - username = random_lower_string(small_string=True) - user_in = UserCreate(email=email, password=password, username=username) - user = CRUD_user.create(db=db, user_create=user_in) - user_id = user.userId - - r = await async_client.get( - f"{settings.API_V1_STR}/{user_prefix}/{user_id}", - headers=normal_user_token_headers, - ) - assert r.status_code == 403 - assert ( - r.json()["detail"] - == UserWithNotEnoughPrivilegesError( - function_name=get_user_by_id.__name__, - ).detail - ) - - @pytest.mark.anyio - async def test_create_user_existing_email( - self, - async_client: AsyncClient, - superuser_token_headers: dict[str, str], - db: Session, - ) -> None: - email = random_email() - password = random_lower_string() - username = random_lower_string(small_string=True) - user_in = UserCreate(email=email, password=password, username=username) - CRUD_user.create(db=db, user_create=user_in) - data = {"email": email, "password": password, "username": username} - r = await async_client.post( - f"{settings.API_V1_STR}/{user_prefix}/", - headers=superuser_token_headers, - json=data, - ) - created_user = r.json() - assert r.status_code == 409 - assert "userId" not in created_user - - @pytest.mark.anyio - async def test_create_user_existing_username( - self, - async_client: AsyncClient, - superuser_token_headers: dict[str, str], - db: Session, - ) -> None: - email = random_email() - password = random_lower_string() - username = random_lower_string(small_string=True) - user_in = UserCreate(email=email, password=password, username=username) - CRUD_user.create(db=db, user_create=user_in) - data = {"email": random_email(), "password": password, "username": username} - r = await async_client.post( - f"{settings.API_V1_STR}/{user_prefix}/", - headers=superuser_token_headers, - json=data, - ) - created_user = r.json() - assert r.status_code == 409 - assert "userId" not in created_user - - @pytest.mark.anyio - async def test_create_user_by_normal_user( - self, async_client: AsyncClient, normal_user_token_headers: dict[str, str] - ) -> None: - email = random_email() - password = random_lower_string() - username = random_lower_string(small_string=True) - data = {"email": email, "password": password, "username": username} - r = await async_client.post( - f"{settings.API_V1_STR}/{user_prefix}/", - headers=normal_user_token_headers, - json=data, - ) - assert r.status_code == 403 - - @pytest.mark.anyio - async def test_retrieve_users( - self, - async_client: AsyncClient, - superuser_token_headers: dict[str, str], - db: Session, - ) -> None: - email = random_email() - password = random_lower_string() - username = random_lower_string(small_string=True) - user_in = UserCreate(email=email, password=password, username=username) - CRUD_user.create(db=db, user_create=user_in) - - email2 = random_email() - password2 = random_lower_string() - username2 = random_lower_string(small_string=True) - user_in2 = UserCreate(email=email2, password=password2, username=username2) - CRUD_user.create(db=db, user_create=user_in2) - - r = await async_client.get( - f"{settings.API_V1_STR}/{user_prefix}/", headers=superuser_token_headers - ) - all_users = r.json() - - assert len(all_users["data"]) > 1 - assert "count" in all_users - for item in all_users["data"]: - assert "email" in item - assert "username" in item - - @pytest.mark.anyio - async def test_update_me_email( - self, - async_client: AsyncClient, - normal_user_token_headers: dict[str, str], - superuser_token_headers: dict[str, str], - db: Session, - user_cache_update_me: UserCache, - ) -> None: - normal_user = await self._get_current_normal_user( - async_client, normal_user_token_headers, db - ) - update_email = random_email() - update_data = {"email": update_email} - r_pre_confirm = await async_client.patch( - f"{settings.API_V1_STR}/{user_prefix}/update-me-email-pre-confirmation", - headers=normal_user_token_headers, - json=update_data, - ) - detail_pre_confirm = r_pre_confirm.json()["message"] - assert r_pre_confirm.status_code == 200 - assert ( - detail_pre_confirm - == get_user_update_me_confirmation_sent_msg(update_email).message - ) - assert normal_user.email != update_data["email"] - - user_update_email_token = await user_cache_update_me.create_user_cache_instance( - user=normal_user, - expire_seconds=settings.EMAIL_RESET_TOKEN_EXPIRE_SECONDS, - update_params=update_data, - ) - data_confirm = {"access_token": user_update_email_token} - r_confirm = await async_client.patch( - f"{settings.API_V1_STR}/{user_prefix}/update-me-email-confirmation", - headers=normal_user_token_headers, - json=data_confirm, - ) - details_confirm = r_confirm.json()["message"] - assert r_confirm.status_code == 200 - assert details_confirm == get_user_update_me_success_msg(update_email).message - db.refresh(normal_user) - assert settings.TEST_USER_EMAIL != normal_user.email - - # turn email back to settings.TEST_USER_EMAIL with superuser headers - update_data = {"email": settings.TEST_USER_EMAIL} - r_pre_confirm = await async_client.patch( - f"{settings.API_V1_STR}/{user_prefix}/{normal_user.userId}", - headers=superuser_token_headers, - json=update_data, - ) - assert r_pre_confirm.status_code == 200 - - @pytest.mark.anyio - async def test_update_me_username( - self, - async_client: AsyncClient, - normal_user_token_headers: dict[str, str], - superuser_token_headers: dict[str, str], - db: Session, - ) -> None: - normal_user = await self._get_current_normal_user( - async_client, normal_user_token_headers, db - ) - update_username = random_lower_string(small_string=True) - update_data = {"username": update_username} - assert normal_user.username != update_data["username"] - - r_confirm = await async_client.patch( - f"{settings.API_V1_STR}/{user_prefix}/update-me-username", - headers=normal_user_token_headers, - json=update_data, - ) - details_confirm = r_confirm.json()["message"] - assert r_confirm.status_code == 200 - assert ( - details_confirm == get_user_update_me_success_msg(update_username).message - ) - db.refresh(normal_user) - assert settings.TEST_USER_USERNAME != normal_user.username - - # turn username back to settings.TEST_USER_USERNAME with superuser headers - update_data = {"username": settings.TEST_USER_USERNAME} - r_pre_confirm = await async_client.patch( - f"{settings.API_V1_STR}/{user_prefix}/{normal_user.userId}", - headers=superuser_token_headers, - json=update_data, - ) - db.refresh(normal_user) - assert r_pre_confirm.status_code == 200 - - @pytest.mark.anyio - async def test_update_password_me( - self, - async_client: AsyncClient, - superuser_token_headers: dict[str, str], - db: Session, - ) -> None: - new_password = random_lower_string() - data = { - "current_password": settings.FIRST_SUPERUSER_PASSWORD, - "new_password": new_password, - } - r = await async_client.patch( - f"{settings.API_V1_STR}/{user_prefix}/me/password", - headers=superuser_token_headers, - json=data, - ) - assert r.status_code == 200 - updated_user = r.json() - assert ( - updated_user["message"] - == get_user_psw_change_msg(settings.FIRST_SUPERUSER_USERNAME).message - ) - - user_db = CRUD_user.get(db=db, filter={"email": settings.FIRST_SUPERUSER}) - assert user_db - assert user_db.email == settings.FIRST_SUPERUSER - assert user_db.username == settings.FIRST_SUPERUSER_USERNAME - assert verify_password(new_password, user_db.hashedPassword) - - # Revert to the old password to keep consistency in test - old_data = { - "current_password": new_password, - "new_password": settings.FIRST_SUPERUSER_PASSWORD, - } - r = await async_client.patch( - f"{settings.API_V1_STR}/{user_prefix}/me/password", - headers=superuser_token_headers, - json=old_data, - ) - db.refresh(user_db) - - assert r.status_code == 200 - assert verify_password( - settings.FIRST_SUPERUSER_PASSWORD, user_db.hashedPassword - ) - - @pytest.mark.anyio - async def test_update_password_me_incorrect_password( - self, async_client: AsyncClient, superuser_token_headers: dict[str, str] - ) -> None: - new_password = random_lower_string() - data = {"current_password": new_password, "new_password": new_password} - r = await async_client.patch( - f"{settings.API_V1_STR}/{user_prefix}/me/password", - headers=superuser_token_headers, - json=data, - ) - assert r.status_code == 401 - updated_user = r.json() - assert ( - updated_user["detail"] - == InvalidPasswordError( - function_name=CRUD_user.update_password.__name__, - class_name=CRUD_user.__class__.__name__, - ).detail - ) - - @pytest.mark.anyio - async def test_update_user_me_email_exists( - self, - async_client: AsyncClient, - normal_user_token_headers: dict[str, str], - db: Session, - ) -> None: - email = random_email() - password = random_lower_string() - username = random_lower_string(small_string=True) - user_in = UserCreate(email=email, password=password, username=username) - user = CRUD_user.create(db=db, user_create=user_in) - - data = {"email": user.email} - r = await async_client.patch( - f"{settings.API_V1_STR}/{user_prefix}/update-me-email-pre-confirmation", - headers=normal_user_token_headers, - json=data, - ) - assert r.status_code == 409 - assert ( - r.json()["detail"] - == DbObjectAlreadyExistsError( - model_table_name=User.__tablename__, - filter={"email": user.email}, - function_name=CRUD_user.check_exists_raise.__name__, - class_name=CRUD_user.__class__.__name__, - ).detail - ) - - @pytest.mark.anyio - async def test_update_user_me_username_exists( - self, - async_client: AsyncClient, - normal_user_token_headers: dict[str, str], - db: Session, - ) -> None: - email = random_email() - password = random_lower_string() - username = random_lower_string(small_string=True) - user_in = UserCreate(email=email, password=password, username=username) - user = CRUD_user.create(db=db, user_create=user_in) - - data = {"username": user.username} - r = await async_client.patch( - f"{settings.API_V1_STR}/{user_prefix}/update-me-username", - headers=normal_user_token_headers, - json=data, - ) - assert r.status_code == 409 - assert ( - r.json()["detail"] - == DbObjectAlreadyExistsError( - model_table_name=User.__tablename__, - filter={"username": user.username}, - function_name=CRUD_user.check_exists_raise.__name__, - class_name=CRUD_user.__class__.__name__, - ).detail - ) - - @pytest.mark.anyio - async def test_update_password_me_same_password_error( - self, async_client: AsyncClient, superuser_token_headers: dict[str, str] - ) -> None: - data = { - "current_password": settings.FIRST_SUPERUSER_PASSWORD, - "new_password": settings.FIRST_SUPERUSER_PASSWORD, - } - r = await async_client.patch( - f"{settings.API_V1_STR}/{user_prefix}/me/password", - headers=superuser_token_headers, - json=data, - ) - assert r.status_code == 400 - updated_user = r.json() - assert ( - updated_user["detail"] - == NewPasswordIsSameError( - function_name=CRUD_user.update_password.__name__, - class_name=CRUD_user.__class__.__name__, - ).detail - ) - - @pytest.mark.anyio - async def test_register_user( - self, - async_client: AsyncClient, - db: Session, - user_cache_register_user: UserCache, - ) -> None: - email = random_email() - password = random_lower_string() - username = random_lower_string(small_string=True) - data = {"email": email, "password": password, "username": username} - r_pre_confirm = await async_client.post( - f"{settings.API_V1_STR}/{user_prefix}/signup-send-confirmation", - json=data, - ) - details_pre_confirm = r_pre_confirm.json()["message"] - assert r_pre_confirm.status_code == 200 - assert ( - details_pre_confirm - == get_user_register_confirmation_sent_msg(username, email).message - ) - - user_pre_confirmed_db = CRUD_user.get(db=db, filter={"email": email}) - assert user_pre_confirmed_db.email == email - assert user_pre_confirmed_db.username == username - assert user_pre_confirmed_db.isActive is False - assert verify_password(password, user_pre_confirmed_db.hashedPassword) - - user_register_token = await user_cache_register_user.create_user_cache_instance( - user=user_pre_confirmed_db, - expire_seconds=settings.EMAIL_RESET_TOKEN_EXPIRE_SECONDS, - ) - data_confirm = {"access_token": user_register_token} - r_confirm = await async_client.post( - f"{settings.API_V1_STR}/{user_prefix}/signup", - json=data_confirm, - ) - assert r_confirm.status_code == 200 - details_confirm = r_confirm.json()["message"] - assert ( - details_confirm - == get_user_successfully_registered_msg(username, email).message - ) - user_after_confirmed_db = CRUD_user.get(db=db, filter={"email": email}) - db.refresh(user_after_confirmed_db) - assert user_after_confirmed_db.isActive - - @pytest.mark.anyio - async def test_register_user_email_already_exists_error( - self, async_client: AsyncClient - ) -> None: - password = random_lower_string() - username = random_lower_string(small_string=True) - data = { - "email": settings.FIRST_SUPERUSER, - "password": password, - "username": username, - } - r = await async_client.post( - f"{settings.API_V1_STR}/{user_prefix}/signup-send-confirmation", - json=data, - ) - assert r.status_code == 409 - assert ( - r.json()["detail"] - == DbObjectAlreadyExistsError( - model_table_name=User.__tablename__, - filter={"email": data["email"]}, - function_name=CRUD_user.check_exists_raise.__name__, - class_name=CRUD_user.__class__.__name__, - ).detail - ) - - @pytest.mark.anyio - async def test_register_user_username_already_exists_error( - self, async_client: AsyncClient - ) -> None: - email = random_email() - password = random_lower_string() - data = { - "email": email, - "password": password, - "username": settings.FIRST_SUPERUSER_USERNAME, - } - r = await async_client.post( - f"{settings.API_V1_STR}/{user_prefix}/signup-send-confirmation", - json=data, - ) - assert r.status_code == 409 - assert ( - r.json()["detail"] - == DbObjectAlreadyExistsError( - model_table_name=User.__tablename__, - filter={"username": data["username"]}, - function_name=CRUD_user.check_exists_raise.__name__, - class_name=CRUD_user.__class__.__name__, - ).detail - ) - - @pytest.mark.anyio - async def test_register_wrong_token( - self, - async_client: AsyncClient, - db: Session, - user_cache_register_user: UserCache, - ) -> None: - email = random_email() - password = random_lower_string() - username = random_lower_string(small_string=True) - data = {"email": email, "password": password, "username": username} - r_pre_confirm = await async_client.post( - f"{settings.API_V1_STR}/{user_prefix}/signup-send-confirmation", - json=data, - ) - details_pre_confirm = r_pre_confirm.json()["message"] - assert r_pre_confirm.status_code == 200 - assert ( - details_pre_confirm - == get_user_register_confirmation_sent_msg(username, email).message - ) - - user_pre_confirmed_db = CRUD_user.get(db=db, filter={"email": email}) - assert user_pre_confirmed_db.email == email - assert user_pre_confirmed_db.username == username - assert user_pre_confirmed_db.isActive is False - assert verify_password(password, user_pre_confirmed_db.hashedPassword) - - user_register_token = await user_cache_register_user.create_user_cache_instance( - user=user_pre_confirmed_db, - expire_seconds=settings.EMAIL_RESET_TOKEN_EXPIRE_SECONDS, - ) - - wrong_token = user_register_token + "wrong" - data_confirm = {"access_token": wrong_token} - r_confirm = await async_client.post( - f"{settings.API_V1_STR}/{user_prefix}/signup", - json=data_confirm, - ) - details_confirm = r_confirm.json()["detail"] - assert r_confirm.status_code == 401 - assert ( - details_confirm - == InvalidTokenError( - token=wrong_token, - function_name=user_cache_register_user.verify_token.__name__, - class_name=user_cache_register_user.__class__.__name__, - ).detail - ) - - @pytest.mark.anyio - async def test_update_user( - self, - async_client: AsyncClient, - superuser_token_headers: dict[str, str], - db: Session, - ) -> None: - email = random_email() - password = random_lower_string() - username = random_lower_string(small_string=True) - user_in = UserCreate(email=email, password=password, username=username) - user = CRUD_user.create(db=db, user_create=user_in) - updated_username = random_lower_string(small_string=True) - - data = {"username": updated_username} - r = await async_client.patch( - f"{settings.API_V1_STR}/{user_prefix}/{user.userId}", - headers=superuser_token_headers, - json=data, - ) - assert r.status_code == 200 - updated_user = r.json() - - assert updated_user["username"] == updated_username - - user_db = CRUD_user.get(db=db, filter={"email": email}) - db.refresh(user_db) - assert user_db - assert user_db.username == updated_username - - @pytest.mark.anyio - async def test_update_user_not_exists( - self, async_client: AsyncClient, superuser_token_headers: dict[str, str] - ) -> None: - data = {"username": "Updated_username"} - not_found_user_id = uuid.uuid4() - r = await async_client.patch( - f"{settings.API_V1_STR}/{user_prefix}/{not_found_user_id}", - headers=superuser_token_headers, - json=data, - ) - assert r.status_code == 404 - assert ( - r.json()["detail"] - == DbObjectDoesNotExistError( - model_table_name=User.__tablename__, - filter={"userId": not_found_user_id}, - function_name=CRUD_user.update.__name__, - class_name=CRUD_user.__class__.__name__, - ).detail - ) - - @pytest.mark.anyio - async def test_update_user_email_exists( - self, - async_client: AsyncClient, - superuser_token_headers: dict[str, str], - db: Session, - ) -> None: - email = random_email() - password = random_lower_string() - username = random_lower_string(small_string=True) - user_in = UserCreate(email=email, password=password, username=username) - user = CRUD_user.create(db=db, user_create=user_in) - - email2 = random_email() - password2 = random_lower_string() - username2 = random_lower_string(small_string=True) - user_in2 = UserCreate(email=email2, password=password2, username=username2) - user2 = CRUD_user.create(db=db, user_create=user_in2) - - data = {"email": user2.email} - r = await async_client.patch( - f"{settings.API_V1_STR}/{user_prefix}/{user.userId}", - headers=superuser_token_headers, - json=data, - ) - assert r.status_code == 409 - assert ( - r.json()["detail"] - == DbObjectAlreadyExistsError( - model_table_name=User.__tablename__, - filter=data, - function_name=CRUD_user.check_exists_raise.__name__, - class_name=CRUD_user.__class__.__name__, - ).detail - ) - - @pytest.mark.anyio - async def test_delete_user_me(self, async_client: AsyncClient, db: Session) -> None: - email = random_email() - password = random_lower_string() - username = random_lower_string(small_string=True) - user_in = UserCreate(email=email, password=password, username=username) - user = CRUD_user.create(db=db, user_create=user_in) - user_id = user.userId - - login_data = { - "email": email, - "password": password, - "username": username, - } - r = await async_client.post( - f"{settings.API_V1_STR}/login/access-token", data=login_data - ) - tokens = r.json() - a_token = tokens["access_token"] - headers = {"Authorization": f"Bearer {a_token}"} - - r = await async_client.delete( - f"{settings.API_V1_STR}/{user_prefix}/me", - headers=headers, - ) - assert r.status_code == 200 - deleted_user = r.json() - assert ( - deleted_user["message"] - == get_delete_return_msg(User.__tablename__, {"userId": user_id}).message - ) - - result = await async_client.get( - f"{settings.API_V1_STR}/{user_prefix}/{user_id}", - headers=headers, - ) - details = result.json()["detail"] - assert result.status_code == 404 - assert ( - details - == DbObjectDoesNotExistError( - model_table_name=User.__tablename__, - filter={"userId": user_id}, - function_name=get_current_user.__name__, - ).detail - ) - user_db = CRUD_user.get(db=db, filter={"userId": user_id}) - assert user_db is None - - @pytest.mark.anyio - async def test_delete_user_me_as_superuser( - self, async_client: AsyncClient, superuser_token_headers: dict[str, str] - ) -> None: - r = await async_client.delete( - f"{settings.API_V1_STR}/{user_prefix}/me", - headers=superuser_token_headers, - ) - assert r.status_code == 403 - response = r.json() - assert ( - response["detail"] - == SuperUserNotAllowedToDeleteSelfError( - function_name=delete_user_me.__name__, - ).detail - ) - - @pytest.mark.anyio - async def test_delete_user_me_not_active( - self, - async_client: AsyncClient, - db: Session, - normal_user_token_headers: dict[str, str], - superuser_token_headers: dict[str, str], - ) -> None: - normal_user = await self._get_current_normal_user( - async_client, normal_user_token_headers, db - ) - update_is_active_data = {"isActive": False} - r = await async_client.patch( - f"{settings.API_V1_STR}/{user_prefix}/{normal_user.userId}", - headers=superuser_token_headers, - json=update_is_active_data, - ) - - assert r.status_code == 200 - updated_user = r.json() - assert updated_user["isActive"] is False - - r = await async_client.delete( - f"{settings.API_V1_STR}/{user_prefix}/me", - headers=normal_user_token_headers, - ) - assert r.status_code == 403 - response = r.json() - - assert ( - response["detail"] - == UserIsNotActiveError( - function_name=get_current_user.__name__, - ).detail - ) - # revert to the old active status to keep consistency in test - update_is_active_data = {"isActive": True} - r = await async_client.patch( - f"{settings.API_V1_STR}/{user_prefix}/{normal_user.userId}", - headers=superuser_token_headers, - json=update_is_active_data, - ) - assert r.status_code == 200 - updated_user = r.json() - assert updated_user["isActive"] - - @pytest.mark.anyio - async def test_delete_user_super_user( - self, - async_client: AsyncClient, - superuser_token_headers: dict[str, str], - db: Session, - ) -> None: - email = random_email() - password = random_lower_string() - username = random_lower_string(small_string=True) - user_in = UserCreate(email=email, password=password, username=username) - user = CRUD_user.create(db=db, user_create=user_in) - user_id = user.userId - r = await async_client.delete( - f"{settings.API_V1_STR}/{user_prefix}/{user_id}", - headers=superuser_token_headers, - ) - assert r.status_code == 200 - deleted_user = r.json() - assert ( - deleted_user["message"] - == get_delete_return_msg(User.__tablename__, {"userId": user_id}).message - ) - result = CRUD_user.get(db=db, filter={"userId": user_id}) - assert result is None - - @pytest.mark.anyio - async def test_delete_user_not_found( - self, async_client: AsyncClient, superuser_token_headers: dict[str, str] - ) -> None: - not_found_user_id = uuid.uuid4() - r = await async_client.delete( - f"{settings.API_V1_STR}/{user_prefix}/{not_found_user_id}", - headers=superuser_token_headers, - ) - assert r.status_code == 404 - assert ( - r.json()["detail"] - == DbObjectDoesNotExistError( - model_table_name=User.__tablename__, - filter={"userId": not_found_user_id}, - function_name=delete_user.__name__, - ).detail - ) - - @pytest.mark.anyio - async def test_delete_user_current_super_user_error( - self, - async_client: AsyncClient, - superuser_token_headers: dict[str, str], - db: Session, - ) -> None: - super_user = CRUD_user.get(db=db, filter={"email": settings.FIRST_SUPERUSER}) - assert super_user - user_id = super_user.userId - - r = await async_client.delete( - f"{settings.API_V1_STR}/{user_prefix}/{user_id}", - headers=superuser_token_headers, - ) - assert r.status_code == 403 - assert ( - r.json()["detail"] - == SuperUserNotAllowedToDeleteSelfError( - function_name=delete_user.__name__, - ).detail - ) - - @pytest.mark.anyio - async def test_delete_user_without_privileges( - self, - async_client: AsyncClient, - normal_user_token_headers: dict[str, str], - db: Session, - ) -> None: - email = random_email() - password = random_lower_string() - username = random_lower_string(small_string=True) - user_in = UserCreate( - email=email, password=password, username=username, isActive=True - ) - user = CRUD_user.create(db=db, user_create=user_in) - - r = await async_client.delete( - f"{settings.API_V1_STR}/{user_prefix}/{user.userId}", - headers=normal_user_token_headers, - ) - assert r.status_code == 403 - assert ( - r.json()["detail"] - == UserWithNotEnoughPrivilegesError( - function_name=get_current_active_superuser.__name__, - ).detail - ) - - @pytest.mark.anyio - async def test_token_expired_user( - self, - async_client: AsyncClient, - db: Session, - get_cache: Redis, - user_cache_register_user: UserCache, - user_cache_session: UserCache, - ) -> None: - email = random_email() - password = random_lower_string() - username = random_lower_string(small_string=True) - data = {"email": email, "password": password, "username": username} - r = await async_client.post( - f"{settings.API_V1_STR}/{user_prefix}/signup-send-confirmation", - json=data, - ) - assert r.status_code == 200 - detail = r.json()["message"] - assert ( - detail == get_user_register_confirmation_sent_msg(username, email).message - ) - assert ( - detail == get_user_register_confirmation_sent_msg(username, email).message - ) - - user_db = CRUD_user.get(db=db, filter={"email": email}) - - token = await user_cache_register_user.create_user_cache_instance( - user=user_db, - expire_seconds=settings.EMAIL_RESET_TOKEN_EXPIRE_SECONDS, - ) - - r = await async_client.post( - f"{settings.API_V1_STR}/{user_prefix}/signup", - json={"access_token": token}, - ) - - assert r.status_code == 200 - - user_db = CRUD_user.get(db=db, filter={"email": email}) - assert user_db - assert user_db.email == email - assert user_db.username == username - assert verify_password(password, user_db.hashedPassword) - - # Test login with expired token - await get_cache.flushall() - with ( - patch("app.core.config.settings.ACCESS_SESSION_EXPIRE_SECONDS", 1), - ): - login_data = { - "email": email, - "password": password, - "username": username, - } - r = await async_client.post( - f"{settings.API_V1_STR}/login/access-token", data=login_data - ) - token = r.json()["access_token"] - headers = {"Authorization": f"Bearer {token}"} - await asyncio.sleep(1.1) # Wait for token to expire - r_get_user_me_ok = await async_client.get( - f"{settings.API_V1_STR}/{user_prefix}/me", - headers=headers, - ) - invalid_token_error = InvalidTokenError( - token=token, - function_name=user_cache_session.verify_token.__name__, - class_name=user_cache_session.__class__.__name__, - ) - assert r_get_user_me_ok.status_code == invalid_token_error.status_code - assert r_get_user_me_ok.json()["detail"] == invalid_token_error.detail - - @pytest.mark.anyio - async def test_change_is_active_user( - self, - async_client: AsyncClient, - db: Session, - superuser_token_headers: dict[str, str], - ) -> None: - email = random_email() - password = random_lower_string() - username = random_lower_string(small_string=True) - user_create = UserCreate( - email=email, password=password, username=username, isActive=True - ) - user = CRUD_user.create(db=db, user_create=user_create) - active_user_db = CRUD_user.get(db=db, filter={"email": email}) - assert active_user_db - assert active_user_db.isActive is True - update_is_active_data = {"user_id": str(user.userId), "is_active": False} - r = await async_client.patch( - f"{settings.API_V1_STR}/{user_prefix}/is_active/{user.userId}", - headers=superuser_token_headers, - params=update_is_active_data, - ) - assert r.status_code == 200 - assert ( - r.json()["message"] - == get_user_active_change_msg(user.username, active=False).message - ) - - updated_user_db = CRUD_user.get(db=db, filter={"email": email}) - db.refresh(updated_user_db) - assert updated_user_db.isActive is False - - @pytest.mark.anyio - async def test_change_rate_limit_tier_user( - self, - async_client: AsyncClient, - db: Session, - superuser_token_headers: dict[str, str], - ) -> None: - email = random_email() - password = random_lower_string() - username = random_lower_string(small_string=True) - user_create = UserCreate( - email=email, password=password, username=username, rateLimitTier=0 - ) - user = CRUD_user.create(db=db, user_create=user_create) - active_user_db = CRUD_user.get(db=db, filter={"email": email}) - assert active_user_db - assert active_user_db.rateLimitTier == 0 - new_rate_limit_tier = 1 - update_rate_limit_tier_data = { - "user_id": str(user.userId), - "rate_limit_tier": new_rate_limit_tier, - } - r = await async_client.patch( - f"{settings.API_V1_STR}/{user_prefix}/rate_limit_tier/{user.userId}", - headers=superuser_token_headers, - params=update_rate_limit_tier_data, - ) - assert r.status_code == 200 - assert ( - r.json()["message"] - == get_set_rate_limit_tier_success_msg( - user.username, rate_limit_tier=new_rate_limit_tier - ).message - ) - - updated_user_db = CRUD_user.get(db=db, filter={"email": email}) - db.refresh(updated_user_db) - assert updated_user_db.rateLimitTier == new_rate_limit_tier - - -@pytest.mark.usefixtures("clear_db", autouse=True) -@pytest.mark.skipif( - settings.SKIP_RATE_LIMIT_TEST is True or settings.SKIP_RATE_LIMIT_TEST == "True", - reason="Rate limit test is disabled", -) -class TestUserRateLimitAPI(TestRateLimitBase): - @pytest.mark.anyio - async def test_pre_register_user_rate_limit( - self, - async_client: AsyncClient, - ip_rate_limiter, # noqa: ARG001 # Do not remove, used to enable ip rate limiter - ) -> None: - """ - Perform rate limit test for pre register user endpoint. - """ - - # Create API function to test - def post_plot_query_from_api_normal_user( - register_data: dict[str, str], - ) -> Awaitable[Response]: - return async_client.post( - f"{settings.API_V1_STR}/{user_prefix}/signup-send-confirmation", - json=register_data, - ) - - # Get rate limit per time interval from register_user_send_confirmation API function - rate_limits_per_interval_format = ( - get_function_decorator_rate_limit_per_time_interval( - register_user_send_confirmation - ) - ) - - # Create object generator function to generate new users for each rate limit test - def create_register_user_object() -> dict[str, str]: - email = random_email() - password = random_lower_string() - username = random_lower_string(small_string=True) - return { - "email": email, - "password": password, - "username": username, - } - - await self.perform_time_interval_requests_with_api_function( - api_function=post_plot_query_from_api_normal_user, - all_rate_limits_per_interval=rate_limits_per_interval_format, - create_object_dict_func=create_register_user_object, - ) diff --git a/src/backend_api/app/tests/test_simulating_env/base_test.py b/src/backend_api/app/tests/test_simulating_env/base_test.py index 75b01455..8bd46ca2 100644 --- a/src/backend_api/app/tests/test_simulating_env/base_test.py +++ b/src/backend_api/app/tests/test_simulating_env/base_test.py @@ -1,7 +1,7 @@ import asyncio import math -from collections.abc import Callable -from typing import Any, Awaitable +from collections.abc import Awaitable, Callable +from typing import Any from sqlalchemy.inspection import inspect from sqlalchemy.orm import Session diff --git a/src/backend_api/app/tests/test_simulating_env/crud/crud_models/test_item_base_type.py b/src/backend_api/app/tests/test_simulating_env/crud/crud_models/test_item_base_type.py index 31fbcfd8..f7c47c46 100644 --- a/src/backend_api/app/tests/test_simulating_env/crud/crud_models/test_item_base_type.py +++ b/src/backend_api/app/tests/test_simulating_env/crud/crud_models/test_item_base_type.py @@ -3,9 +3,9 @@ import pytest import app.tests.test_simulating_env.crud.crud_test_base as test_crud +from app.core.models.models import ItemBaseType as model_ItemBaseType from app.crud import CRUD_itemBaseType from app.crud.base import CRUDBase -from app.core.models.models import ItemBaseType as model_ItemBaseType from app.tests.utils.model_utils.item_base_type import generate_random_item_base_type diff --git a/src/backend_api/app/tests/test_simulating_env/crud/crud_test_user.py b/src/backend_api/app/tests/test_simulating_env/crud/crud_test_user.py index 3d6ae04e..5421109b 100644 --- a/src/backend_api/app/tests/test_simulating_env/crud/crud_test_user.py +++ b/src/backend_api/app/tests/test_simulating_env/crud/crud_test_user.py @@ -1,5 +1,4 @@ import pytest -from fastapi.encoders import jsonable_encoder from sqlalchemy.orm import Session from app.core.schemas import UserCreate, UserUpdate diff --git a/src/backend_data_retrieval/data_retrieval_app/external_data_retrieval/transforming_data/roll_processor.py b/src/backend_data_retrieval/data_retrieval_app/external_data_retrieval/transforming_data/roll_processor.py index 2e1f6269..9242f89f 100644 --- a/src/backend_data_retrieval/data_retrieval_app/external_data_retrieval/transforming_data/roll_processor.py +++ b/src/backend_data_retrieval/data_retrieval_app/external_data_retrieval/transforming_data/roll_processor.py @@ -28,7 +28,9 @@ def add_modifier_df(self, modifier_df: pd.DataFrame): self.modifier_df = modifier_df def _pre_processing(self, df: pd.DataFrame) -> pd.DataFrame: - df.loc[:, "modifier"] = df["modifier"].replace( + df.loc[:, "modifier"] = df[ + "modifier" + ].replace( r"\\n|\n", " ", regex=True ) # Replaces newline with a space, so that it does not mess up the regex and matches modifiers in the `modifier` table @@ -95,9 +97,9 @@ def extract_rolls(matchobj: re.Match) -> str: matched_modifiers_mask = matched_modifiers.str.contains("matched", na=False) dynamic_w_rolls_df.loc[matched_modifiers_mask, "effect"] = effect - dynamic_w_rolls_df.loc[matched_modifiers_mask, "roll"] = ( - matched_modifiers.loc[matched_modifiers_mask] - ) + dynamic_w_rolls_df.loc[ + matched_modifiers_mask, "roll" + ] = matched_modifiers.loc[matched_modifiers_mask] dynamic_df.loc[matched_modifiers_mask, "modifier"] = pd.NA diff --git a/src/backend_data_retrieval/data_retrieval_app/utils.py b/src/backend_data_retrieval/data_retrieval_app/utils.py index 03af4b0a..f8c53062 100644 --- a/src/backend_data_retrieval/data_retrieval_app/utils.py +++ b/src/backend_data_retrieval/data_retrieval_app/utils.py @@ -1,13 +1,13 @@ -from datetime import datetime, timezone import logging from collections.abc import Generator +from datetime import datetime, timezone from typing import Any import pandas as pd import requests -from data_retrieval_app.logs.logger import main_logger as logger from data_retrieval_app.external_data_retrieval.config import settings +from data_retrieval_app.logs.logger import main_logger as logger def _chunks(lst: list[Any], n: int) -> Generator[Any, None, None]: diff --git a/src/frontend/.env b/src/frontend/.env index 7d3de6a7..4bc78a1a 100644 --- a/src/frontend/.env +++ b/src/frontend/.env @@ -1,5 +1,5 @@ VITE_API_URL=http://localhost # This is the URL for the FastAPI backend -VITE_APP_DEFAULT_LEAGUE=Settlers # This is the default league to show on the frontend +VITE_APP_DEFAULT_LEAGUE=Necro Settlers # This is the default league to show on the frontend VITE_APP_TURNSTILE_SITE_KEY=1x00000000000000000000AA # This is the site key for the Turnstile captcha -VITE_APP_LEAGUE_LAUNCH_TIME=2024-07-26T21:00:00Z # ISO 8601 format. Round backwards to whole hour number +VITE_APP_LEAGUE_LAUNCH_TIME=2024-11-07T19:00:00Z # ISO 8601 format. Round backwards to whole hour number diff --git a/src/frontend/openapi.json b/src/frontend/openapi.json index 71b14e83..3b098824 100644 --- a/src/frontend/openapi.json +++ b/src/frontend/openapi.json @@ -552,11 +552,6 @@ "summary": "Get All Item Base Types", "description": "Get all item base types.\n\nReturns a list of all item base types.", "operationId": "get_all_item_base_types", - "security": [ - { - "OAuth2PasswordBearer": [] - } - ], "parameters": [ { "name": "limit", @@ -1220,181 +1215,6 @@ } } }, - "/api/api_v1/login/access-token": { - "post": { - "tags": [ - "logins" - ], - "summary": "Login Access Session", - "description": "OAuth2 compatible session login.", - "operationId": "login_access_session", - "requestBody": { - "content": { - "application/x-www-form-urlencoded": { - "schema": { - "$ref": "#/components/schemas/Body_logins-login_access_session" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Token" - } - } - } - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - } - } - } - } - }, - "/api/api_v1/login/password-recovery/": { - "post": { - "tags": [ - "logins" - ], - "summary": "Recover Password", - "description": "Password Recovery", - "operationId": "recover_password", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/RecoverPassword" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Message" - } - } - } - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - } - } - } - } - }, - "/api/api_v1/login/reset-password/": { - "post": { - "tags": [ - "logins" - ], - "summary": "Reset Password", - "description": "Reset password", - "operationId": "reset_password", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/NewPassword" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Message" - } - } - } - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - } - } - } - } - }, - "/api/api_v1/login/password-recovery-html-content/{email}": { - "post": { - "tags": [ - "logins" - ], - "summary": "Recover Password Html Content", - "description": "HTML Content for Password Recovery", - "operationId": "recover_password_html_content", - "security": [ - { - "OAuth2PasswordBearer": [] - } - ], - "parameters": [ - { - "name": "email", - "in": "path", - "required": true, - "schema": { - "type": "string", - "format": "email", - "title": "Email" - } - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "text/html": { - "schema": { - "type": "string" - } - } - } - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - } - } - } - } - }, "/api/api_v1/modifier/{modifierId}": { "get": { "tags": [ @@ -1795,12 +1615,7 @@ } } } - }, - "security": [ - { - "OAuth2PasswordBearer": [] - } - ] + } } }, "/api/api_v1/plot/": { @@ -1842,12 +1657,7 @@ } } } - }, - "security": [ - { - "OAuth2PasswordBearer": [] - } - ] + } } }, "/api/api_v1/turnstile/": { @@ -1892,14 +1702,14 @@ } } }, - "/api/api_v1/user/": { - "get": { + "/api/api_v1/test/bulk-insert-test": { + "post": { "tags": [ - "users" + "tests" ], - "summary": "Get All Users", - "description": "Retrieve all users.", - "operationId": "get_all_users", + "summary": "Bulk Insert Test", + "description": "Can only be used in `settings.ENVIRONMENT=local` environment.\n\nTest route for bulk inserting records.\n\nReturns a success message once the insertion is complete.", + "operationId": "bulk_insert_test", "security": [ { "OAuth2PasswordBearer": [] @@ -1907,23 +1717,12 @@ ], "parameters": [ { - "name": "skip", - "in": "query", - "required": false, - "schema": { - "type": "integer", - "default": 0, - "title": "Skip" - } - }, - { - "name": "limit", + "name": "count", "in": "query", - "required": false, + "required": true, "schema": { "type": "integer", - "default": 100, - "title": "Limit" + "title": "Count" } } ], @@ -1933,7 +1732,8 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/UsersPublic" + "type": "object", + "title": "Response Tests-Bulk Insert Test" } } } @@ -1949,36 +1749,43 @@ } } } - }, + } + }, + "/api/api_v1/test/bulk-insert-users-and-verify": { "post": { "tags": [ - "users" + "tests" ], - "summary": "Create", - "description": "Create new user.", - "operationId": "create", + "summary": "Bulk Insert Users And Verify", + "description": "Can only be used in `settings.ENVIRONMENT=local` environment.\n\nTest route for bulk inserting users and verifying them.\n\nReturns the access tokens for the created users.", + "operationId": "bulk_insert_users_and_verify", "security": [ { "OAuth2PasswordBearer": [] } ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UserCreate" - } + "parameters": [ + { + "name": "count", + "in": "query", + "required": true, + "schema": { + "type": "integer", + "title": "Count" } } - }, + ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/UserPublic" + "type": "array", + "items": { + "type": "string" + }, + "title": "Response Tests-Bulk Insert Users And Verify" } } } @@ -1996,19 +1803,19 @@ } } }, - "/api/api_v1/user/update-me-email-pre-confirmation": { - "patch": { + "/api/api_v1/login/access-token": { + "post": { "tags": [ - "users" + "logins" ], - "summary": "Update Me Email Send Confirmation", - "description": "Send confirmation to update own user.", - "operationId": "update_me_email_send_confirmation", + "summary": "Login Access Session", + "description": "OAuth2 compatible session login.", + "operationId": "login_access_session", "requestBody": { "content": { - "application/json": { + "application/x-www-form-urlencoded": { "schema": { - "$ref": "#/components/schemas/UserUpdateMe" + "$ref": "#/components/schemas/Body_logins-login_access_session" } } }, @@ -2020,7 +1827,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/Message" + "$ref": "#/components/schemas/Token" } } } @@ -2035,763 +1842,7 @@ } } } - }, - "security": [ - { - "OAuth2PasswordBearer": [] - } - ] - } - }, - "/api/api_v1/user/update-me-email-confirmation": { - "patch": { - "tags": [ - "users" - ], - "summary": "Update Me Email Confirmation", - "description": "Confirm update email.", - "operationId": "update_me_email_confirmation", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Token" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Message" - } - } - } - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - } - } - }, - "security": [ - { - "OAuth2PasswordBearer": [] - } - ] - } - }, - "/api/api_v1/user/update-me-username": { - "patch": { - "tags": [ - "users" - ], - "summary": "Update Me Username", - "description": "Update username. Can only be used by users once a month.", - "operationId": "update_me_username", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UserUpdateMe" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Message" - } - } - } - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - } - } - }, - "security": [ - { - "OAuth2PasswordBearer": [] - } - ] - } - }, - "/api/api_v1/user/check-username-exists": { - "patch": { - "tags": [ - "users" - ], - "summary": "Check Username Exists", - "description": "Checks if username exists in the db.\n\nReturns `True` if the user exists, else `False`", - "operationId": "check_username_exists", - "security": [ - { - "OAuth2PasswordBearer": [] - } - ], - "parameters": [ - { - "name": "username", - "in": "query", - "required": true, - "schema": { - "type": "string", - "title": "Username" - } - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "type": "boolean", - "title": "Response Users-Check Username Exists" - } - } - } - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - } - } - } - } - }, - "/api/api_v1/user/me/password": { - "patch": { - "tags": [ - "users" - ], - "summary": "Update Password Me", - "description": "Update own password.", - "operationId": "update_password_me", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpdatePassword" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Message" - } - } - } - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - } - } - }, - "security": [ - { - "OAuth2PasswordBearer": [] - } - ] - } - }, - "/api/api_v1/user/me": { - "get": { - "tags": [ - "users" - ], - "summary": "Get User Me", - "description": "Get current user. User doesn't have to be active (confirmed email).", - "operationId": "get_user_me", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UserPublic" - } - } - } - } - }, - "security": [ - { - "OAuth2PasswordBearer": [] - } - ] - }, - "delete": { - "tags": [ - "users" - ], - "summary": "Delete User Me", - "description": "Delete own user.", - "operationId": "delete_user_me", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Message" - } - } - } - } - }, - "security": [ - { - "OAuth2PasswordBearer": [] - } - ] - } - }, - "/api/api_v1/user/signup-send-confirmation": { - "post": { - "tags": [ - "users" - ], - "summary": "Register User Send Confirmation", - "description": "Send email confirmation on user register. Account doesn't get created yet.", - "operationId": "register_user_send_confirmation", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UserRegisterPreEmailConfirmation" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Message" - } - } - } - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - } - } - } - } - }, - "/api/api_v1/user/signup": { - "post": { - "tags": [ - "users" - ], - "summary": "Register User Confirm", - "description": "Confirm new user without the need to be logged in. Requires email confirmation.", - "operationId": "register_user_confirm", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Token" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Message" - } - } - } - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - } - } - } - } - }, - "/api/api_v1/user/{user_id}": { - "get": { - "tags": [ - "users" - ], - "summary": "Get User By Id", - "description": "Get a specific user by id.", - "operationId": "get_user_by_id", - "security": [ - { - "OAuth2PasswordBearer": [] - } - ], - "parameters": [ - { - "name": "user_id", - "in": "path", - "required": true, - "schema": { - "type": "string", - "format": "uuid", - "title": "User Id" - } - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UserPublic" - } - } - } - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - } - } - } - }, - "patch": { - "tags": [ - "users" - ], - "summary": "Update User", - "description": "Update a user.", - "operationId": "update_user", - "security": [ - { - "OAuth2PasswordBearer": [] - } - ], - "parameters": [ - { - "name": "user_id", - "in": "path", - "required": true, - "schema": { - "type": "string", - "format": "uuid", - "title": "User Id" - } - } - ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UserUpdate" - } - } - } - }, - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UserPublic" - } - } - } - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - } - } - } - }, - "delete": { - "tags": [ - "users" - ], - "summary": "Delete User", - "description": "Delete a user.", - "operationId": "delete_user", - "security": [ - { - "OAuth2PasswordBearer": [] - } - ], - "parameters": [ - { - "name": "user_id", - "in": "path", - "required": true, - "schema": { - "type": "string", - "format": "uuid", - "title": "User Id" - } - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Message" - } - } - } - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - } - } - } - } - }, - "/api/api_v1/user/is_active/{user_id}": { - "patch": { - "tags": [ - "users" - ], - "summary": "Change Is Active User", - "description": "Change activity to current user.", - "operationId": "change_is_active_user", - "security": [ - { - "OAuth2PasswordBearer": [] - } - ], - "parameters": [ - { - "name": "user_id", - "in": "path", - "required": true, - "schema": { - "type": "string", - "format": "uuid", - "title": "User Id" - } - }, - { - "name": "is_active", - "in": "query", - "required": true, - "schema": { - "type": "boolean", - "title": "Is Active" - } - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Message" - } - } - } - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - } - } - } - } - }, - "/api/api_v1/user/rate_limit_tier/{user_id}": { - "patch": { - "tags": [ - "users" - ], - "summary": "Set Rate Limit Tier User", - "description": "Set rate limit tier to current user.", - "operationId": "set_rate_limit_tier_user", - "security": [ - { - "OAuth2PasswordBearer": [] - } - ], - "parameters": [ - { - "name": "user_id", - "in": "path", - "required": true, - "schema": { - "type": "string", - "format": "uuid", - "title": "User Id" - } - }, - { - "name": "rate_limit_tier", - "in": "query", - "required": true, - "schema": { - "type": "integer", - "title": "Rate Limit Tier" - } - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Message" - } - } - } - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - } - } - } - } - }, - "/api/api_v1/user/check-current-user-active": { - "post": { - "tags": [ - "users" - ], - "summary": "Check Current User Active", - "description": "Checks if the current user is active. Returns True if the user is active, otherwise False.", - "operationId": "check_current_user_active", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "type": "boolean", - "title": "Response Users-Check Current User Active" - } - } - } - } - }, - "security": [ - { - "OAuth2PasswordBearer": [] - } - ] - } - }, - "/api/api_v1/user/activation-token-send-confirmation": { - "post": { - "tags": [ - "users" - ], - "summary": "Set Active User Send Confirmation", - "description": "Send email confirmation to set active user during registration process.\nRute `/signup` is used to confirm the user.", - "operationId": "set_active_user_send_confirmation", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Message" - } - } - } - } - }, - "security": [ - { - "OAuth2PasswordBearer": [] - } - ] - } - }, - "/api/api_v1/test/bulk-insert-test": { - "post": { - "tags": [ - "tests" - ], - "summary": "Bulk Insert Test", - "description": "Can only be used in `settings.ENVIRONMENT=local` environment.\n\nTest route for bulk inserting records.\n\nReturns a success message once the insertion is complete.", - "operationId": "bulk_insert_test", - "security": [ - { - "OAuth2PasswordBearer": [] - } - ], - "parameters": [ - { - "name": "count", - "in": "query", - "required": true, - "schema": { - "type": "integer", - "title": "Count" - } - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "title": "Response Tests-Bulk Insert Test" - } - } - } - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - } - } - } - } - }, - "/api/api_v1/test/bulk-insert-users-and-verify": { - "post": { - "tags": [ - "tests" - ], - "summary": "Bulk Insert Users And Verify", - "description": "Can only be used in `settings.ENVIRONMENT=local` environment.\n\nTest route for bulk inserting users and verifying them.\n\nReturns the access tokens for the created users.", - "operationId": "bulk_insert_users_and_verify", - "security": [ - { - "OAuth2PasswordBearer": [] - } - ], - "parameters": [ - { - "name": "count", - "in": "query", - "required": true, - "schema": { - "type": "integer", - "title": "Count" - } - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "type": "string" - }, - "title": "Response Tests-Bulk Insert Users And Verify" - } - } - } - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - } - } - } + } } } }, @@ -3863,19 +2914,6 @@ "type": "object", "title": "ItemSpecs" }, - "Message": { - "properties": { - "message": { - "type": "string", - "title": "Message" - } - }, - "type": "object", - "required": [ - "message" - ], - "title": "Message" - }, "MetadataObject": { "properties": { "interactive": { @@ -4092,236 +3130,14 @@ }, "type": "object", "required": [ - "position", - "effect", - "modifierId", - "createdAt" - ], - "title": "Modifier" - }, - "ModifierCreate": { - "properties": { - "position": { - "type": "integer", - "title": "Position" - }, - "relatedUniques": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Relateduniques" - }, - "minRoll": { - "anyOf": [ - { - "type": "number" - }, - { - "type": "null" - } - ], - "title": "Minroll" - }, - "maxRoll": { - "anyOf": [ - { - "type": "number" - }, - { - "type": "null" - } - ], - "title": "Maxroll" - }, - "textRolls": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Textrolls" - }, - "static": { - "anyOf": [ - { - "type": "boolean" - }, - { - "type": "null" - } - ], - "title": "Static" - }, - "effect": { - "type": "string", - "title": "Effect" - }, - "regex": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Regex" - }, - "implicit": { - "anyOf": [ - { - "type": "boolean" - }, - { - "type": "null" - } - ], - "title": "Implicit" - }, - "explicit": { - "anyOf": [ - { - "type": "boolean" - }, - { - "type": "null" - } - ], - "title": "Explicit" - }, - "delve": { - "anyOf": [ - { - "type": "boolean" - }, - { - "type": "null" - } - ], - "title": "Delve" - }, - "fractured": { - "anyOf": [ - { - "type": "boolean" - }, - { - "type": "null" - } - ], - "title": "Fractured" - }, - "synthesised": { - "anyOf": [ - { - "type": "boolean" - }, - { - "type": "null" - } - ], - "title": "Synthesised" - }, - "unique": { - "anyOf": [ - { - "type": "boolean" - }, - { - "type": "null" - } - ], - "title": "Unique" - }, - "corrupted": { - "anyOf": [ - { - "type": "boolean" - }, - { - "type": "null" - } - ], - "title": "Corrupted" - }, - "enchanted": { - "anyOf": [ - { - "type": "boolean" - }, - { - "type": "null" - } - ], - "title": "Enchanted" - }, - "veiled": { - "anyOf": [ - { - "type": "boolean" - }, - { - "type": "null" - } - ], - "title": "Veiled" - } - }, - "type": "object", - "required": [ - "position", - "effect" - ], - "title": "ModifierCreate" - }, - "ModifierLimitations": { - "properties": { - "maxRoll": { - "anyOf": [ - { - "type": "number" - }, - { - "type": "null" - } - ], - "title": "Maxroll" - }, - "minRoll": { - "anyOf": [ - { - "type": "number" - }, - { - "type": "null" - } - ], - "title": "Minroll" - }, - "textRoll": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" - } - ], - "title": "Textroll" - } - }, - "type": "object", - "title": "ModifierLimitations" + "position", + "effect", + "modifierId", + "createdAt" + ], + "title": "Modifier" }, - "ModifierUpdate": { + "ModifierCreate": { "properties": { "position": { "type": "integer", @@ -4502,136 +3318,33 @@ "position", "effect" ], - "title": "ModifierUpdate" - }, - "NewPassword": { - "properties": { - "token": { - "type": "string", - "title": "Token" - }, - "new_password": { - "type": "string", - "maxLength": 40, - "minLength": 8, - "title": "New Password" - } - }, - "type": "object", - "required": [ - "token", - "new_password" - ], - "title": "NewPassword" - }, - "PlotData": { - "properties": { - "valueInChaos": { - "items": { - "type": "number" - }, - "type": "array", - "title": "Valueinchaos" - }, - "hoursSinceLaunch": { - "items": { - "type": "integer" - }, - "type": "array", - "title": "Hourssincelaunch" - }, - "valueInMostCommonCurrencyUsed": { - "items": { - "type": "number" - }, - "type": "array", - "title": "Valueinmostcommoncurrencyused" - }, - "confidence": { - "items": { - "type": "string", - "enum": [ - "low", - "medium", - "high" - ] - }, - "type": "array", - "title": "Confidence" - }, - "confidenceRating": { - "type": "string", - "enum": [ - "low", - "medium", - "high" - ], - "title": "Confidencerating" - }, - "mostCommonCurrencyUsed": { - "type": "string", - "title": "Mostcommoncurrencyused" - } - }, - "type": "object", - "required": [ - "valueInChaos", - "hoursSinceLaunch", - "valueInMostCommonCurrencyUsed", - "confidence", - "confidenceRating", - "mostCommonCurrencyUsed" - ], - "title": "PlotData" + "title": "ModifierCreate" }, - "PlotQuery": { + "ModifierLimitations": { "properties": { - "league": { - "type": "string", - "title": "League" - }, - "itemSpecifications": { - "anyOf": [ - { - "$ref": "#/components/schemas/ItemSpecs" - }, - { - "type": "null" - } - ] - }, - "baseSpecifications": { + "maxRoll": { "anyOf": [ { - "$ref": "#/components/schemas/BaseSpecs" + "type": "number" }, { "type": "null" } - ] - }, - "wantedModifiers": { - "items": { - "items": { - "$ref": "#/components/schemas/WantedModifier" - }, - "type": "array" - }, - "type": "array", - "title": "Wantedmodifiers" + ], + "title": "Maxroll" }, - "end": { + "minRoll": { "anyOf": [ { - "type": "integer" + "type": "number" }, { "type": "null" } ], - "title": "End" + "title": "Minroll" }, - "start": { + "textRoll": { "anyOf": [ { "type": "integer" @@ -4640,30 +3353,19 @@ "type": "null" } ], - "title": "Start" + "title": "Textroll" } }, "type": "object", - "required": [ - "league", - "wantedModifiers" - ], - "title": "PlotQuery" + "title": "ModifierLimitations" }, - "RecoverPassword": { + "ModifierUpdate": { "properties": { - "username": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Username" + "position": { + "type": "integer", + "title": "Position" }, - "email": { + "relatedUniques": { "anyOf": [ { "type": "string" @@ -4672,86 +3374,31 @@ "type": "null" } ], - "title": "Email" - } - }, - "type": "object", - "title": "RecoverPassword" - }, - "Token": { - "properties": { - "access_token": { - "type": "string", - "title": "Access Token" - } - }, - "type": "object", - "required": [ - "access_token" - ], - "title": "Token" - }, - "TurnstileQuery": { - "properties": { - "token": { - "type": "string", - "title": "Token" - }, - "ip": { - "type": "string", - "title": "Ip" - } - }, - "type": "object", - "required": [ - "token", - "ip" - ], - "title": "TurnstileQuery" - }, - "TurnstileResponse": { - "properties": { - "success": { - "type": "boolean", - "title": "Success" - }, - "error_codes": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "title": "Error Codes" + "title": "Relateduniques" }, - "challenge_ts": { + "minRoll": { "anyOf": [ { - "type": "string" + "type": "number" }, { "type": "null" } ], - "title": "Challenge Ts" + "title": "Minroll" }, - "hostname": { + "maxRoll": { "anyOf": [ { - "type": "string" + "type": "number" }, { "type": "null" } ], - "title": "Hostname" + "title": "Maxroll" }, - "action": { + "textRolls": { "anyOf": [ { "type": "string" @@ -4760,70 +3407,35 @@ "type": "null" } ], - "title": "Action" + "title": "Textrolls" }, - "cdata": { + "static": { "anyOf": [ { - "type": "string" + "type": "boolean" }, { "type": "null" } ], - "title": "Cdata" - }, - "metadata": { - "anyOf": [ - { - "$ref": "#/components/schemas/MetadataObject" - }, - { - "type": "null" - } - ] - } - }, - "type": "object", - "required": [ - "success" - ], - "title": "TurnstileResponse" - }, - "UpdatePassword": { - "properties": { - "current_password": { - "type": "string", - "minLength": 8, - "title": "Current Password" + "title": "Static" }, - "new_password": { - "type": "string", - "minLength": 8, - "title": "New Password" - } - }, - "type": "object", - "required": [ - "current_password", - "new_password" - ], - "title": "UpdatePassword" - }, - "UserCreate": { - "properties": { - "username": { + "effect": { "type": "string", - "maxLength": 30, - "pattern": "^[\\p{L}\\p{N}_]+$", - "title": "Username" + "title": "Effect" }, - "email": { - "type": "string", - "format": "email", - "title": "Email" + "regex": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Regex" }, - "isActive": { + "implicit": { "anyOf": [ { "type": "boolean" @@ -4832,10 +3444,9 @@ "type": "null" } ], - "title": "Isactive", - "default": true + "title": "Implicit" }, - "isSuperuser": { + "explicit": { "anyOf": [ { "type": "boolean" @@ -4844,22 +3455,20 @@ "type": "null" } ], - "title": "Issuperuser", - "default": false + "title": "Explicit" }, - "rateLimitTier": { + "delve": { "anyOf": [ { - "type": "integer" + "type": "boolean" }, { "type": "null" } ], - "title": "Ratelimittier", - "default": 0 + "title": "Delve" }, - "isBanned": { + "fractured": { "anyOf": [ { "type": "boolean" @@ -4868,37 +3477,9 @@ "type": "null" } ], - "title": "Isbanned", - "default": false - }, - "password": { - "type": "string", - "minLength": 8, - "title": "Password" - } - }, - "type": "object", - "required": [ - "username", - "email", - "password" - ], - "title": "UserCreate" - }, - "UserPublic": { - "properties": { - "username": { - "type": "string", - "maxLength": 30, - "pattern": "^[\\p{L}\\p{N}_]+$", - "title": "Username" - }, - "email": { - "type": "string", - "format": "email", - "title": "Email" + "title": "Fractured" }, - "isActive": { + "synthesised": { "anyOf": [ { "type": "boolean" @@ -4907,10 +3488,9 @@ "type": "null" } ], - "title": "Isactive", - "default": true + "title": "Synthesised" }, - "isSuperuser": { + "unique": { "anyOf": [ { "type": "boolean" @@ -4919,22 +3499,20 @@ "type": "null" } ], - "title": "Issuperuser", - "default": false + "title": "Unique" }, - "rateLimitTier": { + "corrupted": { "anyOf": [ { - "type": "integer" + "type": "boolean" }, { "type": "null" } ], - "title": "Ratelimittier", - "default": 0 + "title": "Corrupted" }, - "isBanned": { + "enchanted": { "anyOf": [ { "type": "boolean" @@ -4943,192 +3521,264 @@ "type": "null" } ], - "title": "Isbanned", - "default": false + "title": "Enchanted" }, - "userId": { - "type": "string", - "format": "uuid", - "title": "Userid" + "veiled": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "title": "Veiled" } }, "type": "object", "required": [ - "username", - "email", - "userId" + "position", + "effect" ], - "title": "UserPublic" + "title": "ModifierUpdate" }, - "UserRegisterPreEmailConfirmation": { + "PlotData": { "properties": { - "username": { - "type": "string", - "maxLength": 30, - "pattern": "^[\\p{L}\\p{N}_]+$", - "title": "Username" + "valueInChaos": { + "items": { + "type": "number" + }, + "type": "array", + "title": "Valueinchaos" + }, + "hoursSinceLaunch": { + "items": { + "type": "integer" + }, + "type": "array", + "title": "Hourssincelaunch" + }, + "valueInMostCommonCurrencyUsed": { + "items": { + "type": "number" + }, + "type": "array", + "title": "Valueinmostcommoncurrencyused" + }, + "confidence": { + "items": { + "type": "string", + "enum": [ + "low", + "medium", + "high" + ] + }, + "type": "array", + "title": "Confidence" }, - "email": { + "confidenceRating": { "type": "string", - "format": "email", - "title": "Email" + "enum": [ + "low", + "medium", + "high" + ], + "title": "Confidencerating" }, - "password": { + "mostCommonCurrencyUsed": { "type": "string", - "minLength": 8, - "title": "Password" + "title": "Mostcommoncurrencyused" } }, "type": "object", "required": [ - "username", - "email", - "password" + "valueInChaos", + "hoursSinceLaunch", + "valueInMostCommonCurrencyUsed", + "confidence", + "confidenceRating", + "mostCommonCurrencyUsed" ], - "title": "UserRegisterPreEmailConfirmation" + "title": "PlotData" }, - "UserUpdate": { + "PlotQuery": { "properties": { - "username": { + "league": { + "type": "string", + "title": "League" + }, + "itemSpecifications": { "anyOf": [ { - "type": "string", - "maxLength": 30, - "pattern": "^[\\p{L}\\p{N}_]+$" + "$ref": "#/components/schemas/ItemSpecs" }, { "type": "null" } - ], - "title": "Username" + ] }, - "email": { + "baseSpecifications": { "anyOf": [ { - "type": "string", - "format": "email" + "$ref": "#/components/schemas/BaseSpecs" }, { "type": "null" } - ], - "title": "Email" + ] + }, + "wantedModifiers": { + "items": { + "items": { + "$ref": "#/components/schemas/WantedModifier" + }, + "type": "array" + }, + "type": "array", + "title": "Wantedmodifiers" }, - "isActive": { + "end": { "anyOf": [ { - "type": "boolean" + "type": "integer" }, { "type": "null" } ], - "title": "Isactive", - "default": true + "title": "End" }, - "isSuperuser": { + "start": { "anyOf": [ { - "type": "boolean" + "type": "integer" }, { "type": "null" } ], - "title": "Issuperuser", - "default": false + "title": "Start" + } + }, + "type": "object", + "required": [ + "league", + "wantedModifiers" + ], + "title": "PlotQuery" + }, + "Token": { + "properties": { + "access_token": { + "type": "string", + "title": "Access Token" + } + }, + "type": "object", + "required": [ + "access_token" + ], + "title": "Token" + }, + "TurnstileQuery": { + "properties": { + "token": { + "type": "string", + "title": "Token" + }, + "ip": { + "type": "string", + "title": "Ip" + } + }, + "type": "object", + "required": [ + "token", + "ip" + ], + "title": "TurnstileQuery" + }, + "TurnstileResponse": { + "properties": { + "success": { + "type": "boolean", + "title": "Success" }, - "rateLimitTier": { + "error_codes": { "anyOf": [ { - "type": "integer" + "items": { + "type": "string" + }, + "type": "array" }, { "type": "null" } ], - "title": "Ratelimittier", - "default": 0 + "title": "Error Codes" }, - "isBanned": { + "challenge_ts": { "anyOf": [ { - "type": "boolean" + "type": "string" }, { "type": "null" } ], - "title": "Isbanned", - "default": false + "title": "Challenge Ts" }, - "password": { + "hostname": { "anyOf": [ { - "type": "string", - "minLength": 8 + "type": "string" }, { "type": "null" } ], - "title": "Password" - } - }, - "type": "object", - "title": "UserUpdate" - }, - "UserUpdateMe": { - "properties": { - "email": { + "title": "Hostname" + }, + "action": { "anyOf": [ { - "type": "string", - "format": "email" + "type": "string" }, { "type": "null" } ], - "title": "Email" + "title": "Action" }, - "username": { + "cdata": { "anyOf": [ { - "type": "string", - "maxLength": 30, - "pattern": "^[\\p{L}\\p{N}_]+$" + "type": "string" }, { "type": "null" } ], - "title": "Username" - } - }, - "type": "object", - "title": "UserUpdateMe" - }, - "UsersPublic": { - "properties": { - "data": { - "items": { - "$ref": "#/components/schemas/UserPublic" - }, - "type": "array", - "title": "Data" + "title": "Cdata" }, - "count": { - "type": "integer", - "title": "Count" + "metadata": { + "anyOf": [ + { + "$ref": "#/components/schemas/MetadataObject" + }, + { + "type": "null" + } + ] } }, "type": "object", "required": [ - "data", - "count" + "success" ], - "title": "UsersPublic" + "title": "TurnstileResponse" }, "ValidationError": { "properties": { @@ -5199,4 +3849,4 @@ } } } -} \ No newline at end of file +} diff --git a/src/frontend/src/client/index.ts b/src/frontend/src/client/index.ts index 30788f5b..9fa0762d 100644 --- a/src/frontend/src/client/index.ts +++ b/src/frontend/src/client/index.ts @@ -24,26 +24,16 @@ export type { ItemCreate } from './models/ItemCreate'; export type { ItemModifier } from './models/ItemModifier'; export type { ItemModifierCreate } from './models/ItemModifierCreate'; export type { ItemSpecs } from './models/ItemSpecs'; -export type { Message } from './models/Message'; export type { MetadataObject } from './models/MetadataObject'; export type { Modifier } from './models/Modifier'; export type { ModifierCreate } from './models/ModifierCreate'; export type { ModifierLimitations } from './models/ModifierLimitations'; export type { ModifierUpdate } from './models/ModifierUpdate'; -export type { NewPassword } from './models/NewPassword'; export type { PlotData } from './models/PlotData'; export type { PlotQuery } from './models/PlotQuery'; -export type { RecoverPassword } from './models/RecoverPassword'; export type { Token } from './models/Token'; export type { TurnstileQuery } from './models/TurnstileQuery'; export type { TurnstileResponse } from './models/TurnstileResponse'; -export type { UpdatePassword } from './models/UpdatePassword'; -export type { UserCreate } from './models/UserCreate'; -export type { UserPublic } from './models/UserPublic'; -export type { UserRegisterPreEmailConfirmation } from './models/UserRegisterPreEmailConfirmation'; -export type { UsersPublic } from './models/UsersPublic'; -export type { UserUpdate } from './models/UserUpdate'; -export type { UserUpdateMe } from './models/UserUpdateMe'; export type { ValidationError } from './models/ValidationError'; export type { WantedModifier } from './models/WantedModifier'; @@ -64,26 +54,16 @@ export { $ItemCreate } from './schemas/$ItemCreate'; export { $ItemModifier } from './schemas/$ItemModifier'; export { $ItemModifierCreate } from './schemas/$ItemModifierCreate'; export { $ItemSpecs } from './schemas/$ItemSpecs'; -export { $Message } from './schemas/$Message'; export { $MetadataObject } from './schemas/$MetadataObject'; export { $Modifier } from './schemas/$Modifier'; export { $ModifierCreate } from './schemas/$ModifierCreate'; export { $ModifierLimitations } from './schemas/$ModifierLimitations'; export { $ModifierUpdate } from './schemas/$ModifierUpdate'; -export { $NewPassword } from './schemas/$NewPassword'; export { $PlotData } from './schemas/$PlotData'; export { $PlotQuery } from './schemas/$PlotQuery'; -export { $RecoverPassword } from './schemas/$RecoverPassword'; export { $Token } from './schemas/$Token'; export { $TurnstileQuery } from './schemas/$TurnstileQuery'; export { $TurnstileResponse } from './schemas/$TurnstileResponse'; -export { $UpdatePassword } from './schemas/$UpdatePassword'; -export { $UserCreate } from './schemas/$UserCreate'; -export { $UserPublic } from './schemas/$UserPublic'; -export { $UserRegisterPreEmailConfirmation } from './schemas/$UserRegisterPreEmailConfirmation'; -export { $UsersPublic } from './schemas/$UsersPublic'; -export { $UserUpdate } from './schemas/$UserUpdate'; -export { $UserUpdateMe } from './schemas/$UserUpdateMe'; export { $ValidationError } from './schemas/$ValidationError'; export { $WantedModifier } from './schemas/$WantedModifier'; @@ -98,4 +78,3 @@ export { ModifiersService } from './services/ModifiersService'; export { PlotsService } from './services/PlotsService'; export { TestsService } from './services/TestsService'; export { TurnstilesService } from './services/TurnstilesService'; -export { UsersService } from './services/UsersService'; diff --git a/src/frontend/src/client/models/Message.ts b/src/frontend/src/client/models/Message.ts deleted file mode 100644 index c642dfc8..00000000 --- a/src/frontend/src/client/models/Message.ts +++ /dev/null @@ -1,8 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -export type Message = { - message: string; -}; - diff --git a/src/frontend/src/client/models/NewPassword.ts b/src/frontend/src/client/models/NewPassword.ts deleted file mode 100644 index 4382b58b..00000000 --- a/src/frontend/src/client/models/NewPassword.ts +++ /dev/null @@ -1,9 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -export type NewPassword = { - token: string; - new_password: string; -}; - diff --git a/src/frontend/src/client/models/RecoverPassword.ts b/src/frontend/src/client/models/RecoverPassword.ts deleted file mode 100644 index 98c98ddd..00000000 --- a/src/frontend/src/client/models/RecoverPassword.ts +++ /dev/null @@ -1,9 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -export type RecoverPassword = { - username?: (string | null); - email?: (string | null); -}; - diff --git a/src/frontend/src/client/models/UpdatePassword.ts b/src/frontend/src/client/models/UpdatePassword.ts deleted file mode 100644 index a6af6a3e..00000000 --- a/src/frontend/src/client/models/UpdatePassword.ts +++ /dev/null @@ -1,9 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -export type UpdatePassword = { - current_password: string; - new_password: string; -}; - diff --git a/src/frontend/src/client/models/UserCreate.ts b/src/frontend/src/client/models/UserCreate.ts deleted file mode 100644 index 16dacc3d..00000000 --- a/src/frontend/src/client/models/UserCreate.ts +++ /dev/null @@ -1,14 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -export type UserCreate = { - username: string; - email: string; - isActive?: (boolean | null); - isSuperuser?: (boolean | null); - rateLimitTier?: (number | null); - isBanned?: (boolean | null); - password: string; -}; - diff --git a/src/frontend/src/client/models/UserPublic.ts b/src/frontend/src/client/models/UserPublic.ts deleted file mode 100644 index 9ea81fed..00000000 --- a/src/frontend/src/client/models/UserPublic.ts +++ /dev/null @@ -1,14 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -export type UserPublic = { - username: string; - email: string; - isActive?: (boolean | null); - isSuperuser?: (boolean | null); - rateLimitTier?: (number | null); - isBanned?: (boolean | null); - userId: string; -}; - diff --git a/src/frontend/src/client/models/UserRegisterPreEmailConfirmation.ts b/src/frontend/src/client/models/UserRegisterPreEmailConfirmation.ts deleted file mode 100644 index 2dae5709..00000000 --- a/src/frontend/src/client/models/UserRegisterPreEmailConfirmation.ts +++ /dev/null @@ -1,10 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -export type UserRegisterPreEmailConfirmation = { - username: string; - email: string; - password: string; -}; - diff --git a/src/frontend/src/client/models/UserUpdate.ts b/src/frontend/src/client/models/UserUpdate.ts deleted file mode 100644 index a071025c..00000000 --- a/src/frontend/src/client/models/UserUpdate.ts +++ /dev/null @@ -1,14 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -export type UserUpdate = { - username?: (string | null); - email?: (string | null); - isActive?: (boolean | null); - isSuperuser?: (boolean | null); - rateLimitTier?: (number | null); - isBanned?: (boolean | null); - password?: (string | null); -}; - diff --git a/src/frontend/src/client/models/UserUpdateMe.ts b/src/frontend/src/client/models/UserUpdateMe.ts deleted file mode 100644 index 6ab4577a..00000000 --- a/src/frontend/src/client/models/UserUpdateMe.ts +++ /dev/null @@ -1,9 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -export type UserUpdateMe = { - email?: (string | null); - username?: (string | null); -}; - diff --git a/src/frontend/src/client/models/UsersPublic.ts b/src/frontend/src/client/models/UsersPublic.ts deleted file mode 100644 index e11eb731..00000000 --- a/src/frontend/src/client/models/UsersPublic.ts +++ /dev/null @@ -1,10 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -import type { UserPublic } from './UserPublic'; -export type UsersPublic = { - data: Array; - count: number; -}; - diff --git a/src/frontend/src/client/schemas/$Message.ts b/src/frontend/src/client/schemas/$Message.ts deleted file mode 100644 index 24678c88..00000000 --- a/src/frontend/src/client/schemas/$Message.ts +++ /dev/null @@ -1,12 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -export const $Message = { - properties: { - message: { - type: 'string', - isRequired: true, - }, - }, -} as const; diff --git a/src/frontend/src/client/schemas/$NewPassword.ts b/src/frontend/src/client/schemas/$NewPassword.ts deleted file mode 100644 index 7980c965..00000000 --- a/src/frontend/src/client/schemas/$NewPassword.ts +++ /dev/null @@ -1,18 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -export const $NewPassword = { - properties: { - token: { - type: 'string', - isRequired: true, - }, - new_password: { - type: 'string', - isRequired: true, - maxLength: 40, - minLength: 8, - }, - }, -} as const; diff --git a/src/frontend/src/client/schemas/$RecoverPassword.ts b/src/frontend/src/client/schemas/$RecoverPassword.ts deleted file mode 100644 index ca6d6b0b..00000000 --- a/src/frontend/src/client/schemas/$RecoverPassword.ts +++ /dev/null @@ -1,24 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -export const $RecoverPassword = { - properties: { - username: { - type: 'any-of', - contains: [{ - type: 'string', - }, { - type: 'null', - }], - }, - email: { - type: 'any-of', - contains: [{ - type: 'string', - }, { - type: 'null', - }], - }, - }, -} as const; diff --git a/src/frontend/src/client/schemas/$UpdatePassword.ts b/src/frontend/src/client/schemas/$UpdatePassword.ts deleted file mode 100644 index 54fbfa39..00000000 --- a/src/frontend/src/client/schemas/$UpdatePassword.ts +++ /dev/null @@ -1,18 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -export const $UpdatePassword = { - properties: { - current_password: { - type: 'string', - isRequired: true, - minLength: 8, - }, - new_password: { - type: 'string', - isRequired: true, - minLength: 8, - }, - }, -} as const; diff --git a/src/frontend/src/client/schemas/$UserCreate.ts b/src/frontend/src/client/schemas/$UserCreate.ts deleted file mode 100644 index cfd2076d..00000000 --- a/src/frontend/src/client/schemas/$UserCreate.ts +++ /dev/null @@ -1,56 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -export const $UserCreate = { - properties: { - username: { - type: 'string', - isRequired: true, - maxLength: 30, - pattern: '^[\\p{L}\\p{N}_]+$', - }, - email: { - type: 'string', - isRequired: true, - format: 'email', - }, - isActive: { - type: 'any-of', - contains: [{ - type: 'boolean', - }, { - type: 'null', - }], - }, - isSuperuser: { - type: 'any-of', - contains: [{ - type: 'boolean', - }, { - type: 'null', - }], - }, - rateLimitTier: { - type: 'any-of', - contains: [{ - type: 'number', - }, { - type: 'null', - }], - }, - isBanned: { - type: 'any-of', - contains: [{ - type: 'boolean', - }, { - type: 'null', - }], - }, - password: { - type: 'string', - isRequired: true, - minLength: 8, - }, - }, -} as const; diff --git a/src/frontend/src/client/schemas/$UserPublic.ts b/src/frontend/src/client/schemas/$UserPublic.ts deleted file mode 100644 index cc387c85..00000000 --- a/src/frontend/src/client/schemas/$UserPublic.ts +++ /dev/null @@ -1,56 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -export const $UserPublic = { - properties: { - username: { - type: 'string', - isRequired: true, - maxLength: 30, - pattern: '^[\\p{L}\\p{N}_]+$', - }, - email: { - type: 'string', - isRequired: true, - format: 'email', - }, - isActive: { - type: 'any-of', - contains: [{ - type: 'boolean', - }, { - type: 'null', - }], - }, - isSuperuser: { - type: 'any-of', - contains: [{ - type: 'boolean', - }, { - type: 'null', - }], - }, - rateLimitTier: { - type: 'any-of', - contains: [{ - type: 'number', - }, { - type: 'null', - }], - }, - isBanned: { - type: 'any-of', - contains: [{ - type: 'boolean', - }, { - type: 'null', - }], - }, - userId: { - type: 'string', - isRequired: true, - format: 'uuid', - }, - }, -} as const; diff --git a/src/frontend/src/client/schemas/$UserRegisterPreEmailConfirmation.ts b/src/frontend/src/client/schemas/$UserRegisterPreEmailConfirmation.ts deleted file mode 100644 index ac5cd78b..00000000 --- a/src/frontend/src/client/schemas/$UserRegisterPreEmailConfirmation.ts +++ /dev/null @@ -1,24 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -export const $UserRegisterPreEmailConfirmation = { - properties: { - username: { - type: 'string', - isRequired: true, - maxLength: 30, - pattern: '^[\\p{L}\\p{N}_]+$', - }, - email: { - type: 'string', - isRequired: true, - format: 'email', - }, - password: { - type: 'string', - isRequired: true, - minLength: 8, - }, - }, -} as const; diff --git a/src/frontend/src/client/schemas/$UserUpdate.ts b/src/frontend/src/client/schemas/$UserUpdate.ts deleted file mode 100644 index cfe21d82..00000000 --- a/src/frontend/src/client/schemas/$UserUpdate.ts +++ /dev/null @@ -1,68 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -export const $UserUpdate = { - properties: { - username: { - type: 'any-of', - contains: [{ - type: 'string', - maxLength: 30, - pattern: '^[\\p{L}\\p{N}_]+$', - }, { - type: 'null', - }], - }, - email: { - type: 'any-of', - contains: [{ - type: 'string', - format: 'email', - }, { - type: 'null', - }], - }, - isActive: { - type: 'any-of', - contains: [{ - type: 'boolean', - }, { - type: 'null', - }], - }, - isSuperuser: { - type: 'any-of', - contains: [{ - type: 'boolean', - }, { - type: 'null', - }], - }, - rateLimitTier: { - type: 'any-of', - contains: [{ - type: 'number', - }, { - type: 'null', - }], - }, - isBanned: { - type: 'any-of', - contains: [{ - type: 'boolean', - }, { - type: 'null', - }], - }, - password: { - type: 'any-of', - contains: [{ - type: 'string', - minLength: 8, - }, { - type: 'null', - }], - }, - }, -} as const; diff --git a/src/frontend/src/client/schemas/$UserUpdateMe.ts b/src/frontend/src/client/schemas/$UserUpdateMe.ts deleted file mode 100644 index 894b5abe..00000000 --- a/src/frontend/src/client/schemas/$UserUpdateMe.ts +++ /dev/null @@ -1,27 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -export const $UserUpdateMe = { - properties: { - email: { - type: 'any-of', - contains: [{ - type: 'string', - format: 'email', - }, { - type: 'null', - }], - }, - username: { - type: 'any-of', - contains: [{ - type: 'string', - maxLength: 30, - pattern: '^[\\p{L}\\p{N}_]+$', - }, { - type: 'null', - }], - }, - }, -} as const; diff --git a/src/frontend/src/client/schemas/$UsersPublic.ts b/src/frontend/src/client/schemas/$UsersPublic.ts deleted file mode 100644 index 7ded9ecd..00000000 --- a/src/frontend/src/client/schemas/$UsersPublic.ts +++ /dev/null @@ -1,19 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -export const $UsersPublic = { - properties: { - data: { - type: 'array', - contains: { - type: 'UserPublic', - }, - isRequired: true, - }, - count: { - type: 'number', - isRequired: true, - }, - }, -} as const; diff --git a/src/frontend/src/client/services/LoginsService.ts b/src/frontend/src/client/services/LoginsService.ts index 6f603b7b..ebdaca76 100644 --- a/src/frontend/src/client/services/LoginsService.ts +++ b/src/frontend/src/client/services/LoginsService.ts @@ -3,9 +3,6 @@ /* tslint:disable */ /* eslint-disable */ import type { Body_logins_login_access_session } from '../models/Body_logins_login_access_session'; -import type { Message } from '../models/Message'; -import type { NewPassword } from '../models/NewPassword'; -import type { RecoverPassword } from '../models/RecoverPassword'; import type { Token } from '../models/Token'; import type { CancelablePromise } from '../core/CancelablePromise'; import { OpenAPI } from '../core/OpenAPI'; @@ -32,68 +29,4 @@ export class LoginsService { }, }); } - /** - * Recover Password - * Password Recovery - * @returns Message Successful Response - * @throws ApiError - */ - public static recoverPassword({ - requestBody, - }: { - requestBody: RecoverPassword, - }): CancelablePromise { - return __request(OpenAPI, { - method: 'POST', - url: '/api/api_v1/login/password-recovery/', - body: requestBody, - mediaType: 'application/json', - errors: { - 422: `Validation Error`, - }, - }); - } - /** - * Reset Password - * Reset password - * @returns Message Successful Response - * @throws ApiError - */ - public static resetPassword({ - requestBody, - }: { - requestBody: NewPassword, - }): CancelablePromise { - return __request(OpenAPI, { - method: 'POST', - url: '/api/api_v1/login/reset-password/', - body: requestBody, - mediaType: 'application/json', - errors: { - 422: `Validation Error`, - }, - }); - } - /** - * Recover Password Html Content - * HTML Content for Password Recovery - * @returns string Successful Response - * @throws ApiError - */ - public static recoverPasswordHtmlContent({ - email, - }: { - email: string, - }): CancelablePromise { - return __request(OpenAPI, { - method: 'POST', - url: '/api/api_v1/login/password-recovery-html-content/{email}', - path: { - 'email': email, - }, - errors: { - 422: `Validation Error`, - }, - }); - } } diff --git a/src/frontend/src/client/services/UsersService.ts b/src/frontend/src/client/services/UsersService.ts deleted file mode 100644 index 7c460d15..00000000 --- a/src/frontend/src/client/services/UsersService.ts +++ /dev/null @@ -1,387 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -import type { Message } from '../models/Message'; -import type { Token } from '../models/Token'; -import type { UpdatePassword } from '../models/UpdatePassword'; -import type { UserCreate } from '../models/UserCreate'; -import type { UserPublic } from '../models/UserPublic'; -import type { UserRegisterPreEmailConfirmation } from '../models/UserRegisterPreEmailConfirmation'; -import type { UsersPublic } from '../models/UsersPublic'; -import type { UserUpdate } from '../models/UserUpdate'; -import type { UserUpdateMe } from '../models/UserUpdateMe'; -import type { CancelablePromise } from '../core/CancelablePromise'; -import { OpenAPI } from '../core/OpenAPI'; -import { request as __request } from '../core/request'; -export class UsersService { - /** - * Get All Users - * Retrieve all users. - * @returns UsersPublic Successful Response - * @throws ApiError - */ - public static getAllUsers({ - skip, - limit = 100, - }: { - skip?: number, - limit?: number, - }): CancelablePromise { - return __request(OpenAPI, { - method: 'GET', - url: '/api/api_v1/user/', - query: { - 'skip': skip, - 'limit': limit, - }, - errors: { - 422: `Validation Error`, - }, - }); - } - /** - * Create - * Create new user. - * @returns UserPublic Successful Response - * @throws ApiError - */ - public static create({ - requestBody, - }: { - requestBody: UserCreate, - }): CancelablePromise { - return __request(OpenAPI, { - method: 'POST', - url: '/api/api_v1/user/', - body: requestBody, - mediaType: 'application/json', - errors: { - 422: `Validation Error`, - }, - }); - } - /** - * Update Me Email Send Confirmation - * Send confirmation to update own user. - * @returns Message Successful Response - * @throws ApiError - */ - public static updateMeEmailSendConfirmation({ - requestBody, - }: { - requestBody: UserUpdateMe, - }): CancelablePromise { - return __request(OpenAPI, { - method: 'PATCH', - url: '/api/api_v1/user/update-me-email-pre-confirmation', - body: requestBody, - mediaType: 'application/json', - errors: { - 422: `Validation Error`, - }, - }); - } - /** - * Update Me Email Confirmation - * Confirm update email. - * @returns Message Successful Response - * @throws ApiError - */ - public static updateMeEmailConfirmation({ - requestBody, - }: { - requestBody: Token, - }): CancelablePromise { - return __request(OpenAPI, { - method: 'PATCH', - url: '/api/api_v1/user/update-me-email-confirmation', - body: requestBody, - mediaType: 'application/json', - errors: { - 422: `Validation Error`, - }, - }); - } - /** - * Update Me Username - * Update username. Can only be used by users once a month. - * @returns Message Successful Response - * @throws ApiError - */ - public static updateMeUsername({ - requestBody, - }: { - requestBody: UserUpdateMe, - }): CancelablePromise { - return __request(OpenAPI, { - method: 'PATCH', - url: '/api/api_v1/user/update-me-username', - body: requestBody, - mediaType: 'application/json', - errors: { - 422: `Validation Error`, - }, - }); - } - /** - * Check Username Exists - * Checks if username exists in the db. - * - * Returns `True` if the user exists, else `False` - * @returns boolean Successful Response - * @throws ApiError - */ - public static checkUsernameExists({ - username, - }: { - username: string, - }): CancelablePromise { - return __request(OpenAPI, { - method: 'PATCH', - url: '/api/api_v1/user/check-username-exists', - query: { - 'username': username, - }, - errors: { - 422: `Validation Error`, - }, - }); - } - /** - * Update Password Me - * Update own password. - * @returns Message Successful Response - * @throws ApiError - */ - public static updatePasswordMe({ - requestBody, - }: { - requestBody: UpdatePassword, - }): CancelablePromise { - return __request(OpenAPI, { - method: 'PATCH', - url: '/api/api_v1/user/me/password', - body: requestBody, - mediaType: 'application/json', - errors: { - 422: `Validation Error`, - }, - }); - } - /** - * Get User Me - * Get current user. User doesn't have to be active (confirmed email). - * @returns UserPublic Successful Response - * @throws ApiError - */ - public static getUserMe(): CancelablePromise { - return __request(OpenAPI, { - method: 'GET', - url: '/api/api_v1/user/me', - }); - } - /** - * Delete User Me - * Delete own user. - * @returns Message Successful Response - * @throws ApiError - */ - public static deleteUserMe(): CancelablePromise { - return __request(OpenAPI, { - method: 'DELETE', - url: '/api/api_v1/user/me', - }); - } - /** - * Register User Send Confirmation - * Send email confirmation on user register. Account doesn't get created yet. - * @returns Message Successful Response - * @throws ApiError - */ - public static registerUserSendConfirmation({ - requestBody, - }: { - requestBody: UserRegisterPreEmailConfirmation, - }): CancelablePromise { - return __request(OpenAPI, { - method: 'POST', - url: '/api/api_v1/user/signup-send-confirmation', - body: requestBody, - mediaType: 'application/json', - errors: { - 422: `Validation Error`, - }, - }); - } - /** - * Register User Confirm - * Confirm new user without the need to be logged in. Requires email confirmation. - * @returns Message Successful Response - * @throws ApiError - */ - public static registerUserConfirm({ - requestBody, - }: { - requestBody: Token, - }): CancelablePromise { - return __request(OpenAPI, { - method: 'POST', - url: '/api/api_v1/user/signup', - body: requestBody, - mediaType: 'application/json', - errors: { - 422: `Validation Error`, - }, - }); - } - /** - * Get User By Id - * Get a specific user by id. - * @returns UserPublic Successful Response - * @throws ApiError - */ - public static getUserById({ - userId, - }: { - userId: string, - }): CancelablePromise { - return __request(OpenAPI, { - method: 'GET', - url: '/api/api_v1/user/{user_id}', - path: { - 'user_id': userId, - }, - errors: { - 422: `Validation Error`, - }, - }); - } - /** - * Update User - * Update a user. - * @returns UserPublic Successful Response - * @throws ApiError - */ - public static updateUser({ - userId, - requestBody, - }: { - userId: string, - requestBody: UserUpdate, - }): CancelablePromise { - return __request(OpenAPI, { - method: 'PATCH', - url: '/api/api_v1/user/{user_id}', - path: { - 'user_id': userId, - }, - body: requestBody, - mediaType: 'application/json', - errors: { - 422: `Validation Error`, - }, - }); - } - /** - * Delete User - * Delete a user. - * @returns Message Successful Response - * @throws ApiError - */ - public static deleteUser({ - userId, - }: { - userId: string, - }): CancelablePromise { - return __request(OpenAPI, { - method: 'DELETE', - url: '/api/api_v1/user/{user_id}', - path: { - 'user_id': userId, - }, - errors: { - 422: `Validation Error`, - }, - }); - } - /** - * Change Is Active User - * Change activity to current user. - * @returns Message Successful Response - * @throws ApiError - */ - public static changeIsActiveUser({ - userId, - isActive, - }: { - userId: string, - isActive: boolean, - }): CancelablePromise { - return __request(OpenAPI, { - method: 'PATCH', - url: '/api/api_v1/user/is_active/{user_id}', - path: { - 'user_id': userId, - }, - query: { - 'is_active': isActive, - }, - errors: { - 422: `Validation Error`, - }, - }); - } - /** - * Set Rate Limit Tier User - * Set rate limit tier to current user. - * @returns Message Successful Response - * @throws ApiError - */ - public static setRateLimitTierUser({ - userId, - rateLimitTier, - }: { - userId: string, - rateLimitTier: number, - }): CancelablePromise { - return __request(OpenAPI, { - method: 'PATCH', - url: '/api/api_v1/user/rate_limit_tier/{user_id}', - path: { - 'user_id': userId, - }, - query: { - 'rate_limit_tier': rateLimitTier, - }, - errors: { - 422: `Validation Error`, - }, - }); - } - /** - * Check Current User Active - * Checks if the current user is active. Returns True if the user is active, otherwise False. - * @returns boolean Successful Response - * @throws ApiError - */ - public static checkCurrentUserActive(): CancelablePromise { - return __request(OpenAPI, { - method: 'POST', - url: '/api/api_v1/user/check-current-user-active', - }); - } - /** - * Set Active User Send Confirmation - * Send email confirmation to set active user during registration process. - * Rute `/signup` is used to confirm the user. - * @returns Message Successful Response - * @throws ApiError - */ - public static setActiveUserSendConfirmation(): CancelablePromise { - return __request(OpenAPI, { - method: 'POST', - url: '/api/api_v1/user/activation-token-send-confirmation', - }); - } -} diff --git a/src/frontend/src/components/Common/Footer.tsx b/src/frontend/src/components/Common/Footer.tsx index 5a0e41ad..564ec13e 100644 --- a/src/frontend/src/components/Common/Footer.tsx +++ b/src/frontend/src/components/Common/Footer.tsx @@ -37,7 +37,6 @@ const Footer = (props: StackProps) => { { - const { logout } = useAuth(); - const { user: currentUser } = useAuth(); - return ( - + { textAlign="center" color="white" /> - - {/* Menu for user actions */} - - - {currentUser?.username} - - - - } - _hover={{ bgColor: "ui.lighterSecondary.100" }} - > - Settings - - - } - onClick={logout} - _hover={{ bgColor: "ui.lighterSecondary.100" }} - > - Logout - - - ); }; diff --git a/src/frontend/src/components/Common/MainPage.tsx b/src/frontend/src/components/Common/MainPage.tsx index 09214e75..7f117ff8 100644 --- a/src/frontend/src/components/Common/MainPage.tsx +++ b/src/frontend/src/components/Common/MainPage.tsx @@ -17,6 +17,7 @@ export const MainPage = (props: MainPageProps) => { bg="ui.main" width="99vw" minWidth="bgBoxes.miniPBox" + minH="100vh" > <> @@ -29,7 +30,6 @@ export const MainPage = (props: MainPageProps) => { justifyContent="center" maxWidth={"100%"} flexWrap="wrap" - minHeight="100vh" p={3} pl={10} pr={10} @@ -37,9 +37,14 @@ export const MainPage = (props: MainPageProps) => { borderTopColor={"ui.darkBrown"} borderTopWidth={1} alignSelf="center" + minH="96vh" > {props.isReady && ( - + @@ -48,10 +53,9 @@ export const MainPage = (props: MainPageProps) => { minH={"bgBoxes.smallBox"} height={"bgBoxes.smallBox"} maxW="98vw" - mb="10rem" justifyItems={"center"} /> -