mirror of
https://github.com/Casvt/MIND.git
synced 2026-04-03 03:00:22 -04:00
Added 2FA in the backend
This commit is contained in:
@@ -158,6 +158,18 @@ class APIKeyExpired(LogUnauthMindException):
|
||||
}
|
||||
|
||||
|
||||
class MFACodeRequired(MindException):
|
||||
"An MFA code is sent and now expected to be supplied"
|
||||
|
||||
@property
|
||||
def api_response(self) -> ApiResponse:
|
||||
return {
|
||||
'code': 200,
|
||||
'error': self.__class__.__name__,
|
||||
'result': {}
|
||||
}
|
||||
|
||||
|
||||
# region Admin Operations
|
||||
class OperationNotAllowed(MindException):
|
||||
"What was requested to be done is not allowed"
|
||||
|
||||
@@ -9,18 +9,15 @@ from __future__ import annotations
|
||||
from abc import ABC, abstractmethod
|
||||
from dataclasses import dataclass
|
||||
from enum import Enum
|
||||
from typing import (TYPE_CHECKING, Any, Callable, Dict, List, Literal,
|
||||
Sequence, Tuple, TypedDict, TypeVar, Union, cast)
|
||||
from typing import (Any, Callable, Dict, List, Literal, Sequence,
|
||||
Tuple, TypedDict, TypeVar, Union, cast)
|
||||
|
||||
from flask import Response
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from backend.implementations.users import User
|
||||
|
||||
|
||||
# region Types
|
||||
T = TypeVar('T')
|
||||
U = TypeVar('U')
|
||||
MISSING = object()
|
||||
WEEKDAY_NUMBER = Literal[0, 1, 2, 3, 4, 5, 6]
|
||||
|
||||
BaseJSONSerialisable = Union[
|
||||
@@ -56,6 +53,7 @@ class Constants:
|
||||
ADMIN_PREFIX = API_PREFIX + ADMIN_API_EXTENSION
|
||||
API_KEY_LENGTH = 32 # hexadecimal characters
|
||||
API_KEY_CLEANUP_INTERVAL = 86400 # seconds
|
||||
MFA_CODE_TIMEOUT = 300 # seconds
|
||||
|
||||
DB_FOLDER = ("db",)
|
||||
DB_NAME = "MIND.db"
|
||||
@@ -238,12 +236,6 @@ class StartTypeHandler(ABC):
|
||||
|
||||
|
||||
# region Dataclasses
|
||||
@dataclass
|
||||
class ApiKeyEntry:
|
||||
exp: int
|
||||
user_data: UserData
|
||||
|
||||
|
||||
@dataclass(frozen=True, order=True)
|
||||
class NotificationServiceData:
|
||||
id: int
|
||||
@@ -261,12 +253,13 @@ class UserData:
|
||||
admin: bool
|
||||
salt: bytes
|
||||
hash: bytes
|
||||
mfa_apprise_url: Union[str, None]
|
||||
|
||||
def todict(self) -> Dict[str, Any]:
|
||||
return {
|
||||
k: v
|
||||
for k, v in self.__dict__.items()
|
||||
if k in ('id', 'username', 'admin')
|
||||
if k in ('id', 'username', 'admin', 'mfa_apprise_url')
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -262,6 +262,15 @@ def generate_api_key() -> str:
|
||||
return token_hex(Constants.API_KEY_LENGTH // 2)
|
||||
|
||||
|
||||
def generate_mfa_code() -> str:
|
||||
"""Generate a 6-digit MFA code.
|
||||
|
||||
Returns:
|
||||
str: The code.
|
||||
"""
|
||||
return str(int.from_bytes(token_bytes(3), 'big') % 1_000_000).zfill(6)
|
||||
|
||||
|
||||
# region Apprise
|
||||
def send_apprise_notification(
|
||||
urls: List[str],
|
||||
|
||||
Reference in New Issue
Block a user