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 76b826549023..ea838aa7e3fd 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 @@ -166,6 +166,14 @@ 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); } 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 9b58d7fc4aab..2cd09cb8d649 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 @@ -476,6 +476,82 @@ void defaultAccessOnEmptyWikis() throws Exception getDoc("an another subwiki", "anySpace", "any Other SubWiki")); } + @Test + void requiredRights() throws Exception + { + initialiseWikiMock("requiredRights"); + DocumentReference simpleDoc = getXDoc("simpleDocument", "space"); + DocumentReference enforcedDoc = getXDoc("enforcedDocument", "space"); + DocumentReference scriptDoc = getXDoc("scriptDocument", "space"); + DocumentReference adminDoc = getXDoc("adminDocument", "space"); + DocumentReference programmingDoc = getXDoc("programmingDocument", "space"); + DocumentReference fakeProgrammingDoc = getXDoc("fakeProgrammingDocument", "space"); + + DocumentReference viewUser = getXUser("viewUser"); + DocumentReference editUser = getXUser("editUser"); + DocumentReference scriptUser = getXUser("scriptUser"); + DocumentReference wikiAdminUser = getXUser("wikiAdminUser"); + DocumentReference spaceAdminUser = getXUser("spaceAdminUser"); + DocumentReference programmingUser = getXUser("programmingUser"); + + // The view user cannot edit any of the documents but view all of them. + for (DocumentReference doc : List.of(simpleDoc, enforcedDoc, scriptDoc, adminDoc, programmingDoc, + fakeProgrammingDoc)) { + assertAccess(new RightSet(VIEW, COMMENT, REGISTER, LOGIN), viewUser, doc); + } + + // All users with edit right can edit all documents that don't enforce specific rights. + for (DocumentReference doc : List.of(simpleDoc, enforcedDoc, fakeProgrammingDoc)) { + assertAccess(new RightSet(VIEW, EDIT, COMMENT, REGISTER, LOGIN), editUser, doc); + assertAccess(new RightSet(VIEW, EDIT, SCRIPT, COMMENT, DELETE, REGISTER, LOGIN, ADMIN), spaceAdminUser, + doc); + assertAccess(new RightSet(VIEW, EDIT, SCRIPT, COMMENT, REGISTER, LOGIN), scriptUser, doc); + assertAccess(new RightSet(VIEW, EDIT, SCRIPT, COMMENT, DELETE, REGISTER, LOGIN, ADMIN), wikiAdminUser, doc); + assertAccess(new RightSet(VIEW, EDIT, SCRIPT, COMMENT, DELETE, REGISTER, LOGIN, ADMIN, PROGRAM, + CREATE_WIKI), + programmingUser, doc); + } + + // Edit user cannot edit documents that enforce more rights. + for (DocumentReference doc : List.of(scriptDoc, adminDoc, programmingDoc)) { + assertAccess(new RightSet(VIEW, COMMENT, REGISTER, LOGIN), editUser, doc); + } + + // The script and space admin user can edit the script document. + assertAccess(new RightSet(VIEW, EDIT, SCRIPT, COMMENT, REGISTER, LOGIN), scriptUser, scriptDoc); + assertAccess(new RightSet(VIEW, SCRIPT, COMMENT, REGISTER, LOGIN), scriptUser, adminDoc); + assertAccess(new RightSet(VIEW, SCRIPT, COMMENT, REGISTER, LOGIN), scriptUser, programmingDoc); + + assertAccess(new RightSet(VIEW, EDIT, SCRIPT, COMMENT, DELETE, REGISTER, LOGIN, ADMIN), spaceAdminUser, + scriptDoc); + assertAccess(new RightSet(VIEW, COMMENT, SCRIPT, DELETE, REGISTER, LOGIN, ADMIN), spaceAdminUser, adminDoc); + assertAccess(new RightSet(VIEW, COMMENT, SCRIPT, DELETE, REGISTER, LOGIN, ADMIN), spaceAdminUser, + programmingDoc); + + // The wiki admin user can edit the script and admin documents. + assertAccess(new RightSet(VIEW, EDIT, COMMENT, SCRIPT, DELETE, REGISTER, LOGIN, ADMIN), wikiAdminUser, + scriptDoc); + assertAccess(new RightSet(VIEW, EDIT, COMMENT, SCRIPT, DELETE, REGISTER, LOGIN, ADMIN), wikiAdminUser, + adminDoc); + assertAccess(new RightSet(VIEW, COMMENT, SCRIPT, DELETE, REGISTER, LOGIN, ADMIN), wikiAdminUser, + programmingDoc); + + // The programming user can edit all documents. + for (DocumentReference doc : List.of(scriptDoc, adminDoc, programmingDoc)) { + assertAccess(new RightSet(VIEW, EDIT, SCRIPT, COMMENT, DELETE, REGISTER, LOGIN, ADMIN, PROGRAM, + CREATE_WIKI), programmingUser, doc); + } + + DocumentReference subWikiAdmin = getUser("subWikiAdmin", "SubWiki"); + DocumentReference subWikiAdminDocument = getDoc("adminDocument", "subWikiSpace", "SubWiki"); + + // Both main wiki and subwiki admin have edit access on the subwiki document. + for (DocumentReference user : List.of(wikiAdminUser, subWikiAdmin)) { + assertAccess(new RightSet(VIEW, EDIT, SCRIPT, COMMENT, DELETE, REGISTER, LOGIN, ADMIN), user, + subWikiAdminDocument); + } + } + @Test void verifyNeedsAuthentication() throws Exception { 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/testwikis/internal/parser/TestRequiredRightFactory.java b/xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-api/src/test/java/org/xwiki/security/authorization/testwikis/internal/parser/TestRequiredRightFactory.java index e67a7f8d8956..e33ca9c85f1a 100644 --- a/xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-api/src/test/java/org/xwiki/security/authorization/testwikis/internal/parser/TestRequiredRightFactory.java +++ b/xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-api/src/test/java/org/xwiki/security/authorization/testwikis/internal/parser/TestRequiredRightFactory.java @@ -58,7 +58,14 @@ TestRequiredRight getNewInstance(ElementParser parser, String name, TestEntity p { Right right = Right.toRight(attributes.getValue("type")); String scopeValue = attributes.getValue("scope"); - EntityType scope = scopeValue != null ? EntityType.valueOf(scopeValue.toUpperCase()) : EntityType.DOCUMENT; + EntityType scope; + if (scopeValue == null) { + scope = EntityType.DOCUMENT; + } else if ("farm".equalsIgnoreCase(scopeValue)) { + scope = null; + } else { + scope = EntityType.valueOf(scopeValue.toUpperCase()); + } return new DefaultTestRequiredRight(right, scope, parent); } diff --git a/xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-api/src/test/resources/testwikis/requiredRights.xml b/xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-api/src/test/resources/testwikis/requiredRights.xml new file mode 100644 index 000000000000..dc62328d4323 --- /dev/null +++ b/xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-api/src/test/resources/testwikis/requiredRights.xml @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file