app-MAIL-temp/app/api/base.py
Adrià Casajús de31e6d072
Allow to set sudo mode for api requests (#1108)
* Allow to set sudo mode for api requests

* Rebase migration on top of master

* PR comments

* Added missing migration

* Removed unused import

* Apply suggestions from code review

Co-authored-by: Adrià Casajús <adria.casajus@proton.ch>
2022-06-23 14:26:36 +02:00

68 lines
1.6 KiB
Python

from functools import wraps
from typing import Tuple, Optional
import arrow
from flask import Blueprint, request, jsonify, g
from flask_login import current_user
from app.db import Session
from app.models import ApiKey
api_bp = Blueprint(name="api", import_name=__name__, url_prefix="/api")
SUDO_MODE_MINUTES_VALID = 5
def authorize_request() -> Optional[Tuple[str, int]]:
api_code = request.headers.get("Authentication")
api_key = ApiKey.get_by(code=api_code)
if not api_key:
if current_user.is_authenticated:
g.user = current_user
else:
return jsonify(error="Wrong api key"), 401
else:
# Update api key stats
api_key.last_used = arrow.now()
api_key.times += 1
Session.commit()
g.user = api_key.user
if g.user.disabled:
return jsonify(error="Disabled account"), 403
g.api_key = api_key
return None
def check_sudo_mode_is_active(api_key: ApiKey) -> bool:
return api_key.sudo_mode_at and g.api_key.sudo_mode_at >= arrow.now().shift(
minutes=-SUDO_MODE_MINUTES_VALID
)
def require_api_auth(f):
@wraps(f)
def decorated(*args, **kwargs):
error_return = authorize_request()
if error_return:
return error_return
return f(*args, **kwargs)
return decorated
def require_api_sudo(f):
@wraps(f)
def decorated(*args, **kwargs):
error_return = authorize_request()
if error_return:
return error_return
if not check_sudo_mode_is_active(g.api_key):
return jsonify(error="Need sudo"), 440
return f(*args, **kwargs)
return decorated