feat: Add internal API endpoints for Customer Panel integration
- Add internal_api_required decorator for internal API authentication - Add /internal/available endpoint to fetch available CF accounts - Add /internal/<id> endpoint to get CF account with API token - Filter accounts by is_active and use_for_verification flags - Require X-Internal-API-Key header for internal endpoints
This commit is contained in:
parent
e149c56f76
commit
d68c4d38ff
|
|
@ -4,9 +4,21 @@ Cloudflare Accounts Management Routes
|
||||||
from flask import Blueprint, request, jsonify
|
from flask import Blueprint, request, jsonify
|
||||||
from app.models import db, CloudflareAccount, AuditLog
|
from app.models import db, CloudflareAccount, AuditLog
|
||||||
from app.routes.auth import token_required
|
from app.routes.auth import token_required
|
||||||
|
from app.config import Config
|
||||||
|
from functools import wraps
|
||||||
|
|
||||||
cf_accounts_bp = Blueprint('cf_accounts', __name__)
|
cf_accounts_bp = Blueprint('cf_accounts', __name__)
|
||||||
|
|
||||||
|
def internal_api_required(f):
|
||||||
|
"""Decorator for internal API endpoints (requires internal API key)"""
|
||||||
|
@wraps(f)
|
||||||
|
def decorated_function(*args, **kwargs):
|
||||||
|
api_key = request.headers.get('X-Internal-API-Key')
|
||||||
|
if not api_key or api_key != Config.CUSTOMER_API_INTERNAL_KEY:
|
||||||
|
return jsonify({'error': 'Unauthorized - Invalid internal API key'}), 401
|
||||||
|
return f(*args, **kwargs)
|
||||||
|
return decorated_function
|
||||||
|
|
||||||
@cf_accounts_bp.route('', methods=['GET'])
|
@cf_accounts_bp.route('', methods=['GET'])
|
||||||
@token_required
|
@token_required
|
||||||
def get_cf_accounts(current_admin):
|
def get_cf_accounts(current_admin):
|
||||||
|
|
@ -170,3 +182,75 @@ def delete_cf_account(current_admin, account_id):
|
||||||
db.session.rollback()
|
db.session.rollback()
|
||||||
return jsonify({'error': str(e)}), 500
|
return jsonify({'error': str(e)}), 500
|
||||||
|
|
||||||
|
|
||||||
|
# Internal API Endpoints (for Customer Panel)
|
||||||
|
@cf_accounts_bp.route('/internal/available', methods=['GET'])
|
||||||
|
@internal_api_required
|
||||||
|
def get_available_cf_accounts_internal():
|
||||||
|
"""
|
||||||
|
Internal API endpoint for Customer Panel to fetch available CF accounts
|
||||||
|
Requires X-Internal-API-Key header
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
# Get active CF accounts that are enabled for verification
|
||||||
|
accounts = CloudflareAccount.query.filter_by(
|
||||||
|
is_active=True,
|
||||||
|
use_for_verification=True
|
||||||
|
).order_by(CloudflareAccount.created_at.desc()).all()
|
||||||
|
|
||||||
|
result = []
|
||||||
|
for account in accounts:
|
||||||
|
account_dict = account.to_dict(include_token=False)
|
||||||
|
# Calculate available capacity
|
||||||
|
account_dict['available_capacity'] = account.max_domains - account.current_domains
|
||||||
|
account_dict['is_full'] = account.current_domains >= account.max_domains
|
||||||
|
result.append(account_dict)
|
||||||
|
|
||||||
|
return jsonify({
|
||||||
|
'status': 'success',
|
||||||
|
'accounts': result,
|
||||||
|
'total': len(result)
|
||||||
|
}), 200
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
return jsonify({
|
||||||
|
'status': 'error',
|
||||||
|
'error': str(e)
|
||||||
|
}), 500
|
||||||
|
|
||||||
|
|
||||||
|
@cf_accounts_bp.route('/internal/<int:account_id>', methods=['GET'])
|
||||||
|
@internal_api_required
|
||||||
|
def get_cf_account_internal(account_id):
|
||||||
|
"""
|
||||||
|
Internal API endpoint to get specific CF account with API token
|
||||||
|
Requires X-Internal-API-Key header
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
account = CloudflareAccount.query.get(account_id)
|
||||||
|
if not account:
|
||||||
|
return jsonify({
|
||||||
|
'status': 'error',
|
||||||
|
'error': 'Account not found'
|
||||||
|
}), 404
|
||||||
|
|
||||||
|
if not account.is_active or not account.use_for_verification:
|
||||||
|
return jsonify({
|
||||||
|
'status': 'error',
|
||||||
|
'error': 'Account not available for verification'
|
||||||
|
}), 403
|
||||||
|
|
||||||
|
# Return account with API token (for internal use)
|
||||||
|
account_dict = account.to_dict(include_token=True)
|
||||||
|
|
||||||
|
return jsonify({
|
||||||
|
'status': 'success',
|
||||||
|
'account': account_dict
|
||||||
|
}), 200
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
return jsonify({
|
||||||
|
'status': 'error',
|
||||||
|
'error': str(e)
|
||||||
|
}), 500
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue