Skip to content

Commit

Permalink
add views
Browse files Browse the repository at this point in the history
  • Loading branch information
Ehco1996 committed Sep 6, 2023
1 parent 59459f0 commit 532d4d2
Show file tree
Hide file tree
Showing 9 changed files with 178 additions and 59 deletions.
4 changes: 2 additions & 2 deletions apps/api/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
gen_datetime_list,
get_client_ip,
get_current_datetime,
handle_json_post,
handle_json_request,
traffic_format,
)

Expand Down Expand Up @@ -133,7 +133,7 @@ def get(self, request, node_id):
JsonResponse(node.get_proxy_configs()) if node else HttpResponseBadRequest()
)

@method_decorator(handle_json_post)
@method_decorator(handle_json_request)
@method_decorator(api_authorized)
def post(self, request, node_id):
node = m.ProxyNode.get_or_none(node_id)
Expand Down
4 changes: 4 additions & 0 deletions apps/openapi/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,7 @@ class UserOpenAPIKey(BaseModel):
class Meta:
verbose_name = "用户秘钥"
verbose_name_plural = "用户秘钥"

@classmethod
def get_by_key(cls, key: str):
return cls.objects.filter(key=key).first()
9 changes: 9 additions & 0 deletions apps/openapi/urls.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
from django.urls import path

from . import views

app_name = "openapi"
urlpatterns = [
path("proxy_nodes/search/", views.ProxyNodeSearchView.as_view()),
path("proxy_nodes/<int:node_id>/", views.ProxyNodeDetailView.as_view()),
]
26 changes: 26 additions & 0 deletions apps/openapi/utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
from functools import wraps

from django.http import JsonResponse

from apps.openapi.models import UserOpenAPIKey


def gen_common_error_response(msg: str, status=400) -> JsonResponse:
return JsonResponse({"error_msg": msg}, status=status)


def openapi_authorized(view_func):
@wraps(view_func)
def wrapper(request, *args, **kwargs):
key = request.META.get("HTTP_X_API_KEY", "")
if not key:
return gen_common_error_response(
"x-api-key in header not found", status=401
)
user_key = UserOpenAPIKey.get_by_key(key)
if not user_key:
return gen_common_error_response("x-api-key is invalid", status=401)
request.user = user_key.user
return view_func(request, *args, **kwargs)

return wrapper
48 changes: 47 additions & 1 deletion apps/openapi/views.py
Original file line number Diff line number Diff line change
@@ -1 +1,47 @@
# Create your views here.
from django.forms import model_to_dict
from django.http import JsonResponse
from django.utils.decorators import method_decorator
from django.views import View
from django.views.decorators.csrf import csrf_exempt

from apps.openapi.utils import gen_common_error_response, openapi_authorized
from apps.proxy.models import ProxyNode
from apps.utils import handle_json_request


class ProxyNodeSearchView(View):
@csrf_exempt
@method_decorator(openapi_authorized)
def dispatch(self, *args, **kwargs):
return super(ProxyNodeSearchView, self).dispatch(*args, **kwargs)

def get(self, request):
ip = request.GET.get("ip")
if not ip:
return gen_common_error_response("ip in query is required")

node = ProxyNode.get_by_ip(ip)
if not node:
return gen_common_error_response(
f"node with ip:{ip} not found", status=404
)
return JsonResponse(model_to_dict(node))


class ProxyNodeDetailView(View):
@csrf_exempt
@method_decorator(openapi_authorized)
@method_decorator(handle_json_request)
def dispatch(self, *args, **kwargs):
return super(ProxyNodeDetailView, self).dispatch(*args, **kwargs)

def patch(self, request, node_id):
node = ProxyNode.get_by_id(node_id)
if not node:
return gen_common_error_response(
f"node with id:{node_id} not found", status=404
)
enable = request.json.get("enable")
node.enable = enable
node.save()
return JsonResponse(model_to_dict(node))
8 changes: 8 additions & 0 deletions apps/proxy/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,10 @@ def __str__(self) -> str:
def get_by_id_with_cache(cls, id):
return cls.objects.get(id=id)

@classmethod
def get_by_id(cls, id):
return cls.objects.filter(id=id).first()

@classmethod
def get_active_nodes(cls, level=None):
query = cls.objects.filter(enable=True)
Expand All @@ -245,6 +249,10 @@ def calc_total_traffic(cls):
used_traffic = aggs["used_traffic"] or 0
return utils.traffic_format(used_traffic)

@classmethod
def get_by_ip(clc, ip: str):
return clc.objects.filter(server=ip).first()

def get_trojan_node_config(self):
xray_config = XRayTemplates.gen_base_config(
self.xray_grpc_port,
Expand Down
32 changes: 28 additions & 4 deletions apps/urls.py
Original file line number Diff line number Diff line change
@@ -1,24 +1,48 @@
import debug_toolbar
from django.conf import settings
from django.contrib import admin
from django.urls import include, path

from apps.custom_views import AsyncPasswordResetView

urlpatterns = [
path("", include("apps.sspanel.urls", namespace="sspanel")),
path("api/", include("apps.api.urls", namespace="api")),
path(
"accounts/password_reset/",
AsyncPasswordResetView.as_view(),
name="password_reset",
), # NOTE 重写了重置密码的逻辑 一定要在`django.contrib.auth.urls`之前注册,不然会被覆盖
path("accounts/", include("django.contrib.auth.urls")),
]

# append sspanel template urls
urlpatterns.append(
path("", include("apps.sspanel.urls", namespace="sspanel")),
)

# append proxy api urls
urlpatterns.append(
path("api/", include("apps.api.urls", namespace="api")),
)

# append admin urls
urlpatterns.append(
path("admin/", admin.site.urls, name="admin"),
)

# append prometheus urls
urlpatterns.append(
path("prom/", include("django_prometheus.urls")),
]
)


# append openapi urls
urlpatterns.append(
path("openapi/v1/", include("apps.openapi.urls", namespace="openapi"))
)


# append django debug toolbar urls
if settings.DEBUG is True:
import debug_toolbar

urlpatterns.append(path("__debug__/", include(debug_toolbar.urls)))

Expand Down
6 changes: 4 additions & 2 deletions apps/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,11 +78,13 @@ def wrapper(request, *args, **kwargs):
return wrapper


def handle_json_post(view_func):
def handle_json_request(view_func):
@wraps(view_func)
def wrapper(request, *args, **kw):
if request.method == "POST":
try:
request.json = json.loads(request.body)
except Exception:
return JsonResponse({"msg": "bad request"}, status=400)
return view_func(request, *args, **kw)

return wrapper
Expand Down
100 changes: 50 additions & 50 deletions wait-for-it.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,76 +4,76 @@ TIMEOUT=15
QUIET=0

echoerr() {
if [ "$QUIET" -ne 1 ]; then printf "%s\n" "$*" 1>&2; fi
if [ "$QUIET" -ne 1 ]; then printf "%s\n" "$*" 1>&2; fi
}

usage() {
exitcode="$1"
exitcode="$1"
cat << USAGE >&2
Usage:
$cmdname host:port [-t timeout] [-- command args]
-q | --quiet Do not output any status messages
-t TIMEOUT | --timeout=timeout Timeout in seconds, zero for no timeout
-- COMMAND ARGS Execute command with args after the test finishes
USAGE
exit "$exitcode"
exit "$exitcode"
}

wait_for() {
for i in `seq $TIMEOUT` ; do
nc -z "$rHOST" "$rPORT" > /dev/null 2>&1

result=$?
if [ $result -eq 0 ] ; then
if [ $# -gt 0 ] ; then
exec "$@"
fi
exit 0
fi
sleep 1
done
echo "Operation timed out" >&2
exit 1
for i in `seq $TIMEOUT` ; do
nc -z "$rHOST" "$rPORT" > /dev/null 2>&1
result=$?
if [ $result -eq 0 ] ; then
if [ $# -gt 0 ] ; then
exec "$@"
fi
exit 0
fi
sleep 1
done
echo "Operation timed out" >&2
exit 1
}

while [ $# -gt 0 ]
do
case "$1" in
*:* )
rHOST=$(printf "%s\n" "$1"| cut -d : -f 1)
rPORT=$(printf "%s\n" "$1"| cut -d : -f 2)
shift 1
;;
-q | --quiet)
QUIET=1
shift 1
;;
-t)
TIMEOUT="$2"
if [ "$TIMEOUT" = "" ]; then break; fi
shift 2
;;
--timeout=*)
TIMEOUT="${1#*=}"
shift 1
;;
--)
shift
break
;;
--help)
usage 0
;;
*)
echoerr "Unknown argument: $1"
usage 1
;;
esac
case "$1" in
*:* )
rHOST=$(printf "%s\n" "$1"| cut -d : -f 1)
rPORT=$(printf "%s\n" "$1"| cut -d : -f 2)
shift 1
;;
-q | --quiet)
QUIET=1
shift 1
;;
-t)
TIMEOUT="$2"
if [ "$TIMEOUT" = "" ]; then break; fi
shift 2
;;
--timeout=*)
TIMEOUT="${1#*=}"
shift 1
;;
--)
shift
break
;;
--help)
usage 0
;;
*)
echoerr "Unknown argument: $1"
usage 1
;;
esac
done

if [ "$rHOST" = "" -o "$rPORT" = "" ]; then
echoerr "Error: you need to provide a host and port to test."
usage 2
echoerr "Error: you need to provide a host and port to test."
usage 2
fi

wait_for "$@"

0 comments on commit 532d4d2

Please sign in to comment.