feat: The RBAC Policies has been added.

Change-Id: I9b35371595d2aefb77ad2122e6c6bfec6d89bb41
This commit is contained in:
nevragurses 2024-05-08 11:04:46 +00:00
parent 5c129f2705
commit d7669a7cc1
13 changed files with 666 additions and 0 deletions

View File

@ -0,0 +1,6 @@
---
features:
- |
The RBAC Policies has been added to Networks.
RBAC Policies and its actions have been included under the Networks in administrator page.

View File

@ -97,6 +97,11 @@ export class NeutronClient extends Base {
},
],
},
{
name: 'rbacPolicies',
key: 'rbac-policies',
responseKey: 'rbac_policy',
},
{
name: 'firewalls',
key: 'fwaas/firewall_groups',

View File

@ -447,6 +447,21 @@ const renderMenu = (t) => {
},
],
},
{
path: '/network/rbac-policies-admin',
name: t('RBAC Policies'),
key: 'rbacPolicyAdmin',
level: 1,
children: [
{
path: /^\/network\/rbac-policies-admin\/detail\/.[^/]+$/,
name: t('RBAC Policy Detail'),
key: 'rbacPolicyDetailAdmin',
level: 2,
routePath: '/network/rbac-policies-admin/detail/:id',
},
],
},
{
path: '/network/firewall-admin',
name: t('Firewalls'),

View File

@ -0,0 +1,57 @@
// Licensed 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.
import { inject, observer } from 'mobx-react';
import Base from 'containers/BaseDetail';
export class BaseDetail extends Base {
get leftCards() {
const cards = [this.baseInfoCard];
return cards;
}
get baseInfoCard() {
const options = [
{
label: t('ID'),
dataIndex: 'id',
},
{
label: t('Project ID'),
dataIndex: 'project_id',
},
{
label: t('Object Type'),
dataIndex: 'object_type',
},
{
label: t('Object ID'),
dataIndex: 'object_id',
},
{
label: t('Action'),
dataIndex: 'action',
},
{
label: t('Target Tenant'),
dataIndex: 'target_tenant',
},
];
return {
title: t('Rbac Policy Detail'),
options,
};
}
}
export default inject('rootStore')(observer(BaseDetail));

View File

@ -0,0 +1,48 @@
// Licensed 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.
import { inject, observer } from 'mobx-react';
import Base from 'containers/TabDetail';
import actionConfigs from 'src/pages/network/containers/RbacPolicies/actions';
import { RbacPoliciesStore } from 'src/stores/neutron/rbac-policies';
import Detail from './Detail';
export class RbacPolicyDetail extends Base {
get name() {
return t('Rbac Policy');
}
get listUrl() {
return this.getRoutePath('rbacPoliciesAdmin');
}
get actionConfigs() {
return actionConfigs;
}
get tabs() {
const tabs = [
{
title: t('Detail'),
key: 'rbacPolicyDetailAdmin',
component: Detail,
},
];
return tabs;
}
init() {
this.store = new RbacPoliciesStore();
}
}
export default inject('rootStore')(observer(RbacPolicyDetail));

View File

@ -0,0 +1,201 @@
// Licensed 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.
import { inject, observer } from 'mobx-react';
import { ModalAction } from 'containers/Action';
import Notify from 'src/components/Notify';
import { RbacPoliciesStore } from 'src/stores/neutron/rbac-policies';
import { ProjectStore } from 'stores/keystone/project';
import { NetworkStore } from 'stores/neutron/network';
import { QoSPolicyStore } from 'stores/neutron/qos-policy';
import { observable } from 'mobx';
export class Create extends ModalAction {
static id = 'create-policy';
static title = t('Create');
@observable allNetworks;
@observable allProjects;
get name() {
return t('Create');
}
init() {
this.state = {
...this.state,
isReady: false,
};
this.store = new RbacPoliciesStore();
this.projectStore = new ProjectStore();
this.qosPolicyStore = new QoSPolicyStore();
this.networkStore = new NetworkStore();
this.getAllData();
}
async getAllData() {
await Promise.all([
this.getProjects(),
this.getQoSPolicy(),
this.getNetworks(),
]);
this.setState({ isReady: true });
}
get tips() {
return t('From here you can create a rbac policy.');
}
async getProjects() {
this.allProjects = await this.projectStore.pureFetchList();
this.addNewElementToProjectList();
}
addNewElementToProjectList() {
const newElement = {
id: '*',
name: '*',
};
this.allProjects.unshift(newElement);
}
async getQoSPolicy() {
await this.qosPolicyStore.fetchList();
}
async getNetworks() {
this.allNetworks = await this.networkStore.pureFetchList();
}
get projects() {
return (this.allProjects || []).map((it) => ({
value: it.id,
label: it.name,
}));
}
get qosPolicy() {
return (this.qosPolicyStore.list.data || []).map((it) => ({
value: it.id,
label: it.name,
}));
}
get networks() {
return (this.allNetworks || []).map((it) => ({
value: it.id,
label: it.name,
}));
}
onSubmit = async (values) => {
try {
const { object_type, ...rest } = values;
const action =
object_type === 'network' || object_type === 'qos_policy'
? 'access_as_shared'
: 'access_as_external';
const updatedType =
object_type === 'external-network' ? 'network' : object_type;
const body = {
...rest,
object_type: updatedType,
action,
};
await this.store.create(body);
} catch (error) {
Notify.errorWithDetail(null, error.toString());
return Promise.reject(error);
}
};
static allowed = () => Promise.resolve(true);
get createObjectList() {
return [
{ value: 'network', label: t('Shared Network') },
{ value: 'external-network', label: t('External Network') },
{ value: 'qos_policy', label: t('Shared QoS Policy') },
];
}
onChangeHandler = async (value) => {
this.setState({
object_type: value,
});
};
get formItems() {
const { object_type } = this.state;
const isNetwork = object_type === 'network';
const isExternalNetwork = object_type === 'external-network';
const isQosPolicy = object_type === 'qos_policy';
return [
{
name: 'target_tenant',
label: t('Target Project'),
placeholder: t('Select a project'),
type: 'select',
options: this.projects,
isLoading: !this.state.isReady,
required: true,
},
{
name: 'object_type',
label: t('Action and Object Type'),
placeholder: t('Select action and object type'),
type: 'select',
onChange: this.onChangeHandler,
options: this.createObjectList,
required: true,
},
{
name: 'object_id',
label: t('Shared Network'),
placeholder: t('Select a network'),
type: 'select',
options: this.networks,
hidden: !isNetwork,
isLoading: !this.state.isReady,
onChange: this.onSourceEnvironmentChange,
required: true,
},
{
name: 'object_id',
label: t('External Network'),
placeholder: t('Select a network'),
type: 'select',
options: this.networks,
hidden: !isExternalNetwork,
isLoading: !this.state.isReady,
required: true,
},
{
name: 'object_id',
label: t('QoS Policy'),
placeholder: t('Select a QoS Policy'),
type: 'select',
options: this.qosPolicy,
hidden: !isQosPolicy,
isLoading: !this.state.isReady,
required: true,
},
];
}
}
export default inject('rootStore')(observer(Create));

View File

@ -0,0 +1,38 @@
// Licensed 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.
import { ConfirmAction } from 'containers/Action';
import globalRbacPoliciesStore from 'stores/neutron/rbac-policies';
export default class Delete extends ConfirmAction {
get id() {
return 'delete';
}
get title() {
return t('Delete RBAC Policy');
}
get isDanger() {
return true;
}
get buttonText() {
return t('Delete');
}
get actionName() {
return t('delete');
}
onSubmit = (data) => globalRbacPoliciesStore.delete(data);
}

View File

@ -0,0 +1,78 @@
// Licensed 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.
import { inject, observer } from 'mobx-react';
import { ModalAction } from 'containers/Action';
import Notify from 'src/components/Notify';
import { RbacPoliciesStore } from 'src/stores/neutron/rbac-policies';
import { ProjectStore } from 'stores/keystone/project';
export class Edit extends ModalAction {
static id = 'edit-policy';
static title = t('Edit');
get name() {
return t('Edit');
}
init() {
this.store = new RbacPoliciesStore();
this.projectStore = new ProjectStore();
this.getProjects();
}
get tips() {
return t('You may update the editable properties of the RBAC policy here.');
}
async getProjects() {
await this.projectStore.fetchProjectsWithDomain();
this.setState({ ...this.state, isReady: true });
}
get projects() {
return (this.projectStore.list.data || []).map((it) => ({
value: it.id,
label: it.name,
}));
}
onSubmit = async (values) => {
const { id } = this.item;
try {
const { ...body } = values;
await this.store.update(id, body);
} catch (error) {
Notify.errorWithDetail(null, error.toString());
return Promise.reject(error);
}
};
static allowed = () => Promise.resolve(true);
get formItems() {
return [
{
name: 'target_tenant',
label: t('Target Project'),
placeholder: t('Select a project'),
type: 'select',
options: this.projects,
isLoading: this.projectStore.list.isLoading,
required: true,
},
];
}
}
export default inject('rootStore')(observer(Edit));

View File

@ -0,0 +1,30 @@
// Licensed 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.
import Delete from './Delete';
import Edit from './Edit';
import Create from './Create';
const actionConfigs = {
rowActions: {
firstAction: Edit,
moreActions: [
{
action: Delete,
},
],
},
batchActions: [Delete],
primaryActions: [Create],
};
export default actionConfigs;

View File

@ -0,0 +1,98 @@
// Licensed 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.
import { observer, inject } from 'mobx-react';
import Base from 'containers/List';
import { RbacPoliciesStore } from 'src/stores/neutron/rbac-policies';
import actionConfigRbacPolicies from './actions';
export class RbacPolicies extends Base {
init() {
this.store = new RbacPoliciesStore();
this.downloadStore = new RbacPoliciesStore();
}
get hasTab() {
return false;
}
get name() {
return t('RBAC Policies');
}
get actionConfigs() {
return actionConfigRbacPolicies;
}
getColumns = () => {
const columns = [
{
title: t('Project'),
dataIndex: 'project_name',
},
{
title: t('ID'),
dataIndex: 'id',
routeName: this.getRouteName('rbacPolicyDetail'),
isLink: true,
},
{
title: t('Object Type'),
dataIndex: 'object_type',
},
{
title: t('Object'),
dataIndex: 'object_name',
},
{
title: t('Target Project'),
dataIndex: 'target_tenant_name',
},
];
return columns;
};
get objectTypes() {
return [
{ key: 'network', label: t('Network') },
{ key: 'qos_policy', label: t('QoS Policy') },
];
}
get searchFilters() {
return [
{
label: t('Project'),
name: 'project_name',
},
{
label: t('Id'),
name: 'id',
},
{
label: t('Target Project'),
name: 'target_tenant_name',
},
{
label: t('Object Type'),
name: 'object_type',
options: this.objectTypes,
},
{
label: t('Object'),
name: 'object_name',
},
];
}
}
export default inject('rootStore')(observer(RbacPolicies));

View File

@ -55,6 +55,8 @@ import RuleDetail from '../containers/Firewall/Rule/Detail';
import PolicyCreate from '../containers/Firewall/Policy/actions/Create';
import PolicyEdit from '../containers/Firewall/Policy/actions/Edit';
import FirewallCreate from '../containers/Firewall/Firewall/actions/Create';
import RbacPolicies from '../containers/RbacPolicies';
import RbacPolicyDetail from '../containers/RbacPolicies/Detail';
const PATH = '/network';
export default [
@ -354,6 +356,16 @@ export default [
component: PolicyEdit,
exact: true,
},
{
path: `${PATH}/rbac-policies-admin`,
component: RbacPolicies,
exact: true,
},
{
path: `${PATH}/rbac-policies-admin/detail/:id`,
component: RbacPolicyDetail,
exact: true,
},
{ path: '*', component: E404 },
],
},

View File

@ -17,6 +17,7 @@ import globalVolumeStore from 'stores/cinder/volume';
import globalComputeHostStore from 'stores/nova/compute-host';
import globalHypervisorStore from 'stores/nova/hypervisor';
import globalStackStore from 'stores/heat/stack';
import globalRbacPoliciesStore from 'stores/neutron/rbac-policies';
export default {
globalFloatingIpsStore,
@ -38,4 +39,5 @@ export default {
globalHypervisorStore,
globalStackStore,
globalPortStore,
globalRbacPoliciesStore,
};

View File

@ -0,0 +1,76 @@
import Base from 'stores/base';
import client from 'client';
export class RbacPoliciesStore extends Base {
get client() {
return client.neutron.rbacPolicies;
}
get listFilterByProject() {
return true;
}
get listResponseKey() {
return 'rbac_policies';
}
get projectClient() {
return client.keystone.projects;
}
get qosClient() {
return client.neutron.qosPolicies;
}
get networkClient() {
return client.neutron.networks;
}
async listDidFetch(items) {
const [
{ networks: allNetworks },
{ policies: allPolicies },
{ projects: allProjects },
] = await Promise.all([
this.networkClient.list(),
this.qosClient.list(),
this.projectClient.list(),
]);
const updatedItems = items.map((item) => {
const networkOfItem = allNetworks.find(
(network) => network.id === item.object_id
);
const policyOfItem = allPolicies.find(
(policy) => policy.id === item.object_id
);
const targetTenant = allProjects.find(
(project) => project.id === item.target_tenant
);
return {
...item,
object_name: networkOfItem
? networkOfItem.name
: policyOfItem
? policyOfItem.name
: '-',
target_tenant_name: targetTenant ? targetTenant.name : '*',
};
});
return updatedItems;
}
async getProjects() {
await this.projectClient.list();
}
async getQoSPolicy() {
await this.qosPolicyClient.list();
}
async getNetworks() {
await this.networkClient.list();
}
}
const globalRbacPoliciesStore = new RbacPoliciesStore();
export default globalRbacPoliciesStore;