来自 node.js 应用程序 returns 的 ArangoDB 事务请求 403:禁止

ArangoDB transaction request from a node.js app returns 403: forbidden

我正在尝试在 node.js 应用程序中用 ArangoDB 替换 OrientDB,但我无法让事务正常工作。此代码创建一个 pmsite 文档、一个 pmprojcat 文档以及两者之间的关系 (pm_child)。代码returns一个403:禁止。但是,如果我 运行 arangosh 中的函数体(非事务性)它工作正常。我在代码中的其他非事务性请求运行没有问题。

这是失败的代码片段:

    db.transaction(tables, actions, function (err, result) {
      console.log('collection:', tables);
      console.log('actions:', actions);
      console.log('err:', err);
      if (err) data.pms.makeError(data, queue, 'Create Object: ' + err.message);
      else {...}

控制台结果是:

collection: { write: [ 'pmsite', 'pmprojcat', 'pm_child' ] }
actions: function(){var db=require("org/arangodb").db;db._useDatabase("gdp2_server");var graph=require("org/arangodb/general-graph")._graph("gdp2_graph");var v=graph.pmsite.save({"connection":"localhost:1680","protocol":"p4+icm","name":"site1","kind":"site","model":"oldGDP","uri":"$(site:protocol)://$(site:connection)/depot/icm/proj/$(project)/$(variant)/$(vartype:dir)/$(library)/..."});var c=graph.pmprojcat.save({"kind":"projcat","name":"."});graph.pm_child.insert(v._id,c._id,{});return v;}
err: { [ArangoError: forbidden]
  name: 'ArangoError',
  message: 'forbidden',
  errorNum: 11,
  code: 403,
  stack: 'ArangoError: forbidden\n    at new ArangoError (/home/gary/icManager/gdp2_server/node_modules/arangojs/lib/error.js:24:15)\n    at /home/gary/icManager/gdp2_server/node_modules/arangojs/lib/connection.js:126:19\n    at callback (/home/gary/icManager/gdp2_server/node_modules/arangojs/lib/util/request.js:90:12)\n    at IncomingMessage.<anonymous> (/home/gary/icManager/gdp2_server/node_modules/arangojs/lib/util/request.js:98:11)\n    at IncomingMessage.emit (events.js:129:20)\n    at _stream_readable.js:908:16\n    at process._tickDomainCallback (node.js:381:11)',
  response: 
   { _readableState: 
      { objectMode: false,
        highWaterMark: 16384,
        buffer: [],
        length: 0,
        pipes: null,
        pipesCount: 0,
    flowing: true,
    ended: true,
    endEmitted: true,
    reading: false,
    sync: true,
    needReadable: false,
    emittedReadable: false,
    readableListening: false,
    defaultEncoding: 'utf8',
    ranOut: false,
    awaitDrain: 0,
    readingMore: false,
    decoder: null,
    encoding: null,
    resumeScheduled: false },
 readable: false,
 domain: null,
 _events: { end: [Object], data: [Function] },
 _maxListeners: undefined,
 socket: 
  { _connecting: false,
    _hadError: false,
    _handle: [Object],
    _host: 'localhost',
    _readableState: [Object],
    readable: true,
    domain: null,
    _events: [Object],
    _maxListeners: undefined,
    _writableState: [Object],
    writable: true,
    allowHalfOpen: false,
    destroyed: false,
    bytesRead: 1564,
    _bytesDispatched: 5409,
    _pendingData: null,
    _pendingEncoding: '',
    parser: null,
    _httpMessage: [Object],
    read: [Function],
    _consuming: true },
 connection: 
  { _connecting: false,
    _hadError: false,
    _handle: [Object],
    _host: 'localhost',
    _readableState: [Object],
    readable: true,
    domain: null,
    _events: [Object],
    _maxListeners: undefined,
    _writableState: [Object],
    writable: true,
    allowHalfOpen: false,
    destroyed: false,
    bytesRead: 1564,
    _bytesDispatched: 5409,
    _pendingData: null,
    _pendingEncoding: '',
    parser: null,
    _httpMessage: [Object],
    read: [Function],
    _consuming: true },
 httpVersionMajor: 1,
 httpVersionMinor: 1,
 httpVersion: '1.1',
 complete: true,
 headers: 
  { server: 'ArangoDB',
    connection: 'Keep-Alive',
    'content-type': 'application/json; charset=utf-8',
    'content-length': '450' },
 rawHeaders: 
  [ 'Server',
    'ArangoDB',
    'Connection',
    'Keep-Alive',
    'Content-Type',
    'application/json; charset=utf-8',
    'Content-Length',
    '450' ],
 trailers: {},
 rawTrailers: [],
 _pendings: [],
 _pendingIndex: 0,
 upgrade: false,
 url: '',
 method: null,
 statusCode: 403,
 statusMessage: 'Forbidden',
 client: 
  { _connecting: false,
    _hadError: false,
    _handle: [Object],
    _host: 'localhost',
    _readableState: [Object],
    readable: true,
    domain: null,
    _events: [Object],
    _maxListeners: undefined,
    _writableState: [Object],
    writable: true,
    allowHalfOpen: false,
    destroyed: false,
    bytesRead: 1564,
    _bytesDispatched: 5409,
    _pendingData: null,
    _pendingEncoding: '',
    parser: null,
    _httpMessage: [Object],
    read: [Function],
    _consuming: true },
 _consuming: true,
 _dumped: false,
 req: 
  { domain: null,
    _events: [Object],
    _maxListeners: undefined,
    output: [],
    outputEncodings: [],
    outputCallbacks: [],
    writable: true,
    _last: false,
    chunkedEncoding: false,
    shouldKeepAlive: true,
    useChunkedEncodingByDefault: true,
    sendDate: false,
    _removedHeader: [Object],
    _hasBody: true,
    _trailer: '',
    finished: true,
    _hangupClose: false,
    _headerSent: true,
    socket: [Object],
    connection: [Object],
    _header: 'POST /_db/gdp2_server/_api/transaction HTTP/1.1\r\ncontent-type: application/json\r\ncontent-length: 598\r\nx-arango-version: 20300\r\nHost: localhost:8529\r\nConnection: keep-alive\r\n\r\n',
    _headers: [Object],
    _headerNames: [Object],
    agent: [Object],
    socketPath: undefined,
    method: 'POST',
    path: '/_db/gdp2_server/_api/transaction',
    parser: null,
    res: [Circular] },
 read: [Function],
 body: 
  { exception: '[ArangoError 11: forbidden]',
    stacktrace: [Object],
    message: 'forbidden',
    error: true,
    code: 403,
    errorNum: 11,
    errorMessage: 'forbidden' },
 rawBody: '{"exception":"[ArangoError 11: forbidden]","stacktrace":["[ArangoError 11: forbidden]","  at Error (native)","  at eval (<anonymous>:1:57)","  at eval (<anonymous>:1:497)","  at post_api_transaction (/usr/share/arangodb/js/actions/api-transaction.js:268:16)","  at Function.actions.defineHttp.callback (/usr/share/arangodb/js/actions/api-transaction.js:288:11)"],"message":"forbidden","error":true,"code":403,"errorNum":11,"errorMessage":"forbidden"}' } }

@ggendel:你关于 _useDatabase() 是问题根源的推理是正确的: 不允许事务更改数据库 in-between,也不允许更改其他 server-side 操作,例如Foxx 动作。

为了让事务运行在不同的数据库中,需要事先切换到另一个数据库,在client-side.