From ad5990cd9a44cf6a9160311ef2d80b364a105b43 Mon Sep 17 00:00:00 2001 From: Michael Hamann <michael.hamann@xwiki.com> Date: Thu, 18 Jul 2024 16:44:26 +0200 Subject: [PATCH] XWIKI-20907: Introduce the notion of required rights * Add a new flag to XWikiDocument if required rights shall be enforced. * Add the new flag to the filter stream and XAR APIs, increase the XAR version and adapt tests. * Add the new flag to the REST API. * Add the new flag to the edit form to support updating it. * Add a DocumentRequiredRightsManager API to allow getting the required rights that are set on a document. * Add a DocumentAuthorizationManager to check rights using required rights. * Restrict edit right to users that have all required rights. * Add a test for DocumentRequiredRightsReader. --- xwiki-platform-core/pom.xml | 21 ++- .../org/xwiki/bridge/DocumentModelBridge.java | 12 ++ .../event/model/WikiDocumentFilter.java | 9 ++ .../filter/xar/internal/XARDocumentModel.java | 2 + .../filter/xar/internal/XARFilterUtils.java | 7 +- .../internal/input/DocumentLocaleReader.java | 1 + .../internal/input/XARInputFilterStream.java | 10 +- .../input/XARInputFilterStreamFactory.java | 10 +- .../output/XAROutputFilterStream.java | 14 +- .../output/XAROutputFilterStreamFactory.java | 10 +- .../test/resources/document/class/class1.test | 4 + .../document/document/document1.test | 7 +- .../document/document/document2.test | 4 + .../documentattachmentwithoutcontent.test | 7 +- .../document/documentwithnestedspaces1.test | 7 +- .../document/documentwithunknownelements.test | 4 + .../document/document/emptydocument.test | 4 + .../resources/document/document/legacy1.test | 4 + .../document/document/legacytranslation1.test | 7 +- .../resources/document/document/new1.test | 4 + .../resources/document/object/object1.test | 7 +- .../document/object/objectwithoutclass.test | 7 +- .../document/property/nullvalueproperty.test | 2 +- .../test1/space/nestedspace/page.xml | 3 +- .../packagefile/test1/space/page.xml | 3 +- .../packagefile/xar1/space2/page2.xml | 1 + .../resources/xar/legacymixed1.input.test | 12 ++ .../src/test/resources/xar/nested1.input.test | 12 ++ .../src/test/resources/xar/nested2.input.test | 8 ++ .../xar/test1-noforcedocument.input.test | 8 ++ .../resources/xar/test1-sourcetype.input.test | 8 ++ .../src/test/resources/xar/test1.input.test | 8 ++ .../src/test/resources/xar/test1.output.test | 4 + .../xar/testSkipFirstDocument.output.xml | 4 + .../xar/testSkipLastSpace.output.xml | 4 + .../src/test/resources/xar/xar1.input.test | 8 ++ .../main/java/com/xpn/xwiki/api/Document.java | 28 ++++ .../com/xpn/xwiki/doc/LazyXWikiDocument.java | 6 + .../java/com/xpn/xwiki/doc/XWikiDocument.java | 54 ++++++++ .../XWikiDocumentLocaleEventGenerator.java | 2 + .../XWikiDocumentOutputFilterStream.java | 3 + .../main/java/com/xpn/xwiki/web/EditForm.java | 25 ++++ .../src/main/resources/xwiki.db2.hbm.xml | 2 + .../src/main/resources/xwiki.derby.hbm.xml | 2 + .../src/main/resources/xwiki.hbm.xml | 2 + .../src/main/resources/xwiki.mssql.hbm.xml | 2 + .../src/main/resources/xwiki.oracle.hbm.xml | 2 + .../main/resources/xwiki.postgresql.hbm.xml | 2 + .../src/test/resources/filter/document1.xml | 12 ++ .../filter/documentwithattachment1content.xml | 4 + .../filter/documentwithattachment2content.xml | 4 + .../src/main/resources/xwiki.rest.model.xsd | 1 + .../org/xwiki/rest/internal/ModelFactory.java | 6 + .../DefaultAuthorizationManager.java | 25 +++- .../DocumentAuthorizationManager.java | 76 +++++++++++ .../DocumentRequiredRightsChecker.java | 103 ++++++++++++++ .../requiredrights/DocumentRequiredRight.java | 38 ++++++ .../DocumentRequiredRights.java | 42 ++++++ .../DocumentRequiredRightsManager.java | 47 +++++++ .../main/resources/META-INF/components.txt | 1 + ...ltAuthorizationManagerIntegrationTest.java | 6 + .../DefaultDocumentAuthorizationManager.java | 122 +++++++++++++++++ .../internal/RightsFilterListener.java | 39 ++++++ .../DefaultDocumentRequiredRightsManager.java | 71 ++++++++++ .../DocumentRequiredRightsReader.java | 103 ++++++++++++++ .../main/resources/META-INF/components.txt | 3 + .../internal/RightsFilterListenerTest.java | 14 ++ .../DocumentRequiredRightsReaderTest.java | 128 ++++++++++++++++++ .../testwikibuilding/LegacyTestWiki.java | 6 + .../xar/internal/model/XarDocumentModel.java | 18 ++- 70 files changed, 1220 insertions(+), 26 deletions(-) create mode 100644 xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-api/src/main/java/org/xwiki/security/authorization/DocumentAuthorizationManager.java create mode 100644 xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-api/src/main/java/org/xwiki/security/authorization/internal/DocumentRequiredRightsChecker.java create mode 100644 xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-api/src/main/java/org/xwiki/security/authorization/requiredrights/DocumentRequiredRight.java create mode 100644 xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-api/src/main/java/org/xwiki/security/authorization/requiredrights/DocumentRequiredRights.java create mode 100644 xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-api/src/main/java/org/xwiki/security/authorization/requiredrights/DocumentRequiredRightsManager.java create mode 100644 xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-bridge/src/main/java/org/xwiki/security/authorization/internal/DefaultDocumentAuthorizationManager.java create mode 100644 xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-bridge/src/main/java/org/xwiki/security/authorization/internal/requiredrights/DefaultDocumentRequiredRightsManager.java create mode 100644 xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-bridge/src/main/java/org/xwiki/security/authorization/internal/requiredrights/DocumentRequiredRightsReader.java create mode 100644 xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-bridge/src/test/java/org/xwiki/security/authorization/internal/requiredrights/DocumentRequiredRightsReaderTest.java diff --git a/xwiki-platform-core/pom.xml b/xwiki-platform-core/pom.xml index 7bfe46023de..fe333ad95f2 100644 --- a/xwiki-platform-core/pom.xml +++ b/xwiki-platform-core/pom.xml @@ -138,10 +138,23 @@ Single justification example: --> - - - - + + <revapi.differences> + <justification>Change in generated class of the REST model to add the + enforceRequiredRights property.</justification> + <criticality>allowed</criticality> + <differences> + <item> + <code>java.annotation.attributeValueChanged</code> + <old>class org.xwiki.rest.model.jaxb.Page</old> + <new>class org.xwiki.rest.model.jaxb.Page</new> + <annotationType>javax.xml.bind.annotation.XmlType</annotationType> + <attribute>propOrder</attribute> + <oldValue>{"language", "majorVersion", "minorVersion", "hidden", "created", "creator", "creatorName", "modified", "modifier", "modifierName", "originalMetadataAuthor", "originalMetadataAuthorName", "comment", "content", "clazz", "objects", "attachments", "hierarchy"}</oldValue> + <newValue>{"language", "majorVersion", "minorVersion", "hidden", "enforceRequiredRights", "created", "creator", "creatorName", "modified", "modifier", "modifierName", "originalMetadataAuthor", "originalMetadataAuthorName", "comment", "content", "clazz", "objects", "attachments", "hierarchy"}</newValue> + </item> + </differences> + </revapi.differences> </analysisConfiguration> </configuration> </plugin> diff --git a/xwiki-platform-core/xwiki-platform-bridge/src/main/java/org/xwiki/bridge/DocumentModelBridge.java b/xwiki-platform-core/xwiki-platform-bridge/src/main/java/org/xwiki/bridge/DocumentModelBridge.java index dfb642810ab..535cadb0a54 100644 --- a/xwiki-platform-core/xwiki-platform-bridge/src/main/java/org/xwiki/bridge/DocumentModelBridge.java +++ b/xwiki-platform-core/xwiki-platform-bridge/src/main/java/org/xwiki/bridge/DocumentModelBridge.java @@ -221,4 +221,16 @@ default boolean isRestricted() { return false; } + + /** + * @return {@code true} if required rights defined in a {@code XWiki.RequiredRightClass} object shall be + * enforced, meaning that editing will be limited to users with these rights and content of this document can't + * use more rights than defined in the object, {@code false} otherwise + * @since 16.10.0RC1 + */ + @Unstable + default boolean isEnforceRequiredRights() + { + return false; + } } diff --git a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-events/xwiki-platform-filter-event-model/src/main/java/org/xwiki/filter/event/model/WikiDocumentFilter.java b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-events/xwiki-platform-filter-event-model/src/main/java/org/xwiki/filter/event/model/WikiDocumentFilter.java index f371bfc469e..5ffb495b5cb 100644 --- a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-events/xwiki-platform-filter-event-model/src/main/java/org/xwiki/filter/event/model/WikiDocumentFilter.java +++ b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-events/xwiki-platform-filter-event-model/src/main/java/org/xwiki/filter/event/model/WikiDocumentFilter.java @@ -26,6 +26,7 @@ import org.xwiki.filter.FilterEventParameters; import org.xwiki.filter.FilterException; import org.xwiki.filter.annotation.Default; +import org.xwiki.stability.Unstable; /** * Document related events. @@ -197,6 +198,14 @@ public interface WikiDocumentFilter */ String PARAMETER_REVISION_MINOR = "revision_minor"; + // required rights + /** + * @type {@link Boolean} + * @since 16.10.0RC1 + */ + @Unstable + String PARAMETER_ENFORCE_REQUIRED_RIGHTS = "enforce_required_rights"; + // Events /** diff --git a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/main/java/org/xwiki/filter/xar/internal/XARDocumentModel.java b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/main/java/org/xwiki/filter/xar/internal/XARDocumentModel.java index 42f2cc533bb..cc0eecfb769 100644 --- a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/main/java/org/xwiki/filter/xar/internal/XARDocumentModel.java +++ b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/main/java/org/xwiki/filter/xar/internal/XARDocumentModel.java @@ -72,6 +72,8 @@ public class XARDocumentModel extends XarDocumentModel new EventParameter(XWikiWikiDocumentFilter.PARAMETER_REVISION_EFFECTIVEMETADATA_AUTHOR)); put(ELEMENT_REVISION_ORIGINALMEDATAAUTHOR, new EventParameter(XWikiWikiDocumentFilter.PARAMETER_REVISION_ORIGINALMETADATA_AUTHOR)); + put(ELEMENT_ENFORCE_REQUIRED_RIGHTS, + new EventParameter(XWikiWikiDocumentFilter.PARAMETER_ENFORCE_REQUIRED_RIGHTS, Boolean.class)); put(ELEMENT_REVISION_COMMENT, new EventParameter(XWikiWikiDocumentFilter.PARAMETER_REVISION_COMMENT)); put(ELEMENT_REVISION_DATE, new EventParameter(XWikiWikiDocumentFilter.PARAMETER_REVISION_DATE, Date.class)); put(ELEMENT_REVISION_MINOR, diff --git a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/main/java/org/xwiki/filter/xar/internal/XARFilterUtils.java b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/main/java/org/xwiki/filter/xar/internal/XARFilterUtils.java index 3fcb53a6cf2..3a2f5802d06 100644 --- a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/main/java/org/xwiki/filter/xar/internal/XARFilterUtils.java +++ b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/main/java/org/xwiki/filter/xar/internal/XARFilterUtils.java @@ -76,10 +76,15 @@ public EventParameter(String name) */ public static final String ROLEHINT_15 = ROLEHINT_PREFIX + XarDocumentModel.VERSION_15; + /** + * @since 16.10.0RC1 + */ + public static final String ROLEHINT_16 = ROLEHINT_PREFIX + XarDocumentModel.VERSION_16; + /** * @since 7.2M1 */ - public static final String ROLEHINT_CURRENT = ROLEHINT_15; + public static final String ROLEHINT_CURRENT = ROLEHINT_16; /** * @since 6.2M1 diff --git a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/main/java/org/xwiki/filter/xar/internal/input/DocumentLocaleReader.java b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/main/java/org/xwiki/filter/xar/internal/input/DocumentLocaleReader.java index e526cea9742..3f355e08922 100644 --- a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/main/java/org/xwiki/filter/xar/internal/input/DocumentLocaleReader.java +++ b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/main/java/org/xwiki/filter/xar/internal/input/DocumentLocaleReader.java @@ -404,6 +404,7 @@ private void readDocument(XMLStreamReader xmlReader, Object filter, XARInputFilt // Initialize with a few defaults (thing that don't exist in old XAR format) this.currentDocumentRevisionParameters.put(XWikiWikiDocumentFilter.PARAMETER_SYNTAX, Syntax.XWIKI_1_0); this.currentDocumentRevisionParameters.put(XWikiWikiDocumentFilter.PARAMETER_HIDDEN, false); + this.currentDocumentRevisionParameters.put(XWikiWikiDocumentFilter.PARAMETER_ENFORCE_REQUIRED_RIGHTS, false); // Reference String referenceString = xmlReader.getAttributeValue(null, XARDocumentModel.ATTRIBUTE_DOCUMENT_REFERENCE); diff --git a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/main/java/org/xwiki/filter/xar/internal/input/XARInputFilterStream.java b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/main/java/org/xwiki/filter/xar/internal/input/XARInputFilterStream.java index 36ad0c86334..394c948d9dc 100644 --- a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/main/java/org/xwiki/filter/xar/internal/input/XARInputFilterStream.java +++ b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/main/java/org/xwiki/filter/xar/internal/input/XARInputFilterStream.java @@ -44,8 +44,14 @@ * @version $Id$ * @since 6.2M1 */ -@Component(hints = {XARFilterUtils.ROLEHINT_15, XARFilterUtils.ROLEHINT_14, XARFilterUtils.ROLEHINT_13, - XARFilterUtils.ROLEHINT_12, XARFilterUtils.ROLEHINT_11}) +@Component(hints = { + XARFilterUtils.ROLEHINT_16, + XARFilterUtils.ROLEHINT_15, + XARFilterUtils.ROLEHINT_14, + XARFilterUtils.ROLEHINT_13, + XARFilterUtils.ROLEHINT_12, + XARFilterUtils.ROLEHINT_11 +}) @InstantiationStrategy(ComponentInstantiationStrategy.PER_LOOKUP) public class XARInputFilterStream extends AbstractBeanInputFilterStream<XARInputProperties, XARInputFilter> { diff --git a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/main/java/org/xwiki/filter/xar/internal/input/XARInputFilterStreamFactory.java b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/main/java/org/xwiki/filter/xar/internal/input/XARInputFilterStreamFactory.java index f31841c318d..adbe2f295f3 100644 --- a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/main/java/org/xwiki/filter/xar/internal/input/XARInputFilterStreamFactory.java +++ b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/main/java/org/xwiki/filter/xar/internal/input/XARInputFilterStreamFactory.java @@ -33,8 +33,14 @@ * @version $Id$ * @since 6.2M1 */ -@Component(hints = {XARFilterUtils.ROLEHINT_15, XARFilterUtils.ROLEHINT_14, XARFilterUtils.ROLEHINT_13, - XARFilterUtils.ROLEHINT_12, XARFilterUtils.ROLEHINT_11}) +@Component(hints = { + XARFilterUtils.ROLEHINT_16, + XARFilterUtils.ROLEHINT_15, + XARFilterUtils.ROLEHINT_14, + XARFilterUtils.ROLEHINT_13, + XARFilterUtils.ROLEHINT_12, + XARFilterUtils.ROLEHINT_11 +}) @Singleton public class XARInputFilterStreamFactory extends AbstractBeanInputFilterStreamFactory<XARInputProperties, XARInputFilter> diff --git a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/main/java/org/xwiki/filter/xar/internal/output/XAROutputFilterStream.java b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/main/java/org/xwiki/filter/xar/internal/output/XAROutputFilterStream.java index 399ff9f4663..752f82ac1f8 100644 --- a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/main/java/org/xwiki/filter/xar/internal/output/XAROutputFilterStream.java +++ b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/main/java/org/xwiki/filter/xar/internal/output/XAROutputFilterStream.java @@ -69,8 +69,14 @@ * @version $Id$ * @since 6.2M1 */ -@Component(hints = {XARFilterUtils.ROLEHINT_15, XARFilterUtils.ROLEHINT_14, XARFilterUtils.ROLEHINT_13, - XARFilterUtils.ROLEHINT_12, XARFilterUtils.ROLEHINT_11}) +@Component(hints = { + XARFilterUtils.ROLEHINT_16, + XARFilterUtils.ROLEHINT_15, + XARFilterUtils.ROLEHINT_14, + XARFilterUtils.ROLEHINT_13, + XARFilterUtils.ROLEHINT_12, + XARFilterUtils.ROLEHINT_11 +}) @InstantiationStrategy(ComponentInstantiationStrategy.PER_LOOKUP) public class XAROutputFilterStream extends AbstractBeanOutputFilterStream<XAROutputProperties> implements XARFilter { @@ -382,6 +388,10 @@ public void beginWikiDocumentRevision(String revision, FilterEventParameters par this.writer.writeElement(XarDocumentModel.ELEMENT_HIDDEN, toString(parameters.get(XWikiWikiDocumentFilter.PARAMETER_HIDDEN))); } + if (parameters.containsKey(XWikiWikiDocumentFilter.PARAMETER_ENFORCE_REQUIRED_RIGHTS)) { + this.writer.writeElement(XarDocumentModel.ELEMENT_ENFORCE_REQUIRED_RIGHTS, + toString(parameters.get(XWikiWikiDocumentFilter.PARAMETER_ENFORCE_REQUIRED_RIGHTS))); + } if (parameters.containsKey(XWikiWikiDocumentFilter.PARAMETER_CONTENT)) { this.writer.writeElement(XarDocumentModel.ELEMENT_CONTENT, (String) parameters.get(XWikiWikiDocumentFilter.PARAMETER_CONTENT)); diff --git a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/main/java/org/xwiki/filter/xar/internal/output/XAROutputFilterStreamFactory.java b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/main/java/org/xwiki/filter/xar/internal/output/XAROutputFilterStreamFactory.java index 6d28e95627c..3a64f7484ad 100644 --- a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/main/java/org/xwiki/filter/xar/internal/output/XAROutputFilterStreamFactory.java +++ b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/main/java/org/xwiki/filter/xar/internal/output/XAROutputFilterStreamFactory.java @@ -34,8 +34,14 @@ * @version $Id$ * @since 6.2M1 */ -@Component(hints = {XARFilterUtils.ROLEHINT_15, XARFilterUtils.ROLEHINT_14, XARFilterUtils.ROLEHINT_13, - XARFilterUtils.ROLEHINT_12, XARFilterUtils.ROLEHINT_11}) +@Component(hints = { + XARFilterUtils.ROLEHINT_16, + XARFilterUtils.ROLEHINT_15, + XARFilterUtils.ROLEHINT_14, + XARFilterUtils.ROLEHINT_13, + XARFilterUtils.ROLEHINT_12, + XARFilterUtils.ROLEHINT_11 +}) @Singleton public class XAROutputFilterStreamFactory extends AbstractBeanOutputFilterStreamFactory<XAROutputProperties, XARFilter> { diff --git a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/document/class/class1.test b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/document/class/class1.test index 33f5d88777d..f37e980d1f6 100644 --- a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/document/class/class1.test +++ b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/document/class/class1.test @@ -58,6 +58,10 @@ <string>hidden</string> <boolean>false</boolean> </entry> + <entry> + <string>enforce_required_rights</string> + <boolean>false</boolean> + </entry> </parameters> </p> <wikiClass> diff --git a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/document/document/document1.test b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/document/document/document1.test index 78de35d8ba2..63b77d0c45b 100644 --- a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/document/document/document1.test +++ b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/document/document/document1.test @@ -2,7 +2,7 @@ .inputexpect|xwiki+xar/1.4 .#------------------------------------------------------------------------------ <?xml version='1.1' encoding='UTF-8'?> -<xwikidoc version="1.5" reference="space.page" locale=""> +<xwikidoc version="1.6" reference="space.page" locale=""> <web>space</web> <name>page</name> <language/> @@ -26,6 +26,7 @@ <minorEdit>false</minorEdit> <syntaxId>syntax/1.0</syntaxId> <hidden>true</hidden> + <enforceRequiredRights>true</enforceRequiredRights> <content>content</content> <renderedcontent/> <attachment> @@ -167,6 +168,10 @@ <string>hidden</string> <boolean>true</boolean> </entry> + <entry> + <string>enforce_required_rights</string> + <boolean>true</boolean> + </entry> <entry> <string>parent_reference</string> <org.xwiki.model.reference.EntityReference> diff --git a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/document/document/document2.test b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/document/document/document2.test index 670b3aacc42..173c3b7b68f 100644 --- a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/document/document/document2.test +++ b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/document/document/document2.test @@ -165,6 +165,10 @@ <string>hidden</string> <boolean>true</boolean> </entry> + <entry> + <string>enforce_required_rights</string> + <boolean>false</boolean> + </entry> <entry> <string>parent_reference</string> <org.xwiki.model.reference.EntityReference> diff --git a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/document/document/documentattachmentwithoutcontent.test b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/document/document/documentattachmentwithoutcontent.test index 334ed032575..1bc08f32de8 100644 --- a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/document/document/documentattachmentwithoutcontent.test +++ b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/document/document/documentattachmentwithoutcontent.test @@ -3,7 +3,7 @@ .# Attachment with no content .#------------------------------------------------------------------------------ <?xml version='1.1' encoding='UTF-8'?> -<xwikidoc version="1.5" reference="space.page" locale=""> +<xwikidoc version="1.6" reference="space.page" locale=""> <web>space</web> <name>page</name> <language/> @@ -26,6 +26,7 @@ <minorEdit>false</minorEdit> <syntaxId>syntax/1.0</syntaxId> <hidden>true</hidden> + <enforceRequiredRights>true</enforceRequiredRights> <content>content</content> <renderedcontent/> <attachment> @@ -87,6 +88,10 @@ <string>hidden</string> <boolean>true</boolean> </entry> + <entry> + <string>enforce_required_rights</string> + <boolean>true</boolean> + </entry> <entry> <string>parent_reference</string> <org.xwiki.model.reference.EntityReference> diff --git a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/document/document/documentwithnestedspaces1.test b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/document/document/documentwithnestedspaces1.test index 55a62b98a49..d411e20eee2 100644 --- a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/document/document/documentwithnestedspaces1.test +++ b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/document/document/documentwithnestedspaces1.test @@ -2,7 +2,7 @@ .inputexpect|xwiki+xar/1.3 .#------------------------------------------------------------------------------ <?xml version='1.1' encoding='UTF-8'?> -<xwikidoc version="1.5" reference="space1.space2.page" locale=""> +<xwikidoc version="1.6" reference="space1.space2.page" locale=""> <web>space1.space2</web> <name>page</name> <language/> @@ -25,6 +25,7 @@ <minorEdit>false</minorEdit> <syntaxId>syntax/1.0</syntaxId> <hidden>true</hidden> + <enforceRequiredRights>true</enforceRequiredRights> <content>content</content> <renderedcontent/> <attachment> @@ -165,6 +166,10 @@ <string>hidden</string> <boolean>true</boolean> </entry> + <entry> + <string>enforce_required_rights</string> + <boolean>true</boolean> + </entry> <entry> <string>parent_reference</string> <org.xwiki.model.reference.EntityReference> diff --git a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/document/document/documentwithunknownelements.test b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/document/document/documentwithunknownelements.test index 093765872ff..42215e0a843 100644 --- a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/document/document/documentwithunknownelements.test +++ b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/document/document/documentwithunknownelements.test @@ -144,6 +144,10 @@ <string>hidden</string> <boolean>true</boolean> </entry> + <entry> + <string>enforce_required_rights</string> + <boolean>false</boolean> + </entry> <entry> <string>parent_reference</string> <org.xwiki.model.reference.EntityReference> diff --git a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/document/document/emptydocument.test b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/document/document/emptydocument.test index a31e808f89d..552894aa5e3 100644 --- a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/document/document/emptydocument.test +++ b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/document/document/emptydocument.test @@ -39,6 +39,10 @@ <string>hidden</string> <boolean>false</boolean> </entry> + <entry> + <string>enforce_required_rights</string> + <boolean>false</boolean> + </entry> </parameters> </p> </wikiDocumentRevision> diff --git a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/document/document/legacy1.test b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/document/document/legacy1.test index 607484f12dc..1646850cd60 100644 --- a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/document/document/legacy1.test +++ b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/document/document/legacy1.test @@ -165,6 +165,10 @@ <string>hidden</string> <boolean>true</boolean> </entry> + <entry> + <string>enforce_required_rights</string> + <boolean>false</boolean> + </entry> <entry> <string>parent_reference</string> <org.xwiki.model.reference.EntityReference> diff --git a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/document/document/legacytranslation1.test b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/document/document/legacytranslation1.test index a5530e5459d..9f93e8f4ae9 100644 --- a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/document/document/legacytranslation1.test +++ b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/document/document/legacytranslation1.test @@ -3,7 +3,7 @@ .# Make sure legacy XAR format is properly parsed .#------------------------------------------------------------------------------ <?xml version='1.1' encoding='UTF-8'?> -<xwikidoc version="1.5" reference="space.page" locale="fr"> +<xwikidoc version="1.6" reference="space.page" locale="fr"> <web>space</web> <name>page</name> <language>fr</language> @@ -26,6 +26,7 @@ <minorEdit>false</minorEdit> <syntaxId>syntax/1.0</syntaxId> <hidden>true</hidden> + <enforceRequiredRights>true</enforceRequiredRights> <content>content</content> <renderedcontent/> <attachment> @@ -165,6 +166,10 @@ <string>hidden</string> <boolean>true</boolean> </entry> + <entry> + <string>enforce_required_rights</string> + <boolean>true</boolean> + </entry> <entry> <string>parent_reference</string> <org.xwiki.model.reference.EntityReference> diff --git a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/document/document/new1.test b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/document/document/new1.test index 1afa12a6bab..36cc0641264 100644 --- a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/document/document/new1.test +++ b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/document/document/new1.test @@ -176,6 +176,10 @@ <string>hidden</string> <boolean>true</boolean> </entry> + <entry> + <string>enforce_required_rights</string> + <boolean>false</boolean> + </entry> <entry> <string>parent_reference</string> <org.xwiki.model.reference.EntityReference> diff --git a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/document/object/object1.test b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/document/object/object1.test index 7e8ea8b84dd..6478c224409 100644 --- a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/document/object/object1.test +++ b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/document/object/object1.test @@ -2,7 +2,7 @@ .inputexpect|xwiki+xar/1.1 .#------------------------------------------------------------------------------ <?xml version='1.1' encoding='UTF-8'?> -<xwikidoc version="1.5" reference="space.page" locale=""> +<xwikidoc version="1.6" reference="space.page" locale=""> <web>space</web> <name>page</name> <language/> @@ -11,6 +11,7 @@ <version>1.1</version> <syntaxId>xwiki/1.0</syntaxId> <hidden>false</hidden> + <enforceRequiredRights>true</enforceRequiredRights> <object> <name>space.page</name> <number>0</number> @@ -117,6 +118,10 @@ <string>hidden</string> <boolean>false</boolean> </entry> + <entry> + <string>enforce_required_rights</string> + <boolean>true</boolean> + </entry> </parameters> </p> <wikiObject name="space.class[0]"> diff --git a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/document/object/objectwithoutclass.test b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/document/object/objectwithoutclass.test index 358e8cd8633..4e45c482962 100644 --- a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/document/object/objectwithoutclass.test +++ b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/document/object/objectwithoutclass.test @@ -2,7 +2,7 @@ .inputexpect|xwiki+xar/1.1 .#------------------------------------------------------------------------------ <?xml version='1.1' encoding='UTF-8'?> -<xwikidoc version="1.5" reference="space.page" locale=""> +<xwikidoc version="1.6" reference="space.page" locale=""> <web>space</web> <name>page</name> <language/> @@ -11,6 +11,7 @@ <version>1.1</version> <syntaxId>xwiki/1.0</syntaxId> <hidden>false</hidden> + <enforceRequiredRights>true</enforceRequiredRights> <object> <name>space.page</name> <number>0</number> @@ -52,6 +53,10 @@ <string>hidden</string> <boolean>false</boolean> </entry> + <entry> + <string>enforce_required_rights</string> + <boolean>true</boolean> + </entry> </parameters> </p> <wikiObject name="space.class[0]"> diff --git a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/document/property/nullvalueproperty.test b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/document/property/nullvalueproperty.test index 0bd1bbd134c..17b95720939 100644 --- a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/document/property/nullvalueproperty.test +++ b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/document/property/nullvalueproperty.test @@ -2,7 +2,7 @@ .expect|xwiki+xar/1.1 .#------------------------------------------------------------------------------ <?xml version='1.1' encoding='UTF-8'?> -<xwikidoc version="1.5" reference="space.page" locale=""> +<xwikidoc version="1.6" reference="space.page" locale=""> <web>space</web> <name>page</name> <language/> diff --git a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/packagefile/test1/space/nestedspace/page.xml b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/packagefile/test1/space/nestedspace/page.xml index ec48980eaf6..9711add6a39 100644 --- a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/packagefile/test1/space/nestedspace/page.xml +++ b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/packagefile/test1/space/nestedspace/page.xml @@ -1,5 +1,5 @@ <?xml version='1.1' encoding='UTF-8'?> -<xwikidoc version="1.5" reference="space.nestedspace.page" locale=""> +<xwikidoc version="1.6" reference="space.nestedspace.page" locale=""> <web>space.nestedspace</web> <name>page</name> <language/> @@ -19,6 +19,7 @@ <validationScript/> <comment/> <minorEdit>false</minorEdit> + <enforceRequiredRights>true</enforceRequiredRights> <syntaxId>xwiki/2.0</syntaxId> <hidden>false</hidden> <content>content</content> diff --git a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/packagefile/test1/space/page.xml b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/packagefile/test1/space/page.xml index 1e4efba789a..bb0cb05bea7 100644 --- a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/packagefile/test1/space/page.xml +++ b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/packagefile/test1/space/page.xml @@ -1,5 +1,5 @@ <?xml version='1.1' encoding='UTF-8'?> -<xwikidoc version="1.5" reference="space.page" locale=""> +<xwikidoc version="1.6" reference="space.page" locale=""> <web>space</web> <name>page</name> <language/> @@ -21,6 +21,7 @@ <minorEdit>false</minorEdit> <syntaxId>xwiki/2.0</syntaxId> <hidden>false</hidden> + <enforceRequiredRights>false</enforceRequiredRights> <content>content</content> <class> <name>space.page</name> diff --git a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/packagefile/xar1/space2/page2.xml b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/packagefile/xar1/space2/page2.xml index a7e2f81fc7c..e41700ea89d 100644 --- a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/packagefile/xar1/space2/page2.xml +++ b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/packagefile/xar1/space2/page2.xml @@ -20,5 +20,6 @@ <minorEdit>false</minorEdit> <syntaxId>xwiki/2.0</syntaxId> <hidden>false</hidden> + <enforceRequiredRights>true</enforceRequiredRights> <content>content2</content> </xwikidoc> \ No newline at end of file diff --git a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/xar/legacymixed1.input.test b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/xar/legacymixed1.input.test index d36b6ca2c5d..a37e11ba3c7 100644 --- a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/xar/legacymixed1.input.test +++ b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/xar/legacymixed1.input.test @@ -47,6 +47,10 @@ <string>hidden</string> <boolean>true</boolean> </entry> + <entry> + <string>enforce_required_rights</string> + <boolean>false</boolean> + </entry> <entry> <string>parent_reference</string> <org.xwiki.model.reference.EntityReference> @@ -151,6 +155,10 @@ <string>hidden</string> <boolean>true</boolean> </entry> + <entry> + <string>enforce_required_rights</string> + <boolean>false</boolean> + </entry> <entry> <string>parent_reference</string> <org.xwiki.model.reference.EntityReference> @@ -255,6 +263,10 @@ <string>hidden</string> <boolean>true</boolean> </entry> + <entry> + <string>enforce_required_rights</string> + <boolean>false</boolean> + </entry> <entry> <string>parent_reference</string> <org.xwiki.model.reference.EntityReference> diff --git a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/xar/nested1.input.test b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/xar/nested1.input.test index a028763a3c2..fe975a13cc6 100644 --- a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/xar/nested1.input.test +++ b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/xar/nested1.input.test @@ -43,6 +43,10 @@ <string>hidden</string> <boolean>false</boolean> </entry> + <entry> + <string>enforce_required_rights</string> + <boolean>false</boolean> + </entry> <entry> <string>revision_author</string> <string>XWiki.author</string> @@ -135,6 +139,10 @@ <string>hidden</string> <boolean>false</boolean> </entry> + <entry> + <string>enforce_required_rights</string> + <boolean>false</boolean> + </entry> <entry> <string>revision_author</string> <string>XWiki.author</string> @@ -227,6 +235,10 @@ <string>hidden</string> <boolean>false</boolean> </entry> + <entry> + <string>enforce_required_rights</string> + <boolean>false</boolean> + </entry> <entry> <string>revision_author</string> <string>XWiki.author</string> diff --git a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/xar/nested2.input.test b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/xar/nested2.input.test index 01dd8e900e0..a0732fcc3d1 100644 --- a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/xar/nested2.input.test +++ b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/xar/nested2.input.test @@ -44,6 +44,10 @@ <string>hidden</string> <boolean>false</boolean> </entry> + <entry> + <string>enforce_required_rights</string> + <boolean>false</boolean> + </entry> <entry> <string>revision_author</string> <string>XWiki.author</string> @@ -137,6 +141,10 @@ <string>hidden</string> <boolean>false</boolean> </entry> + <entry> + <string>enforce_required_rights</string> + <boolean>false</boolean> + </entry> <entry> <string>revision_author</string> <string>XWiki.author</string> diff --git a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/xar/test1-noforcedocument.input.test b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/xar/test1-noforcedocument.input.test index 7804a08b4fe..e2c2a43764d 100644 --- a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/xar/test1-noforcedocument.input.test +++ b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/xar/test1-noforcedocument.input.test @@ -43,6 +43,10 @@ <string>hidden</string> <boolean>false</boolean> </entry> + <entry> + <string>enforce_required_rights</string> + <boolean>false</boolean> + </entry> <entry> <string>revision_author</string> <string>XWiki.author</string> @@ -429,6 +433,10 @@ <string>hidden</string> <boolean>false</boolean> </entry> + <entry> + <string>enforce_required_rights</string> + <boolean>false</boolean> + </entry> <entry> <string>revision_author</string> <string>XWiki.author</string> diff --git a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/xar/test1-sourcetype.input.test b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/xar/test1-sourcetype.input.test index a7beb10b8de..c2d7a0ed224 100644 --- a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/xar/test1-sourcetype.input.test +++ b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/xar/test1-sourcetype.input.test @@ -43,6 +43,10 @@ <string>hidden</string> <boolean>false</boolean> </entry> + <entry> + <string>enforce_required_rights</string> + <boolean>false</boolean> + </entry> <entry> <string>revision_author</string> <string>XWiki.author</string> @@ -429,6 +433,10 @@ <string>hidden</string> <boolean>false</boolean> </entry> + <entry> + <string>enforce_required_rights</string> + <boolean>false</boolean> + </entry> <entry> <string>revision_author</string> <string>XWiki.author</string> diff --git a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/xar/test1.input.test b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/xar/test1.input.test index 2dcd3a50640..c02ae8e92aa 100644 --- a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/xar/test1.input.test +++ b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/xar/test1.input.test @@ -43,6 +43,10 @@ <string>hidden</string> <boolean>false</boolean> </entry> + <entry> + <string>enforce_required_rights</string> + <boolean>false</boolean> + </entry> <entry> <string>revision_author</string> <string>XWiki.author</string> @@ -429,6 +433,10 @@ <string>hidden</string> <boolean>false</boolean> </entry> + <entry> + <string>enforce_required_rights</string> + <boolean>false</boolean> + </entry> <entry> <string>revision_author</string> <string>XWiki.author</string> diff --git a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/xar/test1.output.test b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/xar/test1.output.test index f9459a4cb15..9c641ca36c3 100644 --- a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/xar/test1.output.test +++ b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/xar/test1.output.test @@ -42,6 +42,10 @@ <string>hidden</string> <boolean>false</boolean> </entry> + <entry> + <string>enforce_required_rights</string> + <boolean>true</boolean> + </entry> <entry> <string>revision_author</string> <string>XWiki.author</string> diff --git a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/xar/testSkipFirstDocument.output.xml b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/xar/testSkipFirstDocument.output.xml index b4004f3b04b..823bb94604f 100644 --- a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/xar/testSkipFirstDocument.output.xml +++ b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/xar/testSkipFirstDocument.output.xml @@ -39,6 +39,10 @@ <string>hidden</string> <boolean>false</boolean> </entry> + <entry> + <string>enforce_required_rights</string> + <boolean>true</boolean> + </entry> <entry> <string>revision_author</string> <string>XWiki.author</string> diff --git a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/xar/testSkipLastSpace.output.xml b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/xar/testSkipLastSpace.output.xml index ec147da2d5b..4205194ad91 100644 --- a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/xar/testSkipLastSpace.output.xml +++ b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/xar/testSkipLastSpace.output.xml @@ -39,6 +39,10 @@ <string>hidden</string> <boolean>false</boolean> </entry> + <entry> + <string>enforce_required_rights</string> + <boolean>false</boolean> + </entry> <entry> <string>revision_author</string> <string>XWiki.author</string> diff --git a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/xar/xar1.input.test b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/xar/xar1.input.test index 744c305db9f..900643e203a 100644 --- a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/xar/xar1.input.test +++ b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/xar/xar1.input.test @@ -43,6 +43,10 @@ <string>hidden</string> <boolean>false</boolean> </entry> + <entry> + <string>enforce_required_rights</string> + <boolean>false</boolean> + </entry> <entry> <string>revision_author</string> <string>XWiki.author</string> @@ -134,6 +138,10 @@ <string>hidden</string> <boolean>false</boolean> </entry> + <entry> + <string>enforce_required_rights</string> + <boolean>false</boolean> + </entry> <entry> <string>revision_author</string> <string>XWiki.author</string> diff --git a/xwiki-platform-core/xwiki-platform-oldcore/src/main/java/com/xpn/xwiki/api/Document.java b/xwiki-platform-core/xwiki-platform-oldcore/src/main/java/com/xpn/xwiki/api/Document.java index a610a517951..fd0ab72c1fa 100644 --- a/xwiki-platform-core/xwiki-platform-oldcore/src/main/java/com/xpn/xwiki/api/Document.java +++ b/xwiki-platform-core/xwiki-platform-oldcore/src/main/java/com/xpn/xwiki/api/Document.java @@ -3263,6 +3263,34 @@ public void setHidden(boolean hidden) this.doc.setHidden(hidden); } + /** + * @return {@code true} if required rights defined in a {@code XWiki.RequiredRightClass} object shall be + * enforced, meaning that editing will be limited to users with these rights and content of this document can't + * use more rights than defined in the object, {@code false} otherwise + * @since 16.6.0RC1 + */ + @Unstable + public boolean isEnforceRequiredRights() + { + return this.doc.isEnforceRequiredRights(); + } + + /** + * @param enforceRequiredRights if required rights defined in a {@code XWiki.RequiredRightClass} object shall be + * enforced, meaning that editing will be limited to users with these rights and content of this document can't use + * more rights than defined in the object + * @since 16.6.0RC1 + */ + @Unstable + public void setEnforceRequiredRights(boolean enforceRequiredRights) + { + getDoc().setEnforceRequiredRights(enforceRequiredRights); + + updateAuthor(); + + updateContentAuthor(); + } + /** * Drop permissions for the remainder of the rendering cycle. After this is called: * <ul> diff --git a/xwiki-platform-core/xwiki-platform-oldcore/src/main/java/com/xpn/xwiki/doc/LazyXWikiDocument.java b/xwiki-platform-core/xwiki-platform-oldcore/src/main/java/com/xpn/xwiki/doc/LazyXWikiDocument.java index b5eea80f193..c9c5ffe19fa 100644 --- a/xwiki-platform-core/xwiki-platform-oldcore/src/main/java/com/xpn/xwiki/doc/LazyXWikiDocument.java +++ b/xwiki-platform-core/xwiki-platform-oldcore/src/main/java/com/xpn/xwiki/doc/LazyXWikiDocument.java @@ -286,6 +286,12 @@ public Boolean isHidden() return getDocument().isHidden(); } + @Override + public boolean isEnforceRequiredRights() + { + return getDocument().isEnforceRequiredRights(); + } + @Override public XWikiDocumentArchive getDocumentArchive() { diff --git a/xwiki-platform-core/xwiki-platform-oldcore/src/main/java/com/xpn/xwiki/doc/XWikiDocument.java b/xwiki-platform-core/xwiki-platform-oldcore/src/main/java/com/xpn/xwiki/doc/XWikiDocument.java index 33e7c5ca07e..4b5272563d4 100644 --- a/xwiki-platform-core/xwiki-platform-oldcore/src/main/java/com/xpn/xwiki/doc/XWikiDocument.java +++ b/xwiki-platform-core/xwiki-platform-oldcore/src/main/java/com/xpn/xwiki/doc/XWikiDocument.java @@ -518,6 +518,13 @@ private static Transformation getMacroTransformation() */ private Syntax syntax; + /** + * If required rights that can be defined in a {@code XWiki.RequiredRightClass} shall be enforced. For + * backwards-compatibility reasons, this is {@code false} by default. + * @since 16.10.0RC1 + */ + private boolean enforceRequiredRights = false; + /** * Is latest modification a minor edit. */ @@ -4189,6 +4196,11 @@ public void readDocMetaFromForm(EditForm eform, XWikiContext context) throws XWi if (eform.getHidden() != null) { setHidden("1".equals(eform.getHidden())); } + + // Read the enforce required rights flag from the form + if (eform.getEnforceRequiredRights() != null) { + setEnforceRequiredRights("1".equals(eform.getEnforceRequiredRights())); + } } private Syntax resolveSyntax(String syntaxId) @@ -4537,6 +4549,7 @@ public void clone(XWikiDocument document) setMinorEdit(document.isMinorEdit()); setSyntax(document.getSyntax()); setHidden(document.isHidden()); + setEnforceRequiredRights(document.isEnforceRequiredRights()); cloneXObjects(document); cloneAttachments(document); @@ -4620,6 +4633,7 @@ private XWikiDocument cloneInternal(DocumentReference newDocumentReference, bool doc.setSyntax(getSyntax()); doc.setHidden(isHidden()); doc.setRestricted(isRestricted()); + doc.setEnforceRequiredRights(isEnforceRequiredRights()); if (this.xClass != null) { doc.setXClass(this.xClass.clone()); @@ -4918,6 +4932,10 @@ public boolean equalsData(XWikiDocument otherDocument) return false; } + if (isEnforceRequiredRights() != otherDocument.isEnforceRequiredRights()) { + return false; + } + // XClass if (!getXClass().equals(otherDocument.getXClass())) { @@ -7084,6 +7102,11 @@ public List<MetaDataDiff> getMetaDataDiff(XWikiDocument fromDoc, XWikiDocument t list.add(new MetaDataDiff("hidden", fromDoc.isHidden(), toDoc.isHidden())); } + if (fromDoc.isEnforceRequiredRights() != toDoc.isEnforceRequiredRights()) { + list.add(new MetaDataDiff("enforceRequiredRights", fromDoc.isEnforceRequiredRights(), + toDoc.isEnforceRequiredRights())); + } + return list; } @@ -7700,6 +7723,32 @@ public void setSyntaxId(String syntaxId) setSyntax(syntax); } + /** + * @return {@code true} if required rights defined in a {@code XWiki.RequiredRightClass} object shall be + * enforced, meaning that editing will be limited to users with these rights and content of this document can't + * use more rights than defined in the object, {@code false} otherwise + * @since 16.10.0RC1 + */ + @Unstable + public boolean isEnforceRequiredRights() + { + return this.enforceRequiredRights; + } + + /** + * @param enforceRequiredRights if required rights defined in a {@code XWiki.RequiredRightClass} object shall be + * enforced, meaning that editing will be limited to users with these rights and content of this document can't use + * more rights than defined in the object + * @since 16.10.0RC1 + */ + @Unstable + public void setEnforceRequiredRights(boolean enforceRequiredRights) + { + this.enforceRequiredRights = enforceRequiredRights; + + setContentDirty(true); + } + public Vector<BaseObject> getComments(boolean asc) { List<BaseObject> list = getXObjects(COMMENTSCLASS_REFERENCE); @@ -9370,6 +9419,11 @@ public boolean apply(XWikiDocument document, boolean clean) modified = true; } + if (isEnforceRequiredRights() != document.isEnforceRequiredRights()) { + setEnforceRequiredRights(document.isEnforceRequiredRights()); + modified = true; + } + // ///////////////////////////////// // XObjects diff --git a/xwiki-platform-core/xwiki-platform-oldcore/src/main/java/com/xpn/xwiki/internal/filter/input/XWikiDocumentLocaleEventGenerator.java b/xwiki-platform-core/xwiki-platform-oldcore/src/main/java/com/xpn/xwiki/internal/filter/input/XWikiDocumentLocaleEventGenerator.java index 9fd24ad2678..35f2141bd7f 100644 --- a/xwiki-platform-core/xwiki-platform-oldcore/src/main/java/com/xpn/xwiki/internal/filter/input/XWikiDocumentLocaleEventGenerator.java +++ b/xwiki-platform-core/xwiki-platform-oldcore/src/main/java/com/xpn/xwiki/internal/filter/input/XWikiDocumentLocaleEventGenerator.java @@ -183,6 +183,8 @@ private void writeRevision(XWikiDocument document, Object filter, XWikiDocumentF } revisionParameters.put(WikiDocumentFilter.PARAMETER_SYNTAX, document.getSyntax()); revisionParameters.put(WikiDocumentFilter.PARAMETER_HIDDEN, document.isHidden()); + revisionParameters.put(XWikiWikiDocumentFilter.PARAMETER_ENFORCE_REQUIRED_RIGHTS, + document.isEnforceRequiredRights()); revisionParameters.put(WikiDocumentFilter.PARAMETER_REVISION_EFFECTIVEMETADATA_AUTHOR, toString(document.getAuthors().getEffectiveMetadataAuthor())); revisionParameters.put(WikiDocumentFilter.PARAMETER_REVISION_ORIGINALMETADATA_AUTHOR, toString(document.getAuthors().getOriginalMetadataAuthor())); diff --git a/xwiki-platform-core/xwiki-platform-oldcore/src/main/java/com/xpn/xwiki/internal/filter/output/XWikiDocumentOutputFilterStream.java b/xwiki-platform-core/xwiki-platform-oldcore/src/main/java/com/xpn/xwiki/internal/filter/output/XWikiDocumentOutputFilterStream.java index 90a066ce4e2..5db50c843e8 100644 --- a/xwiki-platform-core/xwiki-platform-oldcore/src/main/java/com/xpn/xwiki/internal/filter/output/XWikiDocumentOutputFilterStream.java +++ b/xwiki-platform-core/xwiki-platform-oldcore/src/main/java/com/xpn/xwiki/internal/filter/output/XWikiDocumentOutputFilterStream.java @@ -293,6 +293,9 @@ private void begin(FilterEventParameters parameters) throws FilterException this.entity.setMinorEdit(getBoolean(WikiDocumentFilter.PARAMETER_REVISION_MINOR, parameters, false)); + this.entity.setEnforceRequiredRights(getBoolean(WikiDocumentFilter.PARAMETER_ENFORCE_REQUIRED_RIGHTS, + parameters, false)); + String revisions = getString(XWikiWikiDocumentFilter.PARAMETER_JRCSREVISIONS, this.currentLocaleParameters, null); if (revisions != null) { diff --git a/xwiki-platform-core/xwiki-platform-oldcore/src/main/java/com/xpn/xwiki/web/EditForm.java b/xwiki-platform-core/xwiki-platform-oldcore/src/main/java/com/xpn/xwiki/web/EditForm.java index ce57090f11a..881ad496fc5 100644 --- a/xwiki-platform-core/xwiki-platform-oldcore/src/main/java/com/xpn/xwiki/web/EditForm.java +++ b/xwiki-platform-core/xwiki-platform-oldcore/src/main/java/com/xpn/xwiki/web/EditForm.java @@ -33,8 +33,10 @@ import org.apache.commons.lang3.math.NumberUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.xwiki.stability.Unstable; import org.xwiki.store.TemporaryAttachmentSessionsManager; +import com.xpn.xwiki.doc.XWikiDocument; import com.xpn.xwiki.util.Util; /** @@ -97,6 +99,8 @@ public class EditForm extends XWikiForm private boolean convertSyntax; private String hidden; + + private String enforceRequiredRights; private ObjectPolicyType objectPolicy; @@ -129,6 +133,7 @@ public void readRequest() setSyntaxId(request.getParameter("syntaxId")); setConvertSyntax(Boolean.valueOf(request.getParameter("convertSyntax"))); setHidden(request.getParameter("xhidden")); + setEnforceRequiredRights(request.getParameter("enforceRequiredRights")); setObjectPolicy(request.getParameter("objectPolicy")); setUpdateOrCreateMap(request); setObjectsToRemove(request.getParameterValues("deletedObjects")); @@ -357,6 +362,26 @@ public void setHidden(String hidden) this.hidden = hidden; } + /** + * @return the enforce required rights flag, see {@link XWikiDocument#isEnforceRequiredRights()} + * @since 16.10.0RC1 + */ + @Unstable + public String getEnforceRequiredRights() + { + return this.enforceRequiredRights; + } + + /** + * @param enforceRequiredRights the enforce required rights flag, see {@link XWikiDocument#isEnforceRequiredRights()} + * @since 16.10.0RC1 + */ + @Unstable + public void setEnforceRequiredRights(String enforceRequiredRights) + { + this.enforceRequiredRights = enforceRequiredRights; + } + /** * Return the object policy given in the HTTP request. See {@link com.xpn.xwiki.web.ObjectPolicyType * ObjectPolicyType} for more information about what is an object policy. diff --git a/xwiki-platform-core/xwiki-platform-oldcore/src/main/resources/xwiki.db2.hbm.xml b/xwiki-platform-core/xwiki-platform-oldcore/src/main/resources/xwiki.db2.hbm.xml index f10d3cdbf5e..0b32367b840 100644 --- a/xwiki-platform-core/xwiki-platform-oldcore/src/main/resources/xwiki.db2.hbm.xml +++ b/xwiki-platform-core/xwiki-platform-oldcore/src/main/resources/xwiki.db2.hbm.xml @@ -75,6 +75,8 @@ <property name="syntaxId" type="string" column="XWD_SYNTAX_ID" length="50" /> <property name="hidden" type="boolean" column="XWD_HIDDEN" index="DOC_HIDDEN" not-null="true" /> <property name="originalMetadataAuthorReference" type="string" column="XWD_ORIGINAL_METADATA_AUTHOR" length="255" index="DOC_ORIGINAL_METADATA_AUTHOR" /> + <property name="enforceRequiredRights" type="boolean" column="XWD_ENFORCE_REQUIRED_RIGHTS" + index="DOC_ENFORCE_REQUIRED_RIGHTS" not-null="true"/> </class> <!-- com.xpn.xwiki.doc.XWikiSpace root --> diff --git a/xwiki-platform-core/xwiki-platform-oldcore/src/main/resources/xwiki.derby.hbm.xml b/xwiki-platform-core/xwiki-platform-oldcore/src/main/resources/xwiki.derby.hbm.xml index fd8297e2f9f..052d9339d3c 100644 --- a/xwiki-platform-core/xwiki-platform-oldcore/src/main/resources/xwiki.derby.hbm.xml +++ b/xwiki-platform-core/xwiki-platform-oldcore/src/main/resources/xwiki.derby.hbm.xml @@ -75,6 +75,8 @@ <property name="syntaxId" type="string" column="XWD_SYNTAX_ID" length="50" /> <property name="hidden" type="boolean" column="XWD_HIDDEN" index="DOC_HIDDEN" not-null="true" /> <property name="originalMetadataAuthorReference" type="string" column="XWD_ORIGINAL_METADATA_AUTHOR" length="768" index="DOC_ORIGINAL_METADATA_AUTHOR" /> + <property name="enforceRequiredRights" type="boolean" column="XWD_ENFORCE_REQUIRED_RIGHTS" + index="DOC_ENFORCE_REQUIRED_RIGHTS" not-null="true"/> </class> <!-- com.xpn.xwiki.doc.XWikiSpace root --> diff --git a/xwiki-platform-core/xwiki-platform-oldcore/src/main/resources/xwiki.hbm.xml b/xwiki-platform-core/xwiki-platform-oldcore/src/main/resources/xwiki.hbm.xml index 9fe3245b3e2..097b6726aff 100644 --- a/xwiki-platform-core/xwiki-platform-oldcore/src/main/resources/xwiki.hbm.xml +++ b/xwiki-platform-core/xwiki-platform-oldcore/src/main/resources/xwiki.hbm.xml @@ -70,6 +70,8 @@ <property name="syntaxId" type="string" column="XWD_SYNTAX_ID" length="50" /> <property name="hidden" type="boolean" column="XWD_HIDDEN" index="DOC_HIDDEN" not-null="true" /> <property name="originalMetadataAuthorReference" type="string" column="XWD_ORIGINAL_METADATA_AUTHOR" length="768" index="DOC_ORIGINAL_METADATA_AUTHOR" /> + <property name="enforceRequiredRights" type="boolean" column="XWD_ENFORCE_REQUIRED_RIGHTS" + index="DOC_ENFORCE_REQUIRED_RIGHTS" not-null="true"/> </class> <!-- com.xpn.xwiki.doc.XWikiSpace root --> diff --git a/xwiki-platform-core/xwiki-platform-oldcore/src/main/resources/xwiki.mssql.hbm.xml b/xwiki-platform-core/xwiki-platform-oldcore/src/main/resources/xwiki.mssql.hbm.xml index 604665327a2..d94c1227f99 100644 --- a/xwiki-platform-core/xwiki-platform-oldcore/src/main/resources/xwiki.mssql.hbm.xml +++ b/xwiki-platform-core/xwiki-platform-oldcore/src/main/resources/xwiki.mssql.hbm.xml @@ -77,6 +77,8 @@ <property name="syntaxId" type="string" column="XWD_SYNTAX_ID" length="50" /> <property name="hidden" type="boolean" column="XWD_HIDDEN" index="DOC_HIDDEN" not-null="true" /> <property name="originalMetadataAuthorReference" type="string" column="XWD_ORIGINAL_METADATA_AUTHOR" length="255" index="DOC_ORIGINAL_METADATA_AUTHOR" /> + <property name="enforceRequiredRights" type="boolean" column="XWD_ENFORCE_REQUIRED_RIGHTS" + index="DOC_ENFORCE_REQUIRED_RIGHTS" not-null="true"/> </class> <!-- com.xpn.xwiki.doc.XWikiSpace root --> diff --git a/xwiki-platform-core/xwiki-platform-oldcore/src/main/resources/xwiki.oracle.hbm.xml b/xwiki-platform-core/xwiki-platform-oldcore/src/main/resources/xwiki.oracle.hbm.xml index e37c976d9af..ce2b676b2c2 100644 --- a/xwiki-platform-core/xwiki-platform-oldcore/src/main/resources/xwiki.oracle.hbm.xml +++ b/xwiki-platform-core/xwiki-platform-oldcore/src/main/resources/xwiki.oracle.hbm.xml @@ -83,6 +83,8 @@ <property name="syntaxId" type="string" column="XWD_SYNTAX_ID" length="50" /> <property name="hidden" type="boolean" column="XWD_HIDDEN" index="DOC_HIDDEN" not-null="true" /> <property name="originalMetadataAuthorReference" type="string" column="XWD_ORIGINAL_METADATA" length="768" index="DOC_ORIGINAL_METADATA" /> + <property name="enforceRequiredRights" type="boolean" column="XWD_ENFORCE_REQUIRED_RIGHTS" + index="DOC_ENFORCE_REQUIRED_RIGHTS" not-null="true"/> </class> <!-- com.xpn.xwiki.doc.XWikiSpace root --> diff --git a/xwiki-platform-core/xwiki-platform-oldcore/src/main/resources/xwiki.postgresql.hbm.xml b/xwiki-platform-core/xwiki-platform-oldcore/src/main/resources/xwiki.postgresql.hbm.xml index 81948bd7fa1..1e2f2d9b4d2 100644 --- a/xwiki-platform-core/xwiki-platform-oldcore/src/main/resources/xwiki.postgresql.hbm.xml +++ b/xwiki-platform-core/xwiki-platform-oldcore/src/main/resources/xwiki.postgresql.hbm.xml @@ -79,6 +79,8 @@ <property name="syntaxId" type="string" column="XWD_SYNTAX_ID" length="50" /> <property name="hidden" type="boolean" column="XWD_HIDDEN" index="DOC_HIDDEN" not-null="true" /> <property name="originalMetadataAuthorReference" type="string" column="XWD_ORIGINAL_METADATA_AUTHOR" length="768" index="DOC_ORIGINAL_METADATA_AUTHOR" /> + <property name="enforceRequiredRights" type="boolean" column="XWD_ENFORCE_REQUIRED_RIGHTS" + index="DOC_ENFORCE_REQUIRED_RIGHTS" not-null="true"/> </class> <!-- com.xpn.xwiki.doc.XWikiSpace root --> diff --git a/xwiki-platform-core/xwiki-platform-oldcore/src/test/resources/filter/document1.xml b/xwiki-platform-core/xwiki-platform-oldcore/src/test/resources/filter/document1.xml index 0f0bb271c52..f1f357da37e 100644 --- a/xwiki-platform-core/xwiki-platform-oldcore/src/test/resources/filter/document1.xml +++ b/xwiki-platform-core/xwiki-platform-oldcore/src/test/resources/filter/document1.xml @@ -48,6 +48,10 @@ <string>hidden</string> <boolean>false</boolean> </entry> + <entry> + <string>enforce_required_rights</string> + <boolean>false</boolean> + </entry> <entry> <string>revision_author</string> <string>XWiki.author</string> @@ -200,6 +204,10 @@ <string>hidden</string> <boolean>true</boolean> </entry> + <entry> + <string>enforce_required_rights</string> + <boolean>false</boolean> + </entry> <entry> <string>revision_author</string> <string>XWiki.author</string> @@ -530,6 +538,10 @@ <string>hidden</string> <boolean>true</boolean> </entry> + <entry> + <string>enforce_required_rights</string> + <boolean>false</boolean> + </entry> <entry> <string>revision_author</string> <string>XWiki.author</string> diff --git a/xwiki-platform-core/xwiki-platform-oldcore/src/test/resources/filter/documentwithattachment1content.xml b/xwiki-platform-core/xwiki-platform-oldcore/src/test/resources/filter/documentwithattachment1content.xml index 3d5891effb6..a107f777731 100644 --- a/xwiki-platform-core/xwiki-platform-oldcore/src/test/resources/filter/documentwithattachment1content.xml +++ b/xwiki-platform-core/xwiki-platform-oldcore/src/test/resources/filter/documentwithattachment1content.xml @@ -49,6 +49,10 @@ <string>hidden</string> <boolean>false</boolean> </entry> + <entry> + <string>enforce_required_rights</string> + <boolean>false</boolean> + </entry> <entry> <string>revision_author</string> <string>XWiki.XWikiGuest</string> diff --git a/xwiki-platform-core/xwiki-platform-oldcore/src/test/resources/filter/documentwithattachment2content.xml b/xwiki-platform-core/xwiki-platform-oldcore/src/test/resources/filter/documentwithattachment2content.xml index 77e524ef589..ffef321f09c 100644 --- a/xwiki-platform-core/xwiki-platform-oldcore/src/test/resources/filter/documentwithattachment2content.xml +++ b/xwiki-platform-core/xwiki-platform-oldcore/src/test/resources/filter/documentwithattachment2content.xml @@ -49,6 +49,10 @@ <string>hidden</string> <boolean>false</boolean> </entry> + <entry> + <string>enforce_required_rights</string> + <boolean>false</boolean> + </entry> <entry> <string>revision_author</string> <string>XWiki.XWikiGuest</string> diff --git a/xwiki-platform-core/xwiki-platform-rest/xwiki-platform-rest-model/src/main/resources/xwiki.rest.model.xsd b/xwiki-platform-core/xwiki-platform-rest/xwiki-platform-rest-model/src/main/resources/xwiki.rest.model.xsd index 5b4b166e1a6..7d157e1d032 100644 --- a/xwiki-platform-core/xwiki-platform-rest/xwiki-platform-rest-model/src/main/resources/xwiki.rest.model.xsd +++ b/xwiki-platform-core/xwiki-platform-rest/xwiki-platform-rest-model/src/main/resources/xwiki.rest.model.xsd @@ -128,6 +128,7 @@ <element name="majorVersion" type="int"></element> <element name="minorVersion" type="int"></element> <element name="hidden" type="boolean" default="false"></element> + <element name="enforceRequiredRights" type="boolean" minOccurs="0"/> <element name="created" type="dateTime"></element> <element name="creator" type="string"></element> <element name="creatorName" type="string"></element> diff --git a/xwiki-platform-core/xwiki-platform-rest/xwiki-platform-rest-server/src/main/java/org/xwiki/rest/internal/ModelFactory.java b/xwiki-platform-core/xwiki-platform-rest/xwiki-platform-rest-server/src/main/java/org/xwiki/rest/internal/ModelFactory.java index 12697d3140b..e74082acd0d 100644 --- a/xwiki-platform-core/xwiki-platform-rest/xwiki-platform-rest-server/src/main/java/org/xwiki/rest/internal/ModelFactory.java +++ b/xwiki-platform-core/xwiki-platform-rest/xwiki-platform-rest-server/src/main/java/org/xwiki/rest/internal/ModelFactory.java @@ -212,6 +212,11 @@ public boolean toDocument(Document doc, org.xwiki.rest.model.jaxb.Page restPage) doc.setHidden(restPage.isHidden()); + if (restPage.isEnforceRequiredRights() != null) { + doc.setEnforceRequiredRights(restPage.isEnforceRequiredRights()); + modified = true; + } + // Set objects if (restPage.getObjects() != null) { Set<ObjectReference> newReferences = new HashSet<>(); @@ -761,6 +766,7 @@ public Page toRestPage(URI baseUri, URI self, Document doc, boolean useVersion, page.setMajorVersion(doc.getRCSVersion().at(0)); page.setMinorVersion(doc.getRCSVersion().at(1)); page.setHidden(doc.isHidden()); + page.setEnforceRequiredRights(doc.isEnforceRequiredRights()); page.setLanguage(doc.getLocale().toString()); page.setCreator(doc.getCreator()); if (withPrettyNames) { diff --git a/xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-api/src/main/java/org/xwiki/security/authorization/DefaultAuthorizationManager.java b/xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-api/src/main/java/org/xwiki/security/authorization/DefaultAuthorizationManager.java index 5366e259711..0b338d81c7b 100644 --- a/xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-api/src/main/java/org/xwiki/security/authorization/DefaultAuthorizationManager.java +++ b/xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-api/src/main/java/org/xwiki/security/authorization/DefaultAuthorizationManager.java @@ -38,6 +38,7 @@ import org.xwiki.security.UserSecurityReference; import org.xwiki.security.authorization.cache.SecurityCache; import org.xwiki.security.authorization.cache.SecurityCacheLoader; +import org.xwiki.security.authorization.internal.DocumentRequiredRightsChecker; import org.xwiki.security.internal.XWikiBridge; /** @@ -79,6 +80,9 @@ public class DefaultAuthorizationManager implements AuthorizationManager @Inject private XWikiBridge xwikiBridge; + @Inject + private DocumentRequiredRightsChecker documentRequiredRightsChecker; + /** * Check if the user is the super admin. * @@ -148,9 +152,7 @@ private boolean hasSecurityAccess(Right right, DocumentReference userReference, } if (right == null || right == Right.ILLEGAL) { - if (check) { - logDeny(userReference, entityReference, right, "no such right"); - } + logDenyIfCheck(right, userReference, entityReference, check, "no such right"); return false; } @@ -159,9 +161,26 @@ private boolean hasSecurityAccess(Right right, DocumentReference userReference, return false; } + // For edit right, check if the user has all required rights. + if (right == Right.EDIT && !this.documentRequiredRightsChecker.hasRequiredRights(userReference, + entityReference)) + { + logDenyIfCheck(right, userReference, entityReference, check, "misses required right"); + + return false; + } + return evaluateSecurityAccess(right, userReference, entityReference, check); } + private void logDenyIfCheck(Right right, DocumentReference userReference, EntityReference entityReference, + boolean check, String info) + { + if (check) { + logDeny(userReference, entityReference, right, info); + } + } + private boolean evaluateSecurityAccess(Right right, DocumentReference userReference, EntityReference entityReference, boolean check) throws AuthorizationException diff --git a/xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-api/src/main/java/org/xwiki/security/authorization/DocumentAuthorizationManager.java b/xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-api/src/main/java/org/xwiki/security/authorization/DocumentAuthorizationManager.java new file mode 100644 index 00000000000..be32b7b671b --- /dev/null +++ b/xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-api/src/main/java/org/xwiki/security/authorization/DocumentAuthorizationManager.java @@ -0,0 +1,76 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.security.authorization; + +import org.xwiki.component.annotation.Role; +import org.xwiki.model.EntityType; +import org.xwiki.model.reference.DocumentReference; +import org.xwiki.stability.Unstable; + +/** + * Authorization manager that checks rights of document authors taking required rights into account. + * + * @version $Id$ + * @since 16.10.0RC1 + */ +@Unstable +@Role +public interface DocumentAuthorizationManager +{ + /** + * Tests if the given context author of the context document has the specified right at the given level, taking the + * required rights of the document into account. + * + * @param right the right to check + * @param level the level of the right, for example, for admin right, this could be {@link EntityType#DOCUMENT} for + * admin right directly on the document itself or {@link EntityType#WIKI} for admin right on the whole wiki. + * @param contextAuthor the author for which rights shall be checked + * @param contextDocument the document for which the rights shall be checked + * @return if the context author has the right + */ + boolean hasAccess(Right right, EntityType level, DocumentReference contextAuthor, + DocumentReference contextDocument); + + /** + * Check if the given document has the given required right. + * + * @param right the right to check + * @param level the level of the right + * @param contextDocument the reference of the context document + * @return if the document has the required right (independent of the actual author) + * @throws AuthorizationException if loading the required rights fails + */ + boolean hasRequiredRight(Right right, EntityType level, DocumentReference contextDocument) + throws AuthorizationException; + + /** + * Checks if the given context author of the context document has the specified right at the given level, taking the + * required rights of the document into account. This function should be used at security checkpoint. + * + * @param right the right to check + * @param level the level of the right, for example, for admin right, this could be {@link EntityType#DOCUMENT} for + * admin right directly on the document itself or {@link EntityType#WIKI} for admin right on the whole wiki. + * @param contextAuthor the author for which rights shall be checked + * @param contextDocument the document for which the rights shall be checked + * @throws AccessDeniedException if the context author does not have the right + */ + void checkAccess(Right right, EntityType level, DocumentReference contextAuthor, + DocumentReference contextDocument) throws AccessDeniedException; +} diff --git a/xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-api/src/main/java/org/xwiki/security/authorization/internal/DocumentRequiredRightsChecker.java b/xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-api/src/main/java/org/xwiki/security/authorization/internal/DocumentRequiredRightsChecker.java new file mode 100644 index 00000000000..3787136158d --- /dev/null +++ b/xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-api/src/main/java/org/xwiki/security/authorization/internal/DocumentRequiredRightsChecker.java @@ -0,0 +1,103 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.security.authorization.internal; + +import javax.inject.Inject; +import javax.inject.Provider; +import javax.inject.Singleton; + +import org.xwiki.component.annotation.Component; +import org.xwiki.model.EntityType; +import org.xwiki.model.reference.DocumentReference; +import org.xwiki.model.reference.EntityReference; +import org.xwiki.security.authorization.AuthorizationException; +import org.xwiki.security.authorization.AuthorizationManager; +import org.xwiki.security.authorization.requiredrights.DocumentRequiredRight; +import org.xwiki.security.authorization.requiredrights.DocumentRequiredRights; +import org.xwiki.security.authorization.requiredrights.DocumentRequiredRightsManager; + +/** + * Check if a user has all required rights defined for an entity. + * + * @version $Id$ + * @since 16.10.0RC1 + */ +@Component(roles = DocumentRequiredRightsChecker.class) +@Singleton +public class DocumentRequiredRightsChecker +{ + @Inject + private Provider<AuthorizationManager> authorizationManagerProvider; + + @Inject + private DocumentRequiredRightsManager documentRequiredRightsManager; + + /** + * Check if a user has all required rights defined for an entity. + * + * @param userReference the user reference + * @param entityReference the entity reference + * @return true if the user has all required rights, false otherwise + * @throws AuthorizationException if an error occurs while loading the required rights + */ + public boolean hasRequiredRights(DocumentReference userReference, EntityReference entityReference) + throws AuthorizationException + { + DocumentReference documentReference = getDocumentReference(entityReference); + + if (documentReference == null) { + return true; + } + + AuthorizationManager authorizationManager = this.authorizationManagerProvider.get(); + + DocumentRequiredRights documentRequiredRights = + this.documentRequiredRightsManager.getRequiredRights(documentReference) + .orElse(DocumentRequiredRights.EMPTY); + if (documentRequiredRights.enforce()) { + for (DocumentRequiredRight requiredRight : documentRequiredRights.rights()) { + if (!authorizationManager.hasAccess(requiredRight.right(), userReference, + documentReference.extractReference(requiredRight.scope()))) + { + return false; + } + } + } + + return true; + } + + private DocumentReference getDocumentReference(EntityReference entityReference) + { + if (entityReference != null) { + if (entityReference instanceof DocumentReference documentReference) { + return documentReference; + } + + EntityReference documentEntityReference = entityReference.extractReference(EntityType.DOCUMENT); + + if (documentEntityReference != null) { + return new DocumentReference(documentEntityReference); + } + } + + return null; + } +} diff --git a/xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-api/src/main/java/org/xwiki/security/authorization/requiredrights/DocumentRequiredRight.java b/xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-api/src/main/java/org/xwiki/security/authorization/requiredrights/DocumentRequiredRight.java new file mode 100644 index 00000000000..595ed91f869 --- /dev/null +++ b/xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-api/src/main/java/org/xwiki/security/authorization/requiredrights/DocumentRequiredRight.java @@ -0,0 +1,38 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.security.authorization.requiredrights; + +import org.xwiki.model.EntityType; +import org.xwiki.security.authorization.Right; +import org.xwiki.stability.Unstable; + +/** + * A required right set on a document. + * + * @param right the right + * @param scope the scope of the right, e.g., wiki or document level + * + * @version $Id$ + * @since 16.10.0RC1 + */ +@Unstable +public record DocumentRequiredRight(Right right, EntityType scope) +{ +} diff --git a/xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-api/src/main/java/org/xwiki/security/authorization/requiredrights/DocumentRequiredRights.java b/xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-api/src/main/java/org/xwiki/security/authorization/requiredrights/DocumentRequiredRights.java new file mode 100644 index 00000000000..aadd0f253b7 --- /dev/null +++ b/xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-api/src/main/java/org/xwiki/security/authorization/requiredrights/DocumentRequiredRights.java @@ -0,0 +1,42 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.security.authorization.requiredrights; + +import java.util.Set; + +import org.xwiki.stability.Unstable; + +/** + * Represents the required rights that are configured on a document. + * + * @param enforce if the required rights shall be enforced + * @param rights the configured rights + * + * @version $Id$ + * @since 16.10.0RC1 + */ +@Unstable +public record DocumentRequiredRights(boolean enforce, Set<DocumentRequiredRight> rights) +{ + /** + * Empty required rights. + */ + public static final DocumentRequiredRights EMPTY = new DocumentRequiredRights(false, Set.of()); +} diff --git a/xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-api/src/main/java/org/xwiki/security/authorization/requiredrights/DocumentRequiredRightsManager.java b/xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-api/src/main/java/org/xwiki/security/authorization/requiredrights/DocumentRequiredRightsManager.java new file mode 100644 index 00000000000..64c68e45758 --- /dev/null +++ b/xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-api/src/main/java/org/xwiki/security/authorization/requiredrights/DocumentRequiredRightsManager.java @@ -0,0 +1,47 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.security.authorization.requiredrights; + +import java.util.Optional; + +import org.xwiki.component.annotation.Role; +import org.xwiki.model.reference.DocumentReference; +import org.xwiki.security.authorization.AuthorizationException; +import org.xwiki.stability.Unstable; + +/** + * Manager for document required rights. + * + * @version $Id$ + * @since 16.10.0RC1 + */ +@Unstable +@Role +public interface DocumentRequiredRightsManager +{ + /** + * Get the document required rights for the given document. + * + * @param documentReference the document to get the required rights for + * @return the document required rights if the document exists, empty otherwise + */ + Optional<DocumentRequiredRights> getRequiredRights(DocumentReference documentReference) + throws AuthorizationException; +} diff --git a/xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-api/src/main/resources/META-INF/components.txt b/xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-api/src/main/resources/META-INF/components.txt index f6e89bad263..0e25145cbe9 100644 --- a/xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-api/src/main/resources/META-INF/components.txt +++ b/xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-api/src/main/resources/META-INF/components.txt @@ -2,6 +2,7 @@ org.xwiki.security.DefaultSecurityReferenceFactory org.xwiki.security.authorization.cache.internal.DefaultSecurityCache org.xwiki.security.authorization.cache.internal.DefaultSecurityCacheLoader org.xwiki.security.authorization.internal.AuthorizationSettlerProvider +org.xwiki.security.authorization.internal.DocumentRequiredRightsChecker org.xwiki.security.authorization.DefaultAuthorizationManager org.xwiki.security.authorization.internal.DefaultAuthorizationManagerConfiguration org.xwiki.security.authorization.internal.DefaultAuthorizationSettler diff --git a/xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-api/src/test/java/org/xwiki/security/authorization/DefaultAuthorizationManagerIntegrationTest.java b/xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-api/src/test/java/org/xwiki/security/authorization/DefaultAuthorizationManagerIntegrationTest.java index f87ed2f51fd..843801ce814 100644 --- a/xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-api/src/test/java/org/xwiki/security/authorization/DefaultAuthorizationManagerIntegrationTest.java +++ b/xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-api/src/test/java/org/xwiki/security/authorization/DefaultAuthorizationManagerIntegrationTest.java @@ -55,6 +55,7 @@ import org.xwiki.security.authorization.cache.internal.TestCache; import org.xwiki.security.authorization.internal.AbstractSecurityRuleEntry; import org.xwiki.security.authorization.internal.DefaultAuthorizationSettler; +import org.xwiki.security.authorization.internal.DocumentRequiredRightsChecker; import org.xwiki.security.authorization.testwikis.SecureTestEntity; import org.xwiki.security.authorization.testwikis.TestAccessRule; import org.xwiki.security.authorization.testwikis.TestDefinition; @@ -137,6 +138,9 @@ class DefaultAuthorizationManagerIntegrationTest extends AbstractAuthorizationTe @MockComponent private SecurityCacheRulesInvalidator securityCacheRulesInvalidator; + @MockComponent + private DocumentRequiredRightsChecker documentRequiredRightsChecker; + /** Mocked cache */ private TestCache<Object> cache; @@ -161,6 +165,8 @@ public EntityReference answer(InvocationOnMock invocation) throws Throwable }); when(xWikiBridge.getMainWikiReference()).thenReturn(new WikiReference("xwiki")); + + when(this.documentRequiredRightsChecker.hasRequiredRights(any(), any())).thenReturn(true); } @BeforeEach diff --git a/xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-bridge/src/main/java/org/xwiki/security/authorization/internal/DefaultDocumentAuthorizationManager.java b/xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-bridge/src/main/java/org/xwiki/security/authorization/internal/DefaultDocumentAuthorizationManager.java new file mode 100644 index 00000000000..e0966cf5599 --- /dev/null +++ b/xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-bridge/src/main/java/org/xwiki/security/authorization/internal/DefaultDocumentAuthorizationManager.java @@ -0,0 +1,122 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.security.authorization.internal; + +import javax.inject.Inject; +import javax.inject.Singleton; + +import org.slf4j.Logger; +import org.xwiki.component.annotation.Component; +import org.xwiki.model.EntityType; +import org.xwiki.model.reference.DocumentReference; +import org.xwiki.model.reference.EntityReference; +import org.xwiki.security.authorization.AccessDeniedException; +import org.xwiki.security.authorization.AuthorizationException; +import org.xwiki.security.authorization.AuthorizationManager; +import org.xwiki.security.authorization.DocumentAuthorizationManager; +import org.xwiki.security.authorization.Right; +import org.xwiki.security.authorization.requiredrights.DocumentRequiredRights; +import org.xwiki.security.authorization.requiredrights.DocumentRequiredRightsManager; + +/** + * Default implementation of {@link DocumentAuthorizationManager}. + * + * @version $Id$ + * @since 16.10.0RC1 + */ +@Component +@Singleton +public class DefaultDocumentAuthorizationManager implements DocumentAuthorizationManager +{ + @Inject + private AuthorizationManager authorizationManager; + + @Inject + private DocumentRequiredRightsManager documentRequiredRightsManager; + + @Inject + private Logger logger; + + @Override + public boolean hasAccess(Right right, EntityType level, DocumentReference contextAuthor, + DocumentReference contextDocument) + { + EntityReference reference = contextDocument != null ? contextDocument.extractReference(level) : null; + + try { + return hasRequiredRight(right, level, contextDocument) + && this.authorizationManager.hasAccess(right, contextAuthor, reference); + } catch (Exception e) { + this.logger.error("Failed to load required rights for user [{}] on [{}].", + contextAuthor, contextDocument, e); + return false; + } + } + + @Override + public boolean hasRequiredRight(Right right, EntityType level, DocumentReference contextDocument) + throws AuthorizationException + { + DocumentRequiredRights documentRequiredRights = + this.documentRequiredRightsManager.getRequiredRights(contextDocument) + .orElse(DocumentRequiredRights.EMPTY); + + boolean hasAccess; + + if (documentRequiredRights.enforce()) { + hasAccess = documentRequiredRights.rights().stream() + .filter(requiredRight -> level.isAllowedAncestor(requiredRight.scope())) + .anyMatch(requiredRight -> + requiredRight.right().equals(right) || requiredRight.right() + .getImpliedRights() + // TODO: this is wrong. Not all rights are implied on all levels. For example, if there was + // no script right on space level, admin right on space level wouldn't imply script right. + // Need to investigate what's the proper solution here but either a) check enabled rights per + // level or b) raise the input level to the first level where the input right is defined. + .contains(right)); + } else { + hasAccess = true; + } + + return hasAccess; + } + + @Override + public void checkAccess(Right right, EntityType level, DocumentReference contextAuthor, + DocumentReference contextDocument) throws AccessDeniedException + { + EntityReference reference = contextDocument != null ? contextDocument.extractReference(level) : null; + + try { + if (hasRequiredRight(right, level, contextDocument)) { + this.authorizationManager.checkAccess(right, contextAuthor, reference); + } else { + this.logger.info("[{}] right has been denied to user [{}] on entity [{}] based on required rights" + + " of document [{}] on level [{}]: security checkpoint", right, contextAuthor, reference, + contextDocument, level); + throw new AccessDeniedException(right, contextAuthor, reference); + } + } catch (AccessDeniedException e) { + throw e; + } catch (Exception e) { + throw new AccessDeniedException(right, contextAuthor, contextDocument, e); + } + } +} diff --git a/xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-bridge/src/main/java/org/xwiki/security/authorization/internal/RightsFilterListener.java b/xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-bridge/src/main/java/org/xwiki/security/authorization/internal/RightsFilterListener.java index 722c52c26f8..9d61582a07c 100644 --- a/xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-bridge/src/main/java/org/xwiki/security/authorization/internal/RightsFilterListener.java +++ b/xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-bridge/src/main/java/org/xwiki/security/authorization/internal/RightsFilterListener.java @@ -32,6 +32,9 @@ import org.xwiki.observation.AbstractEventListener; import org.xwiki.observation.event.CancelableEvent; import org.xwiki.observation.event.Event; +import org.xwiki.security.authorization.internal.requiredrights.DocumentRequiredRightsReader; +import org.xwiki.security.authorization.requiredrights.DocumentRequiredRight; +import org.xwiki.security.authorization.requiredrights.DocumentRequiredRights; import org.xwiki.security.authorization.AccessDeniedException; import org.xwiki.security.authorization.AuthorizationManager; import org.xwiki.security.authorization.Right; @@ -64,9 +67,15 @@ public class RightsFilterListener extends AbstractEventListener */ public static final String NAME = "org.xwiki.security.authorization.internal.RightsFilterListener"; + private static final LocalDocumentReference REQUIRED_RIGHT_CLASS = + new LocalDocumentReference("XWiki", "RequiredRightClass"); + @Inject private AuthorizationManager authorization; + @Inject + private DocumentRequiredRightsReader documentRequiredRightsReader; + /** * The default constructor. */ @@ -89,6 +98,36 @@ public void onEvent(Event event, Object source, Object data) // Check global rights checkModifiedRights(userEvent.getUserReference(), document, XWikiGlobalRightsDocumentInitializer.CLASS_REFERENCE, (CancelableEvent) event); + + // Check the required rights. + checkModifiedRequiredRights(userEvent.getUserReference(), document, (CancelableEvent) event); + } + + private void checkModifiedRequiredRights(DocumentReference user, XWikiDocument document, + CancelableEvent event) + { + XWikiDocument originalDocument = document.getOriginalDocument(); + DocumentRequiredRights originalRequiredRights = + this.documentRequiredRightsReader.readRequiredRights(originalDocument); + DocumentRequiredRights requiredRights = this.documentRequiredRightsReader.readRequiredRights(document); + + if (!originalRequiredRights.equals(requiredRights) && requiredRights.enforce()) { + // We can assume that the current user has all existing required rights as otherwise editing would be + // denied. + // Therefore, only check if the user has all rights specified in the updated document that could either + // have changed required rights or where enforcing has just been enabled. + for (DocumentRequiredRight requiredRight : requiredRights.rights()) { + try { + this.authorization.checkAccess(requiredRight.right(), user, + document.getDocumentReference().extractReference(requiredRight.scope())); + } catch (AccessDeniedException e) { + event.cancel( + "The author doesn't have the right [%s] on the [%s] level that has been specified as required." + .formatted(requiredRight.right().getName(), requiredRight.scope().getLowerCase())); + break; + } + } + } } private void checkModifiedRights(DocumentReference user, XWikiDocument document, diff --git a/xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-bridge/src/main/java/org/xwiki/security/authorization/internal/requiredrights/DefaultDocumentRequiredRightsManager.java b/xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-bridge/src/main/java/org/xwiki/security/authorization/internal/requiredrights/DefaultDocumentRequiredRightsManager.java new file mode 100644 index 00000000000..c5c5465ccab --- /dev/null +++ b/xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-bridge/src/main/java/org/xwiki/security/authorization/internal/requiredrights/DefaultDocumentRequiredRightsManager.java @@ -0,0 +1,71 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.security.authorization.internal.requiredrights; + +import java.util.Optional; + +import javax.inject.Inject; +import javax.inject.Provider; +import javax.inject.Singleton; + +import org.xwiki.component.annotation.Component; +import org.xwiki.model.reference.DocumentReference; +import org.xwiki.security.authorization.AuthorizationException; +import org.xwiki.security.authorization.requiredrights.DocumentRequiredRights; +import org.xwiki.security.authorization.requiredrights.DocumentRequiredRightsManager; + +import com.xpn.xwiki.XWikiContext; +import com.xpn.xwiki.XWikiException; +import com.xpn.xwiki.doc.XWikiDocument; + +/** + * Default implementation of {@link DocumentRequiredRightsManager}. + * + * @version $Id$ + */ +@Component +@Singleton +public class DefaultDocumentRequiredRightsManager implements DocumentRequiredRightsManager +{ + @Inject + private Provider<XWikiContext> contextProvider; + + @Inject + private DocumentRequiredRightsReader documentRequiredRightsReader; + + @Override + public Optional<DocumentRequiredRights> getRequiredRights(DocumentReference documentReference) + throws AuthorizationException + { + XWikiContext context = this.contextProvider.get(); + + // Load the document. + try { + XWikiDocument document = context.getWiki().getDocument(documentReference, context); + if (!document.isNew()) { + return Optional.of(this.documentRequiredRightsReader.readRequiredRights(document)); + } + } catch (XWikiException e) { + throw new AuthorizationException("Failed to load the document", e); + } + + return Optional.empty(); + } +} diff --git a/xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-bridge/src/main/java/org/xwiki/security/authorization/internal/requiredrights/DocumentRequiredRightsReader.java b/xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-bridge/src/main/java/org/xwiki/security/authorization/internal/requiredrights/DocumentRequiredRightsReader.java new file mode 100644 index 00000000000..c8daa1ea347 --- /dev/null +++ b/xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-bridge/src/main/java/org/xwiki/security/authorization/internal/requiredrights/DocumentRequiredRightsReader.java @@ -0,0 +1,103 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.security.authorization.internal.requiredrights; + +import java.util.Objects; +import java.util.Set; +import java.util.stream.Collectors; + +import javax.inject.Singleton; + +import org.apache.commons.lang3.StringUtils; +import org.xwiki.component.annotation.Component; +import org.xwiki.model.EntityType; +import org.xwiki.model.reference.EntityReference; +import org.xwiki.model.reference.LocalDocumentReference; +import org.xwiki.security.authorization.requiredrights.DocumentRequiredRight; +import org.xwiki.security.authorization.requiredrights.DocumentRequiredRights; +import org.xwiki.security.authorization.Right; + +import com.xpn.xwiki.doc.XWikiDocument; +import com.xpn.xwiki.objects.BaseObject; + +/** + * Read the required rights from a document. + * + * @version $Id$ + * @since 16.6.0RC1 + */ +@Component(roles = DocumentRequiredRightsReader.class) +@Singleton +public class DocumentRequiredRightsReader +{ + private static final LocalDocumentReference CLASS_REFERENCE = + new LocalDocumentReference("XWiki", "RequiredRightClass"); + + private static final String PROPERTY_NAME = "level"; + + /** + * Read the required rights from a document. + * + * @param document the document to read the required rights from + * @return the required rights + */ + public DocumentRequiredRights readRequiredRights(XWikiDocument document) + { + return new DocumentRequiredRights(document.isEnforceRequiredRights(), + document.getXObjects(CLASS_REFERENCE).stream() + .filter(Objects::nonNull) + .map(this::readRequiredRight) + // Don't allow edit right/edit right implies no extra right. + .filter(requiredRight -> !Right.EDIT.equals(requiredRight.right())) + .collect(Collectors.toUnmodifiableSet())); + } + + private DocumentRequiredRight readRequiredRight(BaseObject object) + { + String value = object.getStringValue(PROPERTY_NAME); + EntityType entityType = EntityType.DOCUMENT; + Right right = Right.toRight(value); + if (right.equals(Right.ILLEGAL)) { + String[] levelRight = StringUtils.split(value, "_", 2); + if (levelRight.length == 2) { + right = Right.toRight(levelRight[1]); + entityType = EntityType.valueOf(levelRight[0].toUpperCase()); + } + } + + // TODO: add some handling for invalid values. + Set<EntityType> targetedEntityTypes = right.getTargetedEntityType(); + if (targetedEntityTypes == null) { + // This means the right targets only the farm level, which is null. + entityType = null; + } else { + EntityReference entityReference = object.getDocumentReference().extractReference(entityType); + // Try to get the highest level where this right can be assigned. This is done to ensure that, e.g., + // programming right can imply admin right on the wiki level even if programming right is only specified on + // the document level. + while (!targetedEntityTypes.contains(entityType) && entityReference != null) { + entityType = entityReference.getType(); + entityReference = entityReference.getParent(); + } + } + + return new DocumentRequiredRight(right, entityType); + } +} diff --git a/xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-bridge/src/main/resources/META-INF/components.txt b/xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-bridge/src/main/resources/META-INF/components.txt index f9d7d702026..fbfbca70d58 100644 --- a/xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-bridge/src/main/resources/META-INF/components.txt +++ b/xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-bridge/src/main/resources/META-INF/components.txt @@ -1,8 +1,11 @@ 500:org.xwiki.security.authorization.internal.BridgeAuthorizationManager org.xwiki.security.authorization.internal.DefaultContextualAuthorizationManager +org.xwiki.security.authorization.internal.DefaultDocumentAuthorizationManager org.xwiki.security.authorization.internal.DefaultSecurityCacheRulesInvalidator org.xwiki.security.authorization.internal.DefaultSecurityCacheRulesInvalidatorListener org.xwiki.security.authorization.internal.DefaultSecurityEntryReader +org.xwiki.security.authorization.internal.requiredrights.DefaultDocumentRequiredRightsManager +org.xwiki.security.authorization.internal.requiredrights.DocumentRequiredRightsReader org.xwiki.security.authorization.internal.RightsFilterListener org.xwiki.security.internal.DefaultUserBridge org.xwiki.security.internal.DefaultXWikiBridge diff --git a/xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-bridge/src/test/java/org/xwiki/security/authorization/internal/RightsFilterListenerTest.java b/xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-bridge/src/test/java/org/xwiki/security/authorization/internal/RightsFilterListenerTest.java index 9681754a839..52bfc41a47c 100644 --- a/xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-bridge/src/test/java/org/xwiki/security/authorization/internal/RightsFilterListenerTest.java +++ b/xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-bridge/src/test/java/org/xwiki/security/authorization/internal/RightsFilterListenerTest.java @@ -19,11 +19,14 @@ */ package org.xwiki.security.authorization.internal; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.xwiki.model.reference.DocumentReference; import org.xwiki.security.authorization.AccessDeniedException; import org.xwiki.security.authorization.AuthorizationManager; import org.xwiki.security.authorization.Right; +import org.xwiki.security.authorization.internal.requiredrights.DocumentRequiredRightsReader; +import org.xwiki.security.authorization.requiredrights.DocumentRequiredRights; import org.xwiki.test.junit5.mockito.InjectMockComponents; import org.xwiki.test.junit5.mockito.MockComponent; @@ -40,7 +43,9 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotEquals; import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.when; /** * Validate {@link RightsFilterListener}. @@ -54,12 +59,21 @@ public class RightsFilterListenerTest @MockComponent private AuthorizationManager authorization; + @MockComponent + private DocumentRequiredRightsReader requiredRightsReader; + @InjectMockComponents private RightsFilterListener listener; @InjectMockitoOldcore private MockitoOldcore oldcore; + @BeforeEach + void setUp() + { + when(this.requiredRightsReader.readRequiredRights(any())).thenReturn(DocumentRequiredRights.EMPTY); + } + @Test public void noRight() { diff --git a/xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-bridge/src/test/java/org/xwiki/security/authorization/internal/requiredrights/DocumentRequiredRightsReaderTest.java b/xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-bridge/src/test/java/org/xwiki/security/authorization/internal/requiredrights/DocumentRequiredRightsReaderTest.java new file mode 100644 index 00000000000..bedfdcb46db --- /dev/null +++ b/xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-bridge/src/test/java/org/xwiki/security/authorization/internal/requiredrights/DocumentRequiredRightsReaderTest.java @@ -0,0 +1,128 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.security.authorization.internal.requiredrights; + +import java.util.Arrays; +import java.util.List; +import java.util.Set; +import java.util.stream.Stream; + +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; +import org.xwiki.model.EntityType; +import org.xwiki.model.reference.DocumentReference; +import org.xwiki.model.reference.LocalDocumentReference; +import org.xwiki.security.authorization.Right; +import org.xwiki.security.authorization.requiredrights.DocumentRequiredRight; +import org.xwiki.security.authorization.requiredrights.DocumentRequiredRights; +import org.xwiki.test.junit5.mockito.ComponentTest; +import org.xwiki.test.junit5.mockito.InjectMockComponents; + +import com.xpn.xwiki.doc.XWikiDocument; +import com.xpn.xwiki.objects.BaseObject; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +/** + * Unit test for {@link DocumentRequiredRightsReader}. + * + * @version $Id$ + */ +@ComponentTest +class DocumentRequiredRightsReaderTest +{ + private static final LocalDocumentReference CLASS_REFERENCE = + new LocalDocumentReference("XWiki", "RequiredRightClass"); + + private static final DocumentReference DOCUMENT_REFERENCE = + new DocumentReference("wiki", "Space", "Page"); + + @InjectMockComponents + private DocumentRequiredRightsReader documentRequiredRightsReader; + + @ParameterizedTest + @MethodSource("getArguments") + void readRequiredRights(boolean enforce, List<String> values, DocumentRequiredRights expected) + { + XWikiDocument document = mock(); + when(document.isEnforceRequiredRights()).thenReturn(enforce); + List<BaseObject> objects = values.stream() + .map(value -> { + if (value == null) { + return null; + } else { + BaseObject object = mock(); + when(object.getStringValue("level")).thenReturn(value); + when(object.getDocumentReference()).thenReturn(DOCUMENT_REFERENCE); + return object; + } + }) + .toList(); + when(document.getXObjects(CLASS_REFERENCE)).thenReturn(objects); + + DocumentRequiredRights actual = this.documentRequiredRightsReader.readRequiredRights(document); + + assertEquals(expected, actual); + } + + static Stream<Arguments> getArguments() + { + return Stream.of( + Arguments.of( + false, + List.of(), + DocumentRequiredRights.EMPTY + ), + Arguments.of( + true, + List.of(), + new DocumentRequiredRights(true, Set.of()) + ), + Arguments.of( + true, + List.of("programming"), + new DocumentRequiredRights(true, Set.of(new DocumentRequiredRight(Right.PROGRAM, null))) + ), + Arguments.of( + true, + List.of("edit"), + new DocumentRequiredRights(true, Set.of()) + ), + Arguments.of( + true, + List.of("wiki_admin"), + new DocumentRequiredRights(true, Set.of(new DocumentRequiredRight(Right.ADMIN, EntityType.WIKI))) + ), + Arguments.of( + true, + Arrays.asList(null, "script"), + new DocumentRequiredRights(true, Set.of(new DocumentRequiredRight(Right.SCRIPT, EntityType.DOCUMENT))) + ), + Arguments.of( + true, + Arrays.asList(null, "admin", null), + new DocumentRequiredRights(true, Set.of(new DocumentRequiredRight(Right.ADMIN, EntityType.SPACE))) + ) + ); + } +} diff --git a/xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-bridge/src/test/java/org/xwiki/security/authorization/testwikibuilding/LegacyTestWiki.java b/xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-bridge/src/test/java/org/xwiki/security/authorization/testwikibuilding/LegacyTestWiki.java index 0a03bc4596a..e493946830e 100644 --- a/xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-bridge/src/test/java/org/xwiki/security/authorization/testwikibuilding/LegacyTestWiki.java +++ b/xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-bridge/src/test/java/org/xwiki/security/authorization/testwikibuilding/LegacyTestWiki.java @@ -1073,6 +1073,12 @@ public Object invoke(Invocation invocation) allowing(mockedDocument) .getXObjects(XWikiGroupsDocumentInitializer.XWIKI_GROUPS_DOCUMENT_REFERENCE); will(returnValue(Collections.emptyList())); + // TODO: implement support for returning other values to add test cases for required rights. + allowing(mockedDocument).isEnforceRequiredRights(); + will(returnValue(false)); + allowing(mockedDocument) + .getXObjects(with(equal(new LocalDocumentReference("XWiki", "RequiredRightClass")))); + will(returnValue(List.of())); } }); diff --git a/xwiki-platform-core/xwiki-platform-xar/xwiki-platform-xar-model/src/main/java/org/xwiki/xar/internal/model/XarDocumentModel.java b/xwiki-platform-core/xwiki-platform-xar/xwiki-platform-xar-model/src/main/java/org/xwiki/xar/internal/model/XarDocumentModel.java index a49b99ceb5a..703905e136f 100644 --- a/xwiki-platform-core/xwiki-platform-xar/xwiki-platform-xar-model/src/main/java/org/xwiki/xar/internal/model/XarDocumentModel.java +++ b/xwiki-platform-core/xwiki-platform-xar/xwiki-platform-xar-model/src/main/java/org/xwiki/xar/internal/model/XarDocumentModel.java @@ -19,6 +19,8 @@ */ package org.xwiki.xar.internal.model; +import org.xwiki.stability.Unstable; + /** * @version $Id$ * @since 5.4M1 @@ -61,12 +63,20 @@ public class XarDocumentModel */ public static final String VERSION_15 = "1.5"; + /** + * Introduce the concept of required right enforcement. + * + * @since 16.10.0RC1 + */ + @Unstable + public static final String VERSION_16 = "1.6"; + /** * The current version. * * @since 9.0RC1 */ - public static final String VERSION_CURRENT = VERSION_15; + public static final String VERSION_CURRENT = VERSION_16; public static final String ELEMENT_DOCUMENT = "xwikidoc"; @@ -163,6 +173,12 @@ public class XarDocumentModel */ public static final String ELEMENT_REVISION_ORIGINALMEDATAAUTHOR = "originalMetadataAuthor"; + /** + * @since 16.10.0RC1 + */ + @Unstable + public static final String ELEMENT_ENFORCE_REQUIRED_RIGHTS = "enforceRequiredRights"; + public static final String ELEMENT_REVISION_COMMENT = "comment"; public static final String ELEMENT_REVISION_MINOR = "minorEdit"; -- GitLab