diff --git a/apps/application/migrations/0006_applicationapikey_allow_cross_domain_and_more.py b/apps/application/migrations/0006_applicationapikey_allow_cross_domain_and_more.py new file mode 100644 index 000000000..cd24c0edb --- /dev/null +++ b/apps/application/migrations/0006_applicationapikey_allow_cross_domain_and_more.py @@ -0,0 +1,24 @@ +# Generated by Django 4.1.13 on 2024-05-08 13:57 + +import django.contrib.postgres.fields +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('application', '0005_alter_chat_abstract_alter_chatrecord_answer_text'), + ] + + operations = [ + migrations.AddField( + model_name='applicationapikey', + name='allow_cross_domain', + field=models.BooleanField(default=False, verbose_name='是否允许跨域'), + ), + migrations.AddField( + model_name='applicationapikey', + name='cross_domain_list', + field=django.contrib.postgres.fields.ArrayField(base_field=models.CharField(blank=True, max_length=128), default=list, size=None, verbose_name='跨域列表'), + ), + ] diff --git a/apps/application/models/api_key_model.py b/apps/application/models/api_key_model.py index 117ab0664..965e1f1c4 100644 --- a/apps/application/models/api_key_model.py +++ b/apps/application/models/api_key_model.py @@ -22,6 +22,10 @@ class ApplicationApiKey(AppModelMixin): user = models.ForeignKey(User, on_delete=models.CASCADE, verbose_name="用户id") application = models.ForeignKey(Application, on_delete=models.CASCADE, verbose_name="应用id") is_active = models.BooleanField(default=True, verbose_name="是否开启") + allow_cross_domain = models.BooleanField(default=False, verbose_name="是否允许跨域") + cross_domain_list = ArrayField(verbose_name="跨域列表", + base_field=models.CharField(max_length=128, blank=True) + , default=list) class Meta: db_table = "application_api_key" diff --git a/apps/application/serializers/application_serializers.py b/apps/application/serializers/application_serializers.py index e0abb772d..1827c5eb9 100644 --- a/apps/application/serializers/application_serializers.py +++ b/apps/application/serializers/application_serializers.py @@ -37,7 +37,6 @@ from dataset.serializers.common_serializers import list_paragraph from embedding.models import SearchMode from setting.models import AuthOperate from setting.models.model_management import Model -from setting.models_provider.constants.model_provider_constants import ModelProvideConstants from setting.serializers.provider_serializers import ModelSerializer from smartdoc.conf import PROJECT_DIR @@ -583,6 +582,15 @@ class ApplicationSerializer(serializers.Serializer): class Edit(serializers.Serializer): is_active = serializers.BooleanField(required=False, error_messages=ErrMessage.boolean("是否可用")) + allow_cross_domain = serializers.BooleanField(required=False, + error_messages=ErrMessage.boolean("是否允许跨域")) + + cross_domain_list = serializers.ListSerializer(required=False, + child=serializers.CharField(required=True, + error_messages=ErrMessage.char( + "跨域列表")), + error_messages=ErrMessage.char("跨域地址")) + class Operate(serializers.Serializer): application_id = serializers.UUIDField(required=True, error_messages=ErrMessage.uuid("应用id")) @@ -599,15 +607,17 @@ class ApplicationSerializer(serializers.Serializer): def edit(self, instance, with_valid=True): if with_valid: self.is_valid(raise_exception=True) - ApplicationSerializer.Edit(data=instance).is_valid(raise_exception=True) - + ApplicationSerializer.ApplicationKeySerializer.Edit(data=instance).is_valid(raise_exception=True) + api_key_id = self.data.get("api_key_id") + application_id = self.data.get('application_id') + application_api_key = QuerySet(ApplicationApiKey).filter(id=api_key_id, + application_id=application_id).first() + if application_api_key is None: + raise AppApiException(500, '不存在') if 'is_active' in instance and instance.get('is_active') is not None: - api_key_id = self.data.get("api_key_id") - application_id = self.data.get('application_id') - application_api_key = QuerySet(ApplicationApiKey).filter(id=api_key_id, - application_id=application_id).first() - if application_api_key is None: - raise AppApiException(500, '不存在') - application_api_key.is_active = instance.get('is_active') - application_api_key.save() + if 'allow_cross_domain' in instance and instance.get('allow_cross_domain') is not None: + application_api_key.allow_cross_domain = instance.get('allow_cross_domain') + if 'cross_domain_list' in instance and instance.get('cross_domain_list') is not None: + application_api_key.cross_domain_list = instance.get('cross_domain_list') + application_api_key.save() diff --git a/apps/application/swagger_api/application_api.py b/apps/application/swagger_api/application_api.py index 42f2c6a9b..4bacc5831 100644 --- a/apps/application/swagger_api/application_api.py +++ b/apps/application/swagger_api/application_api.py @@ -101,7 +101,10 @@ class ApplicationApi(ApiMixin): properties={ 'is_active': openapi.Schema(type=openapi.TYPE_BOOLEAN, title="是否激活", description="是否激活"), - + 'allow_cross_domain': openapi.Schema(type=openapi.TYPE_BOOLEAN, title="是否允许跨域", + description="是否允许跨域"), + 'cross_domain_list': openapi.Schema(type=openapi.TYPE_ARRAY, title='跨域列表', + items=openapi.Schema(type=openapi.TYPE_STRING)) } ) diff --git a/apps/common/middleware/cross_domain_middleware.py b/apps/common/middleware/cross_domain_middleware.py new file mode 100644 index 000000000..499854e60 --- /dev/null +++ b/apps/common/middleware/cross_domain_middleware.py @@ -0,0 +1,43 @@ +# coding=utf-8 +""" + @project: maxkb + @Author:虎 + @file: cross_domain_middleware.py + @date:2024/5/8 13:36 + @desc: +""" +from django.db.models import QuerySet +from django.http import HttpResponse +from django.utils.deprecation import MiddlewareMixin + +from application.models.api_key_model import ApplicationApiKey + + +class CrossDomainMiddleware(MiddlewareMixin): + + def process_request(self, request): + if request.method == 'OPTIONS': + auth = request.META.get('HTTP_AUTHORIZATION') + if auth is not None and str(auth).startswith("application-"): + application_api_key = QuerySet(ApplicationApiKey).filter(secret_key=auth).first() + if application_api_key.allow_cross_domain: + return HttpResponse(status=200, + headers={ + "Access-Control-Allow-Origin": "*" if application_api_key.cross_domain_list is None or len( + application_api_key.cross_domain_list) == 0 else ",".join( + application_api_key.cross_domain_list), + "Access-Control-Allow-Methods": "GET,POST,DELETE,PUT", + "Access-Control-Allow-Headers": "Origin,X-Requested-With,Content-Type,Accept,Authorization,token"}) + + def process_response(self, request, response): + auth = request.META.get('HTTP_AUTHORIZATION') + if auth is not None and str(auth).startswith("application-"): + application_api_key = QuerySet(ApplicationApiKey).filter(secret_key=auth).first() + if application_api_key.allow_cross_domain: + response['Access-Control-Allow-Origin'] = "*" if application_api_key.cross_domain_list is None or len( + application_api_key.cross_domain_list) == 0 else ",".join( + application_api_key.cross_domain_list) + response['Access-Control-Allow-Methods'] = 'GET,POST,DELETE,PUT' + response[ + 'Access-Control-Allow-Headers'] = "Origin,X-Requested-With,Content-Type,Accept,Authorization,token" + return response diff --git a/apps/smartdoc/settings/base.py b/apps/smartdoc/settings/base.py index 621b0135e..04e8810e5 100644 --- a/apps/smartdoc/settings/base.py +++ b/apps/smartdoc/settings/base.py @@ -47,7 +47,8 @@ MIDDLEWARE = [ 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', - 'common.middleware.static_headers_middleware.StaticHeadersMiddleware' + 'common.middleware.static_headers_middleware.StaticHeadersMiddleware', + 'common.middleware.cross_domain_middleware.CrossDomainMiddleware' ] diff --git a/ui/src/views/application-overview/component/APIKeyDialog.vue b/ui/src/views/application-overview/component/APIKeyDialog.vue index 347d7069e..8a887d911 100644 --- a/ui/src/views/application-overview/component/APIKeyDialog.vue +++ b/ui/src/views/application-overview/component/APIKeyDialog.vue @@ -26,6 +26,13 @@ +