config: refactor to enforce all permission checks (#291)

Changes permission checking behaviour where all list of APIs must be permitted to see a view.
The first API will be used to list/render the table. Remaining APIs will only be used to verify permissions. If any of the passed API is not found in the allowed APIs for logged-in user's role section/sub-section won't be displayed.

Fixes #241
Fixes #244
Fixes #240

Signed-off-by: Abhishek Kumar <abhishek.mrt22@gmail.com>
Signed-off-by: Rohit Yadav <rohit.yadav@shapeblue.com>
Co-authored-by: Rohit Yadav <rohit.yadav@shapeblue.com>
This commit is contained in:
Abhishek Kumar 2020-05-07 02:44:50 +05:30 committed by Rohit Yadav
parent ddcc2435bd
commit b9385f49d0
16 changed files with 456 additions and 395 deletions

View File

@ -348,7 +348,8 @@
<div class="resource-detail-item__label">{{ $t('serviceofferingname') }}</div>
<div class="resource-detail-item__details">
<a-icon type="cloud" />
<router-link :to="{ path: '/computeoffering/' + resource.serviceofferingid }">{{ resource.serviceofferingname || resource.serviceofferingid }} </router-link>
<router-link v-if="$router.resolve('/computeoffering/' + resource.serviceofferingid).route.name !== '404'" :to="{ path: '/computeoffering/' + resource.serviceofferingid }">{{ resource.serviceofferingname || resource.serviceofferingid }} </router-link>
<span v-else>{{ resource.serviceofferingname || resource.serviceofferingid }}</span>
</div>
</div>
<div class="resource-detail-item" v-if="resource.templateid">
@ -362,7 +363,8 @@
<div class="resource-detail-item__label">{{ $t('diskoffering') }}</div>
<div class="resource-detail-item__details">
<a-icon type="hdd" />
<router-link :to="{ path: '/diskoffering/' + resource.diskofferingid }">{{ resource.diskofferingname || resource.diskofferingid }} </router-link>
<router-link v-if="$router.resolve('/diskoffering/' + resource.diskofferingid).route.name !== '404'" :to="{ path: '/diskoffering/' + resource.diskofferingid }">{{ resource.diskofferingname || resource.diskofferingid }} </router-link>
<span v-else>{{ resource.diskofferingname || resource.diskofferingid }}</span>
</div>
</div>
<div class="resource-detail-item" v-if="resource.backupofferingid">

View File

@ -130,16 +130,17 @@
<router-link :to="{ path: '/account', query: { name: record.account, domainid: record.domainid } }" v-else>{{ text }}</router-link>
</a>
<span slot="domain" slot-scope="text, record" href="javascript:;">
<router-link v-if="record.domainid && !record.domainid.includes(',')" :to="{ path: '/domain/' + record.domainid }">{{ text }}</router-link>
<router-link v-if="record.domainid && !record.domainid.includes(',') && $router.resolve('/domain/' + record.domainid).route.name !== '404'" :to="{ path: '/domain/' + record.domainid }">{{ text }}</router-link>
<span v-else>{{ text }}</span>
</span>
<a slot="zone" slot-scope="text, record" href="javascript:;">
<router-link v-if="record.zoneid && !record.zoneid.includes(',')" :to="{ path: '/zone/' + record.zoneid }">{{ text }}</router-link>
<router-link v-if="record.zoneid && !record.zoneid.includes(',') && $router.resolve('/zone/' + record.zoneid).route.name !== '404'" :to="{ path: '/zone/' + record.zoneid }">{{ text }}</router-link>
<span v-else>{{ text }}</span>
</a>
<a slot="zonename" slot-scope="text, record" href="javascript:;">
<router-link :to="{ path: '/zone/' + record.zoneid }">{{ text }}</router-link>
</a>
<span slot="zonename" slot-scope="text, record">
<router-link v-if="$router.resolve('/zone/' + record.zoneid).route.name !== '404'" :to="{ path: '/zone/' + record.zoneid }">{{ text }}</router-link>
<span v-else>{{ text }}</span>
</span>
<div slot="order" slot-scope="text, record" class="shift-btns">
<a-tooltip placement="top">

View File

@ -25,7 +25,10 @@ import network from '@/config/section/network'
import image from '@/config/section/image'
import project from '@/config/section/project'
import event from '@/config/section/event'
import iam from '@/config/section/iam'
import user from '@/config/section/user'
import account from '@/config/section/account'
import domain from '@/config/section/domain'
import role from '@/config/section/role'
import infra from '@/config/section/infra'
import offering from '@/config/section/offering'
import config from '@/config/section/config'
@ -194,9 +197,12 @@ export const asyncRouterMap = [
generateRouterMap(storage),
generateRouterMap(network),
generateRouterMap(image),
generateRouterMap(project),
generateRouterMap(event),
generateRouterMap(iam),
generateRouterMap(project),
generateRouterMap(user),
generateRouterMap(account),
generateRouterMap(domain),
generateRouterMap(role),
generateRouterMap(infra),
generateRouterMap(offering),
generateRouterMap(config),

View File

@ -0,0 +1,157 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
export default {
name: 'account',
title: 'Accounts',
icon: 'team',
permission: ['listAccounts'],
columns: ['name', 'state', 'rolename', 'roletype', 'domain'],
details: ['name', 'id', 'rolename', 'roletype', 'domain', 'networkdomain', 'iptotal', 'vmtotal', 'volumetotal', 'receivedbytes', 'sentbytes', 'vmlimit', 'iplimit', 'volumelimit', 'snapshotlimit', 'templatelimit', 'vpclimit', 'cpulimit', 'memorylimit', 'networklimit', 'primarystoragelimit', 'secondarystoragelimit'],
related: [{
name: 'accountuser',
title: 'Users',
param: 'account'
}],
tabs: [
{
name: 'details',
component: () => import('@/components/view/DetailsTab.vue')
},
{
name: 'certificate',
component: () => import('@/views/iam/SSLCertificateTab.vue')
},
{
name: 'limits',
show: (record, route, user) => { return ['Admin'].includes(user.roletype) },
component: () => import('@/components/view/ResourceLimitTab.vue')
},
{
name: 'Settings',
component: () => import('@/components/view/SettingsTab.vue'),
show: (record, route, user) => { return ['Admin'].includes(user.roletype) }
}
],
actions: [
{
api: 'createAccount',
icon: 'plus',
label: 'label.add.account',
listView: true,
args: ['username', 'password', 'password', 'email', 'firstname', 'lastname', 'domainid', 'account', 'roleid', 'timezone', 'networkdomain']
},
{
api: 'ldapCreateAccount',
icon: 'user-add',
label: 'label.add.ldap.account',
listView: true,
popup: true,
show: (record, store) => {
return store.isLdapEnabled
},
component: () => import('@/views/iam/AddLdapAccount.vue')
},
{
api: 'updateAccount',
icon: 'edit',
label: 'Update Account',
dataView: true,
args: ['newname', 'account', 'domainid', 'networkdomain'],
mapping: {
account: {
value: (record) => { return record.name }
},
domainid: {
value: (record) => { return record.domainid }
}
}
},
{
api: 'updateResourceCount',
icon: 'sync',
label: 'Update Resource Count',
dataView: true,
args: ['account', 'domainid'],
mapping: {
account: {
value: (record) => { return record.name }
},
domainid: {
value: (record) => { return record.domainid }
}
}
},
{
api: 'enableAccount',
icon: 'play-circle',
label: 'Enable Account',
dataView: true,
show: (record) => { return record.state === 'disabled' || record.state === 'locked' },
params: { lock: 'false' }
},
{
api: 'disableAccount',
icon: 'pause-circle',
label: 'Disable Account',
dataView: true,
show: (record) => { return record.state === 'enabled' },
args: ['lock'],
mapping: {
lock: {
value: (record) => { return false }
}
}
},
{
api: 'disableAccount',
icon: 'lock',
label: 'Lock account',
dataView: true,
show: (record) => { return record.state === 'enabled' },
args: ['lock'],
mapping: {
lock: {
value: (record) => { return true }
}
}
},
{
api: 'uploadSslCert',
icon: 'safety-certificate',
label: 'Add certificate',
dataView: true,
args: ['name', 'certificate', 'privatekey', 'certchain', 'password', 'account', 'domainid'],
show: (record) => { return record.state === 'enabled' },
mapping: {
account: {
value: (record) => { return record.name }
},
domainid: {
value: (record) => { return record.domainid }
}
}
},
{
api: 'deleteAccount',
icon: 'delete',
label: 'Delete account',
dataView: true,
hidden: (record) => { return record.name === 'admin' }
}
]
}

View File

@ -27,7 +27,7 @@ export default {
title: 'Instances',
icon: 'desktop',
docHelp: 'adminguide/virtual_machines.html',
permission: ['listVirtualMachinesMetrics', 'listVirtualMachines'],
permission: ['listVirtualMachinesMetrics'],
resourceType: 'UserVm',
columns: [
'name', 'state', 'instancename', 'ipaddress', 'cpunumber', 'cpuused', 'cputotal',

View File

@ -0,0 +1,125 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
export default {
name: 'iam',
title: 'Domains',
icon: 'block',
permission: ['listDomains'],
children: [
{
name: 'domain',
title: 'Domains',
icon: 'block',
permission: ['listDomains'],
resourceType: 'Domain',
columns: ['name', 'state', 'path', 'parentdomainname', 'level'],
details: ['name', 'id', 'path', 'parentdomainname', 'level', 'networkdomain', 'iptotal', 'vmtotal', 'volumetotal', 'vmlimit', 'iplimit', 'volumelimit', 'snapshotlimit', 'templatelimit', 'vpclimit', 'cpulimit', 'memorylimit', 'networklimit', 'primarystoragelimit', 'secondarystoragelimit'],
related: [{
name: 'account',
title: 'Accounts',
param: 'domainid'
}],
tabs: [
{
name: 'Domain',
component: () => import('@/components/view/InfoCard.vue'),
show: (record, route) => { return route.path === '/domain' }
},
{
name: 'details',
component: () => import('@/components/view/DetailsTab.vue')
},
{
name: 'limits',
show: (record, route, user) => { return ['Admin'].includes(user.roletype) },
component: () => import('@/components/view/ResourceLimitTab.vue')
},
{
name: 'Settings',
component: () => import('@/components/view/SettingsTab.vue'),
show: (record, route, user) => { return ['Admin'].includes(user.roletype) }
}
],
treeView: true,
actions: [
{
api: 'createDomain',
icon: 'plus',
label: 'label.add.domain',
listView: true,
dataView: true,
args: ['parentdomainid', 'name', 'networkdomain', 'domainid'],
mapping: {
parentdomainid: {
value: (record) => { return record.id }
}
}
},
{
api: 'updateDomain',
icon: 'edit',
label: 'label.action.edit.domain',
listView: true,
dataView: true,
args: ['name', 'networkdomain']
},
{
api: 'updateResourceCount',
icon: 'sync',
label: 'label.action.update.resource.count',
listView: true,
dataView: true,
args: ['domainid'],
mapping: {
domainid: {
value: (record) => { return record.id }
}
}
},
{
api: 'linkDomainToLdap',
icon: 'link',
label: 'Link Domain to LDAP Group/OU',
listView: true,
dataView: true,
args: ['type', 'domainid', 'name', 'accounttype', 'admin'],
mapping: {
type: {
options: ['GROUP', 'OU']
},
accounttype: {
options: ['0', '2']
},
domainid: {
value: (record) => { return record.id }
}
}
},
{
api: 'deleteDomain',
icon: 'delete',
label: 'label.delete.domain',
listView: true,
dataView: true,
show: (record) => { return record.level !== 0 },
args: ['cleanup']
}
]
}
]
}

View File

@ -1,370 +0,0 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
export default {
name: 'iam',
title: 'Identity and Access',
icon: 'solution',
permission: ['listAccounts', 'listUsers', 'listDomains', 'listRoles'],
children: [
{
name: 'accountuser',
title: 'Users',
icon: 'user',
permission: ['listUsers'],
columns: ['username', 'state', 'firstname', 'lastname', 'email', 'account', 'domain'],
details: ['username', 'id', 'firstname', 'lastname', 'email', 'usersource', 'timezone', 'rolename', 'roletype', 'account', 'domain', 'created'],
actions: [
{
api: 'createUser',
icon: 'plus',
label: 'label.add.user',
listView: true,
args: ['username', 'password', 'password', 'email', 'firstname', 'lastname', 'timezone', 'account', 'domainid']
},
{
api: 'updateUser',
icon: 'edit',
label: 'label.edit',
dataView: true,
args: ['username', 'email', 'firstname', 'lastname', 'timezone']
},
{
api: 'updateUser',
icon: 'key',
label: 'label.action.change.password',
dataView: true,
popup: true,
component: () => import('@/views/iam/ChangeUserPassword.vue')
},
{
api: 'registerUserKeys',
icon: 'file-protect',
label: 'label.action.generate.keys',
dataView: true
},
{
api: 'enableUser',
icon: 'play-circle',
label: 'label.action.enable.user',
dataView: true,
show: (record) => { return record.state === 'disabled' }
},
{
api: 'disableUser',
icon: 'pause-circle',
label: 'label.action.disable.user',
dataView: true,
show: (record) => { return record.state === 'enabled' }
},
{
api: 'deleteUser',
icon: 'delete',
label: 'label.action.delete.user',
dataView: true
}
]
},
{
name: 'account',
title: 'Accounts',
icon: 'team',
permission: ['listAccounts'],
columns: ['name', 'state', 'rolename', 'roletype', 'domain'],
details: ['name', 'id', 'rolename', 'roletype', 'domain', 'networkdomain', 'iptotal', 'vmtotal', 'volumetotal', 'receivedbytes', 'sentbytes', 'vmlimit', 'iplimit', 'volumelimit', 'snapshotlimit', 'templatelimit', 'vpclimit', 'cpulimit', 'memorylimit', 'networklimit', 'primarystoragelimit', 'secondarystoragelimit'],
related: [{
name: 'accountuser',
title: 'Users',
param: 'account'
}],
tabs: [
{
name: 'details',
component: () => import('@/components/view/DetailsTab.vue')
},
{
name: 'certificate',
component: () => import('@/views/iam/SSLCertificateTab.vue')
},
{
name: 'limits',
show: (record, route, user) => { return ['Admin'].includes(user.roletype) },
component: () => import('@/components/view/ResourceLimitTab.vue')
},
{
name: 'Settings',
component: () => import('@/components/view/SettingsTab.vue'),
show: (record, route, user) => { return ['Admin'].includes(user.roletype) }
}
],
actions: [
{
api: 'createAccount',
icon: 'plus',
label: 'label.add.account',
listView: true,
args: ['username', 'password', 'password', 'email', 'firstname', 'lastname', 'domainid', 'account', 'roleid', 'timezone', 'networkdomain']
},
{
api: 'ldapCreateAccount',
icon: 'user-add',
label: 'label.add.ldap.account',
listView: true,
popup: true,
show: (record, store) => {
return store.isLdapEnabled
},
component: () => import('@/views/iam/AddLdapAccount.vue')
},
{
api: 'updateAccount',
icon: 'edit',
label: 'Update Account',
dataView: true,
args: ['newname', 'account', 'domainid', 'networkdomain'],
mapping: {
account: {
value: (record) => { return record.name }
},
domainid: {
value: (record) => { return record.domainid }
}
}
},
{
api: 'updateResourceCount',
icon: 'sync',
label: 'Update Resource Count',
dataView: true,
args: ['account', 'domainid'],
mapping: {
account: {
value: (record) => { return record.name }
},
domainid: {
value: (record) => { return record.domainid }
}
}
},
{
api: 'enableAccount',
icon: 'play-circle',
label: 'Enable Account',
dataView: true,
show: (record) => { return record.state === 'disabled' || record.state === 'locked' },
params: { lock: 'false' }
},
{
api: 'disableAccount',
icon: 'pause-circle',
label: 'Disable Account',
dataView: true,
show: (record) => { return record.state === 'enabled' },
args: ['lock'],
mapping: {
lock: {
value: (record) => { return false }
}
}
},
{
api: 'disableAccount',
icon: 'lock',
label: 'Lock account',
dataView: true,
show: (record) => { return record.state === 'enabled' },
args: ['lock'],
mapping: {
lock: {
value: (record) => { return true }
}
}
},
{
api: 'uploadSslCert',
icon: 'safety-certificate',
label: 'Add certificate',
dataView: true,
args: ['name', 'certificate', 'privatekey', 'certchain', 'password', 'account', 'domainid'],
show: (record) => { return record.state === 'enabled' },
mapping: {
account: {
value: (record) => { return record.name }
},
domainid: {
value: (record) => { return record.domainid }
}
}
},
{
api: 'deleteAccount',
icon: 'delete',
label: 'Delete account',
dataView: true,
hidden: (record) => { return record.name === 'admin' }
}
]
},
{
name: 'domain',
title: 'Domains',
icon: 'block',
permission: ['listDomains', 'listDomainChildren'],
resourceType: 'Domain',
columns: ['name', 'state', 'path', 'parentdomainname', 'level'],
details: ['name', 'id', 'path', 'parentdomainname', 'level', 'networkdomain', 'iptotal', 'vmtotal', 'volumetotal', 'vmlimit', 'iplimit', 'volumelimit', 'snapshotlimit', 'templatelimit', 'vpclimit', 'cpulimit', 'memorylimit', 'networklimit', 'primarystoragelimit', 'secondarystoragelimit'],
related: [{
name: 'account',
title: 'Accounts',
param: 'domainid'
}],
tabs: [
{
name: 'Domain',
component: () => import('@/components/view/InfoCard.vue'),
show: (record, route) => { return route.path === '/domain' }
},
{
name: 'details',
component: () => import('@/components/view/DetailsTab.vue')
},
{
name: 'limits',
show: (record, route, user) => { return ['Admin'].includes(user.roletype) },
component: () => import('@/components/view/ResourceLimitTab.vue')
},
{
name: 'Settings',
component: () => import('@/components/view/SettingsTab.vue'),
show: (record, route, user) => { return ['Admin'].includes(user.roletype) }
}
],
treeView: true,
actions: [
{
api: 'createDomain',
icon: 'plus',
label: 'label.add.domain',
listView: true,
dataView: true,
args: ['parentdomainid', 'name', 'networkdomain', 'domainid'],
mapping: {
parentdomainid: {
value: (record) => { return record.id }
}
}
},
{
api: 'updateDomain',
icon: 'edit',
label: 'label.action.edit.domain',
listView: true,
dataView: true,
args: ['name', 'networkdomain']
},
{
api: 'updateResourceCount',
icon: 'sync',
label: 'label.action.update.resource.count',
listView: true,
dataView: true,
args: ['domainid'],
mapping: {
domainid: {
value: (record) => { return record.id }
}
}
},
{
api: 'linkDomainToLdap',
icon: 'link',
label: 'Link Domain to LDAP Group/OU',
listView: true,
dataView: true,
args: ['type', 'domainid', 'name', 'accounttype', 'admin'],
mapping: {
type: {
options: ['GROUP', 'OU']
},
accounttype: {
options: ['0', '2']
},
domainid: {
value: (record) => { return record.id }
}
}
},
{
api: 'deleteDomain',
icon: 'delete',
label: 'label.delete.domain',
listView: true,
dataView: true,
show: (record) => { return record.level !== 0 },
args: ['cleanup']
}
]
},
{
name: 'role',
title: 'Roles',
icon: 'idcard',
permission: ['listRoles'],
columns: ['name', 'type', 'description'],
details: ['name', 'id', 'type', 'description'],
tabs: [{
name: 'details',
component: () => import('@/components/view/DetailsTab.vue')
}, {
name: 'Rules',
component: () => import('@/views/iam/RolePermissionTab.vue')
}],
actions: [
{
api: 'createRole',
icon: 'plus',
label: 'Create Role',
listView: true,
args: ['name', 'description', 'type'],
mapping: {
type: {
options: ['Admin', 'DomainAdmin', 'User']
}
}
},
{
api: 'updateRole',
icon: 'edit',
label: 'Edit Role',
dataView: true,
args: ['name', 'description', 'type'],
mapping: {
type: {
options: ['Admin', 'DomainAdmin', 'User']
}
}
},
{
api: 'deleteRole',
icon: 'delete',
label: 'label.delete.role',
dataView: true
}
]
}
]
}

View File

@ -19,7 +19,7 @@ export default {
name: 'cluster',
title: 'Clusters',
icon: 'cluster',
permission: ['listClustersMetrics', 'listClusters'],
permission: ['listClustersMetrics'],
columns: ['name', 'state', 'allocationstate', 'clustertype', 'hypervisortype', 'hosts', 'cpuused', 'cpumaxdeviation', 'cpuallocated', 'cputotal', 'memoryused', 'memorymaxdeviation', 'memoryallocated', 'memorytotal', 'podname', 'zonename'],
details: ['name', 'id', 'allocationstate', 'clustertype', 'hypervisortype', 'podname', 'zonename'],
related: [{

View File

@ -19,7 +19,7 @@ export default {
name: 'host',
title: 'Hosts',
icon: 'desktop',
permission: ['listHostsMetrics', 'listHosts'],
permission: ['listHostsMetrics'],
resourceType: 'Host',
params: { type: 'routing' },
columns: ['name', 'state', 'resourcestate', 'powerstate', 'ipaddress', 'hypervisor', 'instances', 'cpunumber', 'cputotalghz', 'cpuusedghz', 'cpuallocatedghz', 'memorytotalgb', 'memoryusedgb', 'memoryallocatedgb', 'networkread', 'networkwrite', 'clustername', 'zonename'],

View File

@ -19,7 +19,7 @@ export default {
name: 'storagepool',
title: 'Primary Storage',
icon: 'database',
permission: ['listStoragePoolsMetrics', 'listStoragePools'],
permission: ['listStoragePoolsMetrics'],
columns: ['name', 'state', 'ipaddress', 'type', 'path', 'scope', 'disksizeusedgb', 'disksizetotalgb', 'disksizeallocatedgb', 'disksizeunallocatedgb', 'clustername', 'zonename'],
details: ['name', 'id', 'ipaddress', 'type', 'scope', 'tags', 'path', 'provider', 'hypervisor', 'overprovisionfactor', 'disksizetotal', 'disksizeallocated', 'disksizeused', 'clustername', 'podname', 'zonename', 'created'],
related: [{

View File

@ -19,7 +19,7 @@ export default {
name: 'zone',
title: 'Zones',
icon: 'global',
permission: ['listZonesMetrics', 'listZones'],
permission: ['listZonesMetrics'],
columns: ['name', 'state', 'allocationstate', 'networktype', 'clusters', 'cpuused', 'cpumaxdeviation', 'cpuallocated', 'cputotal', 'memoryused', 'memorymaxdeviation', 'memoryallocated', 'memorytotal', 'order'],
details: ['name', 'id', 'allocationstate', 'networktype', 'guestcidraddress', 'localstorageenabled', 'securitygroupsenabled', 'dns1', 'dns2', 'internaldns1', 'internaldns2'],
related: [{

View File

@ -19,13 +19,13 @@ export default {
name: 'offering',
title: 'Offerings',
icon: 'shopping',
permission: ['listServiceOfferings'],
permission: ['createServiceOffering', 'createDiskOffering'],
children: [
{
name: 'computeoffering',
title: 'Compute Offerings',
icon: 'cloud',
permission: ['listServiceOfferings'],
permission: ['listServiceOfferings', 'createServiceOffering'],
params: { isrecursive: 'true' },
columns: ['name', 'displaytext', 'cpunumber', 'cpuspeed', 'memory', 'tags', 'domain', 'zone', 'order'],
details: ['name', 'id', 'displaytext', 'offerha', 'provisioningtype', 'storagetype', 'iscustomized', 'limitcpuuse', 'cpunumber', 'cpuspeed', 'memory', 'tags', 'domain', 'zone', 'created'],
@ -96,7 +96,7 @@ export default {
name: 'diskoffering',
title: 'Disk Offerings',
icon: 'hdd',
permission: ['listDiskOfferings'],
permission: ['listDiskOfferings', 'createDiskOffering'],
params: { isrecursive: 'true' },
columns: ['name', 'displaytext', 'disksize', 'tags', 'domain', 'zone', 'order'],
details: ['name', 'id', 'displaytext', 'disksize', 'provisioningtype', 'storagetype', 'iscustomized', 'tags', 'domain', 'zone', 'created'],
@ -136,7 +136,7 @@ export default {
name: 'backupoffering',
title: 'Backup Offerings',
icon: 'cloud-upload',
permission: ['listBackupOfferings'],
permission: ['listBackupOfferings', 'importBackupOffering'],
columns: ['name', 'description', 'zoneid'],
details: ['name', 'id', 'description', 'externalid', 'zone', 'created'],
actions: [{
@ -157,7 +157,7 @@ export default {
name: 'networkoffering',
title: 'Network Offerings',
icon: 'wifi',
permission: ['listNetworkOfferings'],
permission: ['listNetworkOfferings', 'createNetworkOffering'],
params: { isrecursive: 'true' },
columns: ['name', 'state', 'guestiptype', 'traffictype', 'networkrate', 'tags', 'domain', 'zone', 'order'],
details: ['name', 'id', 'displaytext', 'guestiptype', 'traffictype', 'networkrate', 'ispersistent', 'egressdefaultpolicy', 'availability', 'conservemode', 'specifyvlan', 'specifyipranges', 'supportspublicaccess', 'supportsstrechedl2subnet', 'tags', 'service', 'domain', 'zone'],
@ -221,7 +221,7 @@ export default {
name: 'vpcoffering',
title: 'VPC Offerings',
icon: 'deployment-unit',
permission: ['listVPCOfferings'],
permission: ['listVPCOfferings', 'createVPCOffering'],
params: { isrecursive: 'true' },
resourceType: 'VpcOffering',
columns: ['name', 'state', 'displaytext', 'domain', 'zone', 'order'],

View File

@ -0,0 +1,64 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
export default {
name: 'role',
title: 'Roles',
icon: 'idcard',
permission: ['listRoles', 'createRole'],
columns: ['name', 'type', 'description'],
details: ['name', 'id', 'type', 'description'],
tabs: [{
name: 'details',
component: () => import('@/components/view/DetailsTab.vue')
}, {
name: 'Rules',
component: () => import('@/views/iam/RolePermissionTab.vue')
}],
actions: [
{
api: 'createRole',
icon: 'plus',
label: 'Create Role',
listView: true,
args: ['name', 'description', 'type'],
mapping: {
type: {
options: ['Admin', 'DomainAdmin', 'User']
}
}
},
{
api: 'updateRole',
icon: 'edit',
label: 'Edit Role',
dataView: true,
args: ['name', 'description', 'type'],
mapping: {
type: {
options: ['Admin', 'DomainAdmin', 'User']
}
}
},
{
api: 'deleteRole',
icon: 'delete',
label: 'label.delete.role',
dataView: true
}
]
}

View File

@ -24,7 +24,7 @@ export default {
name: 'volume',
title: 'Volumes',
icon: 'hdd',
permission: ['listVolumesMetrics', 'listVolumes'],
permission: ['listVolumesMetrics'],
resourceType: 'Volume',
columns: ['name', 'state', 'type', 'vmname', 'size', 'physicalsize', 'utilization', 'diskkbsread', 'diskkbswrite', 'diskiopstotal', 'storage', 'account', 'zonename'],
details: ['name', 'id', 'type', 'storagetype', 'diskofferingdisplaytext', 'deviceid', 'sizegb', 'physicalsize', 'provisioningtype', 'utilization', 'diskkbsread', 'diskkbswrite', 'diskioread', 'diskiowrite', 'diskiopstotal', 'miniops', 'maxiops', 'path'],

View File

@ -0,0 +1,76 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
export default {
name: 'accountuser',
title: 'Users',
icon: 'user',
hidden: true,
permission: ['listUsers'],
columns: ['username', 'state', 'firstname', 'lastname', 'email', 'account', 'domain'],
details: ['username', 'id', 'firstname', 'lastname', 'email', 'usersource', 'timezone', 'rolename', 'roletype', 'account', 'domain', 'created'],
actions: [
{
api: 'createUser',
icon: 'plus',
label: 'label.add.user',
listView: true,
args: ['username', 'password', 'password', 'email', 'firstname', 'lastname', 'timezone', 'account', 'domainid']
},
{
api: 'updateUser',
icon: 'edit',
label: 'label.edit',
dataView: true,
args: ['username', 'email', 'firstname', 'lastname', 'timezone']
},
{
api: 'updateUser',
icon: 'key',
label: 'label.action.change.password',
dataView: true,
popup: true,
component: () => import('@/views/iam/ChangeUserPassword.vue')
},
{
api: 'registerUserKeys',
icon: 'file-protect',
label: 'label.action.generate.keys',
dataView: true
},
{
api: 'enableUser',
icon: 'play-circle',
label: 'label.action.enable.user',
dataView: true,
show: (record) => { return record.state === 'disabled' }
},
{
api: 'disableUser',
icon: 'pause-circle',
label: 'label.action.disable.user',
dataView: true,
show: (record) => { return record.state === 'enabled' }
},
{
api: 'deleteUser',
icon: 'delete',
label: 'label.action.delete.user',
dataView: true
}
]
}

View File

@ -20,11 +20,11 @@ import { asyncRouterMap, constantRouterMap } from '@/config/router'
function hasApi (apis, route) {
if (route.meta && route.meta.permission) {
for (const permission of route.meta.permission) {
if (apis.includes(permission)) {
return true
if (!apis.includes(permission)) {
return false
}
}
return false
return true
}
return true
}