Skip to content

Commit bfa4721

Browse files
committed
Implementing RUN and BEGIN messages with imp_user
1 parent 376bcb5 commit bfa4721

File tree

4 files changed

+305
-7
lines changed

4 files changed

+305
-7
lines changed

packages/bolt-connection/src/bolt/bolt-protocol-v4x4.js

Lines changed: 86 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@
1919
import BoltProtocolV43 from './bolt-protocol-v4x3'
2020

2121
import { internal } from 'neo4j-driver-core'
22-
import RequestMessage from './request-message'
23-
import { RouteObserver } from './stream-observers'
22+
import RequestMessage, { ALL } from './request-message'
23+
import { RouteObserver, ResultStreamObserver } from './stream-observers'
2424

2525
const {
2626
constants: { BOLT_PROTOCOL_V4_4 },
@@ -66,5 +66,89 @@
6666

6767
return observer
6868
}
69+
70+
run (
71+
query,
72+
parameters,
73+
{
74+
bookmark,
75+
txConfig,
76+
database,
77+
mode,
78+
impersonatedUser,
79+
beforeKeys,
80+
afterKeys,
81+
beforeError,
82+
afterError,
83+
beforeComplete,
84+
afterComplete,
85+
flush = true,
86+
reactive = false,
87+
fetchSize = ALL
88+
} = {}
89+
) {
90+
const observer = new ResultStreamObserver({
91+
server: this._server,
92+
reactive: reactive,
93+
fetchSize: fetchSize,
94+
moreFunction: this._requestMore.bind(this),
95+
discardFunction: this._requestDiscard.bind(this),
96+
beforeKeys,
97+
afterKeys,
98+
beforeError,
99+
afterError,
100+
beforeComplete,
101+
afterComplete
102+
})
103+
104+
const flushRun = reactive
105+
this.write(
106+
RequestMessage.runWithMetadata(query, parameters, {
107+
bookmark,
108+
txConfig,
109+
database,
110+
mode,
111+
impersonatedUser
112+
}),
113+
observer,
114+
flushRun && flush
115+
)
116+
117+
if (!reactive) {
118+
this.write(RequestMessage.pull({ n: fetchSize }), observer, flush)
119+
}
120+
121+
return observer
122+
}
123+
124+
beginTransaction ({
125+
bookmark,
126+
txConfig,
127+
database,
128+
mode,
129+
impersonatedUser,
130+
beforeError,
131+
afterError,
132+
beforeComplete,
133+
afterComplete
134+
} = {}) {
135+
const observer = new ResultStreamObserver({
136+
server: this._server,
137+
beforeError,
138+
afterError,
139+
beforeComplete,
140+
afterComplete
141+
})
142+
observer.prepareToHandleSingleResponse()
143+
144+
this.write(
145+
RequestMessage.begin({ bookmark, txConfig, database, mode, impersonatedUser }),
146+
observer,
147+
true
148+
)
149+
150+
return observer
151+
}
152+
69153
}
70154

packages/bolt-connection/src/bolt/request-message.js

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -124,10 +124,11 @@ export default class RequestMessage {
124124
* @param {TxConfig} txConfig the configuration.
125125
* @param {string} database the database name.
126126
* @param {string} mode the access mode.
127+
* @param {string} impersonatedUser the impersonated user mode.
127128
* @return {RequestMessage} new BEGIN message.
128129
*/
129-
static begin ({ bookmark, txConfig, database, mode } = {}) {
130-
const metadata = buildTxMetadata(bookmark, txConfig, database, mode)
130+
static begin ({ bookmark, txConfig, database, mode, impersonatedUser } = {}) {
131+
const metadata = buildTxMetadata(bookmark, txConfig, database, mode, impersonatedUser)
131132
return new RequestMessage(
132133
BEGIN,
133134
[metadata],
@@ -159,14 +160,15 @@ export default class RequestMessage {
159160
* @param {TxConfig} txConfig the configuration.
160161
* @param {string} database the database name.
161162
* @param {string} mode the access mode.
163+
* @param {string} impersonatedUser the impersonated user mode.
162164
* @return {RequestMessage} new RUN message with additional metadata.
163165
*/
164166
static runWithMetadata (
165167
query,
166168
parameters,
167-
{ bookmark, txConfig, database, mode } = {}
169+
{ bookmark, txConfig, database, mode, impersonatedUser } = {}
168170
) {
169-
const metadata = buildTxMetadata(bookmark, txConfig, database, mode)
171+
const metadata = buildTxMetadata(bookmark, txConfig, database, mode, impersonatedUser)
170172
return new RequestMessage(
171173
RUN,
172174
[query, parameters, metadata],
@@ -267,9 +269,10 @@ export default class RequestMessage {
267269
* @param {TxConfig} txConfig the configuration.
268270
* @param {string} database the database name.
269271
* @param {string} mode the access mode.
272+
* @param {string} impersonatedUser the impersonated user mode.
270273
* @return {Object} a metadata object.
271274
*/
272-
function buildTxMetadata (bookmark, txConfig, database, mode) {
275+
function buildTxMetadata (bookmark, txConfig, database, mode, impersonatedUser) {
273276
const metadata = {}
274277
if (!bookmark.isEmpty()) {
275278
metadata.bookmarks = bookmark.values()
@@ -283,6 +286,9 @@ function buildTxMetadata (bookmark, txConfig, database, mode) {
283286
if (database) {
284287
metadata.db = assertString(database, 'database')
285288
}
289+
if (impersonatedUser) {
290+
metadata.imp_user = assertString(impersonatedUser, 'impersonatedUser')
291+
}
286292
if (mode === ACCESS_MODE_READ) {
287293
metadata.mode = READ_MODE
288294
}

packages/bolt-connection/test/bolt/bolt-protocol-v4x4.test.js

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,49 @@ describe('#unit BoltProtocolV4x4', () => {
139139
expect(protocol.observers).toEqual([observer, observer])
140140
expect(protocol.flushes).toEqual([false, true])
141141
})
142+
143+
it('should run a with impersonated user', () => {
144+
const database = 'testdb'
145+
const impersonatedUser = 'the impostor'
146+
const bookmark = new Bookmark([
147+
'neo4j:bookmark:v1:tx1',
148+
'neo4j:bookmark:v1:tx2'
149+
])
150+
const txConfig = new TxConfig({
151+
timeout: 5000,
152+
metadata: { x: 1, y: 'something' }
153+
})
154+
const recorder = new utils.MessageRecordingConnection()
155+
const protocol = new BoltProtocolV4x4(recorder, null, false)
156+
utils.spyProtocolWrite(protocol)
157+
158+
const query = 'RETURN $x, $y'
159+
const parameters = { x: 'x', y: 'y' }
160+
161+
const observer = protocol.run(query, parameters, {
162+
bookmark,
163+
txConfig,
164+
database,
165+
mode: WRITE,
166+
impersonatedUser
167+
})
168+
169+
protocol.verifyMessageCount(2)
170+
171+
expect(protocol.messages[0]).toBeMessage(
172+
RequestMessage.runWithMetadata(query, parameters, {
173+
bookmark,
174+
txConfig,
175+
database,
176+
mode: WRITE,
177+
impersonatedUser
178+
})
179+
)
180+
expect(protocol.messages[1]).toBeMessage(RequestMessage.pull())
181+
expect(protocol.observers).toEqual([observer, observer])
182+
expect(protocol.flushes).toEqual([false, true])
183+
})
184+
142185
it('should begin a transaction', () => {
143186
const database = 'testdb'
144187
const bookmark = new Bookmark([
@@ -168,6 +211,37 @@ describe('#unit BoltProtocolV4x4', () => {
168211
expect(protocol.flushes).toEqual([true])
169212
})
170213

214+
it('should begin a transaction with impersonated user', () => {
215+
const database = 'testdb'
216+
const impersonatedUser = 'the impostor'
217+
const bookmark = new Bookmark([
218+
'neo4j:bookmark:v1:tx1',
219+
'neo4j:bookmark:v1:tx2'
220+
])
221+
const txConfig = new TxConfig({
222+
timeout: 5000,
223+
metadata: { x: 1, y: 'something' }
224+
})
225+
const recorder = new utils.MessageRecordingConnection()
226+
const protocol = new BoltProtocolV4x4(recorder, null, false)
227+
utils.spyProtocolWrite(protocol)
228+
229+
const observer = protocol.beginTransaction({
230+
bookmark,
231+
txConfig,
232+
database,
233+
mode: WRITE,
234+
impersonatedUser
235+
})
236+
237+
protocol.verifyMessageCount(1)
238+
expect(protocol.messages[0]).toBeMessage(
239+
RequestMessage.begin({ bookmark, txConfig, database, mode: WRITE, impersonatedUser })
240+
)
241+
expect(protocol.observers).toEqual([observer])
242+
expect(protocol.flushes).toEqual([true])
243+
})
244+
171245
it('should return correct bolt version number', () => {
172246
const protocol = new BoltProtocolV4x4(null, null, false)
173247

packages/bolt-connection/test/bolt/request-message.test.js

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,5 +294,139 @@ describe('#unit RequestMessage', () => {
294294
`ROUTE ${json.stringify({})} ${json.stringify([])} ${json.stringify({})}`
295295
)
296296
})
297+
298+
it('should create BEGIN message with impersonated user', () => {
299+
;[READ, WRITE].forEach(mode => {
300+
const bookmark = new Bookmark([
301+
'neo4j:bookmark:v1:tx1',
302+
'neo4j:bookmark:v1:tx10'
303+
])
304+
const impersonatedUser = 'the impostor'
305+
const txConfig = new TxConfig({ timeout: 42, metadata: { key: 42 } })
306+
307+
const message = RequestMessage.begin({ bookmark, txConfig, mode, impersonatedUser })
308+
309+
const expectedMetadata = {
310+
bookmarks: bookmark.values(),
311+
tx_timeout: int(42),
312+
tx_metadata: { key: 42 },
313+
imp_user: impersonatedUser
314+
}
315+
if (mode === READ) {
316+
expectedMetadata.mode = 'r'
317+
}
318+
319+
expect(message.signature).toEqual(0x11)
320+
expect(message.fields).toEqual([expectedMetadata])
321+
expect(message.toString()).toEqual(
322+
`BEGIN ${json.stringify(expectedMetadata)}`
323+
)
324+
})
325+
})
326+
327+
it('should create BEGIN message without impersonated user if it is not supplied or null', () => {
328+
;[undefined, null].forEach(impersonatedUser => {
329+
const bookmark = new Bookmark([
330+
'neo4j:bookmark:v1:tx1',
331+
'neo4j:bookmark:v1:tx10'
332+
])
333+
const mode = WRITE
334+
const txConfig = new TxConfig({ timeout: 42, metadata: { key: 42 } })
335+
336+
const message = RequestMessage.begin({ bookmark, txConfig, mode, impersonatedUser })
337+
338+
const expectedMetadata = {
339+
bookmarks: bookmark.values(),
340+
tx_timeout: int(42),
341+
tx_metadata: { key: 42 }
342+
}
343+
344+
expect(message.signature).toEqual(0x11)
345+
expect(message.fields).toEqual([expectedMetadata])
346+
expect(message.toString()).toEqual(
347+
`BEGIN ${json.stringify(expectedMetadata)}`
348+
)
349+
})
350+
})
351+
352+
it('should create RUN message with the impersonated user', () => {
353+
;[READ, WRITE].forEach(mode => {
354+
const query = 'RETURN $x'
355+
const parameters = { x: 42 }
356+
const bookmark = new Bookmark([
357+
'neo4j:bookmark:v1:tx1',
358+
'neo4j:bookmark:v1:tx10',
359+
'neo4j:bookmark:v1:tx100'
360+
])
361+
const txConfig = new TxConfig({
362+
timeout: 999,
363+
metadata: { a: 'a', b: 'b' }
364+
})
365+
const impersonatedUser = 'the impostor'
366+
367+
const message = RequestMessage.runWithMetadata(query, parameters, {
368+
bookmark,
369+
txConfig,
370+
mode,
371+
impersonatedUser
372+
})
373+
374+
const expectedMetadata = {
375+
bookmarks: bookmark.values(),
376+
tx_timeout: int(999),
377+
tx_metadata: { a: 'a', b: 'b' },
378+
imp_user: impersonatedUser
379+
}
380+
if (mode === READ) {
381+
expectedMetadata.mode = 'r'
382+
}
383+
384+
expect(message.signature).toEqual(0x10)
385+
expect(message.fields).toEqual([query, parameters, expectedMetadata])
386+
expect(message.toString()).toEqual(
387+
`RUN ${query} ${json.stringify(parameters)} ${json.stringify(
388+
expectedMetadata
389+
)}`
390+
)
391+
})
297392
})
393+
394+
it('should create RUN message without impersonated user if it is not supplied or null', () => {
395+
;[undefined, null].forEach(impersonatedUser => {
396+
const mode = WRITE
397+
const query = 'RETURN $x'
398+
const parameters = { x: 42 }
399+
const bookmark = new Bookmark([
400+
'neo4j:bookmark:v1:tx1',
401+
'neo4j:bookmark:v1:tx10',
402+
'neo4j:bookmark:v1:tx100'
403+
])
404+
const txConfig = new TxConfig({
405+
timeout: 999,
406+
metadata: { a: 'a', b: 'b' }
407+
})
408+
409+
const message = RequestMessage.runWithMetadata(query, parameters, {
410+
bookmark,
411+
txConfig,
412+
mode,
413+
impersonatedUser
414+
})
415+
416+
const expectedMetadata = {
417+
bookmarks: bookmark.values(),
418+
tx_timeout: int(999),
419+
tx_metadata: { a: 'a', b: 'b' }
420+
}
421+
422+
expect(message.signature).toEqual(0x10)
423+
expect(message.fields).toEqual([query, parameters, expectedMetadata])
424+
expect(message.toString()).toEqual(
425+
`RUN ${query} ${json.stringify(parameters)} ${json.stringify(
426+
expectedMetadata
427+
)}`
428+
)
429+
})
430+
})
431+
})
298432
})

0 commit comments

Comments
 (0)