Initial commit: abyssVpn project
- Tauri desktop app (apps/desktop) - Python Django API service (services/api) - Deployment scripts and docs
This commit is contained in:
@@ -0,0 +1,142 @@
|
||||
import json
|
||||
|
||||
from django.http import HttpRequest, JsonResponse
|
||||
from django.views.decorators.csrf import csrf_exempt
|
||||
from django.views.decorators.http import require_GET, require_POST
|
||||
|
||||
from common.auth import get_current_user
|
||||
from .models import Device, VpnLog
|
||||
from .services.device_service import issue_connect_token
|
||||
from .services.netmaker_client import NetmakerApiError, NetmakerClient, NetmakerConfigError
|
||||
|
||||
|
||||
@csrf_exempt
|
||||
@require_POST
|
||||
def connect_token(request: HttpRequest) -> JsonResponse:
|
||||
user = get_current_user(request)
|
||||
if user is None:
|
||||
return JsonResponse({"error": "unauthorized"}, status=401)
|
||||
|
||||
body = json.loads(request.body or b"{}")
|
||||
device_name = body.get("device_name") or "unknown-device"
|
||||
fingerprint = body.get("device_fingerprint") or ""
|
||||
try:
|
||||
token = issue_connect_token(user, device_name, fingerprint)
|
||||
except PermissionError as error:
|
||||
return JsonResponse({"error": str(error)}, status=403)
|
||||
except NetmakerConfigError as error:
|
||||
return JsonResponse({"error": str(error)}, status=503)
|
||||
except NetmakerApiError as error:
|
||||
return JsonResponse({"error": str(error)}, status=502)
|
||||
return JsonResponse({"token": token})
|
||||
|
||||
|
||||
@require_GET
|
||||
def status(request: HttpRequest) -> JsonResponse:
|
||||
user = get_current_user(request)
|
||||
if user is None:
|
||||
return JsonResponse({"error": "unauthorized"}, status=401)
|
||||
devices = list(user.devices.values("id", "device_name", "status", "netmaker_node_id", "updated_at"))
|
||||
logs = list(
|
||||
VpnLog.objects.filter(user=user)
|
||||
.select_related("device")
|
||||
.order_by("-created_at")
|
||||
.values("id", "device_id", "action", "detail", "created_at")[:20]
|
||||
)
|
||||
return JsonResponse(
|
||||
{
|
||||
"user": {
|
||||
"id": user.id,
|
||||
"name": user.name,
|
||||
"email": user.email,
|
||||
},
|
||||
"devices": devices,
|
||||
"logs": logs,
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@csrf_exempt
|
||||
@require_POST
|
||||
def register_node(request: HttpRequest) -> JsonResponse:
|
||||
user = get_current_user(request)
|
||||
if user is None:
|
||||
return JsonResponse({"error": "unauthorized"}, status=401)
|
||||
|
||||
body = json.loads(request.body or b"{}")
|
||||
fingerprint = body.get("device_fingerprint") or ""
|
||||
node_id = body.get("netmaker_node_id") or body.get("host_id") or body.get("node_id") or ""
|
||||
device_name = body.get("device_name") or "unknown-device"
|
||||
if not fingerprint:
|
||||
return JsonResponse({"error": "missing_device_fingerprint"}, status=400)
|
||||
if not node_id:
|
||||
return JsonResponse({"error": "missing_netmaker_node_id"}, status=400)
|
||||
|
||||
device, _created = Device.objects.get_or_create(
|
||||
user=user,
|
||||
device_fingerprint=fingerprint,
|
||||
defaults={"device_name": device_name},
|
||||
)
|
||||
if device.status == Device.STATUS_REVOKED:
|
||||
return JsonResponse({"error": "device_revoked"}, status=403)
|
||||
|
||||
changed_fields = []
|
||||
if device.device_name != device_name:
|
||||
device.device_name = device_name
|
||||
changed_fields.append("device_name")
|
||||
if device.netmaker_node_id != node_id:
|
||||
device.netmaker_node_id = node_id
|
||||
changed_fields.append("netmaker_node_id")
|
||||
if changed_fields:
|
||||
changed_fields.append("updated_at")
|
||||
device.save(update_fields=changed_fields)
|
||||
VpnLog.objects.create(
|
||||
user=user,
|
||||
device=device,
|
||||
action="netmaker_node_registered",
|
||||
detail={"netmaker_node_id": node_id},
|
||||
)
|
||||
|
||||
return JsonResponse({"status": "ok", "device_id": device.id})
|
||||
|
||||
|
||||
@csrf_exempt
|
||||
@require_POST
|
||||
def disconnect_log(request: HttpRequest) -> JsonResponse:
|
||||
user = get_current_user(request)
|
||||
if user is None:
|
||||
return JsonResponse({"error": "unauthorized"}, status=401)
|
||||
body = json.loads(request.body or b"{}")
|
||||
fingerprint = body.get("device_fingerprint") or ""
|
||||
device = Device.objects.filter(user=user, device_fingerprint=fingerprint).first()
|
||||
VpnLog.objects.create(user=user, device=device, action="disconnect", detail={"device_fingerprint": fingerprint})
|
||||
return JsonResponse({"status": "ok"})
|
||||
|
||||
|
||||
@csrf_exempt
|
||||
@require_POST
|
||||
def revoke_device(request: HttpRequest) -> JsonResponse:
|
||||
user = get_current_user(request)
|
||||
if user is None:
|
||||
return JsonResponse({"error": "unauthorized"}, status=401)
|
||||
body = json.loads(request.body or b"{}")
|
||||
device = Device.objects.filter(user=user, id=body.get("device_id")).first()
|
||||
if device is None:
|
||||
return JsonResponse({"error": "device_not_found"}, status=404)
|
||||
|
||||
netmaker_error = ""
|
||||
if device.netmaker_node_id:
|
||||
try:
|
||||
NetmakerClient().delete_node(device.netmaker_node_id)
|
||||
except (NetmakerConfigError, NetmakerApiError) as error:
|
||||
netmaker_error = str(error)
|
||||
|
||||
device.status = Device.STATUS_REVOKED
|
||||
device.save(update_fields=["status", "updated_at"])
|
||||
VpnLog.objects.create(
|
||||
user=user,
|
||||
device=device,
|
||||
action="device_revoked",
|
||||
detail={"device_id": device.id, "netmaker_error": netmaker_error},
|
||||
)
|
||||
return JsonResponse({"status": "ok", "netmaker_error": netmaker_error})
|
||||
Reference in New Issue
Block a user