Files
waylume_server/lib/web/peer_routes.dart

280 lines
8.0 KiB
Dart

import 'dart:convert';
import 'package:shelf/shelf.dart';
import 'package:shelf_router/shelf_router.dart';
import 'package:waylume_server/wireguard/peers.dart';
import 'package:waylume_server/wireguard/utils.dart';
import 'package:waylume_server/core/utils.dart';
import 'package:waylume_server/services/vpn_session_service.dart';
import 'package:waylume_server/services/bandwidth_service.dart';
class PeerRoutes {
Router get router {
final router = Router();
router.get('/peers', _getPeers);
router.post('/peer', _createPeer);
router.delete('/peer/<publicKey>', _deletePeer);
router.get('/peer/<publicKey>/config', _getPeerConfig);
router.patch('/peer/<publicKey>/speed-limit', _setSpeedLimit);
router.patch('/peer/<publicKey>/data-cap', _setDataCap);
router.get('/bandwidth-stats', _getBandwidthStats);
return router;
}
Future<Response> _getPeers(Request request) async {
try {
final statusParam = request.url.queryParameters['status']?.toUpperCase();
List<Map<String, dynamic>> peers;
if (statusParam == 'DEAD') {
peers = await VpnSessionService.getInactivePeers();
} else if (statusParam == 'ALIVE') {
final allPeers = await VpnSessionService.getAllLocalPeers();
peers = allPeers.where((peer) => peer['status'] == 'ALIVE').toList();
} else {
// No filter or invalid filter - return all peers
peers = await VpnSessionService.getAllLocalPeers();
}
return Response.ok(
jsonEncode({
'success': true,
'peers': peers,
'total_count': peers.length,
'filter': statusParam,
}),
headers: {'Content-Type': 'application/json'},
);
} catch (e) {
return Response.internalServerError(
body: jsonEncode({
'success': false,
'error': e.toString(),
}),
headers: {'Content-Type': 'application/json'},
);
}
}
Future<Response> _createPeer(Request request) async {
try {
final peer = await createPeer();
final geoData = await getGeolocationData();
String serverEndpoint = '${geoData.ip}:51820';
String serverPublicKey = await getServerPublicKey();
final responseData = <String, dynamic>{
'peer': {
'ip': peer.ip,
'privateKey': peer.privateKey,
'publicKey': peer.publicKey,
},
'server': {
'publicKey': serverPublicKey,
'endpoint': serverEndpoint,
},
'success': true,
};
return Response.ok(
jsonEncode(responseData),
headers: {'Content-Type': 'application/json'},
);
} catch (e) {
return Response.internalServerError(
body: jsonEncode({
'success': false,
'error': e.toString(),
}),
headers: {'Content-Type': 'application/json'},
);
}
}
Future<Response> _deletePeer(Request request) async {
try {
final publicKey = request.params['publicKey'];
if (publicKey == null || publicKey.isEmpty) {
return Response.badRequest(
body: jsonEncode({
'success': false,
'error': 'publicKey parameter is required',
}),
headers: {'Content-Type': 'application/json'},
);
}
final success = await deletePeer(publicKey);
return Response.ok(
jsonEncode({
'success': success,
'message': success ? 'Peer deleted successfully' : 'Failed to delete peer',
}),
headers: {'Content-Type': 'application/json'},
);
} catch (e) {
return Response.internalServerError(
body: jsonEncode({
'success': false,
'error': e.toString(),
}),
headers: {'Content-Type': 'application/json'},
);
}
}
Future<Response> _getPeerConfig(Request request) async {
try {
final publicKey = request.params['publicKey'];
if (publicKey == null || publicKey.isEmpty) {
return Response.badRequest(
body: jsonEncode({
'success': false,
'error': 'publicKey parameter is required',
}),
headers: {'Content-Type': 'application/json'},
);
}
return Response.notFound(
jsonEncode({
'success': false,
'error': 'Config retrieval not implemented - peer info not stored',
}),
headers: {'Content-Type': 'application/json'},
);
} catch (e) {
return Response.internalServerError(
body: jsonEncode({
'success': false,
'error': e.toString(),
}),
headers: {'Content-Type': 'application/json'},
);
}
}
Future<Response> _setSpeedLimit(Request request) async {
try {
final publicKey = request.params['publicKey'];
final body = await request.readAsString();
final data = jsonDecode(body) as Map<String, dynamic>;
final bytesPerSecond = data['bytesPerSecond'] as int?;
if (publicKey == null || publicKey.isEmpty) {
return Response.badRequest(
body: jsonEncode({
'success': false,
'error': 'publicKey parameter is required',
}),
headers: {'Content-Type': 'application/json'},
);
}
if (bytesPerSecond == null) {
return Response.badRequest(
body: jsonEncode({
'success': false,
'error': 'bytesPerSecond parameter is required',
}),
headers: {'Content-Type': 'application/json'},
);
}
await setSpeedLimit(publicKey, bytesPerSecond);
return Response.ok(
jsonEncode({
'success': true,
'message': 'Speed limit set successfully',
}),
headers: {'Content-Type': 'application/json'},
);
} catch (e) {
return Response.internalServerError(
body: jsonEncode({
'success': false,
'error': e.toString(),
}),
headers: {'Content-Type': 'application/json'},
);
}
}
Future<Response> _setDataCap(Request request) async {
try {
final publicKey = request.params['publicKey'];
final body = await request.readAsString();
final data = jsonDecode(body) as Map<String, dynamic>;
final quotaBytes = data['quotaBytes'] as int?;
if (publicKey == null || publicKey.isEmpty) {
return Response.badRequest(
body: jsonEncode({
'success': false,
'error': 'publicKey parameter is required',
}),
headers: {'Content-Type': 'application/json'},
);
}
if (quotaBytes == null) {
return Response.badRequest(
body: jsonEncode({
'success': false,
'error': 'quotaBytes parameter is required',
}),
headers: {'Content-Type': 'application/json'},
);
}
await setDataCap(publicKey, quotaBytes);
return Response.ok(
jsonEncode({
'success': true,
'message': 'Data cap set successfully',
}),
headers: {'Content-Type': 'application/json'},
);
} catch (e) {
return Response.internalServerError(
body: jsonEncode({
'success': false,
'error': e.toString(),
}),
headers: {'Content-Type': 'application/json'},
);
}
}
Future<Response> _getBandwidthStats(Request request) async {
try {
final collectorId = request.url.queryParameters['collector_id'];
final bandwidthData = await BandwidthService.getBandwidthStats(collectorId);
return Response.ok(
jsonEncode({
'success': true,
'data': bandwidthData,
}),
headers: {'Content-Type': 'application/json'},
);
} catch (e) {
return Response.internalServerError(
body: jsonEncode({
'success': false,
'error': e.toString(),
}),
headers: {'Content-Type': 'application/json'},
);
}
}
}