Skip to content

Commit dfae711

Browse files
committed
feat: chat authentication
1 parent 1641039 commit dfae711

File tree

18 files changed

+447
-58
lines changed

18 files changed

+447
-58
lines changed

apps/application/flow/i_step_node.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919

2020
from application.flow.common import Answer, NodeChunk
2121
from application.models import ChatRecord
22-
from application.models import ApplicationPublicAccessClient
22+
from application.models import ApplicationChatClientStats
2323
from common.constants.authentication_type import AuthenticationType
2424
from common.field.common import InstanceField
2525

@@ -89,7 +89,7 @@ def handler(self, chat_id,
8989
chat_cache.set(chat_id,
9090
self.chat_info, timeout=60 * 30)
9191
if self.client_type == AuthenticationType.APPLICATION_ACCESS_TOKEN.value:
92-
application_public_access_client = (QuerySet(ApplicationPublicAccessClient)
92+
application_public_access_client = (QuerySet(ApplicationChatClientStats)
9393
.filter(client_id=self.client_id,
9494
application_id=self.chat_info.application.id).first())
9595
if application_public_access_client is not None:

apps/application/flow/step_node/search_dataset_node/impl/base_search_dataset_node.py

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,19 +9,17 @@
99
import os
1010
from typing import List, Dict
1111

12-
from django.db.models import QuerySet
1312
from django.db import connection
13+
from django.db.models import QuerySet
14+
1415
from application.flow.i_step_node import NodeResult
1516
from application.flow.step_node.search_dataset_node.i_search_dataset_node import ISearchDatasetStepNode
1617
from common.config.embedding_config import VectorStore
1718
from common.db.search import native_search
1819
from common.utils.common import get_file_content
19-
from knowledge.models import Document, Paragraph, Knowledge
20-
21-
from models_provider.tools import get_model_instance_by_model_user_id
20+
from knowledge.models import Document, Paragraph, Knowledge, SearchMode
2221
from maxkb.conf import PROJECT_DIR
23-
24-
SearchMode = None
22+
from models_provider.tools import get_model_instance_by_model_user_id
2523

2624

2725
def get_embedding_id(dataset_id_list):
Lines changed: 36 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
# Generated by Django 5.2 on 2025-06-04 11:57
22

3-
import application.models.application_chat
4-
import common.encoder.encoder
3+
import uuid
4+
55
import django.contrib.postgres.fields
66
import django.db.models.deletion
7-
import uuid
87
import uuid_utils.compat
98
from django.db import migrations, models
109

10+
import common.encoder.encoder
1111

12-
class Migration(migrations.Migration):
1312

13+
class Migration(migrations.Migration):
1414
dependencies = [
1515
('application', '0001_initial'),
1616
]
@@ -21,12 +21,13 @@ class Migration(migrations.Migration):
2121
fields=[
2222
('create_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
2323
('update_time', models.DateTimeField(auto_now=True, verbose_name='修改时间')),
24-
('id', models.UUIDField(default=uuid.UUID('01973acd-fe4c-7fd1-94a8-f7cd668de562'), editable=False, primary_key=True, serialize=False, verbose_name='主键id')),
24+
('id', models.UUIDField(default=uuid.UUID('01973acd-fe4c-7fd1-94a8-f7cd668de562'), editable=False,
25+
primary_key=True, serialize=False, verbose_name='主键id')),
2526
('abstract', models.CharField(max_length=1024, verbose_name='摘要')),
26-
('asker', models.JSONField(default=application.models.application_chat.default_asker, encoder=common.encoder.encoder.SystemEncoder, verbose_name='访问者')),
2727
('client_id', models.UUIDField(default=None, null=True, verbose_name='客户端id')),
2828
('is_deleted', models.BooleanField(default=False, verbose_name='')),
29-
('application', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='application.application')),
29+
('application',
30+
models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='application.application')),
3031
],
3132
options={
3233
'db_table': 'application_chat',
@@ -37,16 +38,25 @@ class Migration(migrations.Migration):
3738
fields=[
3839
('create_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
3940
('update_time', models.DateTimeField(auto_now=True, verbose_name='修改时间')),
40-
('id', models.UUIDField(default=uuid_utils.compat.uuid1, editable=False, primary_key=True, serialize=False, verbose_name='主键id')),
41-
('vote_status', models.CharField(choices=[('-1', '未投票'), ('0', '赞同'), ('1', '反对')], default='-1', max_length=10, verbose_name='投票')),
41+
('id',
42+
models.UUIDField(default=uuid_utils.compat.uuid1, editable=False, primary_key=True, serialize=False,
43+
verbose_name='主键id')),
44+
('vote_status',
45+
models.CharField(choices=[('-1', '未投票'), ('0', '赞同'), ('1', '反对')], default='-1', max_length=10,
46+
verbose_name='投票')),
4247
('problem_text', models.CharField(max_length=10240, verbose_name='问题')),
4348
('answer_text', models.CharField(max_length=40960, verbose_name='答案')),
44-
('answer_text_list', django.contrib.postgres.fields.ArrayField(base_field=models.JSONField(), default=list, size=None, verbose_name='改进标注列表')),
49+
('answer_text_list',
50+
django.contrib.postgres.fields.ArrayField(base_field=models.JSONField(), default=list, size=None,
51+
verbose_name='改进标注列表')),
4552
('message_tokens', models.IntegerField(default=0, verbose_name='请求token数量')),
4653
('answer_tokens', models.IntegerField(default=0, verbose_name='响应token数量')),
4754
('const', models.IntegerField(default=0, verbose_name='总费用')),
48-
('details', models.JSONField(default=dict, encoder=common.encoder.encoder.SystemEncoder, verbose_name='对话详情')),
49-
('improve_paragraph_id_list', django.contrib.postgres.fields.ArrayField(base_field=models.UUIDField(blank=True), default=list, size=None, verbose_name='改进标注列表')),
55+
('details',
56+
models.JSONField(default=dict, encoder=common.encoder.encoder.SystemEncoder, verbose_name='对话详情')),
57+
('improve_paragraph_id_list',
58+
django.contrib.postgres.fields.ArrayField(base_field=models.UUIDField(blank=True), default=list,
59+
size=None, verbose_name='改进标注列表')),
5060
('run_time', models.FloatField(default=0, verbose_name='运行时长')),
5161
('index', models.IntegerField(verbose_name='对话下标')),
5262
('chat', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='application.chat')),
@@ -60,13 +70,17 @@ class Migration(migrations.Migration):
6070
fields=[
6171
('create_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
6272
('update_time', models.DateTimeField(auto_now=True, verbose_name='修改时间')),
63-
('id', models.UUIDField(default=uuid_utils.compat.uuid1, editable=False, primary_key=True, serialize=False, verbose_name='主键id')),
64-
('workspace_id', models.CharField(db_index=True, default='default', max_length=64, verbose_name='工作空间id')),
73+
('id',
74+
models.UUIDField(default=uuid_utils.compat.uuid1, editable=False, primary_key=True, serialize=False,
75+
verbose_name='主键id')),
76+
('workspace_id',
77+
models.CharField(db_index=True, default='default', max_length=64, verbose_name='工作空间id')),
6578
('name', models.CharField(default='', max_length=128, verbose_name='版本名称')),
6679
('publish_user_id', models.UUIDField(default=None, null=True, verbose_name='发布者id')),
6780
('publish_user_name', models.CharField(default='', max_length=128, verbose_name='发布者名称')),
6881
('work_flow', models.JSONField(default=dict, verbose_name='工作流数据')),
69-
('application', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='application.application')),
82+
('application',
83+
models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='application.application')),
7084
],
7185
options={
7286
'db_table': 'application_work_flow_version',
@@ -77,16 +91,20 @@ class Migration(migrations.Migration):
7791
fields=[
7892
('create_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
7993
('update_time', models.DateTimeField(auto_now=True, verbose_name='修改时间')),
80-
('id', models.UUIDField(default=uuid.uuid1, editable=False, primary_key=True, serialize=False, verbose_name='主键id')),
94+
('id', models.UUIDField(default=uuid.uuid1, editable=False, primary_key=True, serialize=False,
95+
verbose_name='主键id')),
8196
('client_id', models.UUIDField(default=uuid.uuid1, verbose_name='公共访问链接客户端id')),
8297
('client_type', models.CharField(max_length=64, verbose_name='客户端类型')),
8398
('access_num', models.IntegerField(default=0, verbose_name='访问总次数次数')),
8499
('intraday_access_num', models.IntegerField(default=0, verbose_name='当日访问次数')),
85-
('application', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='application.application', verbose_name='应用id')),
100+
('application',
101+
models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='application.application',
102+
verbose_name='应用id')),
86103
],
87104
options={
88105
'db_table': 'application_public_access_client',
89-
'indexes': [models.Index(fields=['application_id', 'client_id'], name='application_applica_8aaf45_idx')],
106+
'indexes': [
107+
models.Index(fields=['application_id', 'client_id'], name='application_applica_8aaf45_idx')],
90108
},
91109
),
92110
]

apps/application/models/application_api_key.py

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -24,16 +24,3 @@ class Meta:
2424
db_table = "application_api_key"
2525

2626

27-
class ApplicationPublicAccessClient(AppModelMixin):
28-
id = models.UUIDField(primary_key=True, max_length=128, default=uuid.uuid1, editable=False, verbose_name="主键id")
29-
client_id = models.UUIDField(max_length=128, default=uuid.uuid1, verbose_name="公共访问链接客户端id")
30-
client_type = models.CharField(max_length=64, verbose_name="客户端类型")
31-
application = models.ForeignKey(Application, on_delete=models.CASCADE, verbose_name="应用id")
32-
access_num = models.IntegerField(default=0, verbose_name="访问总次数次数")
33-
intraday_access_num = models.IntegerField(default=0, verbose_name="当日访问次数")
34-
35-
class Meta:
36-
db_table = "application_public_access_client"
37-
indexes = [
38-
models.Index(fields=['application_id', 'client_id']),
39-
]

apps/application/models/application_chat.py

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,17 +17,20 @@
1717
from common.mixins.app_model_mixin import AppModelMixin
1818

1919

20-
def default_asker():
21-
return {'user_name': '游客'}
20+
class ClientType(models.TextChoices):
21+
ANONYMOUS_USER = "ANONYMOUS_USER", '匿名用户'
22+
CHAT_USER = "CHAT_USER", "对话用户"
23+
SYSTEM_API_KEY = "SYSTEM_API_KEY", "系统API_KEY"
24+
APPLICATION_API_KEY = "APPLICATION_API_KEY", "应用API_KEY"
2225

2326

2427
class Chat(AppModelMixin):
2528
id = models.UUIDField(primary_key=True, max_length=128, default=uuid.uuid7(), editable=False, verbose_name="主键id")
2629
application = models.ForeignKey(Application, on_delete=models.CASCADE)
2730
abstract = models.CharField(max_length=1024, verbose_name="摘要")
28-
asker = models.JSONField(verbose_name="访问者", default=default_asker, encoder=SystemEncoder)
2931
client_id = models.UUIDField(verbose_name="客户端id", default=None, null=True)
30-
is_deleted = models.BooleanField(verbose_name="", default=False)
32+
client_type = models.CharField(max_length=64, verbose_name="客户端类型", choices=ClientType.choices)
33+
is_deleted = models.BooleanField(verbose_name="逻辑删除", default=False)
3134

3235
class Meta:
3336
db_table = "application_chat"
@@ -80,3 +83,18 @@ def get_node_details_runtime_node_id(self, runtime_node_id):
8083

8184
class Meta:
8285
db_table = "application_chat_record"
86+
87+
88+
class ApplicationChatClientStats(AppModelMixin):
89+
id = models.UUIDField(primary_key=True, max_length=128, default=uuid.uuid7, editable=False, verbose_name="主键id")
90+
client_id = models.UUIDField(max_length=128, default=uuid.uuid7, verbose_name="公共访问链接客户端id")
91+
client_type = models.CharField(max_length=64, verbose_name="客户端类型", choices=ClientType.choices)
92+
application = models.ForeignKey(Application, on_delete=models.CASCADE, verbose_name="应用id")
93+
access_num = models.IntegerField(default=0, verbose_name="访问总次数次数")
94+
intraday_access_num = models.IntegerField(default=0, verbose_name="当日访问次数")
95+
96+
class Meta:
97+
db_table = "application_chat_client_stats"
98+
indexes = [
99+
models.Index(fields=['application_id', 'client_id']),
100+
]

apps/application/views/application_api_key.py

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,10 @@ class ApplicationKey(APIView):
2020
parameters=ApplicationKeyCreateAPI.get_parameters(),
2121
tags=[_('Application Api Key')] # type: ignore
2222
)
23-
def post(self,request: Request, application_id: str, workspace_id: str):
23+
def post(self, request: Request, workspace_id: str, application_id: str):
2424
return result.success(ApplicationKeySerializer(
25-
data={'application_id': application_id, 'user_id': request.user.id,
26-
'workspace_id':workspace_id}).generate())
25+
data={'application_id': application_id, 'user_id': request.user.id,
26+
'workspace_id': workspace_id}).generate())
2727

2828
@extend_schema(
2929
methods=['GET'],
@@ -33,11 +33,10 @@ def post(self,request: Request, application_id: str, workspace_id: str):
3333
parameters=ApplicationKeyCreateAPI.get_parameters(),
3434
tags=[_('Application Api Key')] # type: ignore
3535
)
36-
def get(self,request: Request, application_id: str, workspace_id: str):
37-
return result,success(ApplicationKeySerializer(
38-
data={'application_id':application_id, 'user_id':request.user.id,
39-
'workspace_id':workspace_id}).list())
40-
36+
def get(self, request: Request, workspace_id: str, application_id: str, ):
37+
return result, success(ApplicationKeySerializer(
38+
data={'application_id': application_id, 'user_id': request.user.id,
39+
'workspace_id': workspace_id}).list())
4140

4241
class Operate(APIView):
4342
authentication_classes = [TokenAuth]
@@ -50,9 +49,8 @@ class Operate(APIView):
5049
parameters=ApplicationKeyCreateAPI.get_parameters(),
5150
tags=[_('Application Api Key')] # type: ignore
5251
)
53-
def put(self, request: Request, application_id: str, workspace_id: str):
52+
def put(self, request: Request, workspace_id: str, application_id: str):
5453
return result.success(ApplicationKeySerializer.Operate(
5554

5655
)
57-
)
58-
56+
)

apps/application/views/application_version.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
from rest_framework.views import APIView
1313

1414
from application.api.application_version import ApplicationVersionListAPI, ApplicationVersionPageAPI, \
15-
ApplicationVersionAPI, ApplicationVersionOperateAPI
15+
ApplicationVersionOperateAPI
1616
from application.serializers.application_version import ApplicationVersionSerializer
1717
from common import result
1818
from common.auth import TokenAuth
@@ -88,6 +88,7 @@ def get(self, request: Request, workspace_id: str, application_id: str, work_flo
8888
responses=ApplicationVersionOperateAPI.get_response(),
8989
tags=[_('Application/Version')] # type: ignore
9090
)
91+
@has_permissions(PermissionConstants.APPLICATION_EDIT.get_workspace_application_permission())
9192
def put(self, request: Request, workspace_id: str, application_id: str, work_flow_version_id: str):
9293
return result.success(
9394
ApplicationVersionSerializer.Operate(
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# coding=utf-8
2+
"""
3+
@project: MaxKB
4+
@Author:虎虎
5+
@file: chat_authentication_api.py
6+
@date:2025/6/6 19:59
7+
@desc:
8+
"""
9+
from chat.serializers.chat_authentication import AuthenticationSerializer
10+
from common.mixins.api_mixin import APIMixin
11+
12+
13+
class ChatAuthenticationAPI(APIMixin):
14+
@staticmethod
15+
def get_request():
16+
return AuthenticationSerializer()
17+
18+
@staticmethod
19+
def get_parameters():
20+
pass
21+
22+
@staticmethod
23+
def get_response():
24+
pass

0 commit comments

Comments
 (0)