Project, Web Technologies, Year 3, Semester 1
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

73 lines
2.2 KiB

from flask.views import MethodView
from flask_smorest import Blueprint
from marshmallow import Schema, fields
from .. import returns, ram_db, decorators
from ..db_utils import get_user
from ..models import User
from ..decorators import ensure_logged_in
from pyotp import TOTP
bp = Blueprint('login', __name__, description='Login operations')
class LoginParams(Schema):
username = fields.String()
code = fields.String()
class LoginResult(returns.SuccessSchema):
token = fields.String()
class LoginSuccessSchema(returns.SuccessSchema):
token = fields.String()
@bp.route('/')
class Login(MethodView):
@bp.arguments(LoginParams, as_kwargs=True)
@bp.response(401, returns.ErrorSchema, description='Login failure')
@bp.response(200, LoginSuccessSchema)
def post(self, username: str, code: str):
"""Login via username and TOTP code"""
user: User | None = get_user(username=username)
if user is None:
return returns.abort(returns.INVALID_DETAILS)
otp = TOTP(user.otp)
if not otp.verify(code, valid_window=1):
return returns.abort(returns.INVALID_DETAILS)
token = ram_db.login_user(user.id)
return returns.success(token=token)
@ensure_logged_in
@bp.doc(security=[{'Token': []}])
@bp.response(401, returns.ErrorSchema, description='Login failure')
@bp.response(204)
def delete(self):
"""Logout"""
ram_db.logout_user(decorators.token)
@bp.post('/logout')
@ensure_logged_in
@bp.doc(security=[{'Token': []}])
@bp.response(401, returns.ErrorSchema, description='Login failure')
@bp.response(204)
def logout_route():
"""Logout"""
ram_db.logout_user(decorators.token)
@bp.route('/whoami')
class WhoAmI(MethodView):
class WhoAmISchema(returns.SuccessSchema):
user = fields.Nested(User.UserSchema)
@bp.response(401, returns.ErrorSchema, description='Login failure')
@bp.response(200, WhoAmISchema)
@bp.doc(security=[{'Token': []}])
@ensure_logged_in
def get(self):
"""Get information about currently logged in user"""
user: User | None = get_user(user_id=decorators.user_id)
# if user is not None:
# user = user.to_json()
return returns.success(user=user)