[OPENIDM-15341] Delegated Admin/Virtual Attribute/onStore using JDBC repo Fails when a DelAdmin user Created: 27/Aug/20  Updated: 14/Jan/21  Resolved: 24/Nov/20

Status: Resolved
Project: OpenIDM
Component/s: Module - Authorization, Module - Relationships
Affects Version/s: 7.0.0
Fix Version/s: 7.1.0

Type: Improvement Priority: Critical
Reporter: David Lee Assignee: Brendan Miller
Resolution: Fixed Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified
Environment:

IDM 7.0.0 with either MySQL or PostgreSQL; same symptoms reproduced with DS, except no 500 im the logs.


Issue Links:
Relates
is related to OPENIDM-15626 Optionally flatten entries in relatio... Closed
Target Version/s:
Epic Link: Better Living through RDVPs

 Description   

Following https://wikis.forgerock.org/confluence/pages/viewpage.action?pageId=81069102 works great when using DS as the repo.  Setup MySQL and then PostgreSQL with same result.

When a Delegated Admin writes to a user they "manage" manager1 updating user1
[103] Aug 26, 2020 7:08:03.884 AM org.forgerock.openidm.servlet.internal.ResourceFilters$3 lambda$handleRequestWithLogging$8
WARNING: Resource exception: 500 Internal Server Error: "Object user1 not found in managed/user"
org.forgerock.json.resource.InternalServerErrorException: Object user1 not found in managed/user
at org.forgerock.openidm.managed.ManagedObjectSet.update(ManagedObjectSet.java:819)
at org.forgerock.openidm.managed.ManagedObjectSet.patchResource(ManagedObjectSet.java:1480)
at org.forgerock.openidm.managed.ManagedObjectSet.patchResourceById(ManagedObjectSet.java:1375)
at org.forgerock.openidm.managed.ManagedObjectSet.patchInstance(ManagedObjectSet.java:1350)
at org.forgerock.json.resource.InterfaceCollectionInstance.handlePatch(InterfaceCollectionInstance.java:52)
at org.forgerock.json.resource.FilterChain$Cursor.handlePatch(FilterChain.java:84)
at org.forgerock.json.resource.Resources$CollectionInstanceIdContextFilter.filterPatch(Resources.java:544)
at org.forgerock.json.resource.FilterChain$Cursor.handlePatch(FilterChain.java:82)
at org.forgerock.json.resource.FilterChain.handlePatch(FilterChain.java:243)
at org.forgerock.json.resource.Router.handlePatch(Router.java:293)
at org.forgerock.openidm.managed.ManagedObjectService$ManagedObjectSetRequestHandler.handlePatch(ManagedObjectService.java:327)
at org.forgerock.json.resource.FilterChain$Cursor.handlePatch(FilterChain.java:84)
at org.forgerock.openidm.notification.NotificationFilter.filterPatch(NotificationFilter.java:245)
at org.forgerock.json.resource.FilterChain$Cursor.handlePatch(FilterChain.java:82)
at org.forgerock.openidm.notification.NotificationFilter.filterPatch(NotificationFilter.java:245)
at org.forgerock.json.resource.FilterChain$Cursor.handlePatch(FilterChain.java:82)
at org.forgerock.json.resource.FilterChain.handlePatch(FilterChain.java:243)
at org.forgerock.json.resource.Router.handlePatch(Router.java:293)
at org.forgerock.openidm.managed.ManagedObjectService.handlePatch(ManagedObjectService.java:571)
at org.forgerock.json.resource.Router.handlePatch(Router.java:293)
at org.forgerock.json.resource.FilterChain$Cursor.handlePatch(FilterChain.java:84)
at org.forgerock.openidm.selfservice.impl.HashKbaFilter.lambda$filterPatch$2(HashKbaFilter.java:127)
at org.forgerock.openidm.selfservice.impl.HashKbaFilter$$Lambda$1370/0000000000000000.apply(Unknown Source)
at org.forgerock.util.promise.PromiseImpl$1.executeCallback(PromiseImpl.java:434)
at org.forgerock.util.promise.PromiseImpl$1.handleStateChange(PromiseImpl.java:422)
at org.forgerock.util.promise.PromiseImpl.handleCompletion(PromiseImpl.java:538)
at org.forgerock.util.promise.PromiseImpl.addOrFireListener(PromiseImpl.java:526)
at org.forgerock.util.promise.PromiseImpl.thenAsync(PromiseImpl.java:416)
at org.forgerock.util.promise.PromiseImpl.thenAsync(PromiseImpl.java:407)
at org.forgerock.util.promise.PromiseImpl.thenAsync(PromiseImpl.java:388)
at org.forgerock.openidm.selfservice.impl.HashKbaFilter.filterPatch(HashKbaFilter.java:127)
at org.forgerock.json.resource.FilterChain$Cursor.handlePatch(FilterChain.java:82)
at org.forgerock.json.resource.ResourceApiVersionRoutingFilter.filterPatch(ResourceApiVersionRoutingFilter.java:63)
at org.forgerock.json.resource.FilterChain$Cursor.handlePatch(FilterChain.java:82)
at org.forgerock.json.resource.FilterChain.handlePatch(FilterChain.java:243)
at org.forgerock.json.resource.Router.handlePatch(Router.java:293)
at org.forgerock.json.resource.FilterChain$Cursor.handlePatch(FilterChain.java:84)
at org.forgerock.json.resource.Filters$ConditionalFilter.filterPatch(Filters.java:74)
at org.forgerock.json.resource.FilterChain$Cursor.handlePatch(FilterChain.java:82)
at org.forgerock.json.resource.Filters$ConditionalFilter.filterPatch(Filters.java:74)
at org.forgerock.json.resource.FilterChain$Cursor.handlePatch(FilterChain.java:82)
at org.forgerock.openidm.authz.DelegatedAdminFilter.lambda$filterPatch$3(DelegatedAdminFilter.java:260)
at org.forgerock.openidm.authz.DelegatedAdminFilter$$Lambda$1167/0000000000000000.apply(Unknown Source)
at org.forgerock.util.promise.Promises$CompletedPromise.thenAsync(Promises.java:263)
at org.forgerock.util.promise.Promises$CompletedPromise.thenAsync(Promises.java:227)
at org.forgerock.openidm.authz.DelegatedAdminFilter.filterRequest(DelegatedAdminFilter.java:303)
at org.forgerock.openidm.authz.DelegatedAdminFilter.filterPatch(DelegatedAdminFilter.java:259)
at org.forgerock.json.resource.Filters$ConditionalFilter.filterPatch(Filters.java:72)
at org.forgerock.json.resource.FilterChain$Cursor.handlePatch(FilterChain.java:82)
at org.forgerock.json.resource.Filters$ConditionalFilter.filterPatch(Filters.java:74)
at org.forgerock.json.resource.FilterChain$Cursor.handlePatch(FilterChain.java:82)
at org.forgerock.json.resource.Filters$ConditionalFilter.filterPatch(Filters.java:74)
at org.forgerock.json.resource.FilterChain$Cursor.handlePatch(FilterChain.java:82)
at org.forgerock.openidm.audit.filter.AuditFilter.lambda$filterPatch$3(AuditFilter.java:139)
at org.forgerock.openidm.audit.filter.AuditFilter$$Lambda$1166/0000000000000000.get(Unknown Source)
at org.forgerock.openidm.audit.filter.AuditFilter.logAuditAccessEntry(AuditFilter.java:177)
at org.forgerock.openidm.audit.filter.AuditFilter.filterPatch(AuditFilter.java:139)
at org.forgerock.openidm.router.filter.MutableFilterDecorator.filterPatch(MutableFilterDecorator.java:84)
at org.forgerock.json.resource.Filters$ConditionalFilter.filterPatch(Filters.java:72)
at org.forgerock.json.resource.FilterChain$Cursor.handlePatch(FilterChain.java:82)
at org.forgerock.openidm.servlet.internal.ResourceFilters$3.lambda$filterPatch$3(ResourceFilters.java:188)
at org.forgerock.openidm.servlet.internal.ResourceFilters$3$$Lambda$1165/0000000000000000.get(Unknown Source)
at org.forgerock.openidm.servlet.internal.ResourceFilters$3.handleRequestWithLogging(ResourceFilters.java:222)
at org.forgerock.openidm.servlet.internal.ResourceFilters$3.filterPatch(ResourceFilters.java:188)
at org.forgerock.json.resource.FilterChain$Cursor.handlePatch(FilterChain.java:82)
at org.forgerock.openidm.router.filter.QueryIdToQueryFilterTransformFilter.filterPatch(QueryIdToQueryFilterTransformFilter.java:239)
at org.forgerock.json.resource.FilterChain$Cursor.handlePatch(FilterChain.java:82)
at org.forgerock.openidm.router.filter.PassthroughFilter.filterPatch(PassthroughFilter.java:60)
at org.forgerock.openidm.router.filter.MutableFilterDecorator.filterPatch(MutableFilterDecorator.java:84)
at org.forgerock.openidm.router.filter.MutableFilterDecorator.filterPatch(MutableFilterDecorator.java:84)
at org.forgerock.json.resource.FilterChain$Cursor.handlePatch(FilterChain.java:82)
at org.forgerock.openidm.router.filter.PassthroughFilter.filterPatch(PassthroughFilter.java:60)
at org.forgerock.openidm.router.filter.MutableFilterDecorator.filterPatch(MutableFilterDecorator.java:84)
at org.forgerock.json.resource.Filters$ConditionalFilter.filterPatch(Filters.java:72)
at org.forgerock.json.resource.FilterChain$Cursor.handlePatch(FilterChain.java:82)
at org.forgerock.openidm.servlet.internal.ResourceFilters$2.filterPatch(ResourceFilters.java:113)
at org.forgerock.json.resource.Filters$ConditionalFilter.filterPatch(Filters.java:72)
at org.forgerock.json.resource.FilterChain$Cursor.handlePatch(FilterChain.java:82)
at org.forgerock.json.resource.FilterChain.handlePatch(FilterChain.java:243)
at org.forgerock.json.resource.InternalConnection.patchAsync(InternalConnection.java:66)
at org.forgerock.json.resource.AbstractConnectionWrapper.patchAsync(AbstractConnectionWrapper.java:155)
at org.forgerock.openidm.servlet.internal.ServletConnectionFactory$InternalConnectionWrapper.lambda$patchAsync$9(ServletConnectionFactory.java:317)
at org.forgerock.openidm.servlet.internal.ServletConnectionFactory$InternalConnectionWrapper$$Lambda$1164/0000000000000000.get(Unknown Source)
at org.forgerock.openidm.metrics.MetricsCollector.time(MetricsCollector.java:112)
at org.forgerock.openidm.servlet.internal.ServletConnectionFactory$InternalConnectionWrapper.time(ServletConnectionFactory.java:263)
at org.forgerock.openidm.servlet.internal.ServletConnectionFactory$InternalConnectionWrapper.patchAsync(ServletConnectionFactory.java:317)
at org.forgerock.json.resource.http.RequestRunner.visitPatchRequest(RequestRunner.java:214)
at org.forgerock.json.resource.http.RequestRunner.visitPatchRequest(RequestRunner.java:87)
at org.forgerock.json.resource.Requests$PatchRequestImpl.accept(Requests.java:362)
at org.forgerock.json.resource.http.RequestRunner.handleResult(RequestRunner.java:143)
at org.forgerock.json.resource.http.HttpAdapter$$Lambda$1057/0000000000000000.apply(Unknown Source)
at org.forgerock.util.promise.Promises$CompletedPromise.thenAsync(Promises.java:263)
at org.forgerock.util.promise.Promises$CompletedPromise.thenAsync(Promises.java:252)
at org.forgerock.json.resource.http.HttpAdapter.doRequest(HttpAdapter.java:747)
at org.forgerock.json.resource.http.HttpAdapter.doPatch(HttpAdapter.java:544)
at org.forgerock.json.resource.http.HttpAdapter.handle(HttpAdapter.java:311)
at org.forgerock.http.handler.Handlers$HandlerDescribableAsDescribableHandler.handle(Handlers.java:147)
at org.forgerock.http.filter.OptionsFilter.filter(OptionsFilter.java:69)
at org.forgerock.http.handler.Handlers$1.handle(Handlers.java:54)
at org.forgerock.openidm.auth.ProfileEnhancementCheckFilter.filter(ProfileEnhancementCheckFilter.java:157)
at org.forgerock.http.handler.Handlers$1.handle(Handlers.java:54)
at org.forgerock.openidm.auth.LoginCountFilter.filter(LoginCountFilter.java:75)
at org.forgerock.http.handler.Handlers$1.handle(Handlers.java:54)
at org.forgerock.caf.authentication.framework.AuthenticationFramework.grantAccess(AuthenticationFramework.java:188)
at org.forgerock.caf.authentication.framework.AuthenticationFramework.lambda$onValidateRequestSuccess$1(AuthenticationFramework.java:181)
at org.forgerock.caf.authentication.framework.AuthenticationFramework$$Lambda$1051/0000000000000000.apply(Unknown Source)
at org.forgerock.util.promise.Promises$CompletedPromise.thenAsync(Promises.java:263)
at org.forgerock.util.promise.Promises$CompletedPromise.thenAsync(Promises.java:252)
at org.forgerock.caf.authentication.framework.AuthenticationFramework.validateRequest(AuthenticationFramework.java:144)
at org.forgerock.caf.authentication.framework.AuthenticationFramework.processMessage(AuthenticationFramework.java:134)
at org.forgerock.caf.authentication.framework.AuthenticationFilter.filter(AuthenticationFilter.java:85)
at org.forgerock.openidm.auth.AuthFilterWrapper.filter(AuthFilterWrapper.java:85)
at org.forgerock.http.handler.Handlers$1.handle(Handlers.java:54)
at org.forgerock.http.swagger.OpenApiRequestFilter.filter(OpenApiRequestFilter.java:63)
at org.forgerock.http.handler.Handlers$1.handle(Handlers.java:54)
at org.forgerock.http.routing.Router.handle(Router.java:100)
at org.forgerock.http.filter.TransactionIdInboundFilter.filter(TransactionIdInboundFilter.java:86)
at org.forgerock.http.handler.Handlers$1.handle(Handlers.java:54)
at org.forgerock.http.servlet.HttpFrameworkServlet.service(HttpFrameworkServlet.java:262)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
at org.eclipse.jetty.servlet.ServletHolder$NotAsyncServlet.service(ServletHolder.java:1386)
at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:755)
at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1617)
at org.eclipse.jetty.servlets.CrossOriginFilter.handle(CrossOriginFilter.java:310)
at org.eclipse.jetty.servlets.CrossOriginFilter.doFilter(CrossOriginFilter.java:264)
at jdk.internal.reflect.GeneratedMethodAccessor101.invoke(Unknown Source)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.forgerock.openidm.servletregistration.impl.ServletRegistrationSingleton$FilterProxy.invoke(ServletRegistrationSingleton.java:327)
at com.sun.proxy.$Proxy60.doFilter(Unknown Source)
at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1604)
at org.forgerock.openidm.jetty.LargePayloadServletFilter.doFilter(LargePayloadServletFilter.java:64)
at jdk.internal.reflect.GeneratedMethodAccessor101.invoke(Unknown Source)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.forgerock.openidm.servletregistration.impl.ServletRegistrationSingleton$FilterProxy.invoke(ServletRegistrationSingleton.java:327)
at com.sun.proxy.$Proxy59.doFilter(Unknown Source)
at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1604)
at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:545)
at org.ops4j.pax.web.service.jetty.internal.HttpServiceServletHandler.doHandle(HttpServiceServletHandler.java:71)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143)
at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:590)
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:127)
at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:235)
at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:1607)
at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:233)
at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1297)
at org.ops4j.pax.web.service.jetty.internal.HttpServiceContext.doHandle(HttpServiceContext.java:290)
at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:188)
at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:485)
at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:1577)
at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:186)
at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1212)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141)
at org.ops4j.pax.web.service.jetty.internal.JettyServerHandlerCollection.handle(JettyServerHandlerCollection.java:80)
at org.eclipse.jetty.server.handler.gzip.GzipHandler.handle(GzipHandler.java:717)
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:127)
at org.eclipse.jetty.server.Server.handle(Server.java:500)
at org.eclipse.jetty.server.HttpChannel.lambda$handle$1(HttpChannel.java:383)
at org.eclipse.jetty.server.HttpChannel$$Lambda$1011/0000000000000000.dispatch(Unknown Source)
at org.eclipse.jetty.server.HttpChannel.dispatch(HttpChannel.java:547)
at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:375)
at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:270)
at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:311)
at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:103)
at org.eclipse.jetty.io.ChannelEndPoint$2.run(ChannelEndPoint.java:117)
at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.runTask(EatWhatYouKill.java:336)
at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.doProduce(EatWhatYouKill.java:313)
at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.tryProduce(EatWhatYouKill.java:171)
at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.run(EatWhatYouKill.java:129)
at org.eclipse.jetty.util.thread.ReservedThreadExecutor$ReservedThread.run(ReservedThreadExecutor.java:388)
at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:806)
at org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.run(QueuedThreadPool.java:938)
at java.base/java.lang.Thread.run(Thread.java:836)
Caused by: org.forgerock.json.resource.NotFoundException: Object user1 not found in managed/user
at org.forgerock.json.resource.ResourceException.newResourceException(ResourceException.java:225)
at org.forgerock.json.resource.ResourceException.newResourceException(ResourceException.java:187)
at org.forgerock.openidm.repo.jdbc.impl.JDBCRepoService.lambda$handleReadUsingFilter$4(JDBCRepoService.java:341)
at org.forgerock.openidm.repo.jdbc.impl.JDBCRepoService$$Lambda$1532/0000000000000000.apply(Unknown Source)
at org.forgerock.util.promise.Promises$CompletedPromise.thenAsync(Promises.java:263)
at org.forgerock.util.promise.Promises$CompletedPromise.thenAsync(Promises.java:227)
at org.forgerock.openidm.repo.jdbc.impl.JDBCRepoService.handleReadUsingFilter(JDBCRepoService.java:338)
at org.forgerock.openidm.repo.jdbc.impl.JDBCRepoService.handleRead(JDBCRepoService.java:283)
at org.forgerock.json.resource.Router.handleRead(Router.java:331)
at org.forgerock.json.resource.FilterChain$Cursor.handleRead(FilterChain.java:104)
at org.forgerock.json.resource.ResourceApiVersionRoutingFilter.filterRead(ResourceApiVersionRoutingFilter.java:79)
at org.forgerock.json.resource.FilterChain$Cursor.handleRead(FilterChain.java:102)
at org.forgerock.json.resource.FilterChain.handleRead(FilterChain.java:255)
at org.forgerock.json.resource.Router.handleRead(Router.java:331)
at org.forgerock.json.resource.FilterChain$Cursor.handleRead(FilterChain.java:104)
at org.forgerock.json.resource.Filters$ConditionalFilter.filterRead(Filters.java:94)
at org.forgerock.json.resource.FilterChain$Cursor.handleRead(FilterChain.java:102)
at org.forgerock.json.resource.Filters$ConditionalFilter.filterRead(Filters.java:94)
at org.forgerock.json.resource.FilterChain$Cursor.handleRead(FilterChain.java:102)
at org.forgerock.json.resource.Filters$ConditionalFilter.filterRead(Filters.java:94)
at org.forgerock.json.resource.FilterChain$Cursor.handleRead(FilterChain.java:102)
at org.forgerock.json.resource.Filters$ConditionalFilter.filterRead(Filters.java:94)
at org.forgerock.json.resource.FilterChain$Cursor.handleRead(FilterChain.java:102)
at org.forgerock.json.resource.Filters$ConditionalFilter.filterRead(Filters.java:94)
at org.forgerock.json.resource.FilterChain$Cursor.handleRead(FilterChain.java:102)
at org.forgerock.openidm.audit.filter.AuditFilter.lambda$filterRead$5(AuditFilter.java:151)
at org.forgerock.openidm.audit.filter.AuditFilter$$Lambda$977/0000000000000000.get(Unknown Source)
at org.forgerock.openidm.audit.filter.AuditFilter.logAuditAccessEntry(AuditFilter.java:177)
at org.forgerock.openidm.audit.filter.AuditFilter.filterRead(AuditFilter.java:151)
at org.forgerock.openidm.router.filter.MutableFilterDecorator.filterRead(MutableFilterDecorator.java:96)
at org.forgerock.json.resource.Filters$ConditionalFilter.filterRead(Filters.java:92)
at org.forgerock.json.resource.FilterChain$Cursor.handleRead(FilterChain.java:102)
at org.forgerock.openidm.servlet.internal.ResourceFilters$3.lambda$filterRead$5(ResourceFilters.java:200)
at org.forgerock.openidm.servlet.internal.ResourceFilters$3$$Lambda$452/0000000000000000.get(Unknown Source)
at org.forgerock.openidm.servlet.internal.ResourceFilters$3.handleRequestWithLogging(ResourceFilters.java:222)
at org.forgerock.openidm.servlet.internal.ResourceFilters$3.filterRead(ResourceFilters.java:200)
at org.forgerock.json.resource.FilterChain$Cursor.handleRead(FilterChain.java:102)
at org.forgerock.openidm.router.filter.QueryIdToQueryFilterTransformFilter.filterRead(QueryIdToQueryFilterTransformFilter.java:245)
at org.forgerock.json.resource.FilterChain$Cursor.handleRead(FilterChain.java:102)
at org.forgerock.openidm.router.filter.PassthroughFilter.filterRead(PassthroughFilter.java:72)
at org.forgerock.openidm.router.filter.MutableFilterDecorator.filterRead(MutableFilterDecorator.java:96)
at org.forgerock.openidm.router.filter.MutableFilterDecorator.filterRead(MutableFilterDecorator.java:96)
at org.forgerock.json.resource.FilterChain$Cursor.handleRead(FilterChain.java:102)
at org.forgerock.json.resource.Filters$ConditionalFilter.filterRead(Filters.java:94)
at org.forgerock.json.resource.FilterChain$Cursor.handleRead(FilterChain.java:102)
at org.forgerock.json.resource.Filters$ConditionalFilter.filterRead(Filters.java:94)
at org.forgerock.json.resource.FilterChain$Cursor.handleRead(FilterChain.java:102)
at org.forgerock.json.resource.FilterChain.handleRead(FilterChain.java:255)
at org.forgerock.json.resource.InternalConnection.readAsync(InternalConnection.java:81)
at org.forgerock.json.resource.AbstractConnectionWrapper.readAsync(AbstractConnectionWrapper.java:203)
at org.forgerock.openidm.servlet.internal.ServletConnectionFactory$InternalConnectionWrapper.lambda$readAsync$3(ServletConnectionFactory.java:286)
at org.forgerock.openidm.servlet.internal.ServletConnectionFactory$InternalConnectionWrapper$$Lambda$451/0000000000000000.get(Unknown Source)
at org.forgerock.openidm.metrics.MetricsCollector.time(MetricsCollector.java:112)
at org.forgerock.openidm.servlet.internal.ServletConnectionFactory$InternalConnectionWrapper.time(ServletConnectionFactory.java:263)
at org.forgerock.openidm.servlet.internal.ServletConnectionFactory$InternalConnectionWrapper.readAsync(ServletConnectionFactory.java:286)
at org.forgerock.json.resource.AbstractConnectionWrapper.readAsync(AbstractConnectionWrapper.java:203)
at org.forgerock.openidm.relationship.AugmentingIDMConnectionFactoryProxy$ConnectionRequestHandlerAdaptor.handleRead(AugmentingIDMConnectionFactoryProxy.java:202)
at org.forgerock.json.resource.FilterChain$Cursor.handleRead(FilterChain.java:104)
at org.forgerock.openidm.relationship.impl.augmentation.NullArrayFilter.filterRead(NullArrayFilter.java:120)
at org.forgerock.json.resource.Filters$ConditionalFilter.filterRead(Filters.java:92)
at org.forgerock.json.resource.FilterChain$Cursor.handleRead(FilterChain.java:102)
at org.forgerock.openidm.relationship.impl.augmentation.FieldAugmentationFilter.filterRead(FieldAugmentationFilter.java:184)
at org.forgerock.json.resource.Filters$ConditionalFilter.filterRead(Filters.java:92)
at org.forgerock.json.resource.FilterChain$Cursor.handleRead(FilterChain.java:102)
at org.forgerock.openidm.relationship.impl.augmentation.EdgeFieldAugmentationFilter.filterRead(EdgeFieldAugmentationFilter.java:235)
at org.forgerock.json.resource.Filters$ConditionalFilter.filterRead(Filters.java:92)
at org.forgerock.json.resource.FilterChain$Cursor.handleRead(FilterChain.java:102)
at org.forgerock.json.resource.FilterChain.handleRead(FilterChain.java:255)
at org.forgerock.openidm.relationship.AugmentingIDMConnectionFactoryProxy$RequestHandlerConnectionAdaptor.readAsync(AugmentingIDMConnectionFactoryProxy.java:272)
at org.forgerock.json.resource.AbstractConnectionWrapper.readAsync(AbstractConnectionWrapper.java:203)
at org.forgerock.openidm.managed.ManagedObjectSet.update(ManagedObjectSet.java:811)
... 173 more
 
User1 then has a blank effectiveManager (virtual attribute updated onStore) even through manager1 can read manager attribute - I even went so far as to allow the manager1 to read/write (not needed when repo was DS).  



 Comments   
Comment by Tim Vogt [ 27/Aug/20 ]

Having successfully reproduced this issue, I'd describe the symptoms as "PATCH operation fails with 500 error for delegated administrator on object with allowed r/w access to attribute", while the root cause seems to be related to virtual property calculation (see bottom).
To reproduce, set up a basic manager/reports DA configuration with a Postgres repo, along the lines of the Wiki article referenced in the main description.
As delegated manager, then attempt a PATCH operation on an allowed attribute, for instance 'description':

PATCH -a manager2:password http://localhost:8080/openidm/managed/user/user2
[
	{
		"operation":"replace",
		"field":"/description",
		"value":"this is my report"
	}
]

Result: 500 internal Server error in the logs.
A read of the affected user as openidm-admin shows that the patch operation succeeded, but the virtual property got set to null:

{
    "_id": "user2",
    "_rev": "2",
    "accountStatus": "active",
    "description": "this is my report",
    "effectiveAssignments": [],
    "effectiveManager": null,
    "effectiveRoles": [],
    "givenName": "User",
    "mail": "user2@test.com",
    "sn": "2",
    "userName": "user2"
}

Some added logging to the onStore script shows that the virtual property returned is the flattened string, rather than the virtual property object, indicating that the virtual property is not being recalculated:

INFO: VIRTUALPROP: manager2, object: {userName=user2, sn=2, givenName=User, mail=user2@test.com, password={$crypto={type=x-simple-encryption, value={cipher=AES/CBC/PKCS5Padding, stableId=openidm-sym-default, salt=RwuIYbyOkI1BL6jIyixQcw==, data=q/GAtyPjOfcMkw9DQBTPYQ==, keySize=16, purpose=idm.password.encryption, iv=B29ths/KnmO0t1NizQIpeQ==, mac=I/86gUhMfKeFhMActa1yrQ==}}}, accountStatus=active, effectiveAssignments=[], effectiveRoles=[], _id=user2, _rev=4, effectiveManager=manager2, description=this is my report}

Because the onStore script returns property._refResourceId, which is undefined, we probably end up with null, which then causes some subsequent action to fail.
So the root cause seems to be that an object update that does not involve a relationship field referenced by a virtual property query, does not trigger virtual property recalculation. Instead, the stored value is used and passed downstream.
A workaround might be to refrain from modifying the stored result, and reference the relevant field of the virtual property directly, will need to test.

Comment by Tim Vogt [ 27/Aug/20 ]

Update: Same issue with DS as repo, except no 500 error in the logs.

As expected, removing the onStore script and using '/effectiveManager/_refResourceId eq {{_id}}' in the privilege query filter works around this problem.

Comment by Dirk Hogan [ 27/Aug/20 ]

Tim Vogt thanks for investigating and providing this detail.

I can confirm that virtual properties will be recalculated only if the relationship property from which it is derived is updated. This is by design, and is a significant performance improvement. So any onStore script needs to accommodate the fact that that this property might currently be in the desired state, and thus no-op.

If this is indeed the case, then the knowledge base article should be updated, and this defect closed. Note that this change was somewhat late-breaking, and likely occurred after Tim Vogt you did your initial work with this feature, and wrote the knowledge-base article.

Comment by Katie Gonzalez [ 27/Aug/20 ]

Thank you Tim Vogt and Dirk Hogan for your feedback on this.
Something similar to the below script will work to avoid the invalid replacement of the effectiveManager. As Dirk stated, it just needs to be written to no-op. Closing the JIRA as not a defect.

if (typeof property === 'object') {
  property = property._id;
}
property;
Comment by Cyril Grosjean [ 07/Sep/20 ]

+1 Tim Vogt )

Comment by Dirk Hogan [ 08/Sep/20 ]

Re-opening per Tim Vogt's comments. Alternatives need to be discussed.

Comment by Brendan Miller [ 23/Sep/20 ]

Engineering to look at virtual property calculation and specific use-cases to try to re-imagine solution without brittle onStore implementation.

In the mean time, a fancier onStore script will solve this as a workaround.

Comment by Dirk Hogan [ 08/Oct/20 ]

Tim Vogt, while working on the organization data model, I was thinking the following. It is easy to implement. Let me know what you think.

If only a single field in referencedObjectFields is specified, then this field will be included, 'bare'(i.e. not in an object, with both _id and _rev), in the virtual property field, either in the array, if the virtual property field traverses a non-singleton relationship, or directly, if only singleton relationships are traversed. So if only '_id' is specified in referencedObjectFields, then effectiveAssignments could look like ["id_1", "id_2", "id_3"] or [], and effectiveManager could look like "my_manager_id" or null. 

This would also mean that if the single field specified in referencedObjectFields was an int field, we could have [1,2,3] or []  (non-singletons) or 1 or null (singletons). (I have not tested this, but this is my expectation.)

And in order to not break backward compatibility, this new behavior will only be toggled by the presence of some state in the queryConfig config object - something like "flattenSingleFieldProperties" : true/false.

Comment by Tim Vogt [ 08/Oct/20 ]

Dirk Hogan I like it ! In a DA scenario, all you want to get out of the traversal is something you can use easily in a privilege filter, and this would exactly do the trick and therefore remove the need for an onStore script.
With that out of the way, I think that the chance of someone needing to transform the returned properties using onStore (and therefore having to handle in that script the different returns causing the original issue) when "flattenSingleFieldProperties" : false is fairly small.

Comment by Dirk Hogan [ 24/Nov/20 ]

Addressed by work done in https://bugster.forgerock.org/jira/browse/OPENIDM-15626

Generated at Mon Mar 08 12:35:42 UTC 2021 using Jira 7.13.12#713012-sha1:6e07c38070d5191bbf7353952ed38f111754533a.