feat(auth): implement user plans and credits system with related endpoints

This commit is contained in:
JSC
2025-06-29 16:40:54 +02:00
parent 52c60db811
commit 91648a858e
10 changed files with 334 additions and 63 deletions

View File

@@ -32,6 +32,8 @@ def get_user_from_jwt() -> dict[str, Any] | None:
"is_active": is_active,
"provider": claims.get("provider", "unknown"),
"providers": claims.get("providers", []),
"plan": claims.get("plan"),
"credits": claims.get("credits"),
}
except Exception:
return None
@@ -64,6 +66,8 @@ def get_user_from_api_token() -> dict[str, Any] | None:
"provider": "api_token",
"providers": [p.provider for p in user.oauth_providers]
+ ["api_token"],
"plan": user.plan.to_dict() if user.plan else None,
"credits": user.credits,
}
return None
@@ -126,3 +130,45 @@ def require_role(required_role: str):
return wrapper
return decorator
def require_credits(credits_needed: int):
"""Decorator to require and deduct credits for routes."""
def decorator(f):
@wraps(f)
def wrapper(*args, **kwargs):
from app.models.user import User
from app.database import db
# First check authentication
user_data = get_current_user()
if not user_data:
return jsonify({"error": "Authentication required"}), 401
# Get the actual user from database to check/update credits
user = User.query.get(int(user_data["id"]))
if not user or not user.is_active:
return jsonify({"error": "User not found or inactive"}), 401
# Check if user has enough credits
if user.credits < credits_needed:
return (
jsonify(
{
"error": f"Insufficient credits. Required: {credits_needed}, Available: {user.credits}"
}
),
402, # Payment Required status code
)
# Deduct credits
user.credits -= credits_needed
db.session.commit()
# Execute the function
result = f(*args, **kwargs)
return result
return wrapper
return decorator