fix: Support tools, knowledge base resource authorization (#4572)

This commit is contained in:
shaohuzhang1 2025-12-26 16:53:59 +08:00 committed by GitHub
parent 5dcb615360
commit 9ed49599cf
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 130 additions and 33 deletions

View File

@ -21,13 +21,19 @@ from maxkb.conf import PROJECT_DIR
class ResourceMappingSerializer(serializers.Serializer):
resource = serializers.CharField(required=True, label=_('resource'))
resource_id = serializers.UUIDField(required=True, label=_('resource Id'))
resource_name = serializers.CharField(required=False, allow_null=True, allow_blank=True, label=_('resource'))
resource_name = serializers.CharField(required=False, allow_null=True, allow_blank=True, label=_('resource Name'))
source_type = serializers.ListField(
label=_('source Type'),
child=serializers.CharField(required=False, allow_null=True, allow_blank=True, label=_('source Type')))
user_name = serializers.CharField(required=False, allow_null=True, allow_blank=True, label=_('creator'))
def get_query_set(self):
queryset = QuerySet(model=get_dynamics_model({
'name': models.CharField(),
'target_id': models.CharField(),
"target_type": models.CharField()
"target_type": models.CharField(),
"u.username": models.CharField(),
'rm.source_type': models.CharField()
}))
queryset = queryset.filter(target_id=self.data.get('resource_id'),
@ -35,7 +41,10 @@ class ResourceMappingSerializer(serializers.Serializer):
if self.data.get('resource_name'):
queryset = queryset.filter(name__icontains=self.data.get('resource_name'))
if self.data.get('user_name'):
queryset = queryset.filter(**{'u.username__icontains': self.data.get('user_name')})
if self.data.get("source_type"):
queryset = queryset.filter(**{'rm.source_type__in': self.data.get('source_type')})
return queryset
def page(self, current_page, page_size):

View File

@ -1,12 +1,13 @@
WITH source_data_cte AS (
SELECT 'APPLICATION' as source_type, id, "name", "desc","user_id"
FROM application
UNION ALL
SELECT 'KNOWLEDGE' as source_type, id, "name", "desc","user_id"
FROM knowledge)
WITH source_data_cte AS (SELECT 'APPLICATION' as source_type, id, "name", "desc", "user_id"
FROM application
UNION ALL
SELECT 'KNOWLEDGE' as source_type, id, "name", "desc", "user_id"
FROM knowledge)
SELECT rm.*,
sdc.*
sdc.*,
u.username as username
FROM resource_mapping rm
LEFT JOIN source_data_cte sdc
ON rm.source_type = sdc.source_type
AND rm.source_id::uuid = sdc.id
AND rm.source_id::uuid = sdc.id
LEFT JOIN "public"."user" u on u.id = sdc.user_id

View File

@ -33,5 +33,7 @@ class ResourceMappingView(APIView):
return result.success(ResourceMappingSerializer({
'resource': resource,
'resource_id': resource_id,
'resource_name': request.query_params.get('resource_name')
'resource_name': request.query_params.get('resource_name'),
'user_name': request.query_params.get('user_name'),
'source_type': request.query_params.getlist('source_type[]'),
}).page(current_page, page_size))

View File

@ -81,4 +81,37 @@ export default {
])
},
},
'app-resource-mapping': {
iconReader: () => {
return h('i', [
h(
'svg',
{
viewBox: '0 0 16 16',
version: '1.1',
xmlns: 'http://www.w3.org/2000/svg',
},
[
h('path', {
d: 'M3.64023 7.55547C4.16284 6.83981 4.62542 5.57247 5.08688 3.7308C5.35033 2.67938 5.67074 2.22214 5.94869 2.22214C6.19415 2.22214 6.39314 2.02316 6.39314 1.7777C6.39314 1.53224 6.19415 1.33325 5.94869 1.33325C5.11916 1.33325 4.57762 2.10607 4.22465 3.51476C3.8289 5.09417 3.42652 6.20022 3.07385 6.81123C2.9227 6.71944 2.74528 6.66658 2.55552 6.66658H1.88886C1.33657 6.66658 0.888855 7.1143 0.888855 7.66658V8.33325C0.888855 8.88554 1.33657 9.33325 1.88886 9.33325H2.55552C2.72067 9.33325 2.87647 9.29322 3.01375 9.22232C3.33858 9.88602 3.69875 10.9575 4.05283 12.4188C4.40498 13.8722 4.9433 14.6666 5.7777 14.6666C6.02316 14.6666 6.22214 14.4676 6.22214 14.2221C6.22214 13.9767 6.02316 13.7777 5.7777 13.7777C5.50461 13.7777 5.18098 13.3001 4.91672 12.2095C4.49159 10.455 4.06638 9.20685 3.59354 8.44436H6.46662C6.57707 8.44436 6.66662 8.35482 6.66662 8.24436V7.75547C6.66662 7.64502 6.57707 7.55547 6.46662 7.55547H3.64023Z',
fill: '#646A73',
}),
h('path', {
d: 'M7.99998 2.11103C7.99998 1.92694 8.14922 1.7777 8.33332 1.7777H14.7778C14.9619 1.7777 15.1111 1.92693 15.1111 2.11103V3.22214C15.1111 3.40624 14.9619 3.55547 14.7778 3.55547H8.33332C8.14922 3.55547 7.99998 3.40624 7.99998 3.22214V2.11103Z',
fill: '#646A73',
}),
h('path', {
d: 'M8.33332 7.11103C8.14922 7.11103 7.99998 7.26027 7.99998 7.44436V8.55547C7.99998 8.73957 8.14922 8.88881 8.33332 8.88881H14.7778C14.9619 8.88881 15.1111 8.73957 15.1111 8.55547V7.44436C15.1111 7.26027 14.9619 7.11103 14.7778 7.11103H8.33332Z',
fill: '#646A73',
}),
h('path', {
d: 'M7.99998 12.7777C7.99998 12.5936 8.14922 12.4444 8.33332 12.4444H14.7778C14.9619 12.4444 15.1111 12.5936 15.1111 12.7777V13.8888C15.1111 14.0729 14.9619 14.2221 14.7778 14.2221H8.33332C8.14922 14.2221 7.99998 14.0729 7.99998 13.8888V12.7777Z',
fill: '#646A73',
}),
],
),
])
},
},
}

View File

@ -1,7 +1,7 @@
<template>
<el-drawer
v-model="visible"
:title="$t('views.system.resourceAuthorization.title')"
:title="$t('views.system.resourceMapping.title', '关联资源')"
size="60%"
:append-to-body="true"
>
@ -9,9 +9,17 @@
<div class="flex-between complex-search">
<el-select class="complex-search__left" v-model="searchType" style="width: 100px">
<el-option
:label="$t('views.userManage.userForm.resourceName.label')"
:label="$t('views.userManage.userForm.resourceName.label', '名称')"
value="resource_name"
/>
<el-option
:label="$t('views.userManage.userForm.user_name.label', '创建者')"
value="user_name"
/>
<el-option
:label="$t('views.userManage.userForm.source_type.label', '资源类型')"
value="source_type"
/>
</el-select>
<el-input
v-if="searchType === 'resource_name'"
@ -21,6 +29,29 @@
clearable
@keyup.enter="pageResouceMapping()"
/>
<el-input
v-if="searchType === 'user_name'"
v-model="query.user_name"
:placeholder="$t('common.search')"
style="width: 220px"
clearable
@keyup.enter="pageResouceMapping()"
/>
<el-select
v-else-if="searchType === 'source_type'"
v-model="query.source_type"
@change="pageResouceMapping()"
filterable
clearable
multiple
:reserve-keyword="false"
collapse-tags
collapse-tags-tooltip
style="width: 220px"
>
<el-option label="应用" value="APPLICATION" />
<el-option label="知识库" value="KNOWLEDGE" />
</el-select>
</div>
</div>
@ -35,18 +66,10 @@
:row-key="(row: any) => row.id"
v-loading="loading"
>
<el-table-column
prop="name"
:label="$t('views.userManage.userForm.name.label', '名称')"
min-width="120"
show-overflow-tooltip
/>
<el-table-column
prop="desc"
min-width="120"
show-overflow-tooltip
:label="$t('views.login.loginForm.desc.label', '描述')"
/>
<el-table-column prop="name" label="名称" min-width="120" show-overflow-tooltip />
<el-table-column prop="desc" min-width="120" show-overflow-tooltip label="描述" />
<el-table-column prop="source_type" min-width="120" show-overflow-tooltip label="资源类型" />
<el-table-column prop="username" min-width="120" show-overflow-tooltip label="创建者" />
</app-table>
</el-drawer>
</template>
@ -60,6 +83,8 @@ const { user } = useStore()
const searchType = ref<string>('resource_name')
const query = ref<any>({
resource_name: '',
user_name: '',
source_type: '',
})
const loading = ref<boolean>(false)
const tableData = ref<Array<any>>()

View File

@ -239,6 +239,13 @@
></AppIcon>
{{ $t('views.system.resourceAuthorization.title') }}
</el-dropdown-item>
<el-dropdown-item text @click.stop="openResourceMappingDrawer(item)">
<AppIcon
iconName="app-resource-mapping"
class="color-secondary"
></AppIcon>
{{ $t('views.system.resourceMapping.title', '查看关联资源') }}
</el-dropdown-item>
<el-dropdown-item
@click.stop="openMoveToDialog(item)"
v-if="permissionPrecise.edit(item.id) && apiType === 'workspace'"
@ -314,6 +321,7 @@
v-if="apiType === 'workspace'"
/>
<TemplateStoreDialog ref="templateStoreDialogRef" :api-type="apiType" @refresh="getList" />
<ResourceMappingDrawer ref="resourceMappingDrawerRef"></ResourceMappingDrawer>
</template>
<script lang="ts" setup>
@ -339,6 +347,15 @@ import { SourceTypeEnum } from '@/enums/common'
import { loadSharedApi } from '@/utils/dynamics-api/shared-api'
import permissionMap from '@/permission'
import TemplateStoreDialog from '@/views/knowledge/template-store/TemplateStoreDialog.vue'
<<<<<<< Updated upstream
=======
import ResourceMappingDrawer from '@/components/resource_mapping/index.vue'
const resourceMappingDrawerRef = ref<InstanceType<typeof ResourceMappingDrawer>>()
const openResourceMappingDrawer = (knowledge: any) => {
resourceMappingDrawerRef.value?.open('KNOWLEDGE', knowledge.id)
}
>>>>>>> Stashed changes
const router = useRouter()
const route = useRoute()
const { folder, user, knowledge } = useStore()

View File

@ -111,13 +111,9 @@
<AppIcon iconName="app-resource-authorization" class="color-secondary"></AppIcon>
{{ $t('views.system.resourceAuthorization.title') }}
</el-dropdown-item>
<el-dropdown-item
text
@click.stop="openResourceMappingDrawer(model)"
v-if="permissionPrecise.delete(model.id)"
>
<AppIcon iconName="app-delete" class="color-secondary"></AppIcon>
{{ $t('common.delete') }}
<el-dropdown-item text @click.stop="openResourceMappingDrawer(model)">
<AppIcon iconName="app-resource-mapping" class="color-secondary"></AppIcon>
{{ $t('views.system.resourceMapping.title', '查看关联资源') }}
</el-dropdown-item>
<el-dropdown-item
divided

View File

@ -291,6 +291,13 @@
></AppIcon>
{{ $t('views.system.resourceAuthorization.title') }}
</el-dropdown-item>
<el-dropdown-item text @click.stop="openResourceMappingDrawer(item)">
<AppIcon
iconName="app-resource-mapping"
class="color-secondary"
></AppIcon>
{{ $t('views.system.resourceMapping.title', '查看关联资源') }}
</el-dropdown-item>
<el-dropdown-item
@click.stop="openMoveToDialog(item)"
v-if="permissionPrecise.copy(item.id) && apiType === 'workspace'"
@ -361,6 +368,7 @@
v-if="apiType === 'workspace'"
/>
<ToolStoreDescDrawer ref="toolStoreDescDrawerRef" />
<ResourceMappingDrawer ref="resourceMappingDrawerRef"></ResourceMappingDrawer>
</template>
<script lang="ts" setup>
@ -388,8 +396,14 @@ import { t } from '@/locales'
import { i18n_name } from '@/utils/common'
import ToolStoreApi from '@/api/tool/store.ts'
import ToolStoreDescDrawer from '@/views/tool/component/ToolStoreDescDrawer.vue'
import bus from '@/bus'
import ResourceMappingDrawer from '@/components/resource_mapping/index.vue'
const resourceMappingDrawerRef = ref<InstanceType<typeof ResourceMappingDrawer>>()
const route = useRoute()
const openResourceMappingDrawer = (tool: any) => {
resourceMappingDrawerRef.value?.open('TOOL', tool.id)
}
const { folder, user, tool } = useStore()
onBeforeRouteLeave((to, from) => {
tool.setToolList([])