refactor(auth): archive app/auth.py + app/auth_wallet.py, migrate all imports to app.domains.auth.* (P4.3 cont)

This commit is contained in:
Crypto Rug Munch 2026-07-07 14:53:21 +07:00
parent f5e1e140dc
commit 018edaded7
19 changed files with 68 additions and 58 deletions

View file

@ -819,7 +819,7 @@ class AdminUserStore:
created_by: str = "",
) -> dict | None:
"""Create a new admin user."""
from app.auth import hash_password
from app.domains.auth.passwords import hash_password
# Check if email already exists
existing = await AdminUserStore.get_admin_by_email(email)
@ -853,7 +853,7 @@ class AdminUserStore:
@staticmethod
async def verify_admin_login(email: str, password: str) -> dict | None:
"""Verify admin login credentials."""
from app.auth import verify_password
from app.domains.auth.passwords import verify_password
admin = await AdminUserStore.get_admin_by_email(email)
if not admin:

View file

@ -51,7 +51,7 @@ async def deep_contract_audit(req: TokenRequest):
# If primary returned no data, use full fallback chain
if not result.get("sources_used"):
from app.auth import get_redis as _get_redis
from app.core.redis import get_redis as _get_redis
from app.fallback_engine import try_all_fallbacks
r = await _get_redis()
@ -72,7 +72,7 @@ async def deep_contract_audit(req: TokenRequest):
except Exception as e:
# Last resort: try fallback before raising error
try:
from app.auth import get_redis as _get_redis
from app.core.redis import get_redis as _get_redis
from app.fallback_engine import try_all_fallbacks
r = await _get_redis()

View file

@ -1128,7 +1128,7 @@ async def reset_admin_password(request: Request, admin_id: str, body: dict = Bod
updater = auth["admin"]
ip, ua = _get_client_info(request)
from app.auth import hash_password
from app.domains.auth.passwords import hash_password
admin = await AdminUserStore.get_admin(admin_id)
if not admin:

View file

@ -33,7 +33,7 @@ router = APIRouter(tags=["admin-users"])
# ── Redis helper ──
async def require_admin(request: Request, min_role: str = "ADMIN"):
"""Require admin authentication."""
from app.auth import get_current_user
from app.domains.auth import get_current_user
user = await get_current_user(request)
if not user:
@ -131,7 +131,7 @@ def _get_all_users() -> list[dict]:
def _get_user_full(user_id: str) -> dict | None:
"""Get user with enriched data."""
from app.auth import _get_user
from app.domains.auth.store import _get_user
user = _get_user(user_id)
if not user:
@ -285,7 +285,7 @@ async def warn_user(user_id: str, req: WarnUserRequest, request: Request):
"""Add a warning to a user."""
admin = await require_admin(request, min_role="MODERATOR")
from app.auth import _get_user
from app.domains.auth.store import _get_user
user = _get_user(user_id)
if not user:
@ -320,7 +320,7 @@ async def flag_suspect(user_id: str, request: Request, reason: str | None = Quer
"""Flag a user as suspicious."""
admin = await require_admin(request, min_role="MODERATOR")
from app.auth import _get_user
from app.domains.auth.store import _get_user
user = _get_user(user_id)
if not user:
@ -360,7 +360,7 @@ async def ban_user(user_id: str, request: Request, reason: str | None = Query(No
"""Ban a user."""
admin = await require_admin(request, min_role="ADMIN")
from app.auth import _get_user
from app.domains.auth.store import _get_user
user = _get_user(user_id)
if not user:
@ -402,7 +402,7 @@ async def delete_user(user_id: str, request: Request, reason: str | None = Query
"""Soft delete a user."""
admin = await require_admin(request, min_role="ADMIN")
from app.auth import _get_user, _save_user
from app.domains.auth.store import _get_user, _save_user
user = _get_user(user_id)
if not user:
@ -430,7 +430,7 @@ async def restore_user(user_id: str, request: Request):
"""Restore a soft-deleted user."""
admin = await require_admin(request, min_role="ADMIN")
from app.auth import _get_user, _save_user
from app.domains.auth.store import _get_user, _save_user
user = _get_user(user_id)
if not user:
@ -454,7 +454,7 @@ async def update_user(user_id: str, req: UpdateUserRequest, request: Request):
"""Update user properties (tier, role, status, etc.)."""
admin = await require_admin(request, min_role="ADMIN")
from app.auth import _get_user, _save_user
from app.domains.auth.store import _get_user, _save_user
user = _get_user(user_id)
if not user:
@ -530,7 +530,7 @@ async def bulk_action(req: BulkActionRequest, request: Request):
r.hset("rmi:user_status", user_id, "active")
results["success"].append({"id": user_id, "action": "cleared_suspect"})
elif req.action == "delete":
from app.auth import _get_user, _save_user
from app.domains.auth.store import _get_user, _save_user
user = _get_user(user_id)
if user:
@ -541,7 +541,7 @@ async def bulk_action(req: BulkActionRequest, request: Request):
r.hset("rmi:user_status", user_id, "deleted")
results["success"].append({"id": user_id, "action": "deleted"})
elif req.action == "restore":
from app.auth import _get_user, _save_user
from app.domains.auth.store import _get_user, _save_user
user = _get_user(user_id)
if user:
@ -553,7 +553,7 @@ async def bulk_action(req: BulkActionRequest, request: Request):
results["success"].append({"id": user_id, "action": "restored"})
elif req.action == "update_tier":
tier = req.params.get("tier", "FREE") if req.params else "FREE"
from app.auth import _get_user, _save_user
from app.domains.auth.store import _get_user, _save_user
user = _get_user(user_id)
if user:

View file

@ -84,7 +84,7 @@ class AgentCommandRequest(BaseModel):
priority: str = Field(default="normal")
from app.auth import get_redis # noqa: E402
from app.domains.auth import get_redis # noqa: E402
# ── Static routes must comes before parameterized routes to avoid FastAPI matching issues ──

View file

@ -21,7 +21,8 @@ class AlertRequest(BaseModel):
webhook_url: str | None = None
from app.auth import get_redis, require_auth # noqa: E402
from app.core.redis import get_redis
from app.domains.auth import require_auth # noqa: E402
def _get_redis_sync():

View file

@ -91,7 +91,7 @@ class ProfileResponse(BaseModel):
@router.post("/forgot-password")
async def forgot_password(req: ForgotPasswordRequest):
"""Request password reset - sends email with reset token."""
from app.auth import _get_user_by_email
from app.domains.auth.store import _get_user_by_email
user = _get_user_by_email(req.email)
if not user:
@ -140,7 +140,8 @@ async def forgot_password(req: ForgotPasswordRequest):
@router.post("/reset-password")
async def reset_password(req: ResetPasswordRequest):
"""Reset password using token from email."""
from app.auth import _get_user, _save_user, hash_password
from app.domains.auth.passwords import hash_password
from app.domains.auth.store import _get_user, _save_user
token_hash = hashlib.sha256(req.token.encode()).hexdigest()
r = get_redis() # noqa: F821 -- pre-existing bug, see fix(f821) tracking issue
@ -173,7 +174,9 @@ async def reset_password(req: ResetPasswordRequest):
@router.post("/change-password")
async def change_password(req: ChangePasswordRequest, request: Request):
"""Change password while logged in."""
from app.auth import _save_user, get_current_user, hash_password, verify_password
from app.domains.auth import get_current_user
from app.domains.auth.passwords import hash_password, verify_password
from app.domains.auth.store import _save_user
user = await get_current_user(request)
if not user:
@ -200,7 +203,7 @@ async def change_password(req: ChangePasswordRequest, request: Request):
@router.get("/profile", response_model=ProfileResponse)
async def get_profile(request: Request):
"""Get full user profile including linked wallets."""
from app.auth import get_current_user
from app.domains.auth import get_current_user
user = await get_current_user(request)
if not user:
@ -229,7 +232,8 @@ async def get_profile(request: Request):
@router.patch("/profile")
async def update_profile(req: UpdateProfileRequest, request: Request):
"""Update user profile (display name, avatar)."""
from app.auth import _save_user, get_current_user
from app.domains.auth import get_current_user
from app.domains.auth.store import _save_user
user = await get_current_user(request)
if not user:
@ -388,7 +392,8 @@ async def list_supported_chains():
@router.post("/wallet/link")
async def link_wallet(req: LinkWalletRequest, request: Request):
"""Link a new wallet to the user's account."""
from app.auth import _save_user, get_current_user
from app.domains.auth import get_current_user
from app.domains.auth.store import _save_user
user = await get_current_user(request)
if not user:
@ -437,7 +442,8 @@ async def link_wallet(req: LinkWalletRequest, request: Request):
@router.post("/wallet/unlink")
async def unlink_wallet(req: UnlinkWalletRequest, request: Request):
"""Unlink a wallet from the user's account."""
from app.auth import _save_user, get_current_user
from app.domains.auth import get_current_user
from app.domains.auth.store import _save_user
user = await get_current_user(request)
if not user:
@ -476,7 +482,7 @@ async def unlink_wallet(req: UnlinkWalletRequest, request: Request):
@router.get("/wallet/list")
async def list_wallets(request: Request):
"""List all wallets linked to the current user."""
from app.auth import get_current_user
from app.domains.auth import get_current_user
user = await get_current_user(request)
if not user:
@ -504,7 +510,7 @@ class PrivacySettings(BaseModel):
@router.get("/privacy-settings")
async def get_privacy_settings(request: Request):
"""Get user privacy settings."""
from app.auth import get_current_user
from app.domains.auth import get_current_user
user = await get_current_user(request)
if not user:
@ -528,7 +534,8 @@ async def get_privacy_settings(request: Request):
@router.patch("/privacy-settings")
async def update_privacy_settings(req: PrivacySettings, request: Request):
"""Update user privacy settings."""
from app.auth import _save_user, get_current_user
from app.domains.auth import get_current_user
from app.domains.auth.store import _save_user
user = await get_current_user(request)
if not user:
@ -559,8 +566,10 @@ async def delete_account(req: DeleteAccountRequest, request: Request):
Permanently delete user account and all associated data (GDPR compliant).
Requires password confirmation.
"""
from app.auth import _delete_user, get_current_user, verify_password
from app.core.redis import get_redis
from app.domains.auth import get_current_user
from app.domains.auth.passwords import verify_password
from app.domains.auth.store import _delete_user
user = await get_current_user(request)
if not user:

View file

@ -33,7 +33,7 @@ from app.services.supabase_service import ( # noqa: E402
# Lazy auth dependency - avoids importing jose+bcrypt at module load
async def _require_public_profile(request: Request):
from app.auth import require_public_profile
from app.domains.auth import require_public_profile
return await require_public_profile(request)

View file

@ -133,7 +133,7 @@ async def create_case(req: CaseCreateRequest, request: Request):
# Resolve creator if authed
creator = "anonymous"
try:
from app.auth import get_current_user
from app.domains.auth import get_current_user
user = await get_current_user(request)
if user:
@ -199,7 +199,7 @@ async def get_case(case_id: str):
async def list_my_cases(request: Request, limit: int = 50):
"""List cases created by the current user. Auth required."""
try:
from app.auth import get_current_user
from app.domains.auth import get_current_user
user = await get_current_user(request)
except Exception:
@ -219,7 +219,7 @@ async def delete_case(case_id: str, request: Request):
if not data:
raise HTTPException(status_code=404, detail="Case not found")
try:
from app.auth import get_current_user
from app.domains.auth import get_current_user
user = await get_current_user(request)
except Exception:
@ -261,7 +261,7 @@ async def get_investigator(username: str):
async def upsert_investigator(username: str, request: Request):
"""Update or create investigator profile. Auth required."""
try:
from app.auth import get_current_user
from app.domains.auth import get_current_user
user = await get_current_user(request)
except Exception:
@ -312,7 +312,7 @@ async def portfolio_features(request: Request):
base_tier = "FREE"
try:
from app.auth import get_current_user
from app.domains.auth import get_current_user
user = await get_current_user(request)
except Exception:
@ -360,7 +360,7 @@ async def add_addon(req: AddonRequest, request: Request):
Returns an x402 challenge for micropayment, or a stripe checkout URL
for fiat, or a crypto payment address.
"""
from app.auth import get_current_user
from app.domains.auth import get_current_user
try:
user = await get_current_user(request)

View file

@ -41,7 +41,7 @@ ai_guard = AIGuard()
# ── Auth ──
# ── AI Router ──
from app.ai_router import router as ai_router # noqa: E402
from app.auth import get_current_user, require_auth # noqa: E402
from app.domains.auth import get_current_user, require_auth # noqa: E402
# ── DB path ──
DB_PATH = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(__file__))), "data", "rmi.db")

View file

@ -21,7 +21,7 @@ from datetime import UTC, datetime, timedelta
from fastapi import APIRouter, Depends, HTTPException, Query
from pydantic import BaseModel
from app.auth import require_public_profile
from app.domains.auth import require_public_profile
logger = logging.getLogger(__name__)

View file

@ -29,7 +29,7 @@ API_BASE = os.getenv("API_BASE", "https://rugmunch.io")
# ── Redis helper ──
async def get_current_user(request: Request) -> dict | None:
"""Extract user from JWT."""
from app.auth import get_current_user as _get_user
from app.domains.auth import get_current_user as _get_user
return await _get_user(request)

View file

@ -354,7 +354,7 @@ async def calculate_pricing(tier: str, period: str):
@router.get("/subscription")
async def get_my_subscription(request: Request):
"""Get current user's active subscription."""
from app.auth import get_current_user
from app.domains.auth import get_current_user
user = await get_current_user(request)
if not user:
@ -391,7 +391,7 @@ async def get_my_subscription(request: Request):
@router.post("/subscription/create")
async def create_subscription(req: SubscriptionCreateRequest, request: Request):
"""Create a new subscription (Stripe, crypto, or x402)."""
from app.auth import get_current_user
from app.domains.auth import get_current_user
user = await get_current_user(request)
if not user:
@ -526,7 +526,8 @@ async def create_subscription(req: SubscriptionCreateRequest, request: Request):
@router.post("/subscription/crypto/confirm")
async def confirm_crypto_payment(req: CryptoPaymentRequest, request: Request):
"""Confirm a crypto payment (called by user after sending tx, or webhook)."""
from app.auth import _save_user, get_current_user
from app.domains.auth import get_current_user
from app.domains.auth.store import _save_user
user = await get_current_user(request)
if not user:
@ -570,7 +571,7 @@ async def confirm_crypto_payment(req: CryptoPaymentRequest, request: Request):
@router.post("/subscription/cancel")
async def cancel_subscription(request: Request):
"""Cancel subscription at period end."""
from app.auth import get_current_user
from app.domains.auth import get_current_user
user = await get_current_user(request)
if not user:
@ -596,7 +597,7 @@ async def cancel_subscription(request: Request):
@router.post("/subscription/upgrade")
async def upgrade_subscription(tier: str, request: Request):
"""Upgrade to a higher tier."""
from app.auth import get_current_user
from app.domains.auth import get_current_user
user = await get_current_user(request)
if not user:
@ -636,7 +637,7 @@ async def upgrade_subscription(tier: str, request: Request):
@router.post("/webhooks/stripe")
async def stripe_webhook(request: Request):
"""Handle Stripe webhooks for subscription events."""
from app.auth import _get_user, _save_user
from app.domains.auth.store import _get_user, _save_user
payload = await request.body()
sig_header = request.headers.get("stripe-signature")
@ -681,7 +682,6 @@ async def stripe_webhook(request: Request):
event["data"]["object"]
# Mark subscription as past_due
# TODO: Implement
pass
return {"status": "ok"}
@ -698,7 +698,7 @@ async def list_all_subscriptions(
offset: int = 0,
):
"""List all subscriptions (admin only)."""
from app.auth import get_current_user
from app.domains.auth import get_current_user
user = await get_current_user(request)
if not user or user.get("role") not in ("ADMIN", "SUPERADMIN"):
@ -732,8 +732,8 @@ async def list_all_subscriptions(
@router.get("/admin/revenue")
async def get_revenue_stats(request: Request):
"""Get revenue statistics (admin only)."""
from app.auth import get_current_user
from app.core.redis import get_redis
from app.domains.auth import get_current_user
user = await get_current_user(request)
if not user or user.get("role") not in ("ADMIN", "SUPERADMIN"):

View file

@ -53,7 +53,7 @@ def _get_redis():
async def _get_redis_async():
"""Async Redis client for dashboard queries."""
try:
from app.auth import get_redis
from app.core.redis import get_redis
r = await get_redis()
return r

View file

@ -338,7 +338,7 @@ async def verify_receipt_public(receipt_id: str):
Returns: receipt data + on-chain proof + verification status.
"""
try:
from app.auth import get_redis
from app.core.redis import get_redis
r = await get_redis()
@ -404,7 +404,7 @@ async def payment_ledger(
No wallet addresses, no PII.
"""
try:
from app.auth import get_redis
from app.core.redis import get_redis
r = await get_redis()
@ -471,7 +471,7 @@ async def transparency_dashboard(hours: int = 24):
No sensitive data - all aggregated and anonymized.
"""
try:
from app.auth import get_redis
from app.core.redis import get_redis
r = await get_redis()
@ -619,7 +619,7 @@ async def verify_payment_endpoint(
# Store verification result for audit trail
if result["verified"]:
try:
from app.auth import get_redis
from app.core.redis import get_redis
r = await get_redis()
verify_key = f"x402:verify:{result.get('settlement_id') or str(time.time())}"
@ -709,7 +709,7 @@ async def store_receipt(request: Request):
amount_float = 0.0
# Store in Redis (sync - app.auth.get_redis returns a sync client)
from app.auth import get_redis as _get_redis
from app.core.redis import get_redis as _get_redis
r = _get_redis()
@ -804,7 +804,7 @@ async def fallback_status():
Shows which fallback layers are working and which are failing.
"""
try:
from app.auth import get_redis
from app.core.redis import get_redis
r = await get_redis()

View file

@ -119,7 +119,7 @@ async def settle_x402(req: SettleRequest, request: Request):
Then activates the subscription / add-on for the user.
"""
from app.auth import get_current_user
from app.domains.auth import get_current_user
try:
user = await get_current_user(request)
@ -187,7 +187,7 @@ async def settle_x402(req: SettleRequest, request: Request):
# Also write the user_metadata flag so /api/v1/portfolio/features picks it up
try:
from app.auth import _save_user
from app.domains.auth.store import _save_user
md = (user.get("user_metadata") or {}).copy()
if addon == "PORTFOLIO_PRO":

View file

@ -350,7 +350,7 @@ def get_identity(request) -> tuple[str, str]:
auth = request.headers.get("Authorization", "") if hasattr(request, "headers") else ""
if auth.startswith("Bearer "):
try:
from app.auth import _verify_jwt
from app.domains.auth.jwt import _verify_jwt
payload = _verify_jwt(auth[7:])
if payload: