mirror of
https://github.com/jhd3197/ServerKit.git
synced 2026-10-30 16:47:01 +09:00
65 lines
2.5 KiB
Python
65 lines
2.5 KiB
Python
# Bucket: PER-APP read (plan 29 #9). Per-app bandwidth is scoped to callers who
|
|
# can access the app (can_access_app); the cross-app overview stays panel-wide.
|
|
"""REST surface for per-domain bandwidth accounting.
|
|
|
|
Mounted at /api/v1/bandwidth (registered in app/__init__.py).
|
|
"""
|
|
from flask import Blueprint, jsonify, request
|
|
from flask_jwt_extended import get_jwt_identity
|
|
|
|
from ..middleware.rbac import admin_required, viewer_required
|
|
from ..models import User, Application
|
|
from ..services.bandwidth_service import BandwidthService
|
|
from ..services.resource_grant_service import ResourceGrantService
|
|
|
|
bandwidth_bp = Blueprint('bandwidth', __name__)
|
|
|
|
|
|
@bandwidth_bp.route('/apps', methods=['GET'])
|
|
@viewer_required
|
|
def get_apps_bandwidth():
|
|
"""Month totals + 30-day sparkline series for every app with traffic —
|
|
one call for the Services list."""
|
|
try:
|
|
data = BandwidthService.overview(days=30)
|
|
# JSON object keys must be strings.
|
|
return jsonify({'apps': {str(k): v for k, v in data.items()}})
|
|
except Exception as exc: # noqa: BLE001 — surface as a clean JSON error
|
|
return jsonify({'error': str(exc)}), 500
|
|
|
|
|
|
@bandwidth_bp.route('/apps/<int:app_id>', methods=['GET'])
|
|
@viewer_required
|
|
def get_app_bandwidth(app_id):
|
|
"""Full daily series (default 90 days) + current-month total for one app,
|
|
scoped to the app's workspace visibility (plan 29 #9 — foreign caller 404)."""
|
|
app = Application.query.get(app_id)
|
|
user = User.query.get(get_jwt_identity())
|
|
if app is None or not ResourceGrantService.can_access_app(user, app):
|
|
return jsonify({'error': 'Not found'}), 404
|
|
try:
|
|
days = request.args.get('days', 90, type=int)
|
|
series = BandwidthService.series(app_id=app_id, days=days)
|
|
return jsonify({
|
|
'app_id': app_id,
|
|
'days': len(series),
|
|
'series': series,
|
|
'month_bytes': BandwidthService.monthly_total(app_id),
|
|
})
|
|
except Exception as exc: # noqa: BLE001
|
|
return jsonify({'error': str(exc)}), 500
|
|
|
|
|
|
@bandwidth_bp.route('/aggregate', methods=['POST'])
|
|
@admin_required
|
|
def run_aggregate():
|
|
"""Run the daily aggregation now (optionally for a specific day)."""
|
|
try:
|
|
payload = request.get_json(silent=True) or {}
|
|
result = BandwidthService.aggregate(day=payload.get('day'))
|
|
return jsonify(result)
|
|
except ValueError:
|
|
return jsonify({'error': 'day must be YYYY-MM-DD'}), 400
|
|
except Exception as exc: # noqa: BLE001
|
|
return jsonify({'error': str(exc)}), 500
|