Implement real, working microservices architecture

This commit is contained in:
2026-01-06 17:28:25 +03:00
Unverified
parent c7c9d9606d
commit 75ef3fc604
52 changed files with 2088 additions and 165 deletions
+11 -11
View File
@@ -8,16 +8,16 @@ import uuid
from user_agents import parse as parse_ua
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
from constants import OWNER_USERNAME
from dependencies import get_current_user, get_db
from models import LoginRequest, RegisterRequest, ChangePasswordRequest, User, CryptoPublicKey, CryptoBackup, DeviceSession
from utils import create_token, get_password_hash, verify_password, get_client_ip
from validation import is_valid_password, is_valid_username, is_valid_display_name
from backend.shared.constants import OWNER_USERNAME
from backend.shared.dependencies import get_current_user, get_db
from backend.shared.models import LoginRequest, RegisterRequest, ChangePasswordRequest, User, CryptoPublicKey, CryptoBackup, DeviceSession
from backend.shared.utils import create_token, get_password_hash, verify_password, get_client_ip
from backend.shared.validation import is_valid_password, is_valid_username, is_valid_display_name
import os
from security.audit import log_security
from security.profanity import contains_profanity
from security.rate_limit import rate_limit_per_ip
from backend.security.audit import log_security
from backend.security.profanity import contains_profanity
from backend.security.rate_limit import rate_limit_per_ip
router = APIRouter()
_FAILED_ATTEMPT_WINDOW_SECONDS = 300
@@ -356,7 +356,7 @@ def delete_user_as_owner(
raise HTTPException(status_code=400, detail="Cannot delete owner account")
# Manually delete user's messages to satisfy FK constraints
from models import Message # local import to avoid circular
from backend.shared.models import Message # local import to avoid circular
db.query(Message).filter(Message.user_id == user.id).delete()
db.delete(user)
@@ -381,7 +381,7 @@ def logout(
db: Session = Depends(get_db)
):
# Revoke current session
from utils import verify_token as _verify_token
from backend.shared.utils import verify_token as _verify_token
payload = _verify_token(credentials.credentials)
if payload and payload.get("session_id"):
db.query(DeviceSession).filter(
@@ -427,7 +427,7 @@ def change_password(
# Optionally revoke all other sessions, keeping the current one
if password_request.logoutAllExceptCurrent:
from utils import verify_token as _verify_token
from backend.shared.utils import verify_token as _verify_token
payload = _verify_token(credentials.credentials)
if not payload:
raise HTTPException(status_code=401, detail="Invalid token")
+3 -3
View File
@@ -2,9 +2,9 @@ from datetime import datetime
from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy.orm import Session
from dependencies import get_current_user, get_db
from models import User, DeviceSession
from utils import verify_token
from backend.shared.dependencies import get_current_user, get_db
from backend.shared.models import User, DeviceSession
from backend.shared.utils import verify_token
from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer
router = APIRouter()
+11 -11
View File
@@ -16,29 +16,29 @@ from fastapi import APIRouter, Depends, HTTPException, WebSocket, WebSocketDisco
from fastapi.responses import FileResponse
from fastapi.security import HTTPAuthorizationCredentials
from sqlalchemy.orm import Session
from dependencies import get_current_user, get_db
from .account import convert_user
from constants import OWNER_USERNAME
from models import Message, SendMessageRequest, EditMessageRequest, User, DMEnvelope, MessageFile, DMFile, Reaction, ReactionRequest, ReactionResponse, DMReaction, DMReactionRequest, DMReactionResponse, UpdateLog
from push_service import push_service
from backend.shared.dependencies import get_current_user, get_db
from backend.shared.utils import convert_user
from backend.shared.constants import OWNER_USERNAME
from backend.shared.models import Message, SendMessageRequest, EditMessageRequest, User, DMEnvelope, MessageFile, DMFile, Reaction, ReactionRequest, ReactionResponse, DMReaction, DMReactionRequest, DMReactionResponse, UpdateLog
import backend.push_service as push_service
from PIL import Image
import io
import json
from pydantic import BaseModel
from better_profanity import profanity as _bp
from security.audit import log_access, log_dm, log_public_chat, log_security
from security.profanity import contains_profanity
from security.rate_limit import rate_limit_per_ip
from websocket.utils import authenticate_user
from backend.security.audit import log_access, log_dm, log_public_chat, log_security
from backend.security.profanity import contains_profanity
from backend.security.rate_limit import rate_limit_per_ip
from backend.websocket.utils import authenticate_user
from models import FcmToken
from backend.shared.models import FcmToken
router = APIRouter()
logger = logging.getLogger("uvicorn.error")
MAX_TOTAL_SIZE = 4 * 1024 * 1024 * 1024 # 4 GB
FILES_BASE_DIR = Path("data/uploads/files")
FILES_BASE_DIR = Path(__file__).resolve().parent.parent / "data" / "uploads" / "files"
FILES_NORMAL_DIR = FILES_BASE_DIR / "normal"
FILES_ENCRYPTED_DIR = FILES_BASE_DIR / "encrypted"
+6 -6
View File
@@ -2,12 +2,12 @@ from fastapi import APIRouter, Depends, HTTPException
from pydantic import BaseModel, Field
from typing import List
from constants import OWNER_USERNAME
from dependencies import get_current_user
from models import User
from security.audit import log_security
from security.profanity import add_to_blocklist, get_blocklist, remove_from_blocklist
from security.rate_limit import reset_rate_limit_for_ip, clear_all_rate_limits
from backend.shared.constants import OWNER_USERNAME
from backend.shared.dependencies import get_current_user
from backend.shared.models import User
from backend.security.audit import log_security
from backend.security.profanity import add_to_blocklist, get_blocklist, remove_from_blocklist
from backend.security.rate_limit import reset_rate_limit_for_ip, clear_all_rate_limits
class BlocklistUpdateRequest(BaseModel):
+8 -8
View File
@@ -9,15 +9,15 @@ import uuid
import io
from fastapi import Request
from dependencies import get_db, get_current_user
from models import User, UpdateBioRequest, UserProfileResponse
from backend.shared.dependencies import get_db, get_current_user
from backend.shared.models import User, UpdateBioRequest, UserProfileResponse
from pydantic import BaseModel
from validation import is_valid_username, is_valid_display_name
from similarity import is_user_similar_to_verified
from backend.shared.validation import is_valid_username, is_valid_display_name
from backend.similarity import is_user_similar_to_verified
from .messaging import messagingManager
from security.audit import log_security
from security.profanity import contains_profanity
from security.rate_limit import rate_limit_per_ip
from backend.security.audit import log_security
from backend.security.profanity import contains_profanity
from backend.security.rate_limit import rate_limit_per_ip
router = APIRouter()
@@ -36,7 +36,7 @@ class UpdateProfileRequest(BaseModel):
description: str | None = None
# Create uploads directory if it doesn't exist
PROFILE_PICTURES_DIR = Path("data/uploads/pfp")
PROFILE_PICTURES_DIR = Path(__file__).resolve().parent.parent / "data" / "uploads" / "pfp"
os.makedirs(PROFILE_PICTURES_DIR, exist_ok=True)
+3 -3
View File
@@ -1,8 +1,8 @@
from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy.orm import Session
from dependencies import get_current_user, get_db
from models import User, PushSubscriptionRequest
from push_service import push_service
from backend.shared.dependencies import get_current_user, get_db
from backend.shared.models import User, PushSubscriptionRequest
import backend.push_service as push_service
router = APIRouter()
+1 -1
View File
@@ -4,7 +4,7 @@ import hmac
import hashlib
import time
from fastapi import APIRouter, Depends
from dependencies import get_current_user
from backend.shared.dependencies import get_current_user
import traceback
router = APIRouter()