Ticket #899 (closed Defect: fixed)

Opened 5 years ago

Last modified 5 years ago

A permission to work with a Topic implicitly allows to read the typeDef

Reported by: Malte Owned by: jri
Priority: Major Milestone: Release 4.8
Component: DeepaMehta Standard Distribution Version: 4.7
Keywords: Cc: jri, dgf, JuergeN
Complexity: 3 Area: Application Framework / API
Module: deepamehta-accesscontrol

Description

Scenario is, when working with dm47-webpages-0.3:

All three Types (Website, Webpage and Redirect) are assigned to the Private Workspace of "admin"
With reasons being: No other user (than "admin") should be able to "Create" a topic of such types and no other user than admin should be able to "Edit" one of the Type Definitions.

The desired behavior here is that "creation" of certain types of topic is limited to users within a workspace but these topics (once created) can then be assigned into other workspaces (e.g. to get published) and once their, can not only be READ but also EDITED by users (who possibly have no membership in the workspaces where the READ permission for the type definitions are assembled).

A topic which flows around into other workspaces should remain READ- or WRITEable if a user has READ or WRITE to this very topic. I think this is what we want and i think we should try to enforce this in the next release.

What do you think?

INFO: ##### Logging out from session 134t3qve08nuv19gef359zhb9z (username=Malte)
Nov 29, 2015 2:02:44 PM de.deepamehta.plugins.topicmaps.TopicmapsPlugin getTopicmap
INFO: Loading topicmap 32613 (includeChilds=false)
Nov 29, 2015 2:02:45 PM de.deepamehta.core.impl.TypeCache loadTopicType
INFO: Loading topic type "de.mikromedia.redirect"
Nov 29, 2015 2:02:45 PM de.deepamehta.core.util.UniversalExceptionMapper logException
SEVERE: Request "GET /" failed. Responding with 401 (Unauthorized). The original exception/error is:
java.lang.RuntimeException: Fetching topic type "de.mikromedia.redirect" failed
	at de.deepamehta.core.impl.EmbeddedService.getTopicType(EmbeddedService.java:346)
	at de.deepamehta.core.impl.AttachedTopic.getType(AttachedTopic.java:242)
	at de.deepamehta.core.impl.AttachedTopic.getType(AttachedTopic.java:25)
	at de.deepamehta.core.impl.AttachedChildTopics.loadChildTopics(AttachedChildTopics.java:332)
	at de.deepamehta.core.impl.AttachedDeepaMehtaObject.loadChildTopics(AttachedDeepaMehtaObject.java:163)
	at de.deepamehta.core.impl.AttachedTopic.loadChildTopics(AttachedTopic.java:88)
	at de.mikromedia.webpages.WebpagePlugin.handleWebsiteRedirects(WebpagePlugin.java:227)
	at de.mikromedia.webpages.WebpagePlugin.getFrontpageView(WebpagePlugin.java:77)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:606)
	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.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.headerComplete(AbstractHttpConnection.java:971)
	at org.eclipse.jetty.server.AbstractHttpConnection$RequestHandler.headerComplete(AbstractHttpConnection.java:1033)
	at org.eclipse.jetty.http.HttpParser.parseNext(HttpParser.java:644)
	at org.eclipse.jetty.http.HttpParser.parseAvailable(HttpParser.java:235)
	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:745)
Caused by: java.lang.RuntimeException: Fetching topic failed (key="uri", value="de.mikromedia.redirect")
	at de.deepamehta.core.impl.EmbeddedService.getTopic(EmbeddedService.java:115)
	at de.deepamehta.core.impl.TypeStorageImpl.fetchTopicType(TypeStorageImpl.java:102)
	at de.deepamehta.core.impl.TypeStorageImpl.getTopicType(TypeStorageImpl.java:72)
	at de.deepamehta.core.impl.TypeCache.loadTopicType(TypeCache.java:97)
	at de.deepamehta.core.impl.TypeCache.getTopicType(TypeCache.java:47)
	at de.deepamehta.core.impl.EmbeddedService.getTopicType(EmbeddedService.java:344)
	... 57 more
Caused by: de.deepamehta.core.service.accesscontrol.AccessControlException: user <anonymous> has no READ permission for object 272704
	at de.deepamehta.plugins.accesscontrol.AccessControlPlugin.checkReadPermission(AccessControlPlugin.java:803)
	at de.deepamehta.plugins.accesscontrol.AccessControlPlugin.preGetTopic(AccessControlPlugin.java:430)
	at de.deepamehta.core.impl.CoreEvent$1.deliver(CoreEvent.java:32)
	at de.deepamehta.core.impl.EventManager.deliverEvent(EventManager.java:97)
	at de.deepamehta.core.impl.EventManager.fireEvent(EventManager.java:63)
	at de.deepamehta.core.impl.EmbeddedService.fireEvent(EmbeddedService.java:531)
	at de.deepamehta.core.impl.EmbeddedService.checkAccess(EmbeddedService.java:747)
	at de.deepamehta.core.impl.EmbeddedService.instantiateTopic(EmbeddedService.java:653)
	at de.deepamehta.core.impl.EmbeddedService.getTopic(EmbeddedService.java:113)
	... 62 more

Nov 29, 2015 2:02:45 PM de.deepamehta.core.impl.TypeCache loadTopicType
INFO: Loading topic type "de.mikromedia.site"
Nov 29, 2015 2:02:45 PM de.deepamehta.core.util.UniversalExceptionMapper logException
SEVERE: Request "GET /favicon.ico" failed. Responding with 401 (Unauthorized). The original exception/error is:
java.lang.RuntimeException: Fetching topic type "de.mikromedia.site" failed
	at de.deepamehta.core.impl.EmbeddedService.getTopicType(EmbeddedService.java:346)
	at de.deepamehta.core.impl.AttachedTopic.getType(AttachedTopic.java:242)
	at de.deepamehta.core.impl.AttachedTopic.getType(AttachedTopic.java:25)
	at de.deepamehta.core.impl.AttachedChildTopics.getAssocDef(AttachedChildTopics.java:697)
	at de.deepamehta.core.impl.AttachedChildTopics.loadChildTopics(AttachedChildTopics.java:338)
	at de.deepamehta.core.impl.AttachedDeepaMehtaObject.loadChildTopics(AttachedDeepaMehtaObject.java:169)
	at de.deepamehta.core.impl.AttachedTopic.loadChildTopics(AttachedTopic.java:93)
	at de.mikromedia.webpages.WebpagePlugin.getCustomSiteTitle(WebpagePlugin.java:329)
	at de.mikromedia.webpages.WebpagePlugin.prepareTemplateSiteData(WebpagePlugin.java:281)
	at de.mikromedia.webpages.WebpagePlugin.getPageView(WebpagePlugin.java:101)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:606)
	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.headerComplete(AbstractHttpConnection.java:971)
	at org.eclipse.jetty.server.AbstractHttpConnection$RequestHandler.headerComplete(AbstractHttpConnection.java:1033)
	at org.eclipse.jetty.http.HttpParser.parseNext(HttpParser.java:644)
	at org.eclipse.jetty.http.HttpParser.parseAvailable(HttpParser.java:235)
	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:745)
Caused by: java.lang.RuntimeException: Fetching topic failed (key="uri", value="de.mikromedia.site")
	at de.deepamehta.core.impl.EmbeddedService.getTopic(EmbeddedService.java:115)
	at de.deepamehta.core.impl.TypeStorageImpl.fetchTopicType(TypeStorageImpl.java:102)
	at de.deepamehta.core.impl.TypeStorageImpl.getTopicType(TypeStorageImpl.java:72)
	at de.deepamehta.core.impl.TypeCache.loadTopicType(TypeCache.java:97)
	at de.deepamehta.core.impl.TypeCache.getTopicType(TypeCache.java:47)
	at de.deepamehta.core.impl.EmbeddedService.getTopicType(EmbeddedService.java:344)
	... 60 more
Caused by: de.deepamehta.core.service.accesscontrol.AccessControlException: user <anonymous> has no READ permission for object 247347
	at de.deepamehta.plugins.accesscontrol.AccessControlPlugin.checkReadPermission(AccessControlPlugin.java:803)
	at de.deepamehta.plugins.accesscontrol.AccessControlPlugin.preGetTopic(AccessControlPlugin.java:430)
	at de.deepamehta.core.impl.CoreEvent$1.deliver(CoreEvent.java:32)
	at de.deepamehta.core.impl.EventManager.deliverEvent(EventManager.java:97)
	at de.deepamehta.core.impl.EventManager.fireEvent(EventManager.java:63)
	at de.deepamehta.core.impl.EmbeddedService.fireEvent(EmbeddedService.java:531)
	at de.deepamehta.core.impl.EmbeddedService.checkAccess(EmbeddedService.java:747)
	at de.deepamehta.core.impl.EmbeddedService.instantiateTopic(EmbeddedService.java:653)
	at de.deepamehta.core.impl.EmbeddedService.getTopic(EmbeddedService.java:113)
	... 65 more

How i read this log output is that the following error occurs:
A user is allowed to READ a topic (a Redirect Topic is created currently within or assigned to a "Public" workspace by admin), but the READ fails since <anonymous> has no implicit READ on the topics Type Definition (is not a member of the "Private Workspace" of admin). This is odd and should be changed.

Also to keep up the following rule (which i understood as a basic rule to follow when writing 4.7 migrations):

The permissions for a topic and a given user/request are defined (and now i would add: solely defined) by the Workspace it is assigned to. (And not by the permissions its type definition is governed by.)

Am i correct on this and what do you think?

Change History

comment:1 Changed 5 years ago by jri

I think you're addressing crucial questions here.

Basically you're saying that if a user has READ or WRITE permission for a particular topic she must have implicit READ permission for the corresponding topic type too.

This makes sense as accessing the type definition is technically required in both situations:

  • The system retrieves a composite topic including its child topics (READ case). Retrieving the child topics is driven by the type definition (in particular the child type hierarchy).
  • The Webclient generates a form (WRITE case). Form generation is driven by the type definition (child type hierarchy, data types, view configuration).

If READing the topic type is not granted in these situations the original permission to READ/WRITE the topic becomes pointless as DM is technically not able to fulfill that permission.

However I'm not sure how to implement that as it partly contradicts with the current Access Control concept.

The READ case would not really be a problem: when retrieving a composite topic the Core could perform the type access as a privileged operation. Thus the composite topic would be readable while the user would still have no READ permission for the type.

The WRITE case on the other hand gives me some headaches. Currently the Webclient generates its forms at client-side, so it definitely needs to retrieve the type definition. Currently the Webclient maintains a client-side type cache with the semantics of "all type definitions the user has READ access to". The Create menu directly reflects the type cache content. (Once the user's authority changes the type cache is invalidated.)

I see 2 challenges, along with possible solutions:

  1. The Webclient definitely requires to read (and cache) a type the user has no READ permission to. To solve this the Core Service could be extended by another getTopicType() call which (besides the type URI) takes the ID of a topic to be edited. The Core then checks if the user has WRITE permission to that topic and if so, fulfills the request.
  1. Types retrieved via 1. must not be put in the client-side type cache as they must not appear in the Create menu. A solution might be the introduction of a 2nd client-side type cache with the semantics "all type definitions the user has implicit READ access to". This 2nd cache would be populated on-demand that is when a ID of a topic-to-be-edited becomes available.

Complexity rises, and I'm not yet fully sure if this is the way to go.

Another option would be to rethink both, the READ permission for types, and the (currently synthesized) CREATE permission for type instances.

I would appreciate if JuergeN chimes in here.

Thank you, Malte, for bringing up these important questions!

comment:2 Changed 5 years ago by JuergeN

Hi all! I am still do not really completely sure if I fully understand the problems, requirements and the usecase here. The workspace ACL paradigm that we have now is very clear and simple. A user needs read access to a TopicType? and write access to the selected workspace to create and edit a new Topic. This topic can be read-only to other people, if they have read-only access to that workspace where the new topic was created.

From what I understand now, at present it is also a necessicty that the anonymous or third-party user has read access to the TopicType? in order to read and more important to edit the Topic itself, right? If so, I agree that this is an implicit requirement that we have not really talked or thought about yet. But obviously this is a situation that can easily occur when moving topics arround in more complex multi-user environment. Let me think about it ... :)


comment:3 Changed 5 years ago by JuergeN

Jörg and I have talked through this on the phone. We agreed that it does not interfere with the ACL workspace rules, but that it is an implicid requirement resulting from the unique DM datastructure. In that sense Jörg will have to fix the problem in the core in that way, that a user who has access to any topic must have imlicit access to the TopicType? through the core.

@Malte: How urgent is this requirement for your further development?

comment:4 Changed 5 years ago by Malte

Ok, thanks.

To elaborate on the urgency for the use case in question, solving the READ case would be enough to help me out within the next 2 weeks and to solve just this (READ) case would provide transparent defaults for the WRITE case too (=User needs READ access to Type to WRITE topic).

In particular, with the new default permission for an (implicit type) READ, plugin developers would not longer need to "assign types conceptualized as private, confidential or collaborative to public or common workspaces (if they just want to publish instances topics/assocs of these types) - as it is my current workaround for this issue.

So yes, please go ahead with your proposal for revising the READ permissions (about implicit type read):

The READ case would not really be a problem: when retrieving a composite topic the Core could perform the type access as a privileged operation. Thus the composite topic would be readable while the user would still have no READ permission for the type.

This would be already an improvement and to avoid any further work (on workarounds for this issue) i would need a fix for this READ case within the next two weeks.

Thanks for your support!

comment:5 follow-up: ↓ 7 Changed 5 years ago by Malte

After a second investigation this issue seems to be even more complex/ i can not understand the current behaviour of the system as it seems to be undeterministic.

To reproduce i used the mentioned dm47-webpages-0.3.jar module (with dm47-webactivator). The default installation of that plugin should trigger this issue as

  • The "Website" Topic Type is assigned to "admins" Private Workspace
  • The "My DM 4 Website" Topic (delivering for example, the frontpage's footer text) is assigned to the public workspace "DeepaMehta"

By requesting http://localhost:8080 the latter topic is loaded but not always the mentioned exception is thrown. In this try, just when i issue the request with Chromium (=a browser which never requested the http://localhost:8080/de.deepamehta.webclient/ before making the frontpage request) i get the same error message. Off course, i (1) was never authenticated in any of my browser before making that request which should bring up this error and (2) the exception seems to not be thrown again, also not with Chromium, after one requested the webclient once, even if i delete all two DeepaMehta 4 Cookies (Workspace ID, Topicmap ID).

Note: The error was first sighted when the platform was started up "headless" (and thus no "Topic Types" where ever cached). Maybe the topic type cache plays also a role here and that cache does not seem to be populated during every "Request" scope.

I look forward for some enlightenment here, thanks.

comment:6 follow-up: ↓ 8 Changed 5 years ago by Malte

So, what might make this issue so crazy to debug, is, once one was logged into DM4 and logs out, one might be automatically re-authenticated (logged in again). I rembember this was an issue once, was that solved?

Restarting the platform will help with debugging (as then all sessions are definitely invalidated) but also, removing the JSESSONID cookie should help.

The thing is definitely that our case is met but:

  • the webclient indicates i am not logged in ("Login" button is present) and i can request the topic in question (despite the issue described in this ticket)
  • after restarting the platform (and the same is indicated) the exception is thrown (despite there is no difference visible)

The only difference may be, with the one browser i once had a session and with the other id definitely hadn't. Phew...

comment:7 in reply to: ↑ 5 Changed 5 years ago by jri

Replying to Malte:

Note: The error was first sighted when the platform was started up "headless" (and thus no "Topic Types" where ever cached). Maybe the topic type cache plays also a role here and that cache does not seem to be populated during every "Request" scope.

Yes, indeed, the type cache plays a role here.

Note that access control for types was never implemented accurately. At the moment READ access for types is actually governed only by generic topic READ access when loading a type topic from DB. This means if a type is already cached access is granted as nothing needs to be READ from the DB.

After a "cold start", that is when no DB exists, every type created by the (Core and plugin) migrations is put in the type cache. That means after a cold start, the type cache is fully populated and effectively no access control is in place for types (as nothing is READ from DB).

In contrast after a warm start the type cache is populated on demand. So, type topics will be read from DB and access control for READing the topic is applied.

This might explain some of your experiences.

Apparently I still must implement access control for types properly. Weather a type is cached or not must have no influence to the READ permission.

comment:8 in reply to: ↑ 6 Changed 5 years ago by jri

Replying to Malte:

So, what might make this issue so crazy to debug, is, once one was logged into DM4 and logs out, one might be automatically re-authenticated (logged in again). I rembember this was an issue once, was that solved?

Automatic re-authentication happens when you 1) set read_requires_login=true, that is logging in with the browser's own login dialog, and then 2) restarting DM with a changed read_requires_login=false setting without logging out before. In this case the browser resends the cached credentials with every request (in the Authorization header).

To stop that you can choose among these options:

  • Restart DM again with read_requires_login=true and logout properly. Note that after logging out the login dialog appears again. Here you MUST click Cancel (possibly 2 times!). Only then you're really logged out. This effectively overrides the cached credentials with invalid ones. This is the only way to stop the browser from automatic re-authentication. This is the only way I know to work around HTTP's lack of a logout semantics.
  • Restart your browser. This clears the cached credentials as well.

comment:9 Changed 5 years ago by jri

  • Status changed from new to accepted

comment:10 Changed 5 years ago by Jörg Richter <jri@…>

In b2d115d29e5a09c3acdd913e9e69afaae76ba044/deepamehta:

Core: fix type permissions (#899).

Type permissions are now implemented properly.
The state of the type cache has no influence on access control.

Note: the feature "Implicit READ permission for types" is not yet implemented, but it will in DM 4.8.1.

BREAKING CHANGES

2 methods dropped from CoreService:

List<String> getTopicTypeUris()
List<String> getAssociationTypeUris()

2 requests dropped from REST API:

GET /core/topictype
GET /core/topictype

2 methods dropped from REST client:

dm4c.restc.get_topic_type_uris()
dm4c.restc.get_association_type_uris()

Use getAllTopicTypes() and getAllAssociationTypes() (and the corresponding REST API) instead.

See #899.

comment:11 Changed 5 years ago by Jörg Richter <jri@…>

In a4687703c1a95aacd8633a09c00dd0804abb13e0/deepamehta:

Core: implicit READ permission for types (#899).

The "implicit READ permission for types" feature is now implemented.
A user is granted implicit READ permission for a type if she has READ permission for a specific topic/association.

The Webclient can display topicmaps containing topics/associations for whose types the user has only implicit READ permission.

CHANGES

2 new methods in CoreService:

TopicType getTopicTypeImplicitly(long topicId)

AssociationType getAssociationTypeImplicitly(long assocId)

Acccesses a type while enforcing the implicit READ permission.
A user has implicit READ permission for a type if she has READ permission for the given instance.

REST API

GET /core/topictype/topic/{id}

GET /core/assoctype/assoc/{id}

REST client

dm4c.restc.get_topic_type_implicitly(topic_id)

dm4c.restc.get_association_type_implicitly(assoc_id)

Webclient API

dm4c.enforce_implicit_topic_type_read_permission(topic)

dm4c.enforce_implicit_association_type_read_permission(assoc)

See #899.

comment:12 Changed 5 years ago by jri

  • Status changed from accepted to closed
  • Resolution set to fixed
Note: See TracTickets for help on using tickets.