Merge "RIFT-16181: Project switch must affect non-polling/non-socket based pages" into projects
diff --git a/skyquake/framework/core/modules/api/projectManagementAPI.js b/skyquake/framework/core/modules/api/projectManagementAPI.js
index 07e873d..c00de32 100644
--- a/skyquake/framework/core/modules/api/projectManagementAPI.js
+++ b/skyquake/framework/core/modules/api/projectManagementAPI.js
@@ -228,6 +228,7 @@
var api_server = req.query['api_server'];
var bodyData = req.body;
data = bodyData;
+ data.user = JSON.parse(data.user)
var updateTasks = [];
var updateUser = rp({
diff --git a/skyquake/framework/core/modules/routes/navigation.js b/skyquake/framework/core/modules/routes/navigation.js
index bf9c47b..16ff25a 100644
--- a/skyquake/framework/core/modules/routes/navigation.js
+++ b/skyquake/framework/core/modules/routes/navigation.js
@@ -1,6 +1,6 @@
/*
- *
+ *
* Copyright 2016 RIFT.IO Inc
*
* Licensed under the Apache License, Version 2.0 (the "License");
diff --git a/skyquake/framework/utils/utils.js b/skyquake/framework/utils/utils.js
index be3278d..16037d7 100644
--- a/skyquake/framework/utils/utils.js
+++ b/skyquake/framework/utils/utils.js
@@ -26,6 +26,7 @@
var Utils = {};
Utils.DescriptorModelMeta = null;
+// Utils.DescriptorModelMeta = require('./../../plugins/composer/src/src/libraries/model/DescriptorModelMeta.json');
var INACTIVITY_TIMEOUT = 600000;
diff --git a/skyquake/framework/widgets/skyquake_nav/skyquakeNav.jsx b/skyquake/framework/widgets/skyquake_nav/skyquakeNav.jsx
index 1aaaf4d..f9161cc 100644
--- a/skyquake/framework/widgets/skyquake_nav/skyquakeNav.jsx
+++ b/skyquake/framework/widgets/skyquake_nav/skyquakeNav.jsx
@@ -25,7 +25,7 @@
import './skyquakeNav.scss';
import SelectOption from '../form_controls/selectOption.jsx';
import {FormSection} from '../form_controls/formControls.jsx';
-import SkyquakeRBAC from 'widgets/skyquake_rbac/skyquakeRBAC.jsx';
+import {isRBACValid, SkyquakeRBAC} from 'widgets/skyquake_rbac/skyquakeRBAC.jsx';
//Temporary, until api server is on same port as webserver
var rw = require('utils/rw.js');
@@ -190,6 +190,9 @@
skyquakeNav.defaultProps = {
nav: {}
}
+skyquakeNav.contextTypes = {
+ userProfile: React.PropTypes.object
+};
/**
* Returns a React Component
* @param {object} link Information about the nav link
@@ -259,6 +262,7 @@
let secondaryNav = [];
let adminNav = [];
let self = this;
+ const User = this.context.userProfile;
self.hasSubNav = {};
let secondaryNavHTML = (
<div className="secondaryNav" key="secondaryNav">
@@ -305,6 +309,7 @@
label: nav[k].label || k,
route: route
});
+ let shouldAllow = nav[k].allow || ['*'];
if (nav[k].pluginName == currentPlugin) {
navClass += " active";
}
@@ -312,22 +317,27 @@
navItem.priority = nav[k].priority;
navItem.order = nav[k].order;
if(nav[k].admin_link) {
- adminNav.push((
- <li key={nav[k].name}>
- {dashboardLink}
- </li>
- ))
+
+ if (isRBACValid(User, shouldAllow) ){
+ adminNav.push((
+ <li key={nav[k].name}>
+ {dashboardLink}
+ </li>
+ ))
+ }
} else {
- navItem.html = (
- <SkyquakeRBAC allow={nav[k].allow || ['*']} key={k} className={navClass}>
- <h2>{dashboardLink} {self.hasSubNav[k] ? <span className="oi" data-glyph="caret-bottom"></span> : ''}</h2>
- <ul className="menu">
- {
- NavList
- }
- </ul>
- </SkyquakeRBAC>
- );
+ if (isRBACValid(User, shouldAllow) ){
+ navItem.html = (
+ <div key={k} className={navClass}>
+ <h2>{dashboardLink} {self.hasSubNav[k] ? <span className="oi" data-glyph="caret-bottom"></span> : ''}</h2>
+ <ul className="menu">
+ {
+ NavList
+ }
+ </ul>
+ </div>
+ );
+ }
navList.push(navItem)
}
diff --git a/skyquake/framework/widgets/skyquake_rbac/skyquakeRBAC.jsx b/skyquake/framework/widgets/skyquake_rbac/skyquakeRBAC.jsx
index cbb6a56..0245e23 100644
--- a/skyquake/framework/widgets/skyquake_rbac/skyquakeRBAC.jsx
+++ b/skyquake/framework/widgets/skyquake_rbac/skyquakeRBAC.jsx
@@ -21,6 +21,25 @@
import ROLES from 'utils/roleConstants.js';
const PLATFORM = ROLES.PLATFORM;
+export function isRBACValid(User, allow){
+ const UserData = User.data;
+ if(UserData) {
+ const PlatformRole = UserData.platform.role;
+ const isPlatformSuper = PlatformRole[PLATFORM.SUPER];
+ const isPlatformAdmin = PlatformRole[PLATFORM.ADMIN];
+ const isPlatformOper = PlatformRole[PLATFORM.OPER];
+ const hasRoleAccess = checkForRoleAccess(UserData.project[User.projectId], PlatformRole, allow)//false//(this.props.roles.indexOf(userProfile.projectRole) > -1)
+ if (isPlatformSuper) {
+ return true;
+ } else {
+ if (hasRoleAccess) {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
export default class SkyquakeRBAC extends React.Component {
constructor(props, context) {
super(props);
@@ -30,19 +49,8 @@
const UserData = User.data;
let HTML = null;
// If user object has platform property then it has been populated by the back end.
- if(UserData) {
- const PlatformRole = UserData.platform.role;
- const isPlatformSuper = PlatformRole[PLATFORM.SUPER];
- const isPlatformAdmin = PlatformRole[PLATFORM.ADMIN];
- const isPlatformOper = PlatformRole[PLATFORM.OPER];
- const hasRoleAccess = checkForRoleAccess(UserData.project[User.projectId], PlatformRole, this.props.allow)//false//(this.props.roles.indexOf(userProfile.projectRole) > -1)
- if (isPlatformSuper) {
- HTML = this.props.children;
- } else {
- if (hasRoleAccess) {
- HTML = this.props.children;
- }
- }
+ if(isRBACValid(User, this.props.allow)) {
+ HTML = this.props.children;
}
return (<div className={this.props.className} style={this.props.style}>{HTML}</div>)
}
diff --git a/skyquake/plugins/composer/src/src/components/Button.js b/skyquake/plugins/composer/src/src/components/Button.js
index 76a569f..6ef41bf 100644
--- a/skyquake/plugins/composer/src/src/components/Button.js
+++ b/skyquake/plugins/composer/src/src/components/Button.js
@@ -40,6 +40,7 @@
label: null,
title: null,
src: null,
+ disabled: false,
onClick: () => {}
};
},
@@ -58,7 +59,7 @@
const draggable = this.props.draggable;
const className = ClassNames(this.props.className, 'Button');
return (
- <div className={className} onClick={this.props.onClick} title={title} draggable={draggable} onDragStart={this.props.onDragStart}>
+ <div className={className} onClick={this.props.onClick} title={title} draggable={draggable} onDragStart={this.props.onDragStart} style={{pointerEvents: (this.props.disabled ? 'none' : 'auto'), cursor: (this.props.disabled ? 'not-allowed' : 'auto'), position: 'relative'}}>
{ src ? <img src={src} /> : null }
{label}
</div>
diff --git a/skyquake/plugins/composer/src/src/components/CatalogItemDetailsEditor.js b/skyquake/plugins/composer/src/src/components/CatalogItemDetailsEditor.js
index 752d678..fe47521 100644
--- a/skyquake/plugins/composer/src/src/components/CatalogItemDetailsEditor.js
+++ b/skyquake/plugins/composer/src/src/components/CatalogItemDetailsEditor.js
@@ -1,5 +1,5 @@
/*
- *
+ *
* Copyright 2016 RIFT.IO Inc
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -20,6 +20,10 @@
import React from 'react'
import PureRenderMixin from 'react-addons-pure-render-mixin'
import EditDescriptorModelProperties from './EditDescriptorModelProperties'
+import {SkyquakeRBAC, isRBACValid} from 'widgets/skyquake_rbac/skyquakeRBAC.jsx';
+import ROLES from 'utils/roleConstants.js';
+const PROJECT_ROLES = ROLES.PROJECT;
+const PLATFORM = ROLES.PLATFORM;
const CatalogItemDetailsEditor = React.createClass({
mixins: [PureRenderMixin],
@@ -32,6 +36,10 @@
width: 0
};
},
+ contextTypes: {
+ router: React.PropTypes.object,
+ userProfile: React.PropTypes.object
+ },
componentWillMount() {
},
componentDidMount() {
@@ -41,6 +49,7 @@
componentWillUnmount() {
},
render() {
+ const User = this.context.userProfile;
const container = this.props.container || {model: {}, uiState: {}};
if (!(container && container.model && container.uiState)) {
@@ -51,7 +60,11 @@
<div className="CatalogItemDetailsEditor">
<form name="details-descriptor-editor-form">
<div className="properties-group">
- <EditDescriptorModelProperties container={this.props.container} width={this.props.width} />
+ {
+ isRBACValid(User, [PROJECT_ROLES.CAT_ADMIN]) ?
+ <EditDescriptorModelProperties container={this.props.container} width={this.props.width} />
+ : <EditDescriptorModelProperties container={this.props.container} width={this.props.width} readonly={true} />
+ }
</div>
</form>
</div>
@@ -60,4 +73,8 @@
}
});
+CatalogItemDetailsEditor.contextTypes = {
+ router: React.PropTypes.object,
+ userProfile: React.PropTypes.object
+};
export default CatalogItemDetailsEditor;
diff --git a/skyquake/plugins/composer/src/src/components/CatalogPanelToolbar.js b/skyquake/plugins/composer/src/src/components/CatalogPanelToolbar.js
index 5e3e3c0..896badd 100644
--- a/skyquake/plugins/composer/src/src/components/CatalogPanelToolbar.js
+++ b/skyquake/plugins/composer/src/src/components/CatalogPanelToolbar.js
@@ -1,6 +1,6 @@
/*
- *
+ *
* Copyright 2016 RIFT.IO Inc
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -32,6 +32,10 @@
import imgUpdate from '../../../node_modules/open-iconic/svg/rain.svg'
import imgDownload from '../../../node_modules/open-iconic/svg/cloud-download.svg'
import imgDelete from '../../../node_modules/open-iconic/svg/trash.svg'
+import {SkyquakeRBAC, isRBACValid} from 'widgets/skyquake_rbac/skyquakeRBAC.jsx';
+import ROLES from 'utils/roleConstants.js';
+const PROJECT_ROLES = ROLES.PROJECT;
+const PLATFORM = ROLES.PLATFORM;
const CatalogHeader = React.createClass({
mixins: [PureRenderMixin],
@@ -48,28 +52,32 @@
},
componentWillUnmount() {
},
+ contextTypes: {
+ userProfile: React.PropTypes.object
+ },
render() {
+ const disabled = !isRBACValid(this.context.userProfile, [PROJECT_ROLES.CAT_ADMIN]);
return (
<div className="CatalogPanelToolbar">
<h1>Descriptor Catalogs</h1>
<div className="btn-bar">
<div className="btn-group">
- <Button type="image" title="OnBoard a catalog package" className="action-onboard-catalog-package" onClick={this.onClickOnBoardCatalog} src={imgOnboard} />
- <Button type="image" title="Update a catalog package" className="action-update-catalog-package" onClick={this.onClickUpdateCatalog} src={imgUpdate} />
- <Button type="image" title="Export selected catalog item(s)" className="action-export-catalog-items" onClick={this.onClickExportCatalogItems} src={imgDownload} />
+ <Button type="image" title="OnBoard a catalog package" className="action-onboard-catalog-package" onClick={this.onClickOnBoardCatalog} src={imgOnboard} disabled={disabled}/>
+ <Button type="image" title="Update a catalog package" className="action-update-catalog-package" onClick={this.onClickUpdateCatalog} src={imgUpdate} disabled={disabled}/>
+ <Button type="image" title="Export selected catalog item(s)" className="action-export-catalog-items" onClick={this.onClickExportCatalogItems} src={imgDownload} disabled={disabled}/>
</div>
<div className="btn-group">
<div className="menu">
- <Button type="image" title="Create a new catalog item" className="action-create-catalog-item" onClick={this.onClickCreateCatalogItem.bind(null, 'nsd')} src={imgAdd} />
+ <Button type="image" title="Create a new catalog item" className="action-create-catalog-item" onClick={this.onClickCreateCatalogItem.bind(null, 'nsd')} src={imgAdd} disabled={disabled}/>
<div className="sub-menu">
- <Button type="image" title="Create a new catalog item" className="action-create-catalog-item" onClick={this.onClickCreateCatalogItem.bind(null, 'nsd')} src={imgAdd} label="Add NSD" />
- <Button type="image" title="Create a new catalog item" className="action-create-catalog-item" onClick={this.onClickCreateCatalogItem.bind(null, 'vnfd')} src={imgAdd} label="Add VNFD" />
+ <Button type="image" title="Create a new catalog item" className="action-create-catalog-item" onClick={this.onClickCreateCatalogItem.bind(null, 'nsd')} src={imgAdd} label="Add NSD" disabled={disabled}/>
+ <Button type="image" title="Create a new catalog item" className="action-create-catalog-item" onClick={this.onClickCreateCatalogItem.bind(null, 'vnfd')} src={imgAdd} label="Add VNFD" disabled={disabled}/>
</div>
</div>
- <Button type="image" title="Copy catalog item" className="action-copy-catalog-item" onClick={this.onClickDuplicateCatalogItem} src={imgCopy} />
+ <Button type="image" title="Copy catalog item" className="action-copy-catalog-item" onClick={this.onClickDuplicateCatalogItem} src={imgCopy} disabled={disabled}/>
</div>
<div className="btn-group">
- <Button type="image" title="Delete catalog item" className="action-delete-catalog-item" onClick = {this.onClickDeleteCatalogItem} src={imgDelete} />
+ <Button type="image" title="Delete catalog item" className="action-delete-catalog-item" onClick = {this.onClickDeleteCatalogItem} src={imgDelete} disabled={disabled}/>
</div>
</div>
</div>
diff --git a/skyquake/plugins/composer/src/src/components/ComposerApp.js b/skyquake/plugins/composer/src/src/components/ComposerApp.js
index 861c38b..fd3fc94 100644
--- a/skyquake/plugins/composer/src/src/components/ComposerApp.js
+++ b/skyquake/plugins/composer/src/src/components/ComposerApp.js
@@ -48,6 +48,9 @@
import CatalogItemsActions from '../actions/CatalogItemsActions'
import CommonUtils from 'utils/utils.js'
import FileManagerActions from './filemanager/FileManagerActions';
+import {SkyquakeRBAC, isRBACValid} from 'widgets/skyquake_rbac/skyquakeRBAC.jsx';
+import ROLES from 'utils/roleConstants.js';
+
import 'normalize.css'
import '../styles/AppRoot.scss'
import 'style/layout.scss'
@@ -60,6 +63,8 @@
const preventDefault = e => e.preventDefault();
const clearDragState = () => ComposerAppActions.setDragState(null);
+const PROJECT_ROLES = ROLES.PROJECT;
+const PLATFORM = ROLES.PLATFORM;
const ComposerApp = React.createClass({
mixins: [PureRenderMixin],
@@ -69,6 +74,10 @@
getDefaultProps() {
return {};
},
+ contextTypes: {
+ router: React.PropTypes.object,
+ userProfile: React.PropTypes.object
+ },
componentWillMount() {
if (clearLocalStorage) {
window.localStorage.clear();
@@ -147,6 +156,7 @@
render() {
let html = null;
let self = this;
+ const User = this.context.userProfile || {};
if(this.state.hasModel) {
function onClickUpdateSelection(event) {
@@ -225,7 +235,7 @@
isEditingVNFD={isEditingVNFD}
isModified={isModified}
isNew={isNew}
- disabled={!hasItem}
+ disabled={!hasItem || !isRBACValid(User, [PROJECT_ROLES.CAT_ADMIN])}
onClick={event => event.stopPropagation()}
panelTabShown={self.state.panelTabShown}/>
</div>
@@ -270,4 +280,5 @@
});
+
export default ComposerApp;
diff --git a/skyquake/plugins/composer/src/src/components/DetailsPanel.js b/skyquake/plugins/composer/src/src/components/DetailsPanel.js
index a20679f..7af2ad1 100644
--- a/skyquake/plugins/composer/src/src/components/DetailsPanel.js
+++ b/skyquake/plugins/composer/src/src/components/DetailsPanel.js
@@ -1,6 +1,6 @@
/*
- *
+ *
* Copyright 2016 RIFT.IO Inc
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -73,4 +73,9 @@
}
});
+DetailsPanel.contextTypes = {
+ router: React.PropTypes.object,
+ userProfile: React.PropTypes.object
+};
+
export default DetailsPanel;
diff --git a/skyquake/plugins/composer/src/src/components/EditDescriptorModelProperties.js b/skyquake/plugins/composer/src/src/components/EditDescriptorModelProperties.js
index 589eef9..e75f3cd 100644
--- a/skyquake/plugins/composer/src/src/components/EditDescriptorModelProperties.js
+++ b/skyquake/plugins/composer/src/src/components/EditDescriptorModelProperties.js
@@ -74,7 +74,7 @@
export default function EditDescriptorModelProperties(props) {
const container = props.container;
-
+ const readonly = props.readonly;
if (!(DescriptorModelFactory.isContainer(container))) {
return
}
@@ -141,6 +141,9 @@
}
CatalogItemsActions.catalogItemDescriptorChanged(this.getRoot());
}
+ if(readonly) {
+ return null;
+ }
return (
<Button className="inline-hint" onClick={onClickAddProperty.bind(container, property, path)} label="Add" src={imgAdd} />
);
@@ -158,6 +161,9 @@
}
CatalogItemsActions.catalogItemDescriptorChanged(this.getRoot());
}
+ if(readonly) {
+ return null;
+ }
return (
<Button className="remove-property-action inline-hint" title="Remove" onClick={onClickRemoveProperty.bind(container, property, path)} label="Remove" src={imgRemove}/>
);
@@ -178,7 +184,7 @@
let catalogs = cds.getTransientCatalogs();
const name = path.join('.');
- const isEditable = true;
+ const isEditable = !readonly; //true
const isGuid = Property.isGuid(property);
const isBoolean = Property.isBoolean(property);
const onChange = onFormFieldValueChanged.bind(container);
@@ -202,7 +208,7 @@
const noValueDisplayText = changeCase.title(property.name);
options.unshift(<option key={'(value-not-in-enum)' + fieldKey.toString()} value="" placeholder={placeholder}>{noValueDisplayText}</option>);
}
- return <select key={fieldKey.toString()} id={fieldKey.toString()} className={ClassNames({'-value-not-set': !isValueSet})} name={name} value={value} title={name} onChange={onChange} onFocus={onFocus} onBlur={endEditing} onMouseDown={startEditing} onMouseOver={startEditing} readOnly={!isEditable}>{options}</select>;
+ return <select key={fieldKey.toString()} id={fieldKey.toString()} className={ClassNames({'-value-not-set': !isValueSet})} name={name} value={value} title={name} onChange={onChange} onFocus={onFocus} onBlur={endEditing} onMouseDown={startEditing} onMouseOver={startEditing} disabled={!isEditable}>{options}</select>;
}
if (isLeafRef) {
@@ -222,7 +228,7 @@
const noValueDisplayText = changeCase.title(property.name);
options.unshift(<option key={'(value-not-in-leafref)' + fieldKey.toString()} value="" placeholder={placeholder}>{noValueDisplayText}</option>);
}
- return <select key={fieldKey.toString()} id={fieldKey.toString()} className={ClassNames({'-value-not-set': !isValueSet})} name={name} value={value} title={name} onChange={onChange} onFocus={onFocus} onBlur={endEditing} onMouseDown={startEditing} onMouseOver={startEditing} readOnly={!isEditable}>{options}</select>;
+ return <select key={fieldKey.toString()} id={fieldKey.toString()} className={ClassNames({'-value-not-set': !isValueSet})} name={name} value={value} title={name} onChange={onChange} onFocus={onFocus} onBlur={endEditing} onMouseDown={startEditing} onMouseOver={startEditing} disabled={!isEditable}>{options}</select>;
}
if (isBoolean) {
@@ -247,28 +253,29 @@
val = value ? "TRUE" : "FALSE"
}
const isValueSet = (val != '' && val)
- return <select key={fieldKey.toString()} id={fieldKey.toString()} className={ClassNames({'-value-not-set': !isValueSet})} name={name} value={val && val.toUpperCase()} title={name} onChange={onChange} onFocus={onFocus} onBlur={endEditing} onMouseDown={startEditing} onMouseOver={startEditing} readOnly={!isEditable}>{options}</select>;
+ return <select key={fieldKey.toString()} id={fieldKey.toString()} className={ClassNames({'-value-not-set': !isValueSet})} name={name} value={val && val.toUpperCase()} title={name} onChange={onChange} onFocus={onFocus} onBlur={endEditing} onMouseDown={startEditing} onMouseOver={startEditing} disabled={!isEditable}>{options}</select>;
}
if (property['preserve-line-breaks']) {
- return <textarea key={fieldKey.toString()} cols="5" id={fieldKey.toString()} name={name} value={value} placeholder={placeholder} onChange={onChange} onFocus={onFocus} onBlur={endEditing} onMouseDown={startEditing} onMouseOver={startEditing} onMouseOut={endEditing} onMouseLeave={endEditing} readOnly={!isEditable} />;
+ return <textarea key={fieldKey.toString()} cols="5" id={fieldKey.toString()} name={name} value={value} placeholder={placeholder} onChange={onChange} onFocus={onFocus} onBlur={endEditing} onMouseDown={startEditing} onMouseOver={startEditing} onMouseOut={endEditing} onMouseLeave={endEditing} readOnly={!!isEditable} />;
}
- return <input key={fieldKey.toString()}
- id={fieldKey.toString()}
- type="text"
- name={name}
- value={fieldValue}
- className={className}
- placeholder={placeholder}
- onChange={onChange}
- onFocus={onFocus}
- onBlur={endEditing}
- onMouseDown={startEditing}
- onMouseOver={startEditing}
- onMouseOut={endEditing}
- onMouseLeave={endEditing}
- readOnly={!isEditable}
+ return <input
+ key={fieldKey.toString()}
+ id={fieldKey.toString()}
+ type="text"
+ name={name}
+ value={fieldValue}
+ className={className}
+ placeholder={placeholder}
+ onChange={onChange}
+ onFocus={onFocus}
+ onBlur={endEditing}
+ onMouseDown={startEditing}
+ onMouseOver={startEditing}
+ onMouseOut={endEditing}
+ onMouseLeave={endEditing}
+ readOnly={!isEditable}
/>;
}
@@ -438,7 +445,7 @@
return (
<div key={key} className="choice">
- <select key={Date.now()} className={ClassNames({'-value-not-set': !selectedOptionValue})} name={selectName} value={selectedOptionValue} onChange={onChange} onFocus={onFocus} onBlur={endEditing} onMouseDown={startEditing} onMouseOver={startEditing} onMouseOut={endEditing} onMouseLeave={endEditing}>
+ <select key={Date.now()} className={ClassNames({'-value-not-set': !selectedOptionValue})} name={selectName} value={selectedOptionValue} onChange={onChange} onFocus={onFocus} onBlur={endEditing} onMouseDown={startEditing} onMouseOver={startEditing} onMouseOut={endEditing} onMouseLeave={endEditing} readOnly={!isEditable}>
{options}
</select>
{valueResponse}
diff --git a/skyquake/plugins/composer/src/src/components/EditorForwardingGraph/EditForwardingGraphPaths.js b/skyquake/plugins/composer/src/src/components/EditorForwardingGraph/EditForwardingGraphPaths.js
index 0f39d30..ba1e0cc 100644
--- a/skyquake/plugins/composer/src/src/components/EditorForwardingGraph/EditForwardingGraphPaths.js
+++ b/skyquake/plugins/composer/src/src/components/EditorForwardingGraph/EditForwardingGraphPaths.js
@@ -1,5 +1,5 @@
/*
- *
+ *
* Copyright 2016 RIFT.IO Inc
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -45,6 +45,11 @@
import onCutDelegateToRemove from './onCutDelegateToRemove'
import onClickSelectAndShowInDetailsPanel from './onClickSelectAndShowInDetailsPanel'
+import {SkyquakeRBAC, isRBACValid} from 'widgets/skyquake_rbac/skyquakeRBAC.jsx';
+import ROLES from 'utils/roleConstants.js';
+const PROJECT_ROLES = ROLES.PROJECT;
+const PLATFORM = ROLES.PLATFORM;
+
import '../../styles/EditForwardingGraphPaths.scss'
import imgNSD from '../../images/default-catalog-icon.svg'
@@ -119,7 +124,11 @@
<div key={i} className={fg.className} data-uid={fg.uid} data-offset-width="true" onClick={onClickSelectAndShowInDetailsPanel.bind(null, fg)} onCut={onCutDelegateToRemove.bind(null, fg)}>
<div key="outline-indicator" data-outline-indicator="true"></div>
<div className="header-actions">
- <Button className="remove-forwarding-graph" title="Remove" onClick={onClickRemoveForwardingGraph.bind(null, fg)} src={imgRemove}/>
+ {
+ this.isRBACValid ?
+ <Button className="remove-forwarding-graph" title="Remove" onClick={onClickRemoveForwardingGraph.bind(null, fg)} src={imgRemove}/>
+ : null
+ }
</div>
<LayoutRow primaryActionColumn={toggleSelectAllPaths} secondaryActionColumn={<img className="fg-icon" src={imgFG} width="20px" />}>
<small>{fg.title}</small>
@@ -133,7 +142,11 @@
{fg.classifier.map(mapClassifier.bind(null, context))}
<div className="footer-actions">
<div className="row-action-column">
- <Button className="create-new-classifier" src={imgAdd} width="20px" onClick={onClickAddClassifier.bind(null, context, fg)} label="Add Classifier" />
+ {
+ this.isRBACValid ?
+ <Button className="create-new-classifier" src={imgAdd} width="20px" onClick={onClickAddClassifier.bind(null, context, fg)} label="Add Classifier" />
+ : null
+ }
</div>
</div>
</div>
@@ -167,7 +180,11 @@
{forwardingGraphs}
<div className="footer-actions">
<div className="row-action-column">
- <Button className="create-new-forwarding-graph" src={imgAdd} width="20px" onClick={onClickAddForwardingGraph.bind(null, nsd)} label="Add new Forwarding Graph" />
+ {
+ this.isRBACValid ?
+ <Button className="create-new-forwarding-graph" src={imgAdd} width="20px" onClick={onClickAddForwardingGraph.bind(null, nsd)} label="Add new Forwarding Graph" />
+ : null
+ }
</div>
</div>
</div>
@@ -193,14 +210,16 @@
},
componentWillUnmount: function () {
},
+ contextTypes: {
+ userProfile: React.PropTypes.object
+ },
render() {
-
const containers = this.props.containers;
const context = {
component: this,
- containers: containers
+ containers: containers,
+ isRBACValid: isRBACValid(this.context.userProfile, [PROJECT_ROLES.CAT_ADMIN])
};
-
const networkService = containers.filter(d => d.type === 'nsd');
if (networkService.length === 0) {
return <p className="welcome-message">No <img src={imgNSD} width="20px" /> NSD open in the canvas. Try opening an NSD.</p>;
diff --git a/skyquake/plugins/project_management/config.json b/skyquake/plugins/project_management/config.json
index 642fb90..34537c6 100644
--- a/skyquake/plugins/project_management/config.json
+++ b/skyquake/plugins/project_management/config.json
@@ -5,6 +5,7 @@
"order": 1,
"priority":2,
"admin_link": true,
+ "allow": ["rw-rbac-platform:super-admin", "rw-rbac-platform:platform-admin", "rw-rbac-platform:platform-oper", "rw-project:project-admin", "rw-project:project-oper"],
"routes": [
{
"label": "Project Management Dashboard",
diff --git a/skyquake/plugins/user_management/src/dashboard/dashboard.jsx b/skyquake/plugins/user_management/src/dashboard/dashboard.jsx
index 09e5c6b..2494df0 100644
--- a/skyquake/plugins/user_management/src/dashboard/dashboard.jsx
+++ b/skyquake/plugins/user_management/src/dashboard/dashboard.jsx
@@ -267,14 +267,12 @@
hasCloseButton={this.closePanel}
no-corners>
<FormSection title="USER INFO">
- {
- this.state.isEdit ?
- null
- : <Input readonly={state.isReadOnly} label="Username" value={state['user-name']} onChange={this.updateInput.bind(null, 'user-name')} />
- }
+ {
+ this.state.isEdit ?
+ null
+ : <Input readonly={state.isReadOnly} label="Username" value={state['user-name']} onChange={this.updateInput.bind(null, 'user-name')} />
+ }
<Input readonly={true} label="Domain" value={state['user-domain']} onChange={this.updateInput.bind(null, 'user-domain')}></Input>
-
- <Input type="radiogroup" readonly={state.isReadOnly} label="Disabled" value={state.disabled} options={[{value: true, label: 'YES'}, {value: false, label: 'NO'}]} onChange={this.disableChange} />
</FormSection>
<FormSection title="PLATFORM ROLES" style={{display:'none'}}>
<Input label="Super Admin" onChange={this.platformChange.bind(null, 'super_admin')} checked={state.platformRoles.super_admin} type="checkbox" />
diff --git a/skyquake/plugins/user_management/src/platformRoleManagement/platformRoleManagement.jsx b/skyquake/plugins/user_management/src/platformRoleManagement/platformRoleManagement.jsx
index 761ce0d..de5064b 100644
--- a/skyquake/plugins/user_management/src/platformRoleManagement/platformRoleManagement.jsx
+++ b/skyquake/plugins/user_management/src/platformRoleManagement/platformRoleManagement.jsx
@@ -94,7 +94,7 @@
this.Store.updatePlatform({
- 'user': platformUsers
+ 'user': JSON.stringify(platformUsers)
}
);
}
diff --git a/skyquake/plugins/user_management/src/platformRoleManagement/platformRoleManagementSource.js b/skyquake/plugins/user_management/src/platformRoleManagement/platformRoleManagementSource.js
index 2e1f3c0..724312e 100644
--- a/skyquake/plugins/user_management/src/platformRoleManagement/platformRoleManagementSource.js
+++ b/skyquake/plugins/user_management/src/platformRoleManagement/platformRoleManagementSource.js
@@ -80,6 +80,7 @@
url: `/platform?api_server=${API_SERVER}`,
type: 'PUT',
data: project,
+ dataType: 'json',
beforeSend: Utils.addAuthorizationStub,
success: function(data, textStatus, jqXHR) {
resolve(data);
diff --git a/skyquake/plugins/user_management/src/platformRoleManagement/platformRoleManagementStore.js b/skyquake/plugins/user_management/src/platformRoleManagement/platformRoleManagementStore.js
index 326f13a..ef03b9d 100644
--- a/skyquake/plugins/user_management/src/platformRoleManagement/platformRoleManagementStore.js
+++ b/skyquake/plugins/user_management/src/platformRoleManagement/platformRoleManagementStore.js
@@ -173,7 +173,7 @@
})
} else {
let role = platformUsers[userIndex].role;
- platformUsers[userIndex].role.splice(roleIndex, 1)
+ platformUsers[userIndex].role.splice(_.findIndex(role, function(r) { return r.role == selectedRole; }), 1)
}
self.setState({platformUsers});