Openidm - 在连接器 groovy 脚本中访问源或目标值

Openidm - Access source or target values in connector groovy script

我目前正在构建自己的 Openidm 连接器,用于使用基于 Groovy 框架连接器 的外部系统ScriptedRest2DJ 示例。

我正在执行 searchScript.groovy 文件以搜索目标系统上的资源(用户),我想传递源系统的当前用户 UID在我的要求下。

这是 SearchScript.groovy 源代码:

import groovyx.net.http.RESTClient
import org.apache.http.client.HttpClient
import org.forgerock.openicf.connectors.scriptedrest.ScriptedRESTConfiguration
import org.forgerock.openicf.misc.scriptedcommon.OperationType
import org.identityconnectors.common.logging.Log
import org.identityconnectors.framework.common.objects.Attribute
import org.identityconnectors.framework.common.objects.AttributeUtil
import org.identityconnectors.framework.common.objects.Name
import org.identityconnectors.framework.common.objects.ObjectClass
import org.identityconnectors.framework.common.objects.OperationOptions
import org.identityconnectors.framework.common.objects.SearchResult
import org.identityconnectors.framework.common.objects.Uid
import org.identityconnectors.framework.common.objects.filter.Filter
import org.identityconnectors.framework.common.objects.AttributesAccessor

import static groovyx.net.http.Method.GET
import static groovyx.net.http.ContentType.JSON;

// imports used for CREST based REST APIs
import org.forgerock.openicf.misc.crest.CRESTFilterVisitor
import org.forgerock.openicf.misc.crest.VisitorParameter

def operation = operation as OperationType
def configuration = configuration as ScriptedRESTConfiguration
def httpClient = connection as HttpClient
def connection = customizedConnection as RESTClient
def filter = filter as Filter
def log = log as Log
def objectClass = objectClass as ObjectClass
def options = options as OperationOptions
def resultHandler = handler

log.info("Entering " + operation + " Script")

switch (objectClass) {
    case ObjectClass.ACCOUNT:
        // Search for a specific user in Alfresco
        // http://docs.alfresco.com/community/references/RESTful-PersonPersonGet.html
        def searchResult = connection.request(GET, JSON) { req ->
            uri.path = 'people'

            headers.Accept = 'application/json'

            response.success = { resp, json ->
                json.people.each() { value ->
                    resultHandler {
                        uid value.userName
                        id value.userName
                        attribute 'email', value?.email
                        attribute 'lastName', value?.lastName
                        attribute 'userName', value?.userName
                        attribute 'firstName', value?.firstName
                        attribute 'enabled', value?.enabled
                        //attribute ('groups', *(value?.groups))
                    }
                }
                json
            }
        }

        return new SearchResult(null, -1) // no remaining results
}

您如何访问脚本中的源值?我测试了 Uid、Id、Name……但没有成功。

感谢您的帮助

要让您的 SearchScript 不仅仅 return 所有用户,您需要使用 "filter" 对象。你在脚本中声明了它,但你没有使用它——这个对象包含连接器需要知道的所有细节的对象 "Search" 这个脚本应该在后端做什么(通过 REST在这种情况下)。过滤器对象本质上是树形结构,它们的预期用途是基于“Visitor Pattern”。

您的代码所基于的 scriptedrest2dj 示例显示了 CRESTFilterVisitor 的使用,这是一个特别有助于使用 OpenDJ(该示例的目标)的特殊示例。对于更通用的访问者实现,我建议查看 sample3 的 SearchScript.groovy。示例 3 是使用 SQL 后端的示例,但此处显示的访问者可用于生成任何类型的查询字符串(例如您可能传递给 REST 服务的查询字符串)。

从 sample3 的过滤器代码中,这个 return 是表示过滤器树的值的常规映射:

def query = filter.accept(MapFilterVisitor.INSTANCE, null)

这是简单值的映射结构(例如字段 eq "value"):

[ 
    "operation": "EQUALS|CONTAINS|STARTSWITH|ENDSWITH",
    "not": "true|false",
    "left": "fieldName",
    "right": "value"
]
这里的

"left"和"right"可以看作是等式的两边。在这种情况下:'Id eq "bob"' 左边是 "Id",右边是 "bob"。 "operation" 将是 "EQUALS".

这里是更复杂表达式的结构(例如 simpleExpr AND simpleExpr):

[ 
    "operation": "AND|OR",
    "left": "simpleExpression|complexExpression",
    "right": "simpleExpression|complexExpression"
]

正如您在此处看到的,您可以在此映射结构中表示任意复杂的布尔表达式。根据您在特定情况下希望支持的复杂程度,您可以选择支持完全递归的表达式构建器(如示例 3 中所示),或者您可以只支持核心情况。

以下是您的脚本应该能够处理的操作类型的一些示例:

GET /openidm/system/scriptedrest/account?_queryId=query-all-ids

  • 这基本上就是你现在所拥有的。执行此操作时,"filter" 对象将为 null,因此您根本不需要过滤任何内容

GET /openidm/system/scriptedrest/account/bob

  • 这是一个"read"操作,但也是通过SearchScript实现的。 "Read" 与针对特定 __UID__ 值的简单过滤器完全相同。实现此目的的快速而肮脏的方法是将您的过滤器对象转换为地图(如我所描述的),然后假设该地图仅包含搜索特定 __UID__ 的过滤器,如下所示:

    def uid = query.get('right')

然后您可以将其传递到您的 REST 调用中(可能通过将其附加到 uri.path 变量)。

理想情况下,您的搜索脚本应该能够处理更复杂的过滤器,例如:

GET /openidm/system/scriptedrest/account?_queryFilter=/email eq "bob@bob.com"

  • 这是对具有特定值的记录的更通用的搜索。您的 REST 后端必须支持这些东西,并且您的过滤器查询构建器必须能够遍历树以构建适当的查询字符串。根据您需要使用此连接器执行的操作,它可能不是必需的。