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});