@ -1,7 +1,11 @@
class VBase {
class VBase {
constructor ( baseURL ) {
constructor ( baseURL , scope ) {
this . baseURL = baseURL || '' ;
if ( ! baseURL ) throw new Error ( 'VBase: baseURL is required' ) ;
if ( ! scope ) throw new Error ( 'VBase: scope is required' ) ;
this . baseURL = baseURL ;
this . scope = scope ;
this . tokenKey = 'vbase_access_token' ;
this . tokenKey = 'vbase_access_token' ;
this . refreshTokenKey = 'vbase_refresh_token' ;
this . refreshTokenKey = 'vbase_refresh_token' ;
this . userKey = 'vbase_user_info' ;
this . userKey = 'vbase_user_info' ;
@ -140,18 +144,108 @@ class VBase {
return headers ;
return headers ;
}
}
// 检查是否有全局管理员权限 (*:* 或 scope:*:*)
_isAdmin ( ) {
const perms = this . user ? . permissions || [ ] ;
for ( const p of perms ) {
const permID = p . permission _id || p ;
const resourceID = p . resource _id || '*' ;
// 必须是全局权限 (resource_id 为 * 或空) 且是通配符权限
if ( resourceID === '*' && ( permID === '*:*' || permID === ` ${ this . scope } :*:* ` ) ) {
return true ;
}
}
return false ;
}
// Permission Check
// Permission Check
hasPermission ( permission ) {
// 基础权限检查 (permissionID 格式: "resource:action")
checkPerm ( permissionID ) {
if ( ! this . user ) return false ;
if ( ! permissionID ) return true ;
// 全局管理员直接通过
if ( this . _isAdmin ( ) ) return true ;
const perms = this . user . permissions || [ ] ;
for ( const p of perms ) {
if ( this . _matchPermission ( p . permission _id || p , permissionID ) ) {
return true ;
}
}
return false ;
}
// 检查对特定资源的权限
// permissionID: "resource:action"
// resourceID: 资源实例ID
checkPermOnResource ( permissionID , resourceID ) {
if ( ! this . user ) return false ;
if ( ! this . user ) return false ;
if ( this . user . is _admin ) return true ;
if ( ! permissionID ) return true ;
if ( ! permission ) return true ;
// 全局管理员直接通过
const userPerms = this . user . permissions || [ ] ;
if ( this . _isAdmin ( ) ) return true ;
return userPerms . includes ( permission ) ;
if ( ! resourceID ) return this . checkPerm ( permissionID ) ;
const perms = this . user . permissions || [ ] ;
for ( const p of perms ) {
const permID = p . permission _id || p ;
const permResourceID = p . resource _id || '*' ;
if ( this . _matchPermission ( permID , permissionID ) ) {
if ( permResourceID === '*' || permResourceID === resourceID ) {
return true ;
}
}
}
return false ;
}
// 满足任一权限即可
checkPermAny ( ... permissionIDs ) {
for ( const pid of permissionIDs ) {
if ( this . checkPerm ( pid ) ) return true ;
}
return false ;
}
// 满足所有权限
checkPermAll ( ... permissionIDs ) {
for ( const pid of permissionIDs ) {
if ( ! this . checkPerm ( pid ) ) return false ;
}
return true ;
}
// 内部方法: 权限匹配
// 支持通配符: *:*, resource:*
// 后端权限可能是 "scope:resource:action" 或 "resource:action"
_matchPermission ( storedPerm , wantPerm ) {
if ( storedPerm === wantPerm ) return true ;
if ( storedPerm === '*:*' ) return true ;
// 从后端存储的权限中提取 resource:action 部分
let havePerm = storedPerm ;
const haveParts = storedPerm . split ( ':' ) ;
if ( haveParts . length === 3 ) {
// scope:resource:action -> resource:action
havePerm = ` ${ haveParts [ 1 ] } : ${ haveParts [ 2 ] } ` ;
}
if ( havePerm === wantPerm ) return true ;
// 通配符匹配 (resource:* 匹配 resource:any_action)
const [ haveRes , haveAct ] = havePerm . split ( ':' ) ;
const [ wantRes , wantAct ] = wantPerm . split ( ':' ) ;
if ( haveRes === '*' || ( haveRes === wantRes && ( haveAct === '*' || haveAct === wantAct ) ) ) {
return true ;
}
return false ;
}
}
hasRole ( role ) {
hasRole ( role ) {
if ( ! this . user ) return false ;
if ( ! this . user ) return false ;
if ( this . user . is _admin ) return true ;
// 全局管理员拥有所有角色
if ( this . _isAdmin ( ) ) return true ;
const userRoles = this . user . roles || [ ] ;
const userRoles = this . user . roles || [ ] ;
return userRoles . includes ( role ) ;
return userRoles . includes ( role ) ;
}
}