Skip to content

Commit

Permalink
V0.12.1 bugfix release (#124)
Browse files Browse the repository at this point in the history
* fixes #122 confusion over open vs. available file descriptors

* fixes #121 identify Halin with global user agent at driver level

* starting point of v0.12.1 release notes

* fixes #97 omit parameters from queries for size/speed

* omit publishing of testrig

* react-scripts major upgrade, which drags along piles of dependencies

* adapt dockerfile to official node image

* fixes #125, database names may contain dots and dashes
  • Loading branch information
moxious authored Jan 9, 2020
1 parent 71c64da commit 0dd6b2f
Show file tree
Hide file tree
Showing 13 changed files with 5,353 additions and 5,739 deletions.
2 changes: 2 additions & 0 deletions .npmignore
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,5 @@ grafana
src/creds/*
reports
code-signing
testrig
neo4j-4.0.0-beta1
4 changes: 3 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# base image
FROM kkarczmarczyk/node-yarn:latest
FROM node:13.5.0-stretch

RUN apt-get update && apt-get install -y yarn

# set working directory
RUN mkdir /app
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "halin",
"description": "Halin helps you monitor and improve your Neo4j graph",
"version": "0.12.0",
"version": "0.12.1",
"neo4jDesktop": {
"apiVersion": "^1.2.0"
},
Expand Down Expand Up @@ -35,7 +35,7 @@
"react-dom": "^16.12.0",
"react-graph-vis": "^1.0.2",
"react-minimal-pie-chart": "^4.0.0",
"react-scripts": "^2.1.8",
"react-scripts": "^3.3.0",
"react-sortable-tree": "^2.2.0",
"react-table": "^6.8.6",
"react-timeseries-charts": "^0.16.1",
Expand Down
9 changes: 9 additions & 0 deletions release-notes.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
# Halin Release Notes

## 0.12.1 Patch Release

- Fixes #121 identify halin with global user-agent string in bolt driver
- Fixes #122 confusion between open and available OS file descriptors
- Fixes #97 omit 'parameters' from query/task view for performance reasons
- Fixes #125 database names may contain dots and dashes
- React scripts updates, which addresses numerous github security notices
- Change base docker image to upgrade node, yarn, and react-scripts

## 0.12.0 (Neo4j 4.0, Multi-database, and Fine-Grained Security)

- Status for both all cluster members and all databases. Users
Expand Down
6 changes: 6 additions & 0 deletions src/api/HalinContext.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ import ClusterManager from './cluster/ClusterManager';
import ClusterMemberSet from './cluster/ClusterMemberSet';
import DatabaseSet from './DatabaseSet';
import DataFeed from './data/DataFeed';
import pkg from '../package.json';
import build from '../build.json';
import moment from 'moment';

const USER_AGENT = `halin/${pkg.version} build ${build.build} on ${moment.utc(build.date).format('YYYY-MM-DD')}`;

/**
* HalinContext is a controller object that keeps track of state and permits diagnostic
Expand Down Expand Up @@ -141,6 +146,7 @@ export default class HalinContext {
const allOptions = _.merge({ encrypted }, this.driverOptions);
const driver = neo4j.driver(addr,
neo4j.auth.basic(username, password), allOptions);
driver._userAgent = USER_AGENT; // https://github.com/moxious/halin/issues/121
this.drivers[addr] = driver;
return driver;
}
Expand Down
8 changes: 4 additions & 4 deletions src/api/cluster/ClusterManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -434,7 +434,7 @@ export default class ClusterManager {
stopDatabase(db) {
if (!db || !db.name) { throw new Error('Invalid or missing database'); }

return this.ctx.getSystemDBWriter().run(`STOP DATABASE ${db.name}`, {}, neo4j.SYSTEM_DB)
return this.ctx.getSystemDBWriter().run(`STOP DATABASE \`${db.name}\``, {}, neo4j.SYSTEM_DB)
.then(results => {
sentry.info('stop results', results);
return results;
Expand All @@ -450,7 +450,7 @@ export default class ClusterManager {
startDatabase(db) {
if (!db || !db.name) { throw new Error('Invalid or missing database'); }

return this.ctx.getSystemDBWriter().run(`START DATABASE ${db.name}`, {}, neo4j.SYSTEM_DB)
return this.ctx.getSystemDBWriter().run(`START DATABASE \`${db.name}\``, {}, neo4j.SYSTEM_DB)
.then(results => {
sentry.info('start results', results);
return results;
Expand All @@ -466,7 +466,7 @@ export default class ClusterManager {
dropDatabase(db) {
if (!db || !db.name) { throw new Error('Invalid or missing database'); }

return this.ctx.getSystemDBWriter().run(`DROP DATABASE ${db.name}`, {}, neo4j.SYSTEM_DB)
return this.ctx.getSystemDBWriter().run(`DROP DATABASE \`${db.name}\``, {}, neo4j.SYSTEM_DB)
.then(results => {
sentry.info('drop results', results);
return results;
Expand All @@ -487,7 +487,7 @@ export default class ClusterManager {
* @param {String} name of the database you want to create
*/
createDatabase(name) {
return this.ctx.getSystemDBWriter().run(`CREATE DATABASE ${name}`, {}, neo4j.SYSTEM_DB)
return this.ctx.getSystemDBWriter().run(`CREATE DATABASE \`${name}\``, {}, neo4j.SYSTEM_DB)
.then(results => {
sentry.info('Created database; results ', results);
return results;
Expand Down
6 changes: 3 additions & 3 deletions src/api/cluster/PrivilegeOperation.js
Original file line number Diff line number Diff line change
Expand Up @@ -229,11 +229,11 @@ export default class PrivilegeOperation {
* https://neo4j.com/docs/cypher-manual/4.0-preview/administration/security/subgraph/#administration-security-subgraph-write
*/
if (priv.indexOf('WRITE') > -1) {
return `${op} ${priv} ON ${graphToken} ${db} ${preposition} ${role}`;
return `${op} ${priv} ON ${graphToken} \`${db}\` ${preposition} ${role}`;
} else if(Object.values(PrivilegeOperation.DATABASE_OPERATIONS).indexOf(priv) > -1) {
return `${op} ${priv} ON DATABASE ${db} ${preposition} ${role}`;
return `${op} ${priv} ON DATABASE \`${db}\` ${preposition} ${role}`;
}

return `${op} ${priv} ON ${graphToken} ${db} ${entity} ${preposition} ${role}`;
return `${op} ${priv} ON ${graphToken} \`${db}\` ${entity} ${preposition} ${role}`;
}
};
18 changes: 9 additions & 9 deletions src/api/cluster/PrivilegeOperation.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ describe('Privilege Operations', function() {

it('can build a query', () => {
const q = op.buildQuery();
expect(q).toEqual('GRANT TRAVERSE ON GRAPH foo ELEMENTS * TO blorko');
expect(q).toEqual('GRANT TRAVERSE ON GRAPH `foo` ELEMENTS * TO blorko');
});

it('WRITE privileges do not include ELEMENTS part of query', () => {
Expand All @@ -57,7 +57,7 @@ describe('Privilege Operations', function() {

// 4.0 doesn't support write privileges on specific elements:
// https://neo4j.com/docs/cypher-manual/4.0-preview/administration/security/subgraph/#administration-security-subgraph-write
expect(q).toEqual('GRANT WRITE ON GRAPH foo TO blorko');
expect(q).toEqual('GRANT WRITE ON GRAPH `foo` TO blorko');
});

it('can generate GRANTs from existing privileges (database permissions)', () => {
Expand All @@ -70,7 +70,7 @@ describe('Privilege Operations', function() {
resource: '',
});

expect(op.buildQuery()).toEqual('GRANT CREATE INDEX ON DATABASE foo TO blorko');
expect(op.buildQuery()).toEqual('GRANT CREATE INDEX ON DATABASE `foo` TO blorko');
});

it('allowsEntity for non-database privileges', () => {
Expand Down Expand Up @@ -98,7 +98,7 @@ describe('Privilege Operations', function() {
segment: 'database',
role: 'test',
},
expected: 'DENY ACCESS ON DATABASE neo4j TO test',
expected: 'DENY ACCESS ON DATABASE `neo4j` TO test',
},
{
reversalAction: 'DENY',
Expand All @@ -110,7 +110,7 @@ describe('Privilege Operations', function() {
segment: 'NODE(*)',
role: 'test',
},
expected: 'DENY TRAVERSE ON GRAPH neo4j NODES * TO test',
expected: 'DENY TRAVERSE ON GRAPH `neo4j` NODES * TO test',
},
{
reversalAction: 'REVOKE',
Expand All @@ -122,7 +122,7 @@ describe('Privilege Operations', function() {
segment: 'database',
role: 'test',
},
expected: 'REVOKE CREATE NEW PROPERTY NAME ON DATABASE neo4j FROM test',
expected: 'REVOKE CREATE NEW PROPERTY NAME ON DATABASE `neo4j` FROM test',
},
{
reversalAction: 'REVOKE',
Expand All @@ -134,7 +134,7 @@ describe('Privilege Operations', function() {
segment: 'RELATIONSHIP(*)',
role: 'test',
},
expected: 'REVOKE READ {*} ON GRAPH neo4j RELATIONSHIPS * FROM test',
expected: 'REVOKE READ {*} ON GRAPH `neo4j` RELATIONSHIPS * FROM test',
},
{
reversalAction: 'GRANT',
Expand All @@ -146,7 +146,7 @@ describe('Privilege Operations', function() {
segment: 'NODE(Address)',
role: 'microuser',
},
expected: 'GRANT READ {*} ON GRAPH neo4j NODES Address TO microuser',
expected: 'GRANT READ {*} ON GRAPH `neo4j` NODES Address TO microuser',
},
{
reversalAction: 'GRANT',
Expand All @@ -158,7 +158,7 @@ describe('Privilege Operations', function() {
segment: 'RELATIONSHIP(PHONE)',
role: 'microuser',
},
expected: 'GRANT TRAVERSE ON GRAPH neo4j RELATIONSHIPS PHONE TO microuser',
expected: 'GRANT TRAVERSE ON GRAPH `neo4j` RELATIONSHIPS PHONE TO microuser',
}
];

Expand Down
8 changes: 4 additions & 4 deletions src/api/data/queries/dbms/3.4/tasks.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,9 @@ export default new HalinQuery({
idleTimeMillis: idleTimeMillis
}) as transactions
/* Grab queries */
/* Grab queries -- omit parameters because of https://github.com/moxious/halin/issues/97 */
CALL dbms.listQueries()
YIELD queryId, username, metaData, query, parameters, planner, runtime, indexes,
YIELD queryId, username, metaData, query, /* parameters, */ planner, runtime, indexes,
startTime, protocol, clientAddress, requestUri, status, resourceInformation,
activeLockCount, elapsedTimeMillis, cpuTimeMillis, waitTimeMillis, idleTimeMillis,
allocatedBytes, pageHits, pageFaults
Expand All @@ -57,7 +57,7 @@ export default new HalinQuery({
WITH transactions, collect({
id: queryId,
query: query,
parameters: parameters,
/* parameters: parameters, */
planner: planner,
runtime: runtime,
indexes: indexes,
Expand Down Expand Up @@ -129,7 +129,7 @@ export default new HalinQuery({
"pageHits": 0,
"id": "query-33",
"planner": "idp",
"parameters": {},
// "parameters": {},
"pageFaults": 0,
"status": "running"
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,7 @@ class AlterPrivilegeForm extends Component {
this.setState({ pending: true });
return mgr.getRoles()
.then(roleData => {
console.log('MY PROPS', this.props);
const roles = roleData.map(entry => optionify(entry.role));
const roles = roleData.map(entry => optionify(entry.role));

const databases = window.halinContext.databases().map(db => optionify(db.getLabel()))
.concat([optionify('*')]);
Expand Down
6 changes: 4 additions & 2 deletions src/components/database/CreateDatabase/CreateDatabase.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ class CreateDatabase extends Component {
}

formValid = () => {
const nameValid = this.state.name && this.state.name.match(/^[A-Za-z0-9]+$/);
// Must start with an ASCII character, then contain only ascii, numbers, dots, dashes.
const nameValid = this.state.name && this.state.name.match(/^[A-Za-z][A-Za-z0-9.-]*$/);

return nameValid &&
// Don't allow duplicate names
Expand Down Expand Up @@ -93,7 +94,8 @@ class CreateDatabase extends Component {
content={
<div>
Database names may consist only of simple letters and numbers,
and may not match any other existing database name.
dots, and dashes, and must start with an ASCII letter.
They may not match any other existing database name.
</div>
} />
</Form>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ import HalinCard from '../../ui/scaffold/HalinCard/HalinCard';
class OpenFileDescriptors extends Component {
state = {
key: uuid.v4(),
displayProperty: 'fdUsed',
displayProperty: 'fdAvailable',
options: [
{ text: 'Used', value: 'fdUsed' },
{ text: 'Available', value: 'fdOpen' },
{ text: 'Used', value: 'fdOpen' },
{ text: 'Available', value: 'fdAvailable' },
{ text: 'Max', value: 'fdMax' },
],
};
Expand All @@ -25,8 +25,8 @@ class OpenFileDescriptors extends Component {
// so we have to augment the data structure because the timeseries doesn't do math
// for us.
augmentData = (/* node */) => (data) => {
const fdUsed = data.fdMax - data.fdOpen;
return { fdUsed };
const fdAvailable = data.fdMax - data.fdOpen;
return { fdAvailable };
};

dataFeedMaker = node => {
Expand All @@ -36,7 +36,7 @@ class OpenFileDescriptors extends Component {

const feed = halin.getDataFeed(_.merge({ node }, queryLibrary.OS_OPEN_FDS));
feed.addAliases({
fdUsed: ClusterTimeseries.keyFor(addr, 'fdUsed'),
fdAvailable: ClusterTimeseries.keyFor(addr, 'fdAvailable'),
fdOpen: ClusterTimeseries.keyFor(addr, 'fdOpen'),
fdMax: ClusterTimeseries.keyFor(addr, 'fdMax'),
});
Expand All @@ -57,7 +57,7 @@ class OpenFileDescriptors extends Component {
<HalinCard header='File Descriptors' knowledgebase='FileDescriptors' owner={this}>
<Dropdown style={{paddingBottom: 10}}
placeholder='Show:'
fluid defaultValue='fdUsed'
fluid defaultValue='fdAvailable'
onChange={this.onChange}
selection
options={this.state.options}
Expand Down
Loading

0 comments on commit 0dd6b2f

Please sign in to comment.