Document rights: handling different rights, non-existent documents and document right changes


I’m currently resuming work on document rights. The background of document rights is that currently the rights of the “active content” in a page like script macros or skin extensions only depend on the last author. This makes it easy to accidentally remove or grant rights when the author or the author’s rights change. The idea of document rights is to improve this situation by explicitly specifying what rights a document has and doesn’t have. Editing would then be restricted to users with the specified right(s), and regardless of the last author, nothing in the document can have more rights than specified in the document. At least for now, the last author would still be relevant and checked, so denying rights to a user could still break content, but it would be much easier to detect. For backwards compatibility, there will also be a “legacy” state where the current behavior is maintained.

In this proposal, I want to talk about three important issues I discovered while looking at the current pull request. Note that to avoid confusion with the required rights application, which we’ve since introduced for similar reasons, I’m talking about document rights here, even though we sometimes used to call the same idea required rights instead.

Changing document rights

The first question is how we should apply changes to document rights. I see the following options:

  1. We treat them like any other document property, they can be modified during editing, and changed values are reflected in the preview and in the WYSIWYG editor.
  2. We treat them like any other document property, but they are only applied after saving, similar to rights.
  3. We treat document rights as something special, and they can only be changed in a special, new action.

Currently, the pull request implements the first option, and this may provide the best usability: Imagine adding a script macro, getting a popup saying that it requires script right, clicking okay to add script right, and then it would just work. Unfortunately, I see a lot of problems with this as executing content with changed permissions seems dangerous, especially if we would allow this from a scripting API. Also, with realtime, multiple users could be editing at the same time - but the moment you enable scripting rights, only those with scripting rights can continue editing - and this would depend on a dynamic state that is invisible to people outside the editing session.

The second option seems the most logical to me, as it would allow similar checks as we have for rights. It would also allow changing document rights in change request I think. Unfortunately, I have no idea how to handle realtime as document rights could still change in the middle of editing when a user changes document rights while the editing session is running. A user could already lose edit right while being part of a realtime session, so I guess realtime needs to handle such changes, anyway. With this second option, at least the rights change is easily visible before joining the session. We could also still provide good usability by just saving the document right change immediately if the user wants.

The third option with a dedicated action would probably be the safest, as we could exclude that rights are changed in a regular save action, e.g. with a hidden form input in an edit sheet. In addition, it would be easier to implement special protections such as displaying a required rights analysis of the existing content to ensure that users are aware of what content they’re giving rights to, and also to ensure that the document hasn’t been modified between the version the user checked and the current version when the document rights are actually changed. However, this seems like too much special treatment that would also prevent reuse of standard editing components like in-place editing.

So I’m +1 for 2.

Non-existent documents

Another tricky question is what to do during page creation. What document rights should we assume for a non-existent document? If we don’t implement option 1, I see basically two options:

  1. Assume no document rights. Scripts would only work after script rights are enabled and saved. This seems logical to me. When the user starts to add, say, a scripting macro, we could have an option to enable script rights and save immediately. Templates that use document rights and require scripting rights could also use Save & Edit mode to ensure that the document is saved first. Templates with legacy mode that require scripting rights would probably need to do the same.
  2. Use legacy mode and enable document rights only after saving. This has the potential to show a working script in preview, only to break it after saving. If we correctly detect content that needs scripting rights and prompt the user to enable them before saving, this won’t happen, but it’s still trickier.

I’m +1 for option 1, but I’m afraid it might be a breaking change for existing templates. Maybe we could also introduce an option to use the document rights from the request for new documents, but that seems kind of dangerous to me as it would reintroduce all the same problems we have without document rights, especially in combination with realtime. Does realtime work for non-existing documents?

Handling different rights

The second question is how to handle rights that are not script or programming right. Script or programming right are special in XWiki because, for example, the contextual authorization manager always takes the document author as the user instead of the current user. Also, we usually check them for a document (reference). So for script and programming right on a document, we could just always take document rights into account. However, we have other content like skin extensions, UIX or wiki macros with wiki scope that require admin right on the wiki. For these, we currently check if the author has admin right on the wiki. I think this case should also be covered by document rights, otherwise they would be quite limited. Also, ideally, document rights should be extensible and also be usable by extensions for extension rights. In these cases, we don’t know which document to check, or if a right is covered by document rights.

Here are some ideas:

  1. Introduce a special DocumentAuthorizationManager with APIs to check a right for a specific document (reference?), level (default document, but could be set to wiki) and user (author). The contextual authorization manager would automatically use this authorization manager for script and programming right, but all other right checks would need to be migrated to use the new authorization manager if document rights shall be considered.
  2. Introduce special “document author” user references that contain the document reference and are returned when the author of a document is retrieved. When checking rights for such a “document author” user reference, take document rights into account when the right demands it. We could have a registry of rights that need document rights when checking with a “document author” user reference.

The problem I see with solution 2 is that it requires a lot of new APIs, since currently none of the APIs for checking rights or context authors support user references. Also, it would be easy to use one of the old APIs to get an author as document reference and implicitly cast that to a user reference in Velocity, thereby losing the document authorship information.

So I would be +1 for option 1 and -0 for 2, but I’m open to other ideas.

Thank you for making it to the bottom of this very long post, and thanks in advance for your feedback!

1 Like

I have the feeling that on the long term option 3 would be the best: I have the feeling that we’re always dealing with exceptions when saving rights as any other properties. We’re used to those exceptions and we now know how to handles them, but I’m not sure it’s such a good design decision.
So I think I’d be +1 for 3 and +0 for 2.

I’d be also +1 for option 1, we can probably check the impact on templates bundled in XS and that exists in contrib or supported extensions.

I’m not sure I understand the proposal 2 here. Proposal 1 sounds good enough to me.

+1 for 2

+1 for 1

+1 for 1

Thanks a lot for this proposal!

+1 for 2

+1 for 1

+1 for 1