From 5f366ac9f602c24f1dc9963253f692f2ffcc54a8 Mon Sep 17 00:00:00 2001 From: Rohan Vazarkar Date: Thu, 5 Oct 2017 04:35:04 -0400 Subject: [PATCH] Add new properties to user/computer --- package.json | 4 +- .../SearchContainer/Tabs/ComputerNodeData.jsx | 51 ++++++----- .../SearchContainer/Tabs/NodePropItem.jsx | 51 +++++++++++ .../SearchContainer/Tabs/UserNodeData.jsx | 88 +++++++++++++------ src/css/styles.css | 9 +- src/js/utils.js | 2 +- 6 files changed, 153 insertions(+), 52 deletions(-) create mode 100644 src/components/SearchContainer/Tabs/NodePropItem.jsx diff --git a/package.json b/package.json index 48d99210f..74cd2fc32 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,7 @@ }, "babel": { "presets": [ - "es2015", + "env", "stage-0", "react" ] @@ -38,7 +38,7 @@ "babel-core": "^6.22.1", "babel-loader": "^7.0.0", "babel-polyfill": "^6.22.0", - "babel-preset-es2015": "^6.22.0", + "babel-preset-env": "^1.6.0", "babel-preset-react": "^6.22.0", "babel-preset-stage-0": "^6.22.0", "concurrently": "^3.1.0", diff --git a/src/components/SearchContainer/Tabs/ComputerNodeData.jsx b/src/components/SearchContainer/Tabs/ComputerNodeData.jsx index 23100d330..20d634f8d 100644 --- a/src/components/SearchContainer/Tabs/ComputerNodeData.jsx +++ b/src/components/SearchContainer/Tabs/ComputerNodeData.jsx @@ -8,8 +8,6 @@ export default class ComputerNodeData extends Component { this.state = { label: "", - os: "None", - unconstrained: "None", explicitAdmins: -1, unrolledAdmins: -1, firstDegreeGroupMembership: -1, @@ -22,7 +20,8 @@ export default class ComputerNodeData extends Component { groupDelegatedControl: -1, transitiveControl: -1, derivativeLocalAdmins: -1, - driversessions: [] + driversessions: [], + propertyMap: {} }; emitter.on('computerNodeClicked', this.getNodeData.bind(this)); @@ -34,8 +33,6 @@ export default class ComputerNodeData extends Component { }); this.setState({ label: payload, - os: "None", - unconstrained: "None", explicitAdmins: -1, unrolledAdmins: -1, firstDegreeGroupMembership: -1, @@ -47,7 +44,8 @@ export default class ComputerNodeData extends Component { firstdegreeControl: -1, groupDelegatedControl: -1, transitiveControl: -1, - derivativeLocalAdmins: -1 + derivativeLocalAdmins: -1, + propertyMap: {} }); var s1 = driver.session(); @@ -66,14 +64,9 @@ export default class ComputerNodeData extends Component { var propCollection = driver.session(); propCollection.run("MATCH (c:Computer {name:{name}}) RETURN c", {name:payload}) - .then(function(results){ - var props = results.records[0]._fields[0].properties; - if (props.hasOwnProperty('UnconstrainedDelegation')){ - this.setState({'unconstrained': props.UnconstrainedDelegation.toString().toTitleCase()}); - } - if (props.hasOwnProperty('OperatingSystem')){ - this.setState({'os': props.OperatingSystem}); - } + .then(function(result){ + var properties = result.records[0]._fields[0].properties; + this.setState({propertyMap: properties}); propCollection.close(); }.bind(this)); @@ -158,6 +151,22 @@ export default class ComputerNodeData extends Component { this.setState({'driversessions': [s1,s2,s3,s4,s5,s6,s7,s8,s9,s10,s11,s12,s13,propCollection]}); } + convertToDisplayProp(propName){ + var obj = this.state.propertyMap[propName]; + var type = typeof obj; + if (type === 'undefined'){ + return "No Data"; + }else if (obj.hasOwnProperty('low')){ + return new Date(obj.low * 1000).toUTCString(); + }else if (type === 'boolean'){ + return obj.toString().toTitleCase(); + }else if (obj === ""){ + return "None"; + }else{ + return obj; + } + } + render() { return (
@@ -173,13 +182,19 @@ export default class ComputerNodeData extends Component { OS
- {this.state.os} + {this.convertToDisplayProp("OperatingSystem")} +
+
+ Enabled +
+
+ {this.convertToDisplayProp("Enabled")}
Allows Unconstrained Delegation
- {this.state.unconstrained} + {this.convertToDisplayProp("UnconstrainedDelegation")}
Sessions @@ -194,7 +209,6 @@ export default class ComputerNodeData extends Component { }.bind(this)} /> -

Local Admins

Explicit Admins @@ -237,7 +251,6 @@ export default class ComputerNodeData extends Component { }.bind(this)} /> -

Group Memberships

First Degree Group Membership @@ -278,7 +291,6 @@ export default class ComputerNodeData extends Component { }.bind(this)} /> -

Local Admin Rights

First Degree Local Admin @@ -319,7 +331,6 @@ export default class ComputerNodeData extends Component { }.bind(this)} /> -

Outbound Object Control

First Degree Object Control diff --git a/src/components/SearchContainer/Tabs/NodePropItem.jsx b/src/components/SearchContainer/Tabs/NodePropItem.jsx new file mode 100644 index 000000000..031f0f6c7 --- /dev/null +++ b/src/components/SearchContainer/Tabs/NodePropItem.jsx @@ -0,0 +1,51 @@ +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; + +export default class NodePropItem extends Component{ + constructor(props){ + super(props); + } + + isArray(object){ + return object && typeof object === 'object' && object.constructor === Array; + } + + render() { + var val; + var obj = this.props.keyValue; + if (obj.hasOwnProperty('low')){ + return [ +
{this.props.keyName}
, +
{obj.low}
+ ]; + }else if (this.isArray(obj)){ + console.log(obj); + if (obj.length === 0){ + return [ +
{this.props.keyName}
, +
None
+ ]; + }else{ + var elements = []; + $.each(obj, function(index, prop){ + elements.push(
); + elements.push(
{prop}
); + }); + elements[0] =
Service Principal Names
; + } + + return elements; + }else if (typeof obj === 'boolean'){ + return [ +
{this.props.keyName}
, +
{this.props.keyValue.toString().toTitleCase()}
+ ]; + }else{ + return [ +
{this.props.keyName}
, +
{this.props.keyValue.toString()}
+ ]; + } + + } +} \ No newline at end of file diff --git a/src/components/SearchContainer/Tabs/UserNodeData.jsx b/src/components/SearchContainer/Tabs/UserNodeData.jsx index 5f73527ac..73f471840 100644 --- a/src/components/SearchContainer/Tabs/UserNodeData.jsx +++ b/src/components/SearchContainer/Tabs/UserNodeData.jsx @@ -1,15 +1,16 @@ import React, { Component } from 'react'; import NodeALink from './NodeALink'; +import NodePropItem from './NodePropItem'; import PropTypes from 'prop-types'; +import { If, Then, Else } from 'react-if'; + export default class UserNodeData extends Component { constructor(){ super(); this.state = { label: "", - displayName: "None", - pwdLastChanged: "None", firstDegreeGroupMembership: -1, unrolledGroupMembership: -1, foreignGroupMembership: -1, @@ -23,7 +24,8 @@ export default class UserNodeData extends Component { firstdegreeControl: -1, unrolledControl: -1, transitiveControl: -1, - driversessions : [] + driversessions : [], + propertyMap: {ServicePrincipalNames: []} }; emitter.on('userNodeClicked', this.getNodeData.bind(this)); @@ -36,8 +38,6 @@ export default class UserNodeData extends Component { this.setState({ label: payload, - displayName: "None", - pwdLastChanged: "None", firstDegreeGroupMembership: -1, unrolledGroupMembership: -1, foreignGroupMembership: -1, @@ -50,7 +50,8 @@ export default class UserNodeData extends Component { transitiveControllers: -1, firstdegreeControl: -1, unrolledControl: -1, - transitiveControl: -1 + transitiveControl: -1, + propertyMap: {ServicePrincipalNames: []} }); var domain = '@' + payload.split('@').last(); @@ -71,19 +72,8 @@ export default class UserNodeData extends Component { var props = driver.session(); props.run("MATCH (n:User {name:{name}}) RETURN n", {name: payload}) - .then(function(result){ - var properties = result.records[0]._fields[0].properties; - if (properties.hasOwnProperty('PwdLastSet')){ - this.setState({'pwdLastChanged': new Date(properties.PwdLastSet.low * 1000).toUTCString() }); - } - - if (properties.hasOwnProperty("DisplayName")){ - var dname = properties.DisplayName; - if (dname === ""){ - dname = "None"; - } - this.setState({'displayName': dname }); - } + .then(function(result){ + this.setState({propertyMap: properties}); props.close(); }.bind(this)); @@ -168,13 +158,33 @@ export default class UserNodeData extends Component { this.setState({'driversessions': [s1,s2,s3,s4,s5,s6,s7,s8,s9,s10,s11,s12,s13,props]}); } + isArray(object){ + return object && typeof object === 'object' && object.constructor === Array; + } + + convertToDisplayProp(propName){ + var obj = this.state.propertyMap[propName]; + var type = typeof obj; + if (type === 'undefined'){ + return "No Data"; + }else if (obj.hasOwnProperty('low')){ + return new Date(obj.low * 1000).toUTCString(); + }else if (type === 'boolean'){ + return obj.toString().toTitleCase(); + }else if (obj === ""){ + return "None"; + }else{ + return obj; + } + } + render() { var domain = '@' + this.state.label.split('@').last(); return (

- Node Info + User Info

Name @@ -186,14 +196,38 @@ export default class UserNodeData extends Component { Display Name
- {this.state.displayName} + {this.convertToDisplayProp("DisplayName")}
Password Last Changed
- {this.state.pwdLastChanged} + {this.convertToDisplayProp("PwdLastSet")} +
+
+ Last Logon +
+
+ {this.convertToDisplayProp("LastLogon")}
+
+ Enabled +
+
+ {this.convertToDisplayProp("Enabled")} +
+
+ Service Principal Names +
+ {(() => { + if (this.state.propertyMap.ServicePrincipalNames.length === 0){ + return
None
; + } + })()} + {Object.keys(this.state.propertyMap.ServicePrincipalNames).map(function(key){ + var x =
{this.state.propertyMap.ServicePrincipalNames[key]}
; + return x; + }.bind(this))}
Sessions
@@ -207,7 +241,7 @@ export default class UserNodeData extends Component { }.bind(this)} /> -
+

Group Membership

First Degree Group Memberships @@ -250,7 +284,7 @@ export default class UserNodeData extends Component { }.bind(this)} /> -
+

Local Admin Rights

@@ -292,7 +326,7 @@ export default class UserNodeData extends Component { }.bind(this)} /> -
+

Outbound Object Control

@@ -334,7 +368,7 @@ export default class UserNodeData extends Component { }.bind(this)} /> -
+

Inbound Object Control

Explicit Object Controllers @@ -382,5 +416,5 @@ export default class UserNodeData extends Component { } UserNodeData.propTypes = { - visible : React.PropTypes.bool.isRequired + visible : PropTypes.bool.isRequired }; \ No newline at end of file diff --git a/src/css/styles.css b/src/css/styles.css index 13de9a266..3cbe9cdc6 100644 --- a/src/css/styles.css +++ b/src/css/styles.css @@ -195,6 +195,12 @@ div.tooltip-inner-custom { margin-bottom: 1em; } +.dl-horizontal > h4 { + margin-top: 10px; + margin-bottom: 5px; + color: blue; +} + .dl-horizontal{ margin-right: 10px; } @@ -771,7 +777,6 @@ div.tooltip-inner-custom { } .tab-content > div:nth-last-child(2) > div{ - height: 600px; + max-height: 600px; overflow-y: auto; - resize: vertical; } \ No newline at end of file diff --git a/src/js/utils.js b/src/js/utils.js index 009533f76..4950e0c6e 100644 --- a/src/js/utils.js +++ b/src/js/utils.js @@ -164,7 +164,7 @@ export function buildSessionProps(rows) { if (row.UserName === 'ANONYMOUS LOGON@UNKNOWN' || row.UserName === '') { return; } - sessions.push({ account: row.UserName.toUpperCase(), computer: row.ComputerName.toUpperCase(), weight: parseInt(row.Weight) }); + sessions.push({ account: row.UserName.toUpperCase(), computer: row.ComputerName.toUpperCase(), weight: row.Weight }); }); return sessions;