Skip to content

Commit

Permalink
Merge pull request #59 from adaptivethreat/BoltRework
Browse files Browse the repository at this point in the history
Bolt rework (BloodHound 1.1)
  • Loading branch information
rvazarkar authored Oct 11, 2016
2 parents 450f0c0 + f58427a commit e3f4cf8
Show file tree
Hide file tree
Showing 23 changed files with 982 additions and 1,231 deletions.
1 change: 1 addition & 0 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
<script src="node_modules/linkurious/dist/plugins.js" type="text/javascript"></script>
<script src="node_modules/dagre/dist/dagre.min.js" type="text/javascript"></script>
<script src="node_modules/bootstrap-3-typeahead/bootstrap3-typeahead.min.js" type="text/javascript"></script>
<script src="node_modules/neo4j-driver/lib/browser/neo4j-web.min.js" type="text/javascript"></script>
<script src="src/js/papaparse.min.js" type="text/javascript"></script>
<script src="src/js/simple-slider.min.js" type="text/javascript"></script>
<link type="text/css" rel="stylesheet" href="src/css/simple-slider.css">
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
"jquery": "^2.2.4",
"linkurious": "^1.5.1",
"mustache": "^2.2.1",
"neo4j-driver": "^1.0.4",
"react": "^15.3.1",
"react-addons-css-transition-group": "^15.3.1",
"react-bootstrap": "^0.30.3",
Expand Down
134 changes: 70 additions & 64 deletions src/components/Float/Login.jsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import React, { Component } from 'react';
import { defaultAjaxSettings } from 'utils';

export default class Login extends Component {
constructor(){
Expand All @@ -26,37 +25,41 @@ export default class Login extends Component {

jQuery(this.refs.urlspinner).toggle(true)

if (!url.startsWith('http://')){
url = 'http://' + url
url = url.replace(/\/$/, "");

if (!url.includes(':')){
url = url + ':7687'
}

url = url.replace(/\/$/, "");
if (!url.startsWith('bolt://')){
url = 'bolt://' + url
}

icon.removeClass();
icon.addClass("fa fa-spinner fa-spin form-control-feedback");
icon.toggle(true);

$.ajax({
url: url,
type: 'GET',
success: function(e){
if (e.data.endsWith('/db/data/')){
icon.removeClass();
icon.addClass("fa fa-check-circle green-icon-color form-control-feedback");
}else{
this.setState({dbHelpVisible: true})
icon.removeClass();
icon.addClass("fa fa-times-circle red-icon-color form-control-feedback");
var driver = neo4j.v1.driver(url)
var session = driver.session()

session.run('MATCH (n) RETURN (n) LIMIT 1')
.subscribe({
onNext: function(next){
},
onError: function(error){
if (error.code){
this.setState({dbHelpVisible: true})
icon.removeClass();
icon.addClass("fa fa-times-circle red-icon-color form-control-feedback");
}else{
icon.removeClass();
icon.addClass("fa fa-check-circle green-icon-color form-control-feedback");
this.setState({loginEnabled: true, url: url})
}
}.bind(this),
onComplete: function(){
session.close()
}

this.setState({loginEnabled: true, url: url})
}.bind(this),
error: function(e){
icon.removeClass();
icon.addClass("fa fa-times-circle red-icon-color form-control-feedback");
this.setState({loginEnabled: false, dbHelpVisible: true})
}.bind(this)
})
})
}

checkDBCreds(){
Expand All @@ -69,47 +72,50 @@ export default class Login extends Component {
loginEnabled: false
})

var header = "Basic " + btoa(this.state.user + ":" + this.state.password)
var btn = jQuery(this.refs.loginButton)

var driver = neo4j.v1.driver(this.state.url, neo4j.v1.auth.basic(this.state.user, this.state.password),{knownHosts: 'known_hosts'})
var session = driver.session()
session.run('MATCH (n) RETURN (n) LIMIT 1')
.subscribe({
onError: function(error){
btn.toggleClass('activate');
this.setState({
loginHelpVisible: true,
loginInProgress: false,
loginEnabled: true
})

}.bind(this),
onNext: function(){

},
onCompleted: function(){
btn.toggleClass('activate');
btn.removeClass('btn-default')
btn.addClass('btn-success')
btn.html('Success!')
this.setState({
loginInProgress: false
})
conf.set('databaseInfo',{
url: this.state.url,
user: this.state.user,
password: this.state.password
})
global.driver = driver
appStore.databaseInfo = conf.get('databaseInfo');
setTimeout(function(){
jQuery(this.refs.outer).fadeOut(400, function(){
renderEmit.emit('login');
});
}.bind(this), 1500)
session.close()
}.bind(this)
})

btn.toggleClass('activate');

$.ajax({
url: this.state.url + '/db/data/',
type: 'GET',
headers: {
Authorization: header
},
success: function(e){
btn.toggleClass('activate');
btn.removeClass('btn-default')
btn.addClass('btn-success')
btn.html('Success!')
this.setState({
loginInProgress: false
})
conf.set('databaseInfo',{
url: this.state.url,
user: this.state.user,
password: this.state.password
})

appStore.databaseInfo = conf.get('databaseInfo');
setTimeout(function(){
jQuery(this.refs.outer).fadeOut(400, function(){
renderEmit.emit('login');
});
}.bind(this), 1500)
}.bind(this),
error: function(e){
btn.toggleClass('activate');
this.setState({
loginHelpVisible: true,
loginInProgress: false,
loginEnabled: true
})
}.bind(this)
})
}

componentWillMount() {
Expand Down Expand Up @@ -165,10 +171,10 @@ export default class Login extends Component {
<span className="input-group-addon" id="dburladdon">
Database URL
</span>
<input ref="url" onFocus={function(){this.setState({dbHelpVisible: false})}.bind(this)} onBlur={this.checkDBPresence.bind(this)} onChange={this._urlChanged.bind(this)} type="text" className="form-control" value={this.state.url} placeholder="http://db-ip:dp-port" aria-describedby="dburladdon" />
<input ref="url" onFocus={function(){this.setState({dbHelpVisible: false})}.bind(this)} onBlur={this.checkDBPresence.bind(this)} onChange={this._urlChanged.bind(this)} type="text" className="form-control" value={this.state.url} placeholder="bolt://localhost:7687" aria-describedby="dburladdon" />
<i ref="urlspinner" className="fa fa-spinner fa-spin form-control-feedback" />
</div>
{this.state.dbHelpVisible ? <p className="help-block help-block-add">No Neo4j REST API Found</p> : null}
{this.state.dbHelpVisible ? <p className="help-block help-block-add">No Neo4j Database Found</p> : null}
<div className="input-group spacing">
<span className="input-group-addon" id="dbuseraddon">DB Username</span>
<input ref="user" type="text" value={this.state.user} onKeyUp={this._triggerLogin.bind(this)} onChange={this._userChanged.bind(this)} className="form-control" placeholder="neo4j" aria-describedby="dbuseraddon" />
Expand Down
39 changes: 29 additions & 10 deletions src/components/Float/QueryNodeSelect.jsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import React, { Component } from 'react';
import { ListGroup, ListGroupItem, Panel } from 'react-bootstrap'
import { fullAjax } from 'utils'
import { If, Then, Else } from 'react-if';
import QueryNodeSelectItem from './QueryNodeSelectItem'

Expand All @@ -19,35 +18,41 @@ export default class QueryNodeSelect extends Component {
getEventInfo(query){
$(this.refs.outer).fadeToggle(true)
this.state.queryData = query
var o = fullAjax(query.query,
function(data){
var y = $.map(data.results[0].data, function(x){
return x.row[0].name
var session = driver.session()
session.run(query.query, query.queryProps)
.then(function(results){
var y = $.map(results.records, function(x){
return x._fields[0]
})

y.sort()
this.setState({data: y})
session.close()
}.bind(this))
$.ajax(o)
}

componentDidMount() {
$(this.refs.outer).fadeToggle(0)
}

_dismiss(){
$(this.refs.outer).fadeToggle(false)
}

handleClick(event){
emitter.emit('query',
this.state.queryData.onFinish.formatAll(event.target.text),
"",
event.target.text,
{result:event.target.text},
this.state.queryData.start.format(event.target.text),
this.state.queryData.end.format(event.target.text),
this.state.queryData.allowCollapse)
$(this.refs.outer).fadeToggle(false)
}

render() {
var header = <QueryNodeSelectHeader length={this.state.data.length} title={this.state.queryData.boxTitle} dismiss={this._dismiss.bind(this)}/>
return (
<div className="queryNodeSelect" ref="outer">
<Panel header={this.state.data.length > 0 ? this.state.queryData.boxTitle : "Loading..."}>
<Panel header={header}>
<If condition={ this.state.data.length > 0 }>
<Then>
<ListGroup ref="list">
Expand All @@ -70,3 +75,17 @@ export default class QueryNodeSelect extends Component {
);
}
}

class QueryNodeSelectHeader extends Component {
render() {
var title = this.props.length > 0 ? this.props.title : "Loading..."
return (
<div>
{title}
<button type="button" className="close" onClick={this.props.dismiss} aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
);
}
}
Loading

0 comments on commit e3f4cf8

Please sign in to comment.