From cb42a651f8d7958a36550cd480945e99166fe41a Mon Sep 17 00:00:00 2001 From: Bai Date: Thu, 22 Jan 2026 15:13:52 +0800 Subject: [PATCH] feat: add generate_webui_schema GET --- apps/authentication/views/login.py | 7 + apps/authentication/views/mfa.py | 6 + apps/settings/api/i18n.py | 7 + apps/settings/api/settings.py | 6 +- apps/users/views/profile/reset.py | 11 + .../output/x_webui_schema copy.json | 928 ++++++++++++++++++ .../output/x_webui_schema.json | 743 ++++++++++++++ utils/api_schema_generator/src/main.py | 245 +++++ .../src_bak/extractors/base.py | 2 - 9 files changed, 1952 insertions(+), 3 deletions(-) create mode 100644 utils/api_schema_generator/output/x_webui_schema copy.json create mode 100644 utils/api_schema_generator/output/x_webui_schema.json create mode 100644 utils/api_schema_generator/src/main.py diff --git a/apps/authentication/views/login.py b/apps/authentication/views/login.py index b62df20ca..46478d6be 100644 --- a/apps/authentication/views/login.py +++ b/apps/authentication/views/login.py @@ -8,6 +8,7 @@ import os from typing import Callable from urllib.parse import urlparse, urlsplit, urlunsplit, urlencode +from rest_framework import serializers from django.conf import settings from django.contrib.auth import BACKEND_SESSION_KEY from django.contrib.auth import login as auth_login, logout as auth_logout @@ -131,6 +132,12 @@ class UserLoginContextMixin: @method_decorator(csrf_protect, name='dispatch') @method_decorator(never_cache, name='dispatch') class UserLoginView(mixins.AuthMixin, UserLoginContextMixin, FormView): + class QuerySerializer(serializers.Serializer): + next = serializers.CharField(required=False) + admin = serializers.IntegerField(required=False) + + query_serializer_class = QuerySerializer + redirect_field_name = 'next' template_name = 'authentication/login.html' diff --git a/apps/authentication/views/mfa.py b/apps/authentication/views/mfa.py index 4898cc093..c4461dad6 100644 --- a/apps/authentication/views/mfa.py +++ b/apps/authentication/views/mfa.py @@ -3,6 +3,7 @@ from __future__ import unicode_literals +from rest_framework import serializers from django.shortcuts import redirect, reverse from django.views.generic.edit import FormView @@ -21,6 +22,11 @@ class UserLoginMFAView(mixins.AuthMixin, FormView): form_class = forms.UserCheckOtpCodeForm redirect_field_name = 'next' + class QuerySerializer(serializers.Serializer): + next = serializers.CharField(required=False) + + query_serializer_class = QuerySerializer + def get(self, *args, **kwargs): try: user = self.get_user_from_session() diff --git a/apps/settings/api/i18n.py b/apps/settings/api/i18n.py index 1dca350b7..a36182c90 100644 --- a/apps/settings/api/i18n.py +++ b/apps/settings/api/i18n.py @@ -3,6 +3,7 @@ import os from django.conf import settings from django.utils._os import safe_join +from rest_framework import serializers from rest_framework.serializers import Serializer from rest_framework.generics import RetrieveAPIView from rest_framework.permissions import AllowAny @@ -17,6 +18,12 @@ class ComponentI18nApi(RetrieveAPIView): lang_data = {} serializer_class = Serializer + class QuerySerializer(Serializer): + lang = serializers.CharField(required=False) + flat = serializers.CharField(required=False) + + query_serializer_class = QuerySerializer + def get_component_translations(self, name): if not settings.DEBUG and name in self.lang_data: return self.lang_data[name] diff --git a/apps/settings/api/settings.py b/apps/settings/api/settings.py index cf95dc00a..b85c26ace 100644 --- a/apps/settings/api/settings.py +++ b/apps/settings/api/settings.py @@ -5,7 +5,7 @@ from django.core.cache import cache from django.http import HttpResponse from django.views.static import serve from rest_framework import generics -from rest_framework import status +from rest_framework import status, serializers as drf_serializers from rest_framework.permissions import AllowAny from rest_framework.response import Response from rest_framework.views import APIView @@ -197,7 +197,11 @@ class SettingsApi(generics.RetrieveUpdateAPIView): class SettingsLogoApi(APIView): + class QuerySerializer(drf_serializers.Serializer): + size = drf_serializers.CharField(required=False) + permission_classes = (AllowAny,) + query_serializer_class = QuerySerializer def get(self, request, *args, **kwargs): size = request.GET.get('size', 'small') diff --git a/apps/users/views/profile/reset.py b/apps/users/views/profile/reset.py index 06320cd68..ff692f1b9 100644 --- a/apps/users/views/profile/reset.py +++ b/apps/users/views/profile/reset.py @@ -4,6 +4,7 @@ from __future__ import unicode_literals import time +from rest_framework import serializers from django.conf import settings from django.core.cache import cache from django.shortcuts import redirect, reverse @@ -80,6 +81,11 @@ class UserForgotPasswordView(FormView): template_name = 'users/forgot_password.html' form_class = forms.UserForgotPasswordForm + class QuerySerializer(serializers.Serializer): + token = serializers.CharField(required=False) + + query_serializer_class = QuerySerializer + def get(self, request, *args, **kwargs): token = self.request.GET.get('token') userinfo = cache.get(token) @@ -173,6 +179,11 @@ class UserResetPasswordView(FormView): template_name = 'users/reset_password.html' form_class = forms.UserTokenResetPasswordForm + class QuerySerializer(serializers.Serializer): + token = serializers.CharField(required=False) + + query_serializer_class = QuerySerializer + def get(self, request, *args, **kwargs): context = self.get_context_data(**kwargs) errors = kwargs.get('errors') diff --git a/utils/api_schema_generator/output/x_webui_schema copy.json b/utils/api_schema_generator/output/x_webui_schema copy.json new file mode 100644 index 000000000..e49f02854 --- /dev/null +++ b/utils/api_schema_generator/output/x_webui_schema copy.json @@ -0,0 +1,928 @@ +{ + "GET": { + "/api/v1/settings/logo/": { + "query": { + "type": "object", + "properties": { + "size": { + "type": "string", + "description": "None" + } + }, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/api/v1/settings/public/open/": { + "query": { + "type": "object", + "properties": {"": "已验证没有"}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/api/v1/settings/i18n//": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/api/v1/settings/client/versions/": { + "query": { + "type": "object", + "properties": {"": "已验证没有"}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/api/v1/authentication/face/context/": { + "query": { + "type": "object", + "properties": {"": "已验证没有"}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/api/v1/authentication/auth/": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/api/v1/authentication/tokens/": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/api/v1/authentication/mfa/verify/": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/api/v1/authentication/mfa/challenge/": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/api/v1/authentication/mfa/select/": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/api/v1/authentication/mfa/send-code/": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/api/v1/authentication/password/reset-code/": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/api/v1/authentication/login-confirm-ticket/status/": { + "query": { + "type": "object", + "properties": {"": "已验证没有"}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/api/v1/authentication/user-session/": { + "query": { + "type": "object", + "properties": {"": "已验证没有"}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/api/v1/notifications/debug-msgs/": { + "query": { + "type": "object", + "properties": {"": "已验证没有"}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/api/v1/prometheus/metrics/": { + "query": { + "type": "object", + "properties": {"": "已验证没有"}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/api/health/": { + "query": { + "type": "object", + "properties": {"": "已验证没有"}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/api/v1/health/": { + "query": { + "type": "object", + "properties": {"": "已验证没有"}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/auth/captcha/image/(?P\\w+)/$": { + "query": { + "type": "object", + "properties": {"": "已验证没有"}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/auth/captcha/image/(?P\\w+)@2/$": { + "query": { + "type": "object", + "properties": {"": "已验证没有"}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/auth/captcha/audio/(?P\\w+).wav$": { + "query": { + "type": "object", + "properties": {"": "已验证没有"}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/auth/captcha/refresh/$": { + "query": { + "type": "object", + "properties": {"": "已验证没有"}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/auth/login/": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/auth/login/mfa/": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/auth/login/wait-confirm/": { + "query": { + "type": "object", + "properties": {"": "已验证没有"}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/auth/login/mfa/face/capture/": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/auth/login/guard/": { + "query": { + "type": "object", + "properties": {"": "已验证没有"}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/auth/logout/": { + "query": { + "type": "object", + "properties": {"": "已验证没有"}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/auth/password/forget/previewing/": { + "query": { + "type": "object", + "properties": {"": "已验证没有"}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/auth/password/forgot/": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/auth/password/reset/": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/auth/password/verify/": { + "query": { + "type": "object", + "properties": {"": "已验证没有"}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/auth/wecom/bind/start/": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/auth/wecom/qr/login/": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/auth/wecom/qr/login/callback/": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/auth/wecom/oauth/login/": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/auth/wecom/oauth/login/callback/": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/auth/dingtalk/bind/start/": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/auth/dingtalk/qr/login/": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/auth/dingtalk/qr/login/callback/": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/auth/dingtalk/oauth/login/": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/auth/dingtalk/oauth/login/callback/": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/auth/feishu/bind/start/": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/auth/feishu/qr/login/": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/auth/feishu/qr/login/callback/": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/auth/lark/bind/start/": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/auth/lark/qr/login/": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/auth/lark/qr/login/callback/": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/auth/slack/bind/start/": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/auth/slack/qr/login/": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/auth/slack/qr/login/callback/": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/auth/profile/otp/enable/start/": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/auth/profile/otp/enable/install-app/": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/auth/profile/otp/enable/bind/": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/auth/profile/face/enable/": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/auth/profile/face/disable/": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/auth/cas/login/": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/auth/cas/logout/": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/auth/cas/callback/": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/auth/openid/login/": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/auth/openid/callback/": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/auth/openid/logout/": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/auth/saml2/login/": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/auth/saml2/logout/": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/auth/saml2/callback/": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/auth/saml2/metadata/": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/auth/oauth2/login/": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/auth/oauth2/callback/": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/auth/oauth2/logout/": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/auth/oauth2-provider/token/": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/auth/oauth2-provider/revoke/": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/auth/oauth2-provider/.well-known/oauth-authorization-server": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/reports/export-pdf/": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/reports/send-mail/": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/tickets/direct-approve//": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/common/flash-message/": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/flower/(?P.*)": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/download/": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/redirect/confirm/": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/i18n//": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/^static/(?P.*)$": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/media/^(?P.*)$": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/^luna/(?P.*)$": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/^ui/(?P.*)$": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/jsi18n/": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + } + }, + "POST": { + "/api/v1/users/^service-account-registrations/$": { + "allowIf": "prelogin" + }, + "/api/v1/users/^service-account-registrations\\.(?P[a-z0-9]+)/?$": { + "allowIf": "prelogin" + }, + "/api/v1/users/^service-account-registrations/(?P[^/.]+)/$": { + "allowIf": "prelogin" + }, + "/api/v1/users/^service-account-registrations/(?P[^/.]+)\\.(?P[a-z0-9]+)/?$": { + "allowIf": "prelogin" + }, + "/api/v1/terminal/terminal-registrations/": { + "allowIf": "prelogin" + }, + "/api/v1/terminal/registration/": { + "allowIf": "prelogin" + }, + "/api/v1/settings/logo/": { + "allowIf": "prelogin" + }, + "/api/v1/settings/public/open/": { + "allowIf": "prelogin" + }, + "/api/v1/settings/i18n//": { + "allowIf": "prelogin" + }, + "/api/v1/settings/client/versions/": { + "allowIf": "prelogin" + }, + "/api/v1/authentication/face/context/": { + "allowIf": "prelogin" + }, + "/api/v1/authentication/auth/": { + "allowIf": "prelogin" + }, + "/api/v1/authentication/tokens/": { + "allowIf": "prelogin" + }, + "/api/v1/authentication/mfa/verify/": { + "allowIf": "prelogin" + }, + "/api/v1/authentication/mfa/challenge/": { + "allowIf": "prelogin" + }, + "/api/v1/authentication/mfa/select/": { + "allowIf": "prelogin" + }, + "/api/v1/authentication/mfa/send-code/": { + "allowIf": "prelogin" + }, + "/api/v1/authentication/password/reset-code/": { + "allowIf": "prelogin" + }, + "/api/v1/authentication/login-confirm-ticket/status/": { + "allowIf": "prelogin" + }, + "/api/v1/authentication/user-session/": { + "allowIf": "prelogin" + }, + "/api/v1/prometheus/metrics/": { + "allowIf": "prelogin" + }, + "/api/health/": { + "allowIf": "prelogin" + }, + "/api/v1/health/": { + "allowIf": "prelogin" + }, + "/core/auth/login/": { + "allowIf": "prelogin" + }, + "/core/auth/login/mfa/": { + "allowIf": "prelogin" + }, + "/core/auth/login/wait-confirm/": { + "allowIf": "prelogin" + }, + "/core/auth/login/mfa/face/capture/": { + "allowIf": "prelogin" + }, + "/core/auth/login/guard/": { + "allowIf": "prelogin" + }, + "/core/auth/logout/": { + "allowIf": "prelogin" + }, + "/core/auth/password/forget/previewing/": { + "allowIf": "prelogin" + }, + "/core/auth/password/forgot/": { + "allowIf": "prelogin" + }, + "/core/auth/password/reset/": { + "allowIf": "prelogin" + }, + "/core/auth/password/verify/": { + "allowIf": "prelogin" + }, + "/core/auth/wecom/bind/start/": { + "allowIf": "prelogin" + }, + "/core/auth/wecom/qr/login/": { + "allowIf": "prelogin" + }, + "/core/auth/wecom/qr/login/callback/": { + "allowIf": "prelogin" + }, + "/core/auth/wecom/oauth/login/": { + "allowIf": "prelogin" + }, + "/core/auth/wecom/oauth/login/callback/": { + "allowIf": "prelogin" + }, + "/core/auth/dingtalk/bind/start/": { + "allowIf": "prelogin" + }, + "/core/auth/dingtalk/qr/login/": { + "allowIf": "prelogin" + }, + "/core/auth/dingtalk/qr/login/callback/": { + "allowIf": "prelogin" + }, + "/core/auth/dingtalk/oauth/login/": { + "allowIf": "prelogin" + }, + "/core/auth/dingtalk/oauth/login/callback/": { + "allowIf": "prelogin" + }, + "/core/auth/feishu/bind/start/": { + "allowIf": "prelogin" + }, + "/core/auth/feishu/qr/login/": { + "allowIf": "prelogin" + }, + "/core/auth/feishu/qr/login/callback/": { + "allowIf": "prelogin" + }, + "/core/auth/lark/bind/start/": { + "allowIf": "prelogin" + }, + "/core/auth/lark/qr/login/": { + "allowIf": "prelogin" + }, + "/core/auth/lark/qr/login/callback/": { + "allowIf": "prelogin" + }, + "/core/auth/slack/bind/start/": { + "allowIf": "prelogin" + }, + "/core/auth/slack/qr/login/": { + "allowIf": "prelogin" + }, + "/core/auth/slack/qr/login/callback/": { + "allowIf": "prelogin" + }, + "/core/auth/profile/otp/enable/start/": { + "allowIf": "prelogin" + }, + "/core/auth/profile/otp/enable/install-app/": { + "allowIf": "prelogin" + }, + "/core/auth/profile/otp/enable/bind/": { + "allowIf": "prelogin" + }, + "/core/auth/profile/face/enable/": { + "allowIf": "prelogin" + }, + "/core/auth/profile/face/disable/": { + "allowIf": "prelogin" + }, + "/core/auth/cas/login/": { + "allowIf": "prelogin" + }, + "/core/auth/cas/logout/": { + "allowIf": "prelogin" + }, + "/core/auth/cas/callback/": { + "allowIf": "prelogin" + }, + "/core/auth/openid/logout/": { + "allowIf": "prelogin" + }, + "/core/auth/saml2/login/": { + "allowIf": "prelogin" + }, + "/core/auth/saml2/logout/": { + "allowIf": "prelogin" + }, + "/core/auth/saml2/callback/": { + "allowIf": "prelogin" + }, + "/core/auth/saml2/metadata/": { + "allowIf": "prelogin" + }, + "/core/auth/oauth2/login/": { + "allowIf": "prelogin" + }, + "/core/auth/oauth2/logout/": { + "allowIf": "prelogin" + }, + "/core/auth/oauth2-provider/token/": { + "allowIf": "prelogin" + }, + "/core/auth/oauth2-provider/revoke/": { + "allowIf": "prelogin" + }, + "/core/auth/oauth2-provider/.well-known/oauth-authorization-server": { + "allowIf": "prelogin" + }, + "/core/reports/export-pdf/": { + "allowIf": "prelogin" + }, + "/core/reports/send-mail/": { + "allowIf": "prelogin" + }, + "/core/tickets/direct-approve//": { + "allowIf": "prelogin" + }, + "/core/common/flash-message/": { + "allowIf": "prelogin" + }, + "/core/download/": { + "allowIf": "prelogin" + }, + "/core/redirect/confirm/": { + "allowIf": "prelogin" + }, + "/core/i18n//": { + "allowIf": "prelogin" + }, + "/media/^(?P.*)$": { + "allowIf": "prelogin" + }, + "/core/jsi18n/": { + "allowIf": "prelogin" + } + } +} \ No newline at end of file diff --git a/utils/api_schema_generator/output/x_webui_schema.json b/utils/api_schema_generator/output/x_webui_schema.json new file mode 100644 index 000000000..f0eecb60a --- /dev/null +++ b/utils/api_schema_generator/output/x_webui_schema.json @@ -0,0 +1,743 @@ +{ + "GET": { + "/api/v1/settings/logo/": { + "query": { + "type": "object", + "properties": { + "size": { + "type": "string" + } + }, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/api/v1/settings/public/open/": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/api/v1/settings/i18n//": { + "query": { + "type": "object", + "properties": { + "lang": { + "type": "string" + }, + "flat": { + "type": "string" + } + }, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/api/v1/settings/client/versions/": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/api/v1/authentication/face/context/": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/api/v1/authentication/login-confirm-ticket/status/": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/api/v1/authentication/user-session/": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/api/v1/notifications/debug-msgs/": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/api/v1/prometheus/metrics/": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/api/health/": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/api/v1/health/": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/auth/captcha/image/(?P\\w+)/$": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/auth/captcha/image/(?P\\w+)@2/$": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/auth/captcha/audio/(?P\\w+).wav$": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/auth/captcha/refresh/$": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/auth/login/": { + "query": { + "type": "object", + "properties": { + "next": { + "type": "string" + }, + "admin": { + "type": "integer" + } + }, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/auth/login/mfa/": { + "query": { + "type": "object", + "properties": { + "next": { + "type": "string" + } + }, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/auth/login/wait-confirm/": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/auth/login/mfa/face/capture/": { + "query": { + "type": "object", + "properties": { + "next": { + "type": "string" + } + }, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/auth/login/guard/": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/auth/logout/": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/auth/password/forget/previewing/": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/auth/password/forgot/": { + "query": { + "type": "object", + "properties": { + "token": { + "type": "string" + } + }, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/auth/password/reset/": { + "query": { + "type": "object", + "properties": { + "token": { + "type": "string" + } + }, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/auth/password/verify/": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/auth/wecom/bind/start/": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/auth/wecom/qr/login/": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/auth/wecom/qr/login/callback/": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/auth/wecom/oauth/login/": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/auth/wecom/oauth/login/callback/": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/auth/dingtalk/bind/start/": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/auth/dingtalk/qr/login/": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/auth/dingtalk/qr/login/callback/": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/auth/dingtalk/oauth/login/": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/auth/dingtalk/oauth/login/callback/": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/auth/feishu/bind/start/": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/auth/feishu/qr/login/": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/auth/feishu/qr/login/callback/": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/auth/lark/bind/start/": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/auth/lark/qr/login/": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/auth/lark/qr/login/callback/": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/auth/slack/bind/start/": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/auth/slack/qr/login/": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/auth/slack/qr/login/callback/": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/auth/profile/otp/enable/start/": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/auth/profile/otp/enable/install-app/": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/auth/profile/otp/enable/bind/": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/auth/profile/face/enable/": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/auth/profile/face/disable/": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/auth/cas/login/": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/auth/cas/logout/": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/auth/cas/callback/": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/auth/openid/login/": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/auth/openid/callback/": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/auth/openid/logout/": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/auth/saml2/login/": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/auth/saml2/logout/": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/auth/saml2/metadata/": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/auth/oauth2/login/": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/auth/oauth2/callback/": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/auth/oauth2/logout/": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/auth/oauth2-provider/.well-known/oauth-authorization-server": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/reports/export-pdf/": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/tickets/direct-approve//": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/common/flash-message/": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/flower/(?P.*)": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/download/": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/redirect/confirm/": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/i18n//": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/^static/(?P.*)$": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/media/^(?P.*)$": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/^luna/(?P.*)$": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/^ui/(?P.*)$": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + }, + "/core/jsi18n/": { + "query": { + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "allowIf": "prelogin" + } + }, + "POST": { + "/api/v1/terminal/terminal-registrations/": { + "allowIf": "prelogin" + }, + "/api/v1/terminal/registration/": { + "allowIf": "prelogin" + }, + "/api/v1/authentication/face/context/": { + "allowIf": "prelogin" + }, + "/api/v1/authentication/auth/": { + "allowIf": "prelogin" + }, + "/api/v1/authentication/tokens/": { + "allowIf": "prelogin" + }, + "/api/v1/authentication/mfa/verify/": { + "allowIf": "prelogin" + }, + "/api/v1/authentication/mfa/challenge/": { + "allowIf": "prelogin" + }, + "/api/v1/authentication/mfa/select/": { + "allowIf": "prelogin" + }, + "/api/v1/authentication/mfa/send-code/": { + "allowIf": "prelogin" + }, + "/api/v1/authentication/password/reset-code/": { + "allowIf": "prelogin" + }, + "/core/auth/login/": { + "allowIf": "prelogin" + }, + "/core/auth/login/mfa/": { + "allowIf": "prelogin" + }, + "/core/auth/login/mfa/face/capture/": { + "allowIf": "prelogin" + }, + "/core/auth/login/guard/": { + "allowIf": "prelogin" + }, + "/core/auth/password/forget/previewing/": { + "allowIf": "prelogin" + }, + "/core/auth/password/forgot/": { + "allowIf": "prelogin" + }, + "/core/auth/password/reset/": { + "allowIf": "prelogin" + }, + "/core/auth/password/verify/": { + "allowIf": "prelogin" + }, + "/core/auth/wecom/bind/start/": { + "allowIf": "prelogin" + }, + "/core/auth/dingtalk/bind/start/": { + "allowIf": "prelogin" + }, + "/core/auth/feishu/bind/start/": { + "allowIf": "prelogin" + }, + "/core/auth/lark/bind/start/": { + "allowIf": "prelogin" + }, + "/core/auth/slack/bind/start/": { + "allowIf": "prelogin" + }, + "/core/auth/profile/otp/enable/bind/": { + "allowIf": "prelogin" + }, + "/core/auth/profile/face/enable/": { + "allowIf": "prelogin" + }, + "/core/auth/profile/face/disable/": { + "allowIf": "prelogin" + }, + "/core/auth/cas/login/": { + "allowIf": "prelogin" + }, + "/core/auth/cas/callback/": { + "allowIf": "prelogin" + }, + "/core/auth/openid/logout/": { + "allowIf": "prelogin" + }, + "/core/auth/saml2/logout/": { + "allowIf": "prelogin" + }, + "/core/auth/saml2/callback/": { + "allowIf": "prelogin" + }, + "/core/auth/oauth2/logout/": { + "allowIf": "prelogin" + }, + "/core/auth/oauth2-provider/token/": { + "allowIf": "prelogin" + }, + "/core/auth/oauth2-provider/revoke/": { + "allowIf": "prelogin" + }, + "/core/reports/export-pdf/": { + "allowIf": "prelogin" + }, + "/core/reports/send-mail/": { + "allowIf": "prelogin" + }, + "/core/tickets/direct-approve//": { + "allowIf": "prelogin" + } + } +} \ No newline at end of file diff --git a/utils/api_schema_generator/src/main.py b/utils/api_schema_generator/src/main.py new file mode 100644 index 000000000..71aae9c73 --- /dev/null +++ b/utils/api_schema_generator/src/main.py @@ -0,0 +1,245 @@ +import os +import json +import sys +import django + +# 获取项目根目录(jumpserver 目录) +BASE_DIR = os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))) +APP_DIR = os.path.join(BASE_DIR, 'apps') + + +# 不改变工作目录,直接加入 sys.path +sys.path.insert(0, APP_DIR) +sys.path.insert(0, BASE_DIR) + +# 设置 Django 环境 +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "jumpserver.settings") +django.setup() + +from django.urls import get_resolver +from django.urls.resolvers import URLPattern, URLResolver +from django.core.handlers.asgi import ASGIRequest +from django.contrib.auth.mixins import LoginRequiredMixin +from rest_framework.permissions import AllowAny, IsAuthenticated +from rest_framework.permissions import OperandHolder, AND, OR, NOT +from rbac.permissions import RBACPermission + +dirname = os.path.dirname + +BASE_DIR = dirname(dirname(os.path.abspath(__file__))) +OUTPUT_FILE_DIR = os.path.join(BASE_DIR, 'output') +os.makedirs(OUTPUT_FILE_DIR, exist_ok=True) + + +scope = { + 'type': 'http', + 'method': 'GET', + 'path': '/', + 'query_string': b'', + 'headers': [], +} +async def receive(): + return {'type': 'http.request', 'body': b''} +fake_request = ASGIRequest(scope, receive) +setattr(fake_request, 'query_params', {}) + + +def extract_url_patterns(patterns, path_prefix='/'): + routes = [] + for p in patterns: + if isinstance(p, URLResolver): + _path_prefix = f'{path_prefix}{p.pattern}' + _routes = extract_url_patterns(p.url_patterns, path_prefix=_path_prefix) + routes.extend(_routes) + elif isinstance(p, URLPattern): + setattr(p, 'path_full', f'{path_prefix}{p.pattern}') + routes.append(p) + else: + print(f'Skip: unknown pattern type: {type(p)}') + return routes + + +def discover_routes(): + resolver = get_resolver() + routes = extract_url_patterns(resolver.url_patterns) + return routes + + +def resolve_view_class(view_func): + view_class = getattr(view_func, 'view_class', None) + if not view_class: + view_class = getattr(view_func, 'cls', None) + return view_class + + +def check_permission_class_requires_auth(permission_class): + if isinstance(permission_class, OperandHolder): + operator = permission_class.operator_class + op1_class = permission_class.op1_class + op2_class = permission_class.op2_class + permission_classes = [op1_class, op2_class] + return check_permission_classes_requires_auth(permission_classes, operator) + else: + if issubclass(permission_class, (IsAuthenticated, RBACPermission)): + return True + if issubclass(permission_class, (AllowAny, )): + return False + + permission_class_name: str = getattr(permission_class, '__name__', None) + if not permission_class_name: + return False + if 'Authenticated' in permission_class_name: + return True + if permission_class_name.startswith('UserConfirmation'): + return True + return False + + +def check_permission_classes_requires_auth(permission_classes, operator): + if operator == AND: + for pc in permission_classes: + if check_permission_class_requires_auth(pc): + return True + return False + + if operator == OR: + for pc in permission_classes: + if not check_permission_class_requires_auth(pc): + return False + return True + + if operator == NOT: + raise ValueError('NOT operator is not supported in permission_classes') + + return False + +def is_required_auth(view_func): + view_class = resolve_view_class(view_func) + if view_class: + if issubclass(view_class, LoginRequiredMixin): + return True + permission_classes = getattr(view_class, 'permission_classes', []) + if not permission_classes: + return False + return check_permission_classes_requires_auth(permission_classes, operator=AND) + # func base view + return False + +def get_view_http_methods(view_func): + view_class = resolve_view_class(view_func) + has_get_method = True + if not view_class: + # function based view + http_method_names = ['GET'] + return http_method_names + view = view_class(request=fake_request) + http_method_names = getattr(view, '_allowed_methods', lambda: [])() + if http_method_names: + return http_method_names + http_method_names = getattr(view, 'http_method_names', []) + if http_method_names: + return http_method_names + http_method_names = [] + has_get_method = hasattr(view_class, 'get') or hasattr(view_class, 'list') or hasattr(view_class, 'retrieve') + if has_get_method: + http_method_names.append('GET') + has_post_method = hasattr(view_class, 'post') or hasattr(view_class, 'create') + if has_post_method: + http_method_names.append('POST') + return http_method_names + +from rest_framework import serializers +from django import forms + +field_type_mapper = { + 'object': [serializers.Serializer, serializers.ModelSerializer], + 'string': [serializers.CharField, forms.CharField], + 'integer': [serializers.IntegerField, forms.IntegerField], + 'boolean': [serializers.BooleanField, forms.BooleanField], +} + +def get_field_type(field): + for json_type, class_list in field_type_mapper.items(): + if isinstance(field, tuple(class_list)): + return json_type + return 'string' + + +def get_view_query_properties(view_func): + view_class = resolve_view_class(view_func) + if not view_class: + # function based view + return {} + query_serializer_class = getattr(view_class, 'query_serializer_class', None) + if not query_serializer_class: + return {} + serializer = query_serializer_class() + fields = serializer.get_fields() + properties = {} + for name, field in fields.items(): + field_schema = {} + field_schema['type'] = get_field_type(field) + help_text = getattr(field, 'help_text', '') + if help_text: + field_schema['description'] = str(help_text) + properties[name] = field_schema + return properties + + +def get_view_query_schema(view_func): + query_properties = get_view_query_properties(view_func) + query_schema = { + 'type': 'object', + 'properties': query_properties, + 'additionalProperties': False, + } + return query_schema + + +def generate_view_schema(view_func): + http_method_names = get_view_http_methods(view_func) + schema = {} + if 'GET' in http_method_names: + schema['GET'] = {} + query_schema = get_view_query_schema(view_func) + if query_schema: + schema['GET']['query'] = query_schema + if 'POST' in http_method_names: + schema['POST'] = {} + return schema + + +def write_schema(schema): + filename = 'x_webui_schema.json' + file_path = os.path.join(OUTPUT_FILE_DIR, filename) + with open(file_path, 'w', encoding='utf-8') as f: + json.dump(schema, f, indent=4, ensure_ascii=False) + + +def generate_schema(): + schema = { + 'GET': {}, + 'POST': {} + } + routes = discover_routes() + for route in routes: + url = route.path_full + view_func = route.callback + if is_required_auth(view_func): + continue + view_schema = generate_view_schema(view_func) + if 'GET' in view_schema: + schema['GET'][url] = { + **view_schema['GET'], + 'allowIf': 'prelogin' + } + if 'POST' in view_schema: + schema['POST'][url] = { + **view_schema['POST'], + 'allowIf': 'prelogin' + } + write_schema(schema) + + +if __name__ == '__main__': + generate_schema() diff --git a/utils/api_schema_generator/src_bak/extractors/base.py b/utils/api_schema_generator/src_bak/extractors/base.py index 1ba8db622..a2d38e966 100644 --- a/utils/api_schema_generator/src_bak/extractors/base.py +++ b/utils/api_schema_generator/src_bak/extractors/base.py @@ -27,8 +27,6 @@ class BaseExtractor: def extract(self) -> Endpoint: url = self.view.route.path - if url.startswith('/api/v1/users/^users'): - pass endpoint = Endpoint( path=self.view.route.path, requires_auth=self.view_requires_auth()