Reset hesla, doplneni mailu
This commit is contained in:
+1
-1
@@ -12,7 +12,7 @@ FROM python:3.11-alpine AS app
|
|||||||
RUN apk update && \
|
RUN apk update && \
|
||||||
apk add --no-cache tzdata mariadb-client mariadb-dev && \
|
apk add --no-cache tzdata mariadb-client mariadb-dev && \
|
||||||
pip install --upgrade pip
|
pip install --upgrade pip
|
||||||
\
|
|
||||||
# protoze xfs uzivatel ma id=33
|
# protoze xfs uzivatel ma id=33
|
||||||
RUN deluser xfs
|
RUN deluser xfs
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,35 @@
|
|||||||
|
"""add password_reset_token table
|
||||||
|
|
||||||
|
Revision ID: a410455fb3bb
|
||||||
|
Revises: 39ebf5a1ab7e
|
||||||
|
Create Date: 2024-02-08 07:59:02.066212
|
||||||
|
|
||||||
|
"""
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = 'a410455fb3bb'
|
||||||
|
down_revision = '39ebf5a1ab7e'
|
||||||
|
branch_labels = None
|
||||||
|
depends_on = None
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade() -> None:
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.create_table('password_reset_token',
|
||||||
|
sa.Column('id', sa.Integer(), nullable=False),
|
||||||
|
sa.Column('user_id', sa.Integer(), nullable=False),
|
||||||
|
sa.Column('token', sa.String(length=64), nullable=False),
|
||||||
|
sa.Column('valid_until', sa.DateTime(), nullable=True),
|
||||||
|
sa.ForeignKeyConstraint(['user_id'], ['user.id'], ),
|
||||||
|
sa.PrimaryKeyConstraint('id')
|
||||||
|
)
|
||||||
|
# ### end Alembic commands ###
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade() -> None:
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.drop_table('password_reset_token')
|
||||||
|
# ### end Alembic commands ###
|
||||||
@@ -8,7 +8,7 @@ from logger import log
|
|||||||
|
|
||||||
async def download_weather(date_time: datetime, flight_id: int, airport_id: int, type_: Literal['landing', 'takeoff']):
|
async def download_weather(date_time: datetime, flight_id: int, airport_id: int, type_: Literal['landing', 'takeoff']):
|
||||||
async with get_session() as db:
|
async with get_session() as db:
|
||||||
airport = await models.Airport.get_one(db, airport_id)
|
airport = await models.Airport.get_one(db, id=airport_id)
|
||||||
gps = (airport.gps_latitude, airport.gps_longitude)
|
gps = (airport.gps_latitude, airport.gps_longitude)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@@ -31,7 +31,7 @@ async def download_weather(date_time: datetime, flight_id: int, airport_id: int,
|
|||||||
}
|
}
|
||||||
|
|
||||||
async with get_session() as db:
|
async with get_session() as db:
|
||||||
flight = await models.Flight.get_one(db, flight_id)
|
flight = await models.Flight.get_one(db, id=flight_id)
|
||||||
existing_weather_id = getattr(flight, f'{type_}_weather_info_id')
|
existing_weather_id = getattr(flight, f'{type_}_weather_info_id')
|
||||||
|
|
||||||
if existing_weather_id:
|
if existing_weather_id:
|
||||||
|
|||||||
+14
-3
@@ -18,8 +18,8 @@ class BaseModel:
|
|||||||
return {c: getattr(self, c) for c in self._get_column_names() if c not in self.excluded_columns_in_dict}
|
return {c: getattr(self, c) for c in self._get_column_names() if c not in self.excluded_columns_in_dict}
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
async def get_one(cls, db_session: AsyncSession, id: int):
|
async def get_one(cls, db_session: AsyncSession, **kwargs):
|
||||||
return (await db_session.scalars(select(cls).filter_by(id=id))).one()
|
return (await db_session.scalars(select(cls).filter_by(**kwargs))).one()
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
async def create(cls, db_session: AsyncSession, data: dict):
|
async def create(cls, db_session: AsyncSession, data: dict):
|
||||||
@@ -35,7 +35,7 @@ class BaseModel:
|
|||||||
raise ValueError("Provide either obj or id!")
|
raise ValueError("Provide either obj or id!")
|
||||||
|
|
||||||
if not obj:
|
if not obj:
|
||||||
obj = await cls.get_one(db_session, id)
|
obj = await cls.get_one(db_session, id=id)
|
||||||
for key, value in data.items():
|
for key, value in data.items():
|
||||||
if key in cls._get_column_names() and getattr(obj, key) != value:
|
if key in cls._get_column_names() and getattr(obj, key) != value:
|
||||||
setattr(obj, key, value)
|
setattr(obj, key, value)
|
||||||
@@ -371,3 +371,14 @@ class User(BaseModel):
|
|||||||
licences: Mapped[Set['License']] = relationship()
|
licences: Mapped[Set['License']] = relationship()
|
||||||
flights: Mapped[Set['Flight']] = relationship()
|
flights: Mapped[Set['Flight']] = relationship()
|
||||||
organizations: Mapped[Set['Organization']] = relationship(secondary=user_is_in_organization)
|
organizations: Mapped[Set['Organization']] = relationship(secondary=user_is_in_organization)
|
||||||
|
|
||||||
|
|
||||||
|
class PasswordResetToken(BaseModel):
|
||||||
|
__tablename__ = "password_reset_token"
|
||||||
|
|
||||||
|
id: Mapped[int] = mapped_column(primary_key=True)
|
||||||
|
user_id: Mapped[int] = mapped_column(Integer, ForeignKey('user.id'))
|
||||||
|
token: Mapped[str] = mapped_column(String(64), nullable=False)
|
||||||
|
valid_until: Mapped[datetime] = mapped_column(DateTime, nullable=True)
|
||||||
|
|
||||||
|
user: Mapped['User'] = relationship()
|
||||||
|
|||||||
@@ -30,9 +30,9 @@ class ContactFormEmail(Email):
|
|||||||
|
|
||||||
|
|
||||||
class WelcomeEmail(Email):
|
class WelcomeEmail(Email):
|
||||||
def __init__(self, to: list[EmailStr | str]):
|
def __init__(self, to: EmailStr | str):
|
||||||
super().__init__(
|
super().__init__(
|
||||||
to=to,
|
to=[to],
|
||||||
subject="Vítej",
|
subject="Vítej",
|
||||||
template="welcome.html",
|
template="welcome.html",
|
||||||
template_variables={}
|
template_variables={}
|
||||||
@@ -40,10 +40,13 @@ class WelcomeEmail(Email):
|
|||||||
|
|
||||||
|
|
||||||
class ResetPasswordEmail(Email):
|
class ResetPasswordEmail(Email):
|
||||||
def __init__(self, to: list[EmailStr | str], template_variables: dict):
|
def __init__(self, to: EmailStr | str, reset_token: str, validity_hours: int):
|
||||||
super().__init__(
|
super().__init__(
|
||||||
to=to,
|
to=[to],
|
||||||
subject="Reset hesla",
|
subject="Žádost o reset",
|
||||||
template="reset_password.html",
|
template="reset_password.html",
|
||||||
template_variables=template_variables
|
template_variables={
|
||||||
|
"token": reset_token,
|
||||||
|
"validity_hours": validity_hours,
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -11,10 +11,16 @@ class ContactInput(BaseModel):
|
|||||||
|
|
||||||
|
|
||||||
class ContactEndpoint():
|
class ContactEndpoint():
|
||||||
async def on_post(self, input: ContactInput, resp: Response, backgorund_tasks: BackgroundTasks):
|
async def on_post(self, input: ContactInput, backgorund_tasks: BackgroundTasks):
|
||||||
backgorund_tasks.add_task(send_email, ContactFormEmail(
|
backgorund_tasks.add_task(send_email, ContactFormEmail(
|
||||||
email_from=input.email_from,
|
email_from=input.email_from,
|
||||||
content=input.content
|
content=input.content
|
||||||
))
|
))
|
||||||
|
|
||||||
# todo vratit nejakou smysluplnou
|
return {
|
||||||
|
"status": "success",
|
||||||
|
"email": {
|
||||||
|
"from": input.email_from,
|
||||||
|
"content": input.content
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,4 +1,84 @@
|
|||||||
|
import os
|
||||||
|
import random
|
||||||
|
import string
|
||||||
|
|
||||||
|
import binascii
|
||||||
|
from datetime import datetime, timedelta
|
||||||
|
from fastapi import BackgroundTasks
|
||||||
|
from passlib.hash import bcrypt
|
||||||
|
from pydantic import BaseModel
|
||||||
|
from background_jobs.send_email import send_email
|
||||||
|
from database import models
|
||||||
|
from database.transaction import get_session
|
||||||
|
from emails.emails import ResetPasswordEmail
|
||||||
|
|
||||||
|
|
||||||
|
class ForgottenPasswordRequest(BaseModel):
|
||||||
|
email: str
|
||||||
|
|
||||||
|
|
||||||
|
class ChangeForgottenPassword(BaseModel):
|
||||||
|
password: str
|
||||||
|
token: str
|
||||||
|
|
||||||
|
|
||||||
class ForgottenPasswordEndpoint():
|
class ForgottenPasswordEndpoint():
|
||||||
async def on_get(self):
|
|
||||||
pass
|
@staticmethod
|
||||||
|
def generate_random_token(length):
|
||||||
|
characters = string.ascii_letters + string.digits
|
||||||
|
return ''.join(random.choice(characters) for i in range(length))
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
async def token_info(token: str):
|
||||||
|
async with get_session() as db:
|
||||||
|
reset = await models.PasswordResetToken.get_one(db, token=token)
|
||||||
|
user = await models.User.get_one(db, id=reset.user_id)
|
||||||
|
token_validity = reset.valid_until
|
||||||
|
email, name = user.email, user.name
|
||||||
|
|
||||||
|
return {
|
||||||
|
"token": token,
|
||||||
|
"token_validity": token_validity,
|
||||||
|
"user_email": email,
|
||||||
|
"user_name": name
|
||||||
|
}
|
||||||
|
|
||||||
|
async def request(self, input: ForgottenPasswordRequest, backgorund_tasks: BackgroundTasks):
|
||||||
|
validity_hours = 8
|
||||||
|
validity = datetime.now() + timedelta(hours=validity_hours)
|
||||||
|
random_str_token = self.generate_random_token(64)
|
||||||
|
|
||||||
|
async with get_session() as db:
|
||||||
|
user = await models.User.get_one(db, email=input.email)
|
||||||
|
token = await models.PasswordResetToken.create(db, {
|
||||||
|
"user_id": user.id,
|
||||||
|
"token": random_str_token,
|
||||||
|
"valid_until": validity
|
||||||
|
})
|
||||||
|
|
||||||
|
backgorund_tasks.add_task(
|
||||||
|
send_email,
|
||||||
|
email=ResetPasswordEmail(
|
||||||
|
to=input.email,
|
||||||
|
reset_token=token,
|
||||||
|
validity_hours=validity_hours
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
async def change_password(input: ChangeForgottenPassword):
|
||||||
|
async with get_session() as db:
|
||||||
|
token = await models.PasswordResetToken.get_one(db, token=input.token)
|
||||||
|
user_id = token.user_id
|
||||||
|
|
||||||
|
await models.User.update(
|
||||||
|
db, id=token.user_id,
|
||||||
|
data={"password_hashed": bcrypt.hash(input.password)}
|
||||||
|
)
|
||||||
|
|
||||||
|
await db.delete(token)
|
||||||
|
|
||||||
|
return {
|
||||||
|
"user_id": user_id
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,49 @@
|
|||||||
|
from datetime import timedelta
|
||||||
|
from fastapi import FastAPI, Security, Depends, BackgroundTasks, APIRouter
|
||||||
|
from fastapi_jwt import JwtAuthorizationCredentials
|
||||||
|
from fastapi_jwt.jwt import JwtAccessBearerCookie
|
||||||
|
from sqlalchemy import select
|
||||||
|
from starlette.responses import RedirectResponse
|
||||||
|
from strawberry.fastapi import GraphQLRouter
|
||||||
|
from config import GRAPHIQL, APP_DEBUG
|
||||||
|
from database import async_session, models
|
||||||
|
from graphql_schema.schema import GraphQLContext, schema
|
||||||
|
|
||||||
|
|
||||||
|
def setup_graphql_endpoint(app: FastAPI, access_security: JwtAccessBearerCookie, api_router: APIRouter):
|
||||||
|
async def setup_graphql_context(credentials: JwtAuthorizationCredentials = Security(access_security)):
|
||||||
|
user_id = credentials['id'] if credentials else None
|
||||||
|
organization_ids = set()
|
||||||
|
|
||||||
|
if user_id:
|
||||||
|
async with async_session() as db:
|
||||||
|
organization_ids = set((await db.scalars(
|
||||||
|
select(models.user_is_in_organization.c.organization_id)
|
||||||
|
.filter(models.user_is_in_organization.c.user_id == user_id)
|
||||||
|
)).all())
|
||||||
|
|
||||||
|
if APP_DEBUG:
|
||||||
|
@api_router.get("/graphql/autologin")
|
||||||
|
async def autologin():
|
||||||
|
access_token = access_security.create_access_token(subject={"id": 6, "name": "Franta Vomacka"})
|
||||||
|
|
||||||
|
response = RedirectResponse(url="/graphql")
|
||||||
|
access_security.set_access_cookie(response, access_token, expires_delta=timedelta(days=14))
|
||||||
|
|
||||||
|
return response
|
||||||
|
|
||||||
|
return GraphQLContext(
|
||||||
|
user_id=user_id,
|
||||||
|
organization_ids=organization_ids,
|
||||||
|
jwt_auth_credentials=credentials,
|
||||||
|
jwt=access_security,
|
||||||
|
background_tasks=Depends(BackgroundTasks)
|
||||||
|
)
|
||||||
|
|
||||||
|
graphql_app = GraphQLRouter(
|
||||||
|
schema,
|
||||||
|
graphiql=GRAPHIQL,
|
||||||
|
debug=APP_DEBUG,
|
||||||
|
context_getter=setup_graphql_context
|
||||||
|
)
|
||||||
|
app.include_router(graphql_app, prefix="/graphql")
|
||||||
@@ -1,11 +1,13 @@
|
|||||||
import re
|
import re
|
||||||
from fastapi import HTTPException
|
from fastapi import HTTPException, BackgroundTasks
|
||||||
from sqlalchemy import select
|
from sqlalchemy import select
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
from pydantic import BaseModel, Field, model_validator
|
from pydantic import BaseModel, Field, model_validator
|
||||||
|
from background_jobs.send_email import send_email
|
||||||
from database.models import User
|
from database.models import User
|
||||||
from database.transaction import get_session
|
from database.transaction import get_session
|
||||||
from passlib.hash import bcrypt
|
from passlib.hash import bcrypt
|
||||||
|
from emails.emails import WelcomeEmail
|
||||||
|
|
||||||
|
|
||||||
class RegistrationInput(BaseModel):
|
class RegistrationInput(BaseModel):
|
||||||
@@ -24,7 +26,8 @@ class RegistrationInput(BaseModel):
|
|||||||
|
|
||||||
|
|
||||||
class RegistrationEndpoint:
|
class RegistrationEndpoint:
|
||||||
async def on_post(self, user_data: RegistrationInput) -> User:
|
@staticmethod
|
||||||
|
async def on_post(user_data: RegistrationInput, backgorund_tasks: BackgroundTasks) -> User:
|
||||||
query = select(User).filter_by(email=user_data.email)
|
query = select(User).filter_by(email=user_data.email)
|
||||||
async with get_session() as db:
|
async with get_session() as db:
|
||||||
existing_user = (await db.scalars(query)).first()
|
existing_user = (await db.scalars(query)).first()
|
||||||
@@ -39,6 +42,6 @@ class RegistrationEndpoint:
|
|||||||
"description": ""
|
"description": ""
|
||||||
})
|
})
|
||||||
|
|
||||||
# TODO: odeslat WelcomeEmail
|
backgorund_tasks.add_task(send_email, WelcomeEmail(to=user_data.email))
|
||||||
|
|
||||||
return model.as_dict()
|
return model.as_dict()
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ class Mailer:
|
|||||||
self.conf = ConnectionConfig(
|
self.conf = ConnectionConfig(
|
||||||
MAIL_USERNAME=SMTP_USERNAME,
|
MAIL_USERNAME=SMTP_USERNAME,
|
||||||
MAIL_PASSWORD=SMTP_PASSWORD,
|
MAIL_PASSWORD=SMTP_PASSWORD,
|
||||||
|
MAIL_FROM="michalkv@gmail.com",
|
||||||
MAIL_FROM_NAME="Polétání",
|
MAIL_FROM_NAME="Polétání",
|
||||||
MAIL_PORT=SMTP_PORT,
|
MAIL_PORT=SMTP_PORT,
|
||||||
MAIL_SERVER=SMTP_HOST,
|
MAIL_SERVER=SMTP_HOST,
|
||||||
|
|||||||
+28
-60
@@ -1,25 +1,21 @@
|
|||||||
import sentry_sdk
|
import sentry_sdk
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
from fastapi import FastAPI, APIRouter, Depends, Security, HTTPException
|
from fastapi import FastAPI, APIRouter, Security, HTTPException
|
||||||
from fastapi_jwt import JwtAuthorizationCredentials, JwtAccessBearerCookie, JwtRefreshBearerCookie
|
from fastapi_jwt import JwtAuthorizationCredentials, JwtAccessBearerCookie, JwtRefreshBearerCookie
|
||||||
from graphql import GraphQLError
|
from graphql import GraphQLError
|
||||||
from sqlalchemy import select
|
from sqlalchemy.exc import NoResultFound
|
||||||
from starlette.background import BackgroundTasks
|
from starlette.background import BackgroundTasks
|
||||||
from starlette.middleware.cors import CORSMiddleware
|
from starlette.middleware.cors import CORSMiddleware
|
||||||
from starlette.responses import RedirectResponse, Response
|
from starlette.responses import Response, JSONResponse
|
||||||
from starlette.staticfiles import StaticFiles
|
from starlette.staticfiles import StaticFiles
|
||||||
from strawberry.fastapi import GraphQLRouter
|
from config import APP_SECRET_KEY, ALLOW_CORS_ORIGINS, SENTRY_DSN, REFRESH_TOKEN_VALIDITY_DAYS
|
||||||
from config import APP_SECRET_KEY, GRAPHIQL, APP_DEBUG, ALLOW_CORS_ORIGINS, SENTRY_DSN, REFRESH_TOKEN_VALIDITY_DAYS
|
|
||||||
from database import models, async_session
|
|
||||||
from emails.emails import WelcomeEmail
|
|
||||||
from endpoints.contact import ContactEndpoint, ContactInput
|
from endpoints.contact import ContactEndpoint, ContactInput
|
||||||
from endpoints.forgotten_password import ForgottenPasswordEndpoint
|
from endpoints.forgotten_password import ForgottenPasswordRequest, ForgottenPasswordEndpoint, ChangeForgottenPassword
|
||||||
|
from endpoints.graphql import setup_graphql_endpoint
|
||||||
from endpoints.login import LoginEndpoint, LoginInput, RefreshEndpoint, LogoutEndpoint
|
from endpoints.login import LoginEndpoint, LoginInput, RefreshEndpoint, LogoutEndpoint
|
||||||
from endpoints.photo_editor_preview import PhotoEditorEndpoint
|
from endpoints.photo_editor_preview import PhotoEditorEndpoint
|
||||||
from endpoints.registration import RegistrationInput, RegistrationEndpoint
|
from endpoints.registration import RegistrationInput, RegistrationEndpoint
|
||||||
from graphql_schema.schema import schema, GraphQLContext
|
|
||||||
from mailer import Mailer
|
|
||||||
|
|
||||||
|
|
||||||
class App:
|
class App:
|
||||||
@@ -53,7 +49,9 @@ class App:
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def setup_exception_handlers(app: FastAPI):
|
def setup_exception_handlers(app: FastAPI):
|
||||||
pass
|
@app.exception_handler(NoResultFound)
|
||||||
|
async def validation_exception_handler(request, exc):
|
||||||
|
return JSONResponse({"message": "Not found"}, status_code=404)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def setup_middleware(app: FastAPI):
|
def setup_middleware(app: FastAPI):
|
||||||
@@ -70,46 +68,8 @@ class App:
|
|||||||
app.mount("/uploads", StaticFiles(directory="/app/uploads"), name="uploads")
|
app.mount("/uploads", StaticFiles(directory="/app/uploads"), name="uploads")
|
||||||
app.mount("/static", StaticFiles(directory="/app/static"), name="static")
|
app.mount("/static", StaticFiles(directory="/app/static"), name="static")
|
||||||
|
|
||||||
def setup_graphql_endpoint(self, app: FastAPI):
|
|
||||||
async def setup_graphql_context(credentials: JwtAuthorizationCredentials = Security(self.access_security)):
|
|
||||||
user_id = credentials['id'] if credentials else None
|
|
||||||
organization_ids = set()
|
|
||||||
|
|
||||||
if user_id:
|
|
||||||
async with async_session() as db:
|
|
||||||
organization_ids = set((await db.scalars(
|
|
||||||
select(models.user_is_in_organization.c.organization_id)
|
|
||||||
.filter(models.user_is_in_organization.c.user_id == user_id)
|
|
||||||
)).all())
|
|
||||||
|
|
||||||
return GraphQLContext(
|
|
||||||
user_id=user_id,
|
|
||||||
organization_ids=organization_ids,
|
|
||||||
jwt_auth_credentials=credentials,
|
|
||||||
jwt=self.access_security,
|
|
||||||
background_tasks=Depends(BackgroundTasks)
|
|
||||||
)
|
|
||||||
|
|
||||||
graphql_app = GraphQLRouter(
|
|
||||||
schema,
|
|
||||||
graphiql=GRAPHIQL,
|
|
||||||
debug=APP_DEBUG,
|
|
||||||
context_getter=setup_graphql_context
|
|
||||||
)
|
|
||||||
app.include_router(graphql_app, prefix="/graphql")
|
|
||||||
|
|
||||||
def setup_routes(self, app: FastAPI):
|
def setup_routes(self, app: FastAPI):
|
||||||
self.setup_graphql_endpoint(app)
|
setup_graphql_endpoint(app, self.access_security, self.api_router)
|
||||||
|
|
||||||
if APP_DEBUG:
|
|
||||||
@self.api_router.get("/graphql/autologin")
|
|
||||||
async def autologin():
|
|
||||||
access_token = self.access_security.create_access_token(subject={"id": 6, "name": "Franta Vomacka"})
|
|
||||||
|
|
||||||
response = RedirectResponse(url="/graphql")
|
|
||||||
self.access_security.set_access_cookie(response, access_token, expires_delta=timedelta(days=14))
|
|
||||||
|
|
||||||
return response
|
|
||||||
|
|
||||||
@self.api_router.post("/refresh")
|
@self.api_router.post("/refresh")
|
||||||
async def refresh(
|
async def refresh(
|
||||||
@@ -121,6 +81,10 @@ class App:
|
|||||||
refresh_token=self.refresh_security
|
refresh_token=self.refresh_security
|
||||||
).on_post(resp, credentials)
|
).on_post(resp, credentials)
|
||||||
|
|
||||||
|
@self.api_router.post("/registration", status_code=201)
|
||||||
|
async def registration(user: RegistrationInput, background_tasks: BackgroundTasks):
|
||||||
|
return await RegistrationEndpoint().on_post(user, background_tasks)
|
||||||
|
|
||||||
@self.api_router.post("/login")
|
@self.api_router.post("/login")
|
||||||
async def login(resp: Response, user: LoginInput):
|
async def login(resp: Response, user: LoginInput):
|
||||||
return await LoginEndpoint(
|
return await LoginEndpoint(
|
||||||
@@ -128,13 +92,21 @@ class App:
|
|||||||
refresh_token=self.refresh_security
|
refresh_token=self.refresh_security
|
||||||
).on_post(user, resp)
|
).on_post(user, resp)
|
||||||
|
|
||||||
|
@self.api_router.get("/forgotten-password/token/{token}")
|
||||||
|
async def token_info(token: str):
|
||||||
|
return await ForgottenPasswordEndpoint().token_info(token)
|
||||||
|
|
||||||
|
@self.api_router.post("/forgotten-password/request")
|
||||||
|
async def password_reset(input: ForgottenPasswordRequest, background_tasks: BackgroundTasks):
|
||||||
|
return await ForgottenPasswordEndpoint().request(input, background_tasks)
|
||||||
|
|
||||||
|
@self.api_router.post("/forgotten-password/reset")
|
||||||
|
async def password_reset(input: ChangeForgottenPassword):
|
||||||
|
return await ForgottenPasswordEndpoint().change_password(input)
|
||||||
|
|
||||||
@self.api_router.post("/contact")
|
@self.api_router.post("/contact")
|
||||||
async def contact(resp: Response, input: ContactInput, background_tasks: BackgroundTasks):
|
async def contact(input: ContactInput, background_tasks: BackgroundTasks):
|
||||||
return await ContactEndpoint().on_post(
|
return await ContactEndpoint().on_post(input, background_tasks)
|
||||||
input,
|
|
||||||
resp,
|
|
||||||
background_tasks
|
|
||||||
)
|
|
||||||
|
|
||||||
@self.api_router.post("/logout")
|
@self.api_router.post("/logout")
|
||||||
async def logout(resp: Response):
|
async def logout(resp: Response):
|
||||||
@@ -173,9 +145,5 @@ class App:
|
|||||||
rotate=rotate,
|
rotate=rotate,
|
||||||
)
|
)
|
||||||
|
|
||||||
@self.api_router.post("/registration", status_code=201)
|
|
||||||
async def registration(user: RegistrationInput):
|
|
||||||
return await RegistrationEndpoint().on_post(user)
|
|
||||||
|
|
||||||
# musi byt na konci
|
# musi byt na konci
|
||||||
app.include_router(self.api_router)
|
app.include_router(self.api_router)
|
||||||
|
|||||||
Reference in New Issue
Block a user