Merge "RIFT-16181: Project switch must affect non-polling/non-socket based pages...
authorKIRAN KASHALKAR <kiran.kashalkar@riftio.com>
Thu, 13 Apr 2017 00:53:14 +0000 (02:53 +0200)
committerGerrit Code Review <root@osm.etsi.org>
Thu, 13 Apr 2017 00:53:14 +0000 (02:53 +0200)
17 files changed:
skyquake/framework/core/modules/api/projectManagementAPI.js
skyquake/framework/core/modules/routes/navigation.js
skyquake/framework/utils/utils.js
skyquake/framework/widgets/skyquake_nav/skyquakeNav.jsx
skyquake/framework/widgets/skyquake_rbac/skyquakeRBAC.jsx
skyquake/plugins/composer/src/src/components/Button.js
skyquake/plugins/composer/src/src/components/CatalogItemDetailsEditor.js
skyquake/plugins/composer/src/src/components/CatalogPanelToolbar.js
skyquake/plugins/composer/src/src/components/ComposerApp.js
skyquake/plugins/composer/src/src/components/DetailsPanel.js
skyquake/plugins/composer/src/src/components/EditDescriptorModelProperties.js
skyquake/plugins/composer/src/src/components/EditorForwardingGraph/EditForwardingGraphPaths.js
skyquake/plugins/project_management/config.json
skyquake/plugins/user_management/src/dashboard/dashboard.jsx
skyquake/plugins/user_management/src/platformRoleManagement/platformRoleManagement.jsx
skyquake/plugins/user_management/src/platformRoleManagement/platformRoleManagementSource.js
skyquake/plugins/user_management/src/platformRoleManagement/platformRoleManagementStore.js

index 07e873d..c00de32 100644 (file)
@@ -228,6 +228,7 @@ ProjectManagement.updatePlatform = function(req) {
     var api_server = req.query['api_server'];
     var bodyData = req.body;
     data = bodyData;
+    data.user = JSON.parse(data.user)
     var updateTasks = [];
 
     var updateUser = rp({
index bf9c47b..16ff25a 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * 
+ *
  *   Copyright 2016 RIFT.IO Inc
  *
  *   Licensed under the Apache License, Version 2.0 (the "License");
index be3278d..16037d7 100644 (file)
@@ -26,6 +26,7 @@ var SockJS = require('sockjs-client');
 var Utils = {};
 
 Utils.DescriptorModelMeta = null;
+// Utils.DescriptorModelMeta = require('./../../plugins/composer/src/src/libraries/model/DescriptorModelMeta.json');
 
 var INACTIVITY_TIMEOUT = 600000;
 
index 1aaaf4d..f9161cc 100644 (file)
@@ -25,7 +25,7 @@ import 'style/common.scss';
 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 @@ export default class skyquakeNav extends React.Component {
 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 @@ export function buildNav(nav, currentPlugin, props) {
     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 @@ export function buildNav(nav, currentPlugin, props) {
                 label: nav[k].label || k,
                 route: route
             });
+            let shouldAllow = nav[k].allow || ['*'];
             if (nav[k].pluginName == currentPlugin) {
                 navClass += " active";
             }
@@ -312,22 +317,27 @@ export function buildNav(nav, currentPlugin, props) {
             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)
             }
 
index cbb6a56..0245e23 100644 (file)
@@ -21,6 +21,25 @@ import React from 'react';
 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 @@ export default class SkyquakeRBAC extends React.Component {
       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>)
     }
index 76a569f..6ef41bf 100644 (file)
@@ -40,6 +40,7 @@ const Button = React.createClass({
                        label: null,
                        title: null,
                        src: null,
+                       disabled: false,
                        onClick: () => {}
                };
        },
@@ -58,7 +59,7 @@ const Button = React.createClass({
                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>
index 752d678..fe47521 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * 
+ *
  *   Copyright 2016 RIFT.IO Inc
  *
  *   Licensed under the Apache License, Version 2.0 (the "License");
 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 @@ const CatalogItemDetailsEditor = React.createClass({
                        width: 0
                };
        },
+       contextTypes: {
+           router: React.PropTypes.object,
+           userProfile: React.PropTypes.object
+       },
        componentWillMount() {
        },
        componentDidMount() {
@@ -41,6 +49,7 @@ const CatalogItemDetailsEditor = React.createClass({
        componentWillUnmount() {
        },
        render() {
+       const User = this.context.userProfile;
 
                const container = this.props.container || {model: {}, uiState: {}};
                if (!(container && container.model && container.uiState)) {
@@ -51,7 +60,11 @@ const CatalogItemDetailsEditor = React.createClass({
                        <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 @@ const CatalogItemDetailsEditor = React.createClass({
        }
 });
 
+CatalogItemDetailsEditor.contextTypes = {
+    router: React.PropTypes.object,
+    userProfile: React.PropTypes.object
+};
 export default CatalogItemDetailsEditor;
index 5e3e3c0..896badd 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * 
+ *
  *   Copyright 2016 RIFT.IO Inc
  *
  *   Licensed under the Apache License, Version 2.0 (the "License");
@@ -32,6 +32,10 @@ import imgOnboard from '../../../node_modules/open-iconic/svg/cloud-upload.svg'
 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 @@ const CatalogHeader = React.createClass({
        },
        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>
index 861c38b..fd3fc94 100644 (file)
@@ -48,6 +48,9 @@ import TooltipManager from '../libraries/TooltipManager'
 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 clearLocalStorage = utils.getSearchParams(window.location).hasOwnProperty(
 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 @@ const ComposerApp = React.createClass({
        getDefaultProps() {
                return {};
        },
+       contextTypes: {
+           router: React.PropTypes.object,
+           userProfile: React.PropTypes.object
+       },
        componentWillMount() {
                if (clearLocalStorage) {
                        window.localStorage.clear();
@@ -147,6 +156,7 @@ const ComposerApp = React.createClass({
        render() {
                let html = null;
                let self = this;
+               const User = this.context.userProfile || {};
                if(this.state.hasModel) {
 
                        function onClickUpdateSelection(event) {
@@ -225,7 +235,7 @@ const ComposerApp = React.createClass({
                                                                                                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 @@ const ComposerApp = React.createClass({
 
 });
 
+
 export default ComposerApp;
index a20679f..7af2ad1 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * 
+ *
  *   Copyright 2016 RIFT.IO Inc
  *
  *   Licensed under the Apache License, Version 2.0 (the "License");
@@ -73,4 +73,9 @@ const DetailsPanel = React.createClass({
        }
 });
 
+DetailsPanel.contextTypes = {
+    router: React.PropTypes.object,
+    userProfile: React.PropTypes.object
+};
+
 export default DetailsPanel;
index 589eef9..e75f3cd 100644 (file)
@@ -74,7 +74,7 @@ function getTitle(model = {}) {
 export default function EditDescriptorModelProperties(props) {
 
        const container = props.container;
-
+       const readonly = props.readonly;
        if (!(DescriptorModelFactory.isContainer(container))) {
                return
        }
@@ -141,6 +141,9 @@ export default function EditDescriptorModelProperties(props) {
                        }
                        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 @@ export default function EditDescriptorModelProperties(props) {
                        }
                        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 @@ export default function EditDescriptorModelProperties(props) {
                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 @@ export default function EditDescriptorModelProperties(props) {
                                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 @@ export default function EditDescriptorModelProperties(props) {
                                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 @@ export default function EditDescriptorModelProperties(props) {
                                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 @@ export default function EditDescriptorModelProperties(props) {
 
                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}
index 0f39d30..ba1e0cc 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * 
+ *
  *   Copyright 2016 RIFT.IO Inc
  *
  *   Licensed under the Apache License, Version 2.0 (the "License");
@@ -45,6 +45,11 @@ import mapRecordServicePath from './mapRecordServicePath'
 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 @@ function mapFG(fg, i) {
                <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 @@ function mapFG(fg, i) {
                                {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 @@ function mapNSD(nsd, i) {
                        {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 @@ const EditForwardingGraphPaths = React.createClass({
        },
        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>;
index 642fb90..34537c6 100644 (file)
@@ -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",
index 09e5c6b..2494df0 100644 (file)
@@ -267,14 +267,12 @@ class UserManagementDashboard extends React.Component {
                             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" />
index 761ce0d..de5064b 100644 (file)
@@ -94,7 +94,7 @@ class PlatformRoleManagement extends React.Component {
 
 
         this.Store.updatePlatform({
-                'user': platformUsers
+                'user': JSON.stringify(platformUsers)
             }
         );
     }
index 2e1f3c0..724312e 100644 (file)
@@ -80,6 +80,7 @@ module.exports = function(Alt) {
                   url: `/platform?api_server=${API_SERVER}`,
                   type: 'PUT',
                   data: project,
+                  dataType: 'json',
                   beforeSend: Utils.addAuthorizationStub,
                   success: function(data, textStatus, jqXHR) {
                     resolve(data);
index 326f13a..ef03b9d 100644 (file)
@@ -173,7 +173,7 @@ export default class PlatformRoleManagementStore {
             })
         } 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});