1

我正在使用 xdmp:invoke 调用在安全数据库中创建一个新角色。作为调用调用的选项,我指定了以下选项:

<options xmlns="xdmp:eval">
  <database>{ xdmp:security-database() }</database>
  <transaction-mode>update</transaction-mode>
  <isolation>different-transaction</isolation>
  <prevent-deadlocks>false</prevent-deadlocks>
</options>

我的想法是这将在单独的事务中执行,然后我将能够访问此调用后代码中的更改。但是,当我使用刚刚创建的角色的名称对 xdmp:permission() 进行全部操作时,我得到一个角色不存在的错误。

有没有办法解决这个问题?

更新

以下代码段有效。因此,我将进行更多故障排除,以查看我更复杂的代码中是否存在其他问题。

xquery version "1.0-ml";

import module namespace sec = "http://marklogic.com/xdmp/security"
  at "/MarkLogic/security.xqy";

let $create_role :=
  xdmp:invoke-function(
    function() {
      sec:create-role(
        'sec_test',
        'Security Test Role',
        (),
        (),
        ()
      )
    },
    <options xmlns="xdmp:eval">
      <database>{xdmp:security-database()}</database>
      <transaction-mode>update-auto-commit</transaction-mode>
      <isolation>different-transaction</isolation>
    </options>
  )

return xdmp:permission('sec_test', 'read')

第二次更新

看来,如果我调用来执行创建角色的函数在另一个 xqy 文件中,那么它会失败并出现角色未找到错误。例如,我在 security-util.xqy 中有以下模块。

xquery version "1.0-ml";
module namespace asu = "http://ir.abbvie.com/marklogic/authorization/lib/security-util";

import module namespace sec = "http://marklogic.com/xdmp/security"
  at "/MarkLogic/security.xqy";

declare option xdmp:mapping "false";

declare function asu:create-role-2(
  $role_name as xs:string
)
{
  xdmp:invoke-function(
    function() {
      sec:create-role(
        $role_name,
        "Role auto created by AbbVie authorization library.",
        (),
        (),
        ()
      )
    },
    <options xmlns="xdmp:eval">
      <database>{ xdmp:security-database() }</database>
      <transaction-mode>update-auto-commit</transaction-mode>
      <isolation>different-transaction</isolation>
    </options>
  )
};

如果我从查询控制台调用它:

xquery version "1.0-ml";

import module namespace asu =    "http://ir.abbvie.com/marklogic/authorization/lib/security-util"
  at "security-util.xqy";

asu:create-role-2('sec_test7'), xdmp:permission('sec_test7', 'read')

这将出错,因为以下内容可以正常工作:

xquery version "1.0-ml";

import module namespace sec = "http://marklogic.com/xdmp/security"
  at "/MarkLogic/security.xqy";  

declare function local:create-role(
  $role_name as xs:string
)
{
  xdmp:invoke-function(
    function() {
      sec:create-role(
        $role_name,
        "Security Test Role",
        (),
        (),
        ()
      )
    },
    <options xmlns="xdmp:eval">

      <database>{ xdmp:security-database() }</database>
      <transaction-mode>update-auto-commit</transaction-mode>
      <isolation>different-transaction</isolation>
    </options>
  )
};

local:create-role('sec_test8'), xdmp:permission('sec_test8', 'read')
4

2 回答 2

5

考虑通过调用函数获得许可。您正在单独的事务中创建角色,因此当前请求可能正在查看该提交之前的数据库状态。这是 MarkLogic 用来支持非锁定查询模式的 MVCC 模型的一部分。

也可能是惰性评估正在干扰您的代码。序列中的子表达式(例如逗号分隔的任何内容)可以并行执行。使用来自 FLWOR 的 let-return 来强制执行订单。

于 2016-02-10T09:29:24.070 回答
1

您是否确认它确实创建了角色?如果它实际上没有被创建,请尝试将事务模式更改为“update-auto-commit”。我怀疑你添加角色的交易实际上并没有得到承诺。

此外,如果您所做的只是创建一个角色,那么使用以下内容可能会更简单,这样您就不必为一小段代码定义单独的 .xqy。

xdmp:invoke-function(
  function() { sec:create-role(...) },
  <options xmlns="xdmp:eval">
    <database>{xdmp:security-database()}</database>
    <transaction-mode>update-auto-commit</transaction-mode>
    <isolation>different-transaction</isolation>
  </options>)
于 2016-02-10T05:24:34.840 回答