diff --git a/API_EXAMPLES.md b/API_EXAMPLES.md new file mode 100644 index 0000000..d813884 --- /dev/null +++ b/API_EXAMPLES.md @@ -0,0 +1,276 @@ +# API Usage Examples + +## Authentication + +### Get JWT Token +```bash +curl -X POST http://localhost:8082/api/auth/token \ + -d "email=admin@amnez.ia&password=admin123" +``` + +Response: +```json +{ + "success": true, + "token": "eyJ0eXAiOiJKV1QiLCJhbGc...", + "type": "Bearer", + "expires_in": 2592000 +} +``` + +## Clients + +### Create Client with QR Code +```bash +TOKEN="your-jwt-token" + +curl -X POST http://localhost:8082/api/clients/create \ + -H "Authorization: Bearer $TOKEN" \ + -H "Content-Type: application/json" \ + -d '{ + "server_id": 1, + "name": "My Phone" + }' +``` + +Response: +```json +{ + "success": true, + "client": { + "id": 1, + "name": "My Phone", + "server_id": 1, + "client_ip": "10.8.1.1", + "status": "active", + "created_at": "2025-11-07 12:00:00", + "config": "[Interface]\nPrivateKey = ...\n...", + "qr_code": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA..." + } +} +``` + +The `qr_code` field contains a data URI that can be used directly in HTML: +```html +QR Code +``` + +### Get Client QR Code +```bash +curl -X GET http://localhost:8082/api/clients/1/qr \ + -H "Authorization: Bearer $TOKEN" +``` + +Response: +```json +{ + "success": true, + "qr_code": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA...", + "client_name": "My Phone" +} +``` + +### Get Client Details with Stats, Config and QR +```bash +curl -X GET http://localhost:8082/api/clients/1/details \ + -H "Authorization: Bearer $TOKEN" +``` + +Response: +```json +{ + "success": true, + "client": { + "id": 1, + "name": "My Phone", + "server_id": 1, + "client_ip": "10.8.1.1", + "status": "active", + "created_at": "2025-11-07 12:00:00", + "stats": { + "sent": "1.23 GB", + "received": "456.78 MB", + "total": "1.68 GB", + "last_seen": "Online", + "is_online": true + }, + "bytes_sent": 1320000000, + "bytes_received": 478800000, + "last_handshake": "2025-11-07 12:30:00", + "config": "[Interface]\nPrivateKey = ...\n...", + "qr_code": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA..." + } +} +``` + +## Servers + +### List Servers +```bash +curl -X GET http://localhost:8082/api/servers \ + -H "Authorization: Bearer $TOKEN" +``` + +### Create Server +```bash +curl -X POST http://localhost:8082/api/servers/create \ + -H "Authorization: Bearer $TOKEN" \ + -H "Content-Type: application/json" \ + -d '{ + "name": "US Server", + "host": "192.168.1.100", + "port": 22, + "username": "root", + "password": "your-password" + }' +``` + +### Get Server Clients +```bash +curl -X GET http://localhost:8082/api/servers/1/clients \ + -H "Authorization: Bearer $TOKEN" +``` + +## Client Management + +### Revoke Client +```bash +curl -X POST http://localhost:8082/api/clients/1/revoke \ + -H "Authorization: Bearer $TOKEN" +``` + +### Restore Client +```bash +curl -X POST http://localhost:8082/api/clients/1/restore \ + -H "Authorization: Bearer $TOKEN" +``` + +### Delete Client +```bash +curl -X DELETE http://localhost:8082/api/clients/1/delete \ + -H "Authorization: Bearer $TOKEN" +``` + +## Integration Examples + +### Python Example +```python +import requests +import base64 +from io import BytesIO +from PIL import Image + +# Get token +response = requests.post('http://localhost:8082/api/auth/token', + data={'email': 'admin@amnez.ia', 'password': 'admin123'}) +token = response.json()['token'] + +headers = {'Authorization': f'Bearer {token}'} + +# Create client +client_data = { + 'server_id': 1, + 'name': 'My Phone' +} +response = requests.post('http://localhost:8082/api/clients/create', + json=client_data, headers=headers) + +result = response.json() +qr_code_data_uri = result['client']['qr_code'] + +# Save QR code as image +qr_base64 = qr_code_data_uri.split(',')[1] +qr_bytes = base64.b64decode(qr_base64) +image = Image.open(BytesIO(qr_bytes)) +image.save('qr_code.png') + +print(f"Client created: {result['client']['name']}") +print(f"QR code saved to qr_code.png") +``` + +### JavaScript/Node.js Example +```javascript +const axios = require('axios'); +const fs = require('fs'); + +// Get token +const authResponse = await axios.post('http://localhost:8082/api/auth/token', + 'email=admin@amnez.ia&password=admin123'); +const token = authResponse.data.token; + +const headers = { 'Authorization': `Bearer ${token}` }; + +// Create client +const clientData = { + server_id: 1, + name: 'My Phone' +}; + +const response = await axios.post('http://localhost:8082/api/clients/create', + clientData, { headers }); + +const qrCodeDataUri = response.data.client.qr_code; + +// Save QR code as image +const base64Data = qrCodeDataUri.split(',')[1]; +fs.writeFileSync('qr_code.png', base64Data, 'base64'); + +console.log(`Client created: ${response.data.client.name}`); +console.log('QR code saved to qr_code.png'); +``` + +### Display QR Code in Web Page +```html + + + + VPN Client QR Code + + +

Scan this QR code with Amnezia VPN app

+
+ + + + +``` diff --git a/README.md b/README.md index 148daea..04786e2 100644 --- a/README.md +++ b/README.md @@ -99,8 +99,9 @@ GET /api/servers/{id}/clients - List clients on server ### Clients ``` GET /api/clients - List all clients -GET /api/clients/{id}/details - Get client details with stats -POST /api/clients/create - Create new client +GET /api/clients/{id}/details - Get client details with stats, config and QR code +GET /api/clients/{id}/qr - Get client QR code +POST /api/clients/create - Create new client (returns config and QR code) Parameters: server_id, name POST /api/clients/{id}/revoke - Revoke client access POST /api/clients/{id}/restore - Restore client access diff --git a/public/index.php b/public/index.php index 9b67e14..2f3fbab 100644 --- a/public/index.php +++ b/public/index.php @@ -820,6 +820,8 @@ Router::get('/api/clients/{id}/details', function ($params) { 'bytes_sent' => $clientData['bytes_sent'], 'bytes_received' => $clientData['bytes_received'], 'last_handshake' => $clientData['last_handshake'], + 'config' => $clientData['config'], + 'qr_code' => $clientData['qr_code'], ] ]); } catch (Exception $e) { @@ -828,6 +830,37 @@ Router::get('/api/clients/{id}/details', function ($params) { } }); +// API: Get client QR code +Router::get('/api/clients/{id}/qr', function ($params) { + header('Content-Type: application/json'); + + $user = JWT::requireAuth(); + if (!$user) return; + + $clientId = (int)$params['id']; + + try { + $client = new VpnClient($clientId); + $clientData = $client->getData(); + + // Check ownership + if ($clientData['user_id'] != $user['id']) { + http_response_code(403); + echo json_encode(['error' => 'Forbidden']); + return; + } + + echo json_encode([ + 'success' => true, + 'qr_code' => $clientData['qr_code'], + 'client_name' => $clientData['name'] + ]); + } catch (Exception $e) { + http_response_code(404); + echo json_encode(['error' => 'Client not found']); + } +}); + // API: Revoke client Router::post('/api/clients/{id}/revoke', function ($params) { header('Content-Type: application/json'); @@ -968,7 +1001,20 @@ Router::post('/api/clients/create', function () { $client = new VpnClient($clientId); $clientData = $client->getData(); - echo json_encode(['client' => $clientData]); + // Return client data with config and QR code + echo json_encode([ + 'success' => true, + 'client' => [ + 'id' => $clientData['id'], + 'name' => $clientData['name'], + 'server_id' => $clientData['server_id'], + 'client_ip' => $clientData['client_ip'], + 'status' => $clientData['status'], + 'created_at' => $clientData['created_at'], + 'config' => $clientData['config'], + 'qr_code' => $clientData['qr_code'], + ] + ]); } catch (Exception $e) { http_response_code(500); echo json_encode(['error' => $e->getMessage()]);