Messages sent by UserA cannot be written into the Private Workspace of UserB
Problem: The following code was used to create a notification, to which UserB has subscribed to receive, but cannot due to our access-control concept.
Topic usersWorkspace = dmx.getPrivilegedAccess().getPrivateWorkspace(username.getSimpleValue().toString());
dmx.getPrivilegedAccess().runInWorkspaceContext(usersWorkspace.getId(), () -> {
// 1) Create notification topic
ChildTopicsModel message = mf.newChildTopicsModel()
.set(NOTIFICATION_SEEN, false)
.set(NOTIFICATION_TITLE, title)
.set(NOTIFICATION_BODY, text)
.setRef(USERNAME, actingUsername)
.set(INVOLVED_ITEM_ID, involvedItem.getId());
if (subscribedItem != null) message.set(SUBSCRIBED_ITEM_ID, subscribedItem.getId());
TopicModel model = mf.newTopicModel(NOTIFICATION, message);
Topic notification = dmx.createTopic(model);
// Improvement: Try using topicmaps.setViewProperties()... (not having a topicmap) to colorize..
// 2) Relate notification to subscribing username topic
AssocModel recipientModel = mf.newAssocModel(NOTIFICATION_RECIPIENT_EDGE,
model.createPlayerModel(DEFAULT),
mf.newTopicPlayerModel(username.getId(), DEFAULT));
dmx.createAssoc(recipientModel);
log.info("Created notification for " + username.getSimpleValue() + " with title " + notification.getSimpleValue());
return notification;
});
Which produces the following stacktrace:
Jan 03, 2021 5:38:25 PM systems.dmx.core.util.UniversalExceptionMapper logException
SCHWERWIEGEND: Request "POST /core/topic" failed. Responding with 401 (Unauthorized). The original exception/error is:
java.lang.RuntimeException: Creating topic failed, model=TopicModelImpl {
"id": -1,
"typeUri": "dmx.notes.note",
"children": {"dmx.notes.title": {
"id": 6339,
"typeUri": "dmx.notes.title",
"value": "Note 2",
"children": {}
}}
}
at systems.dmx.core.impl.AccessLayer.createTopic(AccessLayer.java:140)
at systems.dmx.core.impl.CoreServiceImpl.createTopic(CoreServiceImpl.java:133)
at systems.dmx.core.impl.CoreServiceImpl.createTopic(CoreServiceImpl.java:35)
at systems.dmx.webservice.WebservicePlugin.createTopic(WebservicePlugin.java:121)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.sun.jersey.spi.container.JavaMethodInvokerFactory$1.invoke(JavaMethodInvokerFactory.java:60)
at com.sun.jersey.server.impl.model.method.dispatch.AbstractResourceMethodDispatchProvider$TypeOutInvoker._dispatch(AbstractResourceMethodDispatchProvider.java:185)
at com.sun.jersey.server.impl.model.method.dispatch.ResourceJavaMethodDispatcher.dispatch(ResourceJavaMethodDispatcher.java:75)
at com.sun.jersey.server.impl.uri.rules.HttpMethodRule.accept(HttpMethodRule.java:302)
at com.sun.jersey.server.impl.uri.rules.RightHandPathRule.accept(RightHandPathRule.java:147)
at com.sun.jersey.server.impl.uri.rules.ResourceObjectRule.accept(ResourceObjectRule.java:100)
at com.sun.jersey.server.impl.uri.rules.RightHandPathRule.accept(RightHandPathRule.java:147)
at com.sun.jersey.server.impl.uri.rules.RootResourceClassesRule.accept(RootResourceClassesRule.java:84)
at com.sun.jersey.server.impl.application.WebApplicationImpl._handleRequest(WebApplicationImpl.java:1480)
at com.sun.jersey.server.impl.application.WebApplicationImpl._handleRequest(WebApplicationImpl.java:1411)
at com.sun.jersey.server.impl.application.WebApplicationImpl.handleRequest(WebApplicationImpl.java:1360)
at com.sun.jersey.server.impl.application.WebApplicationImpl.handleRequest(WebApplicationImpl.java:1350)
at com.sun.jersey.spi.container.servlet.WebComponent.service(WebComponent.java:416)
at com.sun.jersey.spi.container.servlet.ServletContainer.service(ServletContainer.java:538)
at com.sun.jersey.spi.container.servlet.ServletContainer.service(ServletContainer.java:716)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
at org.apache.felix.http.base.internal.handler.ServletHandler.doHandle(ServletHandler.java:339)
at org.apache.felix.http.base.internal.handler.ServletHandler.handle(ServletHandler.java:300)
at org.apache.felix.http.base.internal.dispatch.ServletPipeline.handle(ServletPipeline.java:93)
at org.apache.felix.http.base.internal.dispatch.InvocationFilterChain.doFilter(InvocationFilterChain.java:50)
at org.apache.felix.http.base.internal.dispatch.HttpFilterChain.doFilter(HttpFilterChain.java:31)
at org.apache.felix.http.base.internal.dispatch.FilterPipeline.dispatch(FilterPipeline.java:76)
at org.apache.felix.http.base.internal.dispatch.Dispatcher.dispatch(Dispatcher.java:49)
at org.apache.felix.http.base.internal.DispatcherServlet.service(DispatcherServlet.java:67)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:684)
at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:501)
at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:229)
at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1086)
at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:428)
at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:193)
at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1020)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:135)
at org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:255)
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:116)
at org.eclipse.jetty.server.Server.handle(Server.java:370)
at org.eclipse.jetty.server.AbstractHttpConnection.handleRequest(AbstractHttpConnection.java:494)
at org.eclipse.jetty.server.AbstractHttpConnection.content(AbstractHttpConnection.java:982)
at org.eclipse.jetty.server.AbstractHttpConnection$RequestHandler.content(AbstractHttpConnection.java:1043)
at org.eclipse.jetty.http.HttpParser.parseNext(HttpParser.java:865)
at org.eclipse.jetty.http.HttpParser.parseAvailable(HttpParser.java:240)
at org.eclipse.jetty.server.AsyncHttpConnection.handle(AsyncHttpConnection.java:82)
at org.eclipse.jetty.io.nio.SelectChannelEndPoint.handle(SelectChannelEndPoint.java:667)
at org.eclipse.jetty.io.nio.SelectChannelEndPoint$1.run(SelectChannelEndPoint.java:52)
at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:608)
at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:543)
at java.lang.Thread.run(Thread.java:748)
Caused by: java.lang.RuntimeException: Value integration failed, newValues=TopicModelImpl {
"id": -1,
"typeUri": "dmx.notes.note",
"children": {"dmx.notes.title": {
"id": 6339,
"typeUri": "dmx.notes.title",
"value": "Note 2",
"children": {}
}}
}, targetObject=null, compDef=null
at systems.dmx.core.impl.ValueIntegrator.integrate(ValueIntegrator.java:115)
at systems.dmx.core.impl.AccessLayer.updateValues(AccessLayer.java:1031)
at systems.dmx.core.impl.AccessLayer.createTopic(AccessLayer.java:138)
... 54 more
Caused by: java.lang.RuntimeException: An error occurred in the PostCreateTopic listener of plugin "DMX Notifications"
at systems.dmx.core.impl.EventManager.dispatchEvent(EventManager.java:96)
at systems.dmx.core.impl.EventManager.fireEvent(EventManager.java:59)
at systems.dmx.core.impl.ValueIntegrator.integrate(ValueIntegrator.java:108)
... 56 more
Caused by: java.lang.RuntimeException: Creating notification for user admin failed
at systems.dmx.notifications.NotificationsPlugin.createNotificationTopic(NotificationsPlugin.java:465)
at systems.dmx.notifications.NotificationsPlugin.createNotifications(NotificationsPlugin.java:417)
at systems.dmx.notifications.NotificationsPlugin.notifySubscribers(NotificationsPlugin.java:218)
at systems.dmx.notifications.NotificationsPlugin.notifyWorkspaceSubscribersAboutNewNote(NotificationsPlugin.java:344)
at systems.dmx.notifications.NotificationsPlugin.postCreateTopic(NotificationsPlugin.java:82)
at systems.dmx.core.impl.CoreEvent$9.dispatch(CoreEvent.java:113)
at systems.dmx.core.impl.EventManager.dispatchEvent(EventManager.java:83)
... 58 more
Caused by: java.lang.RuntimeException: Creating topic failed, model=TopicModelImpl {
"id": -1,
"typeUri": "dmx.notification",
"children": {
"dmx.notification_body": {
"id": -1,
"typeUri": "dmx.notification_body",
"value": "UserA noted \"Note 2\" in workspace \"Webpages\"",
"children": {}
},
"dmx.accesscontrol.username": {
"id": 6223,
"typeUri": "dmx.accesscontrol.username",
"children": {}
},
"dmx.notification_title": {
"id": -1,
"typeUri": "dmx.notification_title",
"value": "UserA noted \"Note 2\" in workspace \"Webpages\"",
"children": {}
},
"dmx.subscribed_item_id": {
"id": -1,
"typeUri": "dmx.subscribed_item_id",
"value": 5124,
"children": {}
},
"dmx.notification_seen": {
"id": -1,
"typeUri": "dmx.notification_seen",
"value": false,
"children": {}
},
"dmx.involved_item_id": {
"id": -1,
"typeUri": "dmx.involved_item_id",
"value": 6431,
"children": {}
}
}
}
at systems.dmx.core.impl.AccessLayer.createTopic(AccessLayer.java:140)
at systems.dmx.core.impl.CoreServiceImpl.createTopic(CoreServiceImpl.java:133)
at systems.dmx.core.impl.CoreServiceImpl.createTopic(CoreServiceImpl.java:35)
at systems.dmx.notifications.NotificationsPlugin.lambda$createNotificationTopic$0(NotificationsPlugin.java:454)
at systems.dmx.core.util.ContextTracker.run(ContextTracker.java:20)
at systems.dmx.core.impl.PrivilegedAccessImpl.runInWorkspaceContext(PrivilegedAccessImpl.java:354)
at systems.dmx.notifications.NotificationsPlugin.createNotificationTopic(NotificationsPlugin.java:444)
... 64 more
Caused by: java.lang.RuntimeException: Value integration failed, newValues=TopicModelImpl {
"id": -1,
"typeUri": "dmx.notification",
"children": {
"dmx.notification_body": {
"id": -1,
"typeUri": "dmx.notification_body",
"value": "UserA noted \"Note 2\" in workspace \"Webpages\"",
"children": {}
},
"dmx.accesscontrol.username": {
"id": 6223,
"typeUri": "dmx.accesscontrol.username",
"children": {}
},
"dmx.notification_title": {
"id": -1,
"typeUri": "dmx.notification_title",
"value": "UserA noted \"Note 2\" in workspace \"Webpages\"",
"children": {}
},
"dmx.subscribed_item_id": {
"id": -1,
"typeUri": "dmx.subscribed_item_id",
"value": 5124,
"children": {}
},
"dmx.notification_seen": {
"id": -1,
"typeUri": "dmx.notification_seen",
"value": false,
"children": {}
},
"dmx.involved_item_id": {
"id": -1,
"typeUri": "dmx.involved_item_id",
"value": 6431,
"children": {}
}
}
}, targetObject=null, compDef=null
at systems.dmx.core.impl.ValueIntegrator.integrate(ValueIntegrator.java:115)
at systems.dmx.core.impl.AccessLayer.updateValues(AccessLayer.java:1031)
at systems.dmx.core.impl.AccessLayer.createTopic(AccessLayer.java:138)
... 70 more
Caused by: java.lang.RuntimeException: Value integration failed, newValues=RelatedTopicModelImpl {
"id": -1,
"typeUri": "dmx.notification_title",
"value": "UserA noted \"Note 2\" in workspace \"Webpages\"",
"children": {}
}, targetObject=null, compDef=null
at systems.dmx.core.impl.ValueIntegrator.integrate(ValueIntegrator.java:115)
at systems.dmx.core.impl.ValueIntegrator.integrateChildValue(ValueIntegrator.java:289)
at systems.dmx.core.impl.ValueIntegrator.integrateComposite(ValueIntegrator.java:257)
at systems.dmx.core.impl.ValueIntegrator.integrate(ValueIntegrator.java:103)
... 72 more
Caused by: java.lang.RuntimeException: An error occurred in the PostCreateTopic listener of plugin "DMX Workspaces"
at systems.dmx.core.impl.EventManager.dispatchEvent(EventManager.java:96)
at systems.dmx.core.impl.EventManager.fireEvent(EventManager.java:59)
at systems.dmx.core.impl.ValueIntegrator.integrate(ValueIntegrator.java:108)
... 75 more
Caused by: java.lang.RuntimeException: Assigning topic 6440 (typeUri="dmx.notification_title", uri="") to workspace 3791 failed
at systems.dmx.workspaces.WorkspacesPlugin._assignToWorkspace(WorkspacesPlugin.java:458)
at systems.dmx.workspaces.WorkspacesPlugin.postCreateTopic(WorkspacesPlugin.java:365)
at systems.dmx.core.impl.CoreEvent$9.dispatch(CoreEvent.java:113)
at systems.dmx.core.impl.EventManager.dispatchEvent(EventManager.java:83)
... 77 more
Caused by: java.lang.RuntimeException: Fetching topic 3791 failed
at systems.dmx.core.impl.AccessLayer.getTopic(AccessLayer.java:69)
at systems.dmx.core.impl.CoreServiceImpl.getTopic(CoreServiceImpl.java:84)
at systems.dmx.workspaces.WorkspacesPlugin.checkAssignmentArgs(WorkspacesPlugin.java:489)
at systems.dmx.workspaces.WorkspacesPlugin._assignToWorkspace(WorkspacesPlugin.java:455)
... 80 more
Caused by: systems.dmx.core.service.accesscontrol.AccessControlException: user "UserA" has no READ permission for object 3791
at systems.dmx.accesscontrol.AccessControlPlugin.checkAccess(AccessControlPlugin.java:966)
at systems.dmx.accesscontrol.AccessControlPlugin.checkReadAccess(AccessControlPlugin.java:944)
at systems.dmx.accesscontrol.AccessControlPlugin.checkTopicReadAccess(AccessControlPlugin.java:529)
at systems.dmx.core.impl.CoreEvent$1.dispatch(CoreEvent.java:35)
at systems.dmx.core.impl.EventManager.dispatchEvent(EventManager.java:83)
at systems.dmx.core.impl.EventManager.fireEvent(EventManager.java:59)
at systems.dmx.core.impl.AccessLayer.checkTopicReadAccess(AccessLayer.java:780)
at systems.dmx.core.impl.TopicModelImpl.checkReadAccess(TopicModelImpl.java:137)
at systems.dmx.core.impl.AccessLayer.getTopic(AccessLayer.java:67)
... 83 more
Topic with ID 3791
is the "Private Workspace" of UserB
.
I suspect, despite the use of the "getPrivilegedAccess" method, this is expected behaviour so that a plugin cannot write into the private workspace of UserB on behalf of UserA. Is this correct?
Solution:
Following the access-control concept the obvious solution is that such a message can only be send confidentially from UserA to UserB if a shared workspace is created exactly for this purpose. UserA and UserB would then be the only members of this workspace and the workspace sharing mode would be set to Confidential.
For guaranteeing confidentility of the messages the notifications plugin would then need to create a workspace for every combination of users who issue notifications (think messages) to each other and the plugin should check for and re-use such a workspace for sending subsequent notifications. These workspaces could be auto-named as "UserA / UserB" workspaces.
If anyone sees another solution for this case, please bring it on.