feat: add default permission settings and dialog for resource authorization

This commit is contained in:
wxg0103 2025-12-24 09:44:19 +08:00
parent f7b3cc9ae0
commit e728647752
5 changed files with 148 additions and 23 deletions

View File

@ -144,6 +144,8 @@ export default {
currentOnly: 'Current resource only',
includeAll: 'Include all sub-resources',
effectiveResource: 'Effective Resource',
defaultPermission: 'Default Permission',
defaultPermissionTip: 'Default permissions for all resources under the selected workspace',
},
},
resource_management: {

View File

@ -145,6 +145,8 @@ export default {
currentOnly: '仅当前资源',
includeAll: '包含所有子资源',
effectiveResource: '生效资源',
defaultPermission: '默认权限',
defaultPermissionTip: '所选工作空间下所有资源的默认权限',
},
},
resource_management: {

View File

@ -145,6 +145,8 @@ export default {
currentOnly: '僅當前資源',
includeAll: '包含所有子資源',
effectiveResource: '生效資源',
defaultPermission: '預設權限',
defaultPermissionTip: '所選工作空間下所有資源的預設權限',
},
},
resource_management: {

View File

@ -172,13 +172,13 @@
</template>
<script setup lang="ts">
import { ref, onMounted, computed } from 'vue'
import { ComplexPermission } from '@/utils/permission/type'
import { PermissionConst, RoleConst } from '@/utils/permission/data'
import type { FormInstance } from 'element-plus'
import { t } from '@/locales'
import {ref, onMounted, computed} from 'vue'
import {ComplexPermission} from '@/utils/permission/type'
import {PermissionConst, RoleConst} from '@/utils/permission/data'
import type {FormInstance} from 'element-plus'
import {t} from '@/locales'
import authApi from '@/api/system-settings/auth-setting.ts'
import { MsgSuccess } from '@/utils/message.ts'
import {MsgSuccess} from '@/utils/message.ts'
import WorkspaceApi from '@/api/workspace/workspace.ts'
import useStore from '@/stores'
@ -247,7 +247,7 @@ const submit = async () => {
const roleOptions = ref<Array<{ id: string; name: string; type?: string }>>([])
const workspaceOptions = ref<Array<{ id: string; name: string }>>([])
const { user } = useStore()
const {user} = useStore()
const selectedRoleType = ref<string>('') // workspace
const showWorkspaceSelector = computed(() => selectedRoleType.value !== 'ADMIN')
@ -255,6 +255,9 @@ const showWorkspaceSelector = computed(() => selectedRoleType.value !== 'ADMIN')
const handleRoleChange = (roleId: string) => {
const selectedRole = roleOptions.value.find((role) => role.id === roleId)
selectedRoleType.value = selectedRole?.type || ''
if (form.value.workspace_id === 'None' && showWorkspaceSelector) {
form.value.workspace_id = 'default'
}
}
onMounted(async () => {
@ -265,24 +268,24 @@ onMounted(async () => {
// + EE workspace
const roleP = WorkspaceApi.getWorkspaceRoleList()
.then((r) => r)
.catch(() => ({ data: [] }))
.catch(() => ({data: []}))
const settingP = authApi
.getLoginSetting()
.then((r) => r)
.catch(() => ({ data: {} }))
.catch(() => ({data: {}}))
const tasks: Promise<any>[] = [roleP, settingP]
if (isEE) {
tasks.push(
WorkspaceApi.getWorkspaceList()
.then((r) => r)
.catch(() => ({ data: [] })),
.catch(() => ({data: []})),
)
}
const results = await Promise.all(tasks)
const roleRes = results[0] ?? { data: [] }
const settingRes = results[1] ?? { data: {} }
const workspaceRes = isEE ? (results[2] ?? { data: [] }) : null
const roleRes = results[0] ?? {data: []}
const settingRes = results[1] ?? {data: {}}
const workspaceRes = isEE ? (results[2] ?? {data: []}) : null
//
const rolesData = Array.isArray(roleRes?.data) ? roleRes.data : []
@ -307,7 +310,7 @@ onMounted(async () => {
// workspace
if (isEE && workspaceRes) {
const wks = Array.isArray(workspaceRes.data) ? workspaceRes.data : []
workspaceOptions.value = wks.map((item: any) => ({ id: item.id, name: item.name }))
workspaceOptions.value = wks.map((item: any) => ({id: item.id, name: item.name}))
}
// selectedRoleType role_id roleOptions

View File

@ -69,12 +69,51 @@
:deleteButtonDisabled="deleteButtonDisabled"
/>
<template #footer>
<el-button @click.prevent="visible = false"> {{ $t('common.cancel') }}</el-button>
<el-button type="primary" @click="submit(userFormRef)" :loading="loading">
{{ $t('common.save') }}
</el-button>
<div style="display: flex; width: 100%;">
<el-button @click="openDialog" v-if="!isEdit && showPermission">
{{ $t('views.system.resourceAuthorization.setting.defaultPermission') }}
</el-button>
<div style="margin-left: auto;">
<el-button @click.prevent="visible = false">{{ $t('common.cancel') }}</el-button>
<el-button type="primary" @click="submit(userFormRef)" :loading="loading">
{{ $t('common.save') }}
</el-button>
</div>
</div>
</template>
</el-drawer>
<el-dialog
v-model="dialogVisible"
:title="$t('views.system.resourceAuthorization.setting.defaultPermission')"
destroy-on-close
@close="closeDialog"
>
<template #header="{ titleId, titleClass }" v-if="user.isEE()">
<div class="dialog-header">
<h4 :id="titleId" :class="titleClass" style="margin: 0;">
{{ $t('views.system.resourceAuthorization.setting.defaultPermission') }}
<span class="dialog-subtitle">
{{ $t('views.system.resourceAuthorization.setting.defaultPermissionTip') }}
</span>
</h4>
</div>
</template>
<el-radio-group v-model="radioPermission" class="radio-block">
<template v-for="(item, index) in permissionOptions" :key="index">
<el-radio :value="item.value" class="mr-16">
<p class="color-text-primary lighter">{{ item.label }}</p>
<el-text class="color-secondary lighter">{{ item.desc }}</el-text>
</el-radio>
</template>
</el-radio-group>
<template #footer>
<div class="dialog-footer mt-24">
<el-button @click="closeDialog"> {{ $t('common.cancel') }}</el-button>
<el-button type="primary" @click="submitDialog"> {{ $t('common.confirm') }}</el-button>
</div>
</template>
</el-dialog>
</template>
<script setup lang="ts">
import {ref, reactive, watch, onBeforeMount, computed} from 'vue'
@ -85,8 +124,10 @@ import {t} from '@/locales'
import type {FormItemModel} from '@/api/type/role'
import WorkspaceApi from '@/api/workspace/workspace'
import MemberFormContent from '@/views/system/role/component/MemberFormContent.vue'
import {RoleTypeEnum} from '@/enums/system'
import {AuthorizationEnum, RoleTypeEnum} from '@/enums/system'
import useStore from '@/stores'
import {hasPermission} from "@/utils/permission";
import {EditionConst} from "@/utils/permission/data.ts";
const {user} = useStore()
const props = defineProps({
@ -109,15 +150,56 @@ const memberFormContentLoading = ref(false)
const formItemModel = ref<FormItemModel[]>([])
const roleFormItem = ref<FormItemModel[]>([])
const adminRoleList = ref<any[]>([])
const userRoleList = ref<any[]>([])
const workspaceFormItem = ref<FormItemModel[]>([])
const isAdmin = computed(() => userForm.value['id'] === 'f0dd8f71-e4ee-11ee-8c84-a8a1595801ab')
const dialogVisible = ref(false)
const radioPermission = ref('NOT_AUTH')
const defaultPermission = ref('NOT_AUTH')
const permissionOptions = computed(() => {
const baseOptions = [
{
label: t('views.system.resourceAuthorization.setting.check'),
value: AuthorizationEnum.VIEW,
desc: t('views.system.resourceAuthorization.setting.checkDesc'),
},
{
label: t('views.system.resourceAuthorization.setting.management'),
value: AuthorizationEnum.MANAGE,
desc: t('views.system.resourceAuthorization.setting.managementDesc'),
},
{
label: t('views.system.resourceAuthorization.setting.notAuthorized'),
value: AuthorizationEnum.NOT_AUTH,
desc: '',
}
];
function deleteButtonDisabled(element: any) {
if (isAdmin.value && ['ADMIN', 'WORKSPACE_MANAGE', 'USER'].includes(element.role_id)) {
if (hasPermission([EditionConst.IS_EE, EditionConst.IS_PE], 'OR')) {
baseOptions.splice(2, 0, {
label: t('views.system.resourceAuthorization.setting.role'),
value: AuthorizationEnum.ROLE,
desc: t('views.system.resourceAuthorization.setting.roleDesc'),
});
}
return baseOptions;
});
const showPermission = computed(() => {
//
if (user.isCE() || user.isExpire()) {
return true
}
return false
const hasUserRole = list.value.some((item) => userRoleList.value.includes(item.role_id));
return (user.isEE() || user.isPE()) && hasUserRole
})
function deleteButtonDisabled(element: any) {
return isAdmin.value && ['ADMIN', 'WORKSPACE_MANAGE', 'USER'].includes(element.role_id);
}
async function getRoleFormItem() {
@ -145,6 +227,10 @@ async function getRoleFormItem() {
},
]
adminRoleList.value = res.data.filter((item) => item.type === RoleTypeEnum.ADMIN)
userRoleList.value = res.data
.filter((item) => item.type === RoleTypeEnum.USER)
.map((item) => item.id)
} catch (e) {
console.error(e)
}
@ -352,6 +438,7 @@ const submit = async (formEl: FormInstance | undefined) => {
visible.value = false
})
} else {
params.defaultPermission = defaultPermission.value
userManageApi
.postUserManage(params, loading)
.then((res) => {
@ -369,6 +456,35 @@ const submit = async (formEl: FormInstance | undefined) => {
})
}
const openDialog = () => {
dialogVisible.value = true
}
const closeDialog = () => {
dialogVisible.value = false
}
const submitDialog = () => {
defaultPermission.value = radioPermission.value
closeDialog()
}
defineExpose({open})
</script>
<style lang="scss" scoped></style>
<style lang="scss" scoped>
.dialog-header {
h4 {
display: flex;
align-items: baseline;
gap: 8px;
margin: 0;
}
.dialog-subtitle {
font-size: 14px;
color: var(--el-text-color-secondary);
}
}
</style>