mirror of
https://github.com/jhd3197/ServerKit.git
synced 2026-11-09 21:43:05 +09:00
Enforce admin and workspace permissions, improve logging, and add DNS frontend/API support. - Backend: added admin checks to cloud_provisioning and marketplace endpoints; added require_workspace_access helper and applied to multiple workspace endpoints to enforce membership/admin access; persist push subscription data in mobile API (commit to DB); replaced print() debugging with structured logger calls across agent_registry and added logging/exception handling in monitoring_service. - Frontend: added a DNS API client (frontend/src/services/api/dns.js) and registered it in the API index; extended DNSZones UI to collect provider zone ID and API token, updated create payload and form reset; added optional modal footer prop to Modal component; moved rollup native binding to optionalDependencies in package.json. - Misc: added '*.png' to .gitignore and a minor spacing change in install.sh. These changes improve security checks, observability, and add DNS management features in the UI/API.
163 lines
5.5 KiB
Python
163 lines
5.5 KiB
Python
from flask import Blueprint, request, jsonify
|
|
from flask_jwt_extended import jwt_required
|
|
from app.services.cloud_provisioning_service import CloudProvisioningService
|
|
|
|
cloud_provisioning_bp = Blueprint('cloud_provisioning', __name__)
|
|
|
|
|
|
def get_current_user():
|
|
from flask_jwt_extended import get_jwt_identity
|
|
from app.models.user import User
|
|
return User.query.get(get_jwt_identity())
|
|
|
|
|
|
# --- Providers ---
|
|
|
|
@cloud_provisioning_bp.route('/providers', methods=['GET'])
|
|
@jwt_required()
|
|
def list_providers():
|
|
providers = CloudProvisioningService.list_providers()
|
|
return jsonify({'providers': [p.to_dict() for p in providers]})
|
|
|
|
|
|
@cloud_provisioning_bp.route('/providers', methods=['POST'])
|
|
@jwt_required()
|
|
def create_provider():
|
|
user = get_current_user()
|
|
if not user or not user.is_admin:
|
|
return jsonify({'error': 'Admin access required'}), 403
|
|
data = request.get_json()
|
|
try:
|
|
provider = CloudProvisioningService.create_provider(data, user.id)
|
|
return jsonify(provider.to_dict()), 201
|
|
except ValueError as e:
|
|
return jsonify({'error': str(e)}), 400
|
|
|
|
|
|
@cloud_provisioning_bp.route('/providers/<int:provider_id>', methods=['DELETE'])
|
|
@jwt_required()
|
|
def delete_provider(provider_id):
|
|
user = get_current_user()
|
|
if not user or not user.is_admin:
|
|
return jsonify({'error': 'Admin access required'}), 403
|
|
if not CloudProvisioningService.delete_provider(provider_id):
|
|
return jsonify({'error': 'Not found'}), 404
|
|
return jsonify({'message': 'Provider removed'})
|
|
|
|
|
|
@cloud_provisioning_bp.route('/providers/<provider_type>/options', methods=['GET'])
|
|
@jwt_required()
|
|
def get_options(provider_type):
|
|
options = CloudProvisioningService.get_provider_options(provider_type)
|
|
if not options:
|
|
return jsonify({'error': 'Unknown provider'}), 404
|
|
return jsonify(options)
|
|
|
|
|
|
# --- Servers ---
|
|
|
|
@cloud_provisioning_bp.route('/servers', methods=['GET'])
|
|
@jwt_required()
|
|
def list_servers():
|
|
provider_id = request.args.get('provider_id', type=int)
|
|
servers = CloudProvisioningService.list_servers(provider_id)
|
|
return jsonify({'servers': [s.to_dict() for s in servers]})
|
|
|
|
|
|
@cloud_provisioning_bp.route('/servers/<int:server_id>', methods=['GET'])
|
|
@jwt_required()
|
|
def get_server(server_id):
|
|
server = CloudProvisioningService.get_server(server_id)
|
|
if not server:
|
|
return jsonify({'error': 'Not found'}), 404
|
|
return jsonify(server.to_dict())
|
|
|
|
|
|
@cloud_provisioning_bp.route('/servers', methods=['POST'])
|
|
@jwt_required()
|
|
def create_server():
|
|
user = get_current_user()
|
|
if not user or not user.is_admin:
|
|
return jsonify({'error': 'Admin access required'}), 403
|
|
data = request.get_json()
|
|
if not data or 'name' not in data or 'provider_id' not in data:
|
|
return jsonify({'error': 'name and provider_id required'}), 400
|
|
try:
|
|
server = CloudProvisioningService.create_server(data, user.id)
|
|
return jsonify(server.to_dict()), 201
|
|
except (ValueError, Exception) as e:
|
|
return jsonify({'error': str(e)}), 400
|
|
|
|
|
|
@cloud_provisioning_bp.route('/servers/<int:server_id>', methods=['DELETE'])
|
|
@jwt_required()
|
|
def destroy_server(server_id):
|
|
user = get_current_user()
|
|
if not user or not user.is_admin:
|
|
return jsonify({'error': 'Admin access required'}), 403
|
|
if not CloudProvisioningService.destroy_server(server_id):
|
|
return jsonify({'error': 'Not found'}), 404
|
|
return jsonify({'message': 'Server destroyed'})
|
|
|
|
|
|
@cloud_provisioning_bp.route('/servers/<int:server_id>/resize', methods=['POST'])
|
|
@jwt_required()
|
|
def resize_server(server_id):
|
|
user = get_current_user()
|
|
if not user or not user.is_admin:
|
|
return jsonify({'error': 'Admin access required'}), 403
|
|
data = request.get_json() or {}
|
|
new_size = data.get('size')
|
|
if not new_size:
|
|
return jsonify({'error': 'size required'}), 400
|
|
try:
|
|
server = CloudProvisioningService.resize_server(server_id, new_size)
|
|
if not server:
|
|
return jsonify({'error': 'Not found'}), 404
|
|
return jsonify(server.to_dict())
|
|
except ValueError as e:
|
|
return jsonify({'error': str(e)}), 400
|
|
|
|
|
|
# --- Snapshots ---
|
|
|
|
@cloud_provisioning_bp.route('/servers/<int:server_id>/snapshots', methods=['GET'])
|
|
@jwt_required()
|
|
def list_snapshots(server_id):
|
|
snapshots = CloudProvisioningService.get_snapshots(server_id)
|
|
return jsonify({'snapshots': [s.to_dict() for s in snapshots]})
|
|
|
|
|
|
@cloud_provisioning_bp.route('/servers/<int:server_id>/snapshots', methods=['POST'])
|
|
@jwt_required()
|
|
def create_snapshot(server_id):
|
|
user = get_current_user()
|
|
if not user or not user.is_admin:
|
|
return jsonify({'error': 'Admin access required'}), 403
|
|
data = request.get_json() or {}
|
|
name = data.get('name', f'snapshot-{server_id}')
|
|
try:
|
|
snapshot = CloudProvisioningService.create_snapshot(server_id, name)
|
|
return jsonify(snapshot.to_dict()), 201
|
|
except ValueError as e:
|
|
return jsonify({'error': str(e)}), 400
|
|
|
|
|
|
@cloud_provisioning_bp.route('/snapshots/<int:snapshot_id>', methods=['DELETE'])
|
|
@jwt_required()
|
|
def delete_snapshot(snapshot_id):
|
|
user = get_current_user()
|
|
if not user or not user.is_admin:
|
|
return jsonify({'error': 'Admin access required'}), 403
|
|
if not CloudProvisioningService.delete_snapshot(snapshot_id):
|
|
return jsonify({'error': 'Not found'}), 404
|
|
return jsonify({'message': 'Snapshot deleted'})
|
|
|
|
|
|
# --- Cost ---
|
|
|
|
@cloud_provisioning_bp.route('/costs', methods=['GET'])
|
|
@jwt_required()
|
|
def cost_summary():
|
|
return jsonify(CloudProvisioningService.get_cost_summary())
|