135 lines
4.3 KiB
TypeScript
135 lines
4.3 KiB
TypeScript
/**
|
||
* 资源中心协作权限 composable
|
||
*
|
||
* 权限级别:
|
||
* 0 - 无权限
|
||
* 1 - 基础查看:名称/IP/端口/状态(所有团队成员)
|
||
* 2 - 连接查看:用户名、Host、连接方式(技术负责人及以上)
|
||
* 3 - 完全权限:密码、私钥、编辑/删除(仅资源 Owner)
|
||
*/
|
||
import type { AppResource } from '@/api/app/appResource/model'
|
||
|
||
export type ResourceAccessLevel = 0 | 1 | 2 | 3
|
||
|
||
/**
|
||
* 判断当前用户是否是资源所有者
|
||
* 后端在返回时会带 ownerUserId 字段,前端基于 localStorage UserId 判断
|
||
*/
|
||
export function isResourceOwner(resource: AppResource): boolean {
|
||
if (!import.meta.client) return false
|
||
const currentUserId = localStorage.getItem('UserId')
|
||
if (!currentUserId) return false
|
||
return Number(currentUserId) === Number(resource.ownerUserId)
|
||
|| Number(currentUserId) === Number(resource.userId)
|
||
}
|
||
|
||
/**
|
||
* 获取当前用户对某资源的访问级别
|
||
* - 后端若已计算 accessLevel,直接使用
|
||
* - 否则前端保底逻辑:Owner=3,其余=1
|
||
*/
|
||
export function getResourceAccessLevel(resource: AppResource): ResourceAccessLevel {
|
||
// 后端已计算的权限级别,优先使用
|
||
if (resource.accessLevel !== undefined) {
|
||
return resource.accessLevel
|
||
}
|
||
// 降级:判断是否是 owner
|
||
return isResourceOwner(resource) ? 3 : 1
|
||
}
|
||
|
||
/** 是否有基础查看权限(所有人) */
|
||
export function canViewBasic(resource: AppResource): boolean {
|
||
return getResourceAccessLevel(resource) >= 1
|
||
}
|
||
|
||
/** 是否有连接信息查看权限(用户名、Host 等) */
|
||
export function canViewConnection(resource: AppResource): boolean {
|
||
return getResourceAccessLevel(resource) >= 2
|
||
}
|
||
|
||
/** 是否有完整权限(编辑、删除、查看密码/私钥) */
|
||
export function canViewSensitive(resource: AppResource): boolean {
|
||
return getResourceAccessLevel(resource) >= 3
|
||
}
|
||
|
||
/** 是否能编辑/删除该资源 */
|
||
export function canManageResource(resource: AppResource): boolean {
|
||
return getResourceAccessLevel(resource) >= 3
|
||
}
|
||
|
||
/** 脱敏占位符:判断某字段是否已被后端脱敏 */
|
||
export function isMaskedValue(value: string | null | undefined): boolean {
|
||
if (!value) return false
|
||
return value === '******' || value === '***' || /^\*{3,}$/.test(value)
|
||
}
|
||
|
||
/**
|
||
* 资源权限 composable(reactive,接受 computed/ref 的资源对象)
|
||
*/
|
||
export function useResourceAccess(resource: AppResource | (() => AppResource | null | undefined)) {
|
||
const getResource = (): AppResource | null | undefined =>
|
||
typeof resource === 'function' ? resource() : resource
|
||
|
||
const accessLevel = computed<ResourceAccessLevel>(() => {
|
||
const r = getResource()
|
||
if (!r) return 0
|
||
return getResourceAccessLevel(r)
|
||
})
|
||
|
||
const isOwner = computed(() => {
|
||
const r = getResource()
|
||
if (!r) return false
|
||
return isResourceOwner(r)
|
||
})
|
||
|
||
const canBasic = computed(() => accessLevel.value >= 1)
|
||
const canConnection = computed(() => accessLevel.value >= 2)
|
||
const canSensitive = computed(() => accessLevel.value >= 3)
|
||
const canManage = computed(() => accessLevel.value >= 3)
|
||
|
||
/** 权限级别对应的文字说明 */
|
||
const accessLevelText = computed(() => {
|
||
switch (accessLevel.value) {
|
||
case 3: return '完全权限'
|
||
case 2: return '连接权限'
|
||
case 1: return '查看权限'
|
||
default: return '无权限'
|
||
}
|
||
})
|
||
|
||
/** 权限不足时的提示文字 */
|
||
const noPermissionTip = computed(() =>
|
||
isOwner.value ? '' : '如需查看完整信息,请联系资源创建者',
|
||
)
|
||
|
||
return {
|
||
accessLevel,
|
||
isOwner,
|
||
canBasic,
|
||
canConnection,
|
||
canSensitive,
|
||
canManage,
|
||
accessLevelText,
|
||
noPermissionTip,
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 批量处理资源列表,为每个资源附加 isOwner 字段
|
||
* 调用时机:后端未返回 accessLevel 时的前端降级处理
|
||
*/
|
||
export function enrichResourcesWithPermission<T extends AppResource>(resources: T[]): T[] {
|
||
if (!import.meta.client) return resources
|
||
const currentUserId = localStorage.getItem('UserId')
|
||
if (!currentUserId) return resources
|
||
return resources.map(r => ({
|
||
...r,
|
||
isOwner: Number(currentUserId) === Number(r.ownerUserId) || Number(currentUserId) === Number(r.userId),
|
||
accessLevel: r.accessLevel ?? (
|
||
(Number(currentUserId) === Number(r.ownerUserId) || Number(currentUserId) === Number(r.userId))
|
||
? 3
|
||
: 1
|
||
),
|
||
}))
|
||
}
|