RBAC React Component, displays/hides components based on role

Signed-off-by: Laurence Maultsby <laurence.maultsby@riftio.com>
diff --git a/skyquake/framework/core/modules/api/projectManagementAPI.js b/skyquake/framework/core/modules/api/projectManagementAPI.js
index 3238aec..07e873d 100644
--- a/skyquake/framework/core/modules/api/projectManagementAPI.js
+++ b/skyquake/framework/core/modules/api/projectManagementAPI.js
@@ -178,14 +178,18 @@
 }
 
 
-ProjectManagement.getPlatform = function(req) {
+ProjectManagement.getPlatform = function(req, userId) {
     var self = this;
     var api_server = req.query['api_server'];
-
+    var user = req.params['userId'] || userId;
     return new Promise(function(resolve, reject) {
+        var url = utils.confdPort(api_server) + '/api/operational/rbac-platform-config';
+        if(user) {
+            url = url + '/user/' + user;
+        }
         Promise.all([
             rp({
-                uri: utils.confdPort(api_server) + '/api/operational/rbac-platform-config',
+                uri: url,
                 method: 'GET',
                 headers: _.extend({}, constants.HTTP_HEADERS.accept.data, {
                     'Authorization': req.session && req.session.authorization
@@ -198,7 +202,11 @@
             var response = {};
             response['data'] = {};
             if (result[0].body) {
-                response['data']['platform'] = JSON.parse(result[0].body)['rw-rbac-platform:rbac-platform-config'];
+                if(user) {
+                    response['data']['platform'] = JSON.parse(result[0].body)['rw-rbac-platform:user'];
+                } else {
+                    response['data']['platform'] = JSON.parse(result[0].body)['rw-rbac-platform:rbac-platform-config'];
+                }
             }
             response.statusCode = constants.HTTP_RESPONSE_CODES.SUCCESS.OK
 
diff --git a/skyquake/framework/core/modules/api/userManagementAPI.js b/skyquake/framework/core/modules/api/userManagementAPI.js
index 0608c5d..873ab19 100644
--- a/skyquake/framework/core/modules/api/userManagementAPI.js
+++ b/skyquake/framework/core/modules/api/userManagementAPI.js
@@ -25,6 +25,7 @@
 var constants = require('../../api_utils/constants');
 var utils = require('../../api_utils/utils');
 var _ = require('lodash');
+var ProjectManagementAPI = require('./projectManagementAPI.js');
 
 UserManagement.get = function(req) {
     var self = this;
@@ -63,20 +64,96 @@
     });
 };
 
+
 UserManagement.getProfile = function(req) {
     var self = this;
     var api_server = req.query['api_server'];
     return new Promise(function(resolve, reject) {
         var response = {};
-            response['data'] = {
-            userId: req.session.userdata.username,
+        var userId = req.session.userdata.username
+        response['data'] = {
+            userId: userId,
             projectId: req.session.projectId
         };
-        response.statusCode = constants.HTTP_RESPONSE_CODES.SUCCESS.OK
+        UserManagement.getUserInfo(req, userId).then(function(result) {
+            response.statusCode = constants.HTTP_RESPONSE_CODES.SUCCESS.OK;
+            response.data.data =result.data
+            resolve(response);
+        }, function(error) {
+            console.log('Error retrieving getUserInfo');
+            response.statusCode = constants.HTTP_RESPONSE_CODES.ERROR.INTERNAL_SERVER_ERROR;
+            reject(response);
+        })
 
-        resolve(response);
     });
 };
+UserManagement.getUserInfo = function(req, userId, domain) {
+    var self = this;
+    var api_server = req.query['api_server'];
+    var id = req.params['userId'] || userId;
+    var domain = req.params['domainId'] || domain;
+    var response = {};
+    return new Promise(function(resolve, reject) {
+        if (id) {
+            var getProjects = ProjectManagementAPI.get(req)
+            var getPlatformUser = ProjectManagementAPI.getPlatform(req, id)
+            Promise.all([
+                getProjects,
+                getPlatformUser
+            ]).then(function(result) {
+                var userData = {
+                    platform: {
+                        role: {
+
+                        }
+                    },
+                    project: {
+                        /**
+                         *  [projectId] : {
+                         *      data: [project object],
+                         *      role: {
+                         *          [roleId]: true
+                         *      }
+                         *  }
+                         */
+                    }
+                }
+                //Build project roles
+                var projects = result[0].data.project;
+                var userProjects = [];
+                projects && projects.map(function(p, i) {
+                    var users = p['project-config'] && p['project-config'].user;
+                    users && users.map(function(u) {
+                        if(u['user-name'] == id) {
+                            userData.project[p.name] = {
+                                data: p,
+                                role: {}
+                            }
+                            u.role.map(function(r) {
+                                userData.project[p.name].role[r.role] = true
+                            });
+                        }
+                    })
+                });
+                //Build platform roles
+                var platformRoles = result[1].data.platform && result[1].data.platform.role;
+                platformRoles && platformRoles.map(function(r) {
+                    userData.platform.role[r.role] = true
+                });
+                response.data = userData;
+                response.statusCode = constants.HTTP_RESPONSE_CODES.SUCCESS.OK
+                resolve(response);
+            })
+        } else {
+            var errorMsg = 'userId not specified in UserManagement.getUserInfo';
+            console.error(errorMsg);
+            response.statusCode = constants.HTTP_RESPONSE_CODES.ERROR.BAD_REQUEST;
+            response.error = errorMsg;
+            reject(response)
+        }
+
+    })
+}
 UserManagement.create = function(req) {
     var self = this;
     var api_server = req.query['api_server'];
diff --git a/skyquake/framework/core/modules/navigation_manager.js b/skyquake/framework/core/modules/navigation_manager.js
index 6ed1e49..f690359 100644
--- a/skyquake/framework/core/modules/navigation_manager.js
+++ b/skyquake/framework/core/modules/navigation_manager.js
@@ -68,6 +68,13 @@
 	NAVIGATION[plugin_name].label = label || 'RW.UI Plugin';
 }
 
+function addAllow(plugin_name, allow) {
+	if (!NAVIGATION[plugin_name]) {
+		NAVIGATION[plugin_name] = {};
+	}
+	NAVIGATION[plugin_name].allow = allow || '*';
+}
+
 function getNavigation() {
 	return NAVIGATION;
 }
@@ -81,6 +88,7 @@
 	addOrder(plugin_name, plugin.order);
 	addPriority(plugin_name, plugin.priority);
 	addLabel(plugin_name, plugin.name);
+	addAllow(plugin_name, plugin.allow);
 }
 
 function init() {
diff --git a/skyquake/framework/core/modules/routes/projectManagement.js b/skyquake/framework/core/modules/routes/projectManagement.js
index ef52ba3..c106f30 100644
--- a/skyquake/framework/core/modules/routes/projectManagement.js
+++ b/skyquake/framework/core/modules/routes/projectManagement.js
@@ -1,4 +1,3 @@
-
 /*
  *
  *   Copyright 2016 RIFT.IO Inc
diff --git a/skyquake/framework/core/modules/routes/userManagement.js b/skyquake/framework/core/modules/routes/userManagement.js
index 4e272d0..22a2d74 100644
--- a/skyquake/framework/core/modules/routes/userManagement.js
+++ b/skyquake/framework/core/modules/routes/userManagement.js
@@ -50,6 +50,13 @@
         utils.sendErrorResponse(error, res);
     });
 });
+Router.get('/user-data/:userId/:domain?', cors(), function(req, res) {
+    UserManagementAPI.getUserInfo(req).then(function(response) {
+        utils.sendSuccessResponse(response, res);
+    }, function(error) {
+        utils.sendErrorResponse(error, res);
+    });
+});
 Router.post('/user', cors(), function(req, res) {
     UserManagementAPI.create(req).then(function(response) {
         utils.sendSuccessResponse(response, res);
diff --git a/skyquake/framework/utils/roleConstants.js b/skyquake/framework/utils/roleConstants.js
new file mode 100644
index 0000000..95e36fc
--- /dev/null
+++ b/skyquake/framework/utils/roleConstants.js
@@ -0,0 +1,16 @@
+var c = {};
+
+c.PLATFORM = {
+  OPER: "rw-rbac-platform:platform-oper",
+  ADMIN: "rw-rbac-platform:platform-admin",
+  SUPER: "rw-rbac-platform:super-admin"
+}
+
+c.PROJECT = {
+    MANO_OPER: "rw-project-mano:mano-oper",
+    MANO_ADMIN: "rw-project-mano:mano-admin",
+    PROJECT_ADMIN: "rw-project:project-admin",
+    PROJECT_OPER: "rw-project:project-oper",
+}
+
+module.exports = c;
diff --git a/skyquake/framework/widgets/skyquake_nav/skyquakeNav.jsx b/skyquake/framework/widgets/skyquake_nav/skyquakeNav.jsx
index 51a21a0..a752bf6 100644
--- a/skyquake/framework/widgets/skyquake_nav/skyquakeNav.jsx
+++ b/skyquake/framework/widgets/skyquake_nav/skyquakeNav.jsx
@@ -25,6 +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';
 
 //Temporary, until api server is on same port as webserver
 var rw = require('utils/rw.js');
@@ -298,14 +299,14 @@
             navItem.priority = nav[k].priority;
             navItem.order = nav[k].order;
             navItem.html = (
-                <div key={k} className={navClass}>
+                <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>
-                </div>
+                </SkyquakeRBAC>
             );
             navList.push(navItem)
         }
diff --git a/skyquake/framework/widgets/skyquake_rbac/skyquakeRBAC.jsx b/skyquake/framework/widgets/skyquake_rbac/skyquakeRBAC.jsx
new file mode 100644
index 0000000..e00e672
--- /dev/null
+++ b/skyquake/framework/widgets/skyquake_rbac/skyquakeRBAC.jsx
@@ -0,0 +1,108 @@
+/*
+ *
+ *   Copyright 2016 RIFT.IO Inc
+ *
+ *   Licensed under the Apache License, Version 2.0 (the "License");
+ *   you may not use this file except in compliance with the License.
+ *   You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing, software
+ *   distributed under the License is distributed on an "AS IS" BASIS,
+ *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *   See the License for the specific language governing permissions and
+ *   limitations under the License.
+ *
+ */
+
+
+import React from 'react';
+import ROLES from 'utils/roleConstants.js';
+const PLATFORM = ROLES.PLATFORM;
+
+export default class SkyquakeRBAC extends React.Component {
+    constructor(props, context) {
+        super(props);
+    }
+    render() {
+      const User = this.context.userProfile.data;
+      let HTML = null;
+      // If user object has platform property then it has been populated by the back end.
+      if(User) {
+        const PlatformRole = User.platform.role;
+        const isPlatformSuper = PlatformRole[PLATFORM.SUPER];
+        const isPlatformAdmin = PlatformRole[PLATFORM.ADMIN];
+        const isPlatformOper = PlatformRole[PLATFORM.OPER];
+        const hasRoleAccess =  checkForRoleAccess(User.project[this.props.project], 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;
+          }
+        }
+      }
+      return (<div className={this.props.className} style={this.props.style}>{HTML}</div>)
+    }
+}
+SkyquakeRBAC.defaultProps = {
+  allow: []
+}
+SkyquakeRBAC.contextTypes = {
+  userProfile: React.PropTypes.object
+}
+
+function checkForRoleAccess(project, PlatformRole, allow) {
+    if (allow.indexOf('*') > -1) return true;
+    for (let i = 0; i<allow.length; i++) {
+      if((project && project.role[allow[i]] )|| PlatformRole[allow[i]]) {
+        return true
+      }
+    }
+    return false;
+  }
+
+
+
+// export default function(Component) {
+//   class SkyquakeRBAC extends React.Component {
+//     constructor(props, context) {
+//         super(props);
+//             }
+//     render(props) {
+//       console.log(this.context.userProfile)
+//       const User = this.context.userProfile.data;
+//       // If user object has platform property then it has been populated by the back end.
+//       if(User) {
+//         const PlatformRole = User.platform.role;
+//         const HTML = <Component {...this.props} router={this.router} actions={this.actions} flux={this.context.flux}/>;
+//         const isPlatformSuper = PlatformRole[PLATFORM.SUPER];
+//         const isPlatformAdmin = PlatformRole[PLATFORM.ADMIN];
+//         const isPlatformOper = PlatformRole[PLATFORM.OPER];
+//         const hasRoleAccess =  false//(this.props.roles.indexOf(userProfile.projectRole) > -1)
+//         if (isPlatformSuper || isPlatformOper || isPlatformAdmin) {
+//           return HTML
+//         } else {
+//           if (hasRoleAccess) {
+//             return HTML
+//           } else {
+//             return null;
+//           }
+//         }
+//       }
+//       else {
+//         return null;
+
+//       }
+//     }
+//   }
+//   SkyquakeRBAC.defaultProps = {
+
+//   }
+//   SkyquakeRBAC.contextTypes = {
+//     userProfile: React.PropTypes.object,
+//     allowedRoles: []
+//   };
+//   return SkyquakeRBAC;
+// }