/* * (C) Copyright 2015 Nuxeo SA (http://nuxeo.com/) and others. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Contributors: * Thomas Roger */ package org.nuxeo.ecm.permissions; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.nuxeo.ecm.core.api.security.SecurityConstants.EVERYTHING; import static org.nuxeo.ecm.core.api.security.SecurityConstants.READ; import static org.nuxeo.ecm.core.api.security.SecurityConstants.WRITE; import static org.nuxeo.ecm.permissions.Constants.ACE_INFO_DIRECTORY; import static org.nuxeo.ecm.permissions.Constants.COMMENT_KEY; import static org.nuxeo.ecm.permissions.Constants.NOTIFY_KEY; import java.io.Serializable; import java.util.HashMap; import java.util.Map; import javax.security.auth.login.LoginContext; import javax.security.auth.login.LoginException; import org.junit.Test; import org.junit.runner.RunWith; import org.nuxeo.ecm.core.api.CoreInstance; import org.nuxeo.ecm.core.api.CoreSession; import org.nuxeo.ecm.core.api.DocumentModel; import org.nuxeo.ecm.core.api.DocumentModelList; import org.nuxeo.ecm.core.api.IdRef; import org.nuxeo.ecm.core.api.security.ACE; import org.nuxeo.ecm.core.api.security.ACL; import org.nuxeo.ecm.core.api.security.ACP; import org.nuxeo.ecm.core.test.CoreFeature; import org.nuxeo.ecm.core.test.TransactionalFeature; import org.nuxeo.ecm.core.test.annotations.Granularity; import org.nuxeo.ecm.core.test.annotations.RepositoryConfig; import org.nuxeo.ecm.directory.Session; import org.nuxeo.ecm.directory.api.DirectoryService; import org.nuxeo.ecm.platform.test.PlatformFeature; import org.nuxeo.runtime.api.Framework; import org.nuxeo.runtime.test.runner.Deploy; import org.nuxeo.runtime.test.runner.Features; import org.nuxeo.runtime.test.runner.FeaturesRunner; import com.google.inject.Inject; /** * @since 7.4 */ @RunWith(FeaturesRunner.class) @Features({ TransactionalFeature.class, PlatformFeature.class }) @RepositoryConfig(cleanup = Granularity.METHOD) @Deploy({ "org.nuxeo.ecm.permissions" }) public class TestPermissionListener { @Inject protected CoreFeature coreFeature; @Inject protected CoreSession session; @Inject protected DirectoryService directoryService; protected LoginContext loginContext; protected void login(String username) throws LoginException { loginContext = Framework.login(username, username); } protected void logout() throws LoginException { loginContext.logout(); } @Test public void shouldFillDirectory() { DocumentModel doc = createTestDocument(); ACE fryACE = new ACE("fry", WRITE, true); ACE leelaACE = new ACE("leela", READ, true); ACP acp = doc.getACP(); acp.addACE(ACL.LOCAL_ACL, fryACE); acp.addACE(ACL.LOCAL_ACL, leelaACE); doc.setACP(acp, true); try (Session session = directoryService.open(ACE_INFO_DIRECTORY)) { Map<String, Serializable> filter = new HashMap<>(); filter.put("docId", doc.getId()); DocumentModelList entries = session.query(filter); assertEquals(2, entries.size()); String id = PermissionHelper.computeDirectoryId(doc, ACL.LOCAL_ACL, fryACE.getId()); DocumentModel entry = session.getEntry(id); assertEquals(doc.getRepositoryName(), entry.getPropertyValue("aceinfo:repositoryName")); assertEquals("local", entry.getPropertyValue("aceinfo:aclName")); assertEquals(fryACE.getId(), entry.getPropertyValue("aceinfo:aceId")); id = PermissionHelper.computeDirectoryId(doc, ACL.LOCAL_ACL, leelaACE.getId()); entry = session.getEntry(id); assertEquals(doc.getRepositoryName(), entry.getPropertyValue("aceinfo:repositoryName")); assertEquals("local", entry.getPropertyValue("aceinfo:aclName")); assertEquals(leelaACE.getId(), entry.getPropertyValue("aceinfo:aceId")); } } protected DocumentModel createTestDocument() { DocumentModel doc = session.createDocumentModel("/", "file", "File"); return session.createDocument(doc); } @Test public void shouldUpdateDirectory() throws Exception { String repositoryName = session.getRepositoryName(); String docId; String fryACEId; DocumentModel root = session.getRootDocument(); ACP rootACP = root.getACP(); rootACP.addACE(ACL.LOCAL_ACL, new ACE("joe", EVERYTHING, true)); root.setACP(rootACP, true); login("joe"); try (CoreSession joeSession = CoreInstance.openCoreSession(repositoryName)) { DocumentModel doc = joeSession.createDocumentModel("/", "file", "File"); doc = joeSession.createDocument(doc); docId = doc.getId(); ACE fryACE = new ACE("fry", WRITE, true); ACE leelaACE = new ACE("leela", READ, true); ACP acp = doc.getACP(); acp.addACE(ACL.LOCAL_ACL, fryACE); acp.addACE(ACL.LOCAL_ACL, leelaACE); doc.setACP(acp, true); acp = doc.getACP(); acp.removeACE(ACL.LOCAL_ACL, leelaACE); acp.removeACE(ACL.LOCAL_ACL, fryACE); fryACE = new ACE("fry", READ, true); acp.addACE(ACL.LOCAL_ACL, fryACE); doc.setACP(acp, true); fryACEId = fryACE.getId(); } finally { logout(); } try (Session session = directoryService.open(ACE_INFO_DIRECTORY)) { Map<String, Serializable> filter = new HashMap<>(); filter.put("docId", docId); DocumentModelList entries = session.query(filter); assertEquals(1, entries.size()); DocumentModel entry = entries.get(0); assertEquals(repositoryName, entry.getPropertyValue("aceinfo:repositoryName")); assertEquals("local", entry.getPropertyValue("aceinfo:aclName")); assertEquals(fryACEId, entry.getPropertyValue("aceinfo:aceId")); } login("joe"); try (CoreSession joeSession = CoreInstance.openCoreSession(repositoryName)) { DocumentModel doc = joeSession.getDocument(new IdRef(docId)); ACP acp = doc.getACP(); ACL acl = acp.getOrCreateACL(); acl.clear(); acp.addACL(acl); doc.setACP(acp, true); } finally { logout(); } try (Session session = directoryService.open(ACE_INFO_DIRECTORY)) { Map<String, Serializable> filter = new HashMap<>(); filter.put("docId", docId); DocumentModelList entries = session.query(filter); assertTrue(entries.isEmpty()); } } @Test public void shouldStoreNotifyAndComment() { DocumentModel doc = createTestDocument(); ACP acp = doc.getACP(); ACL acl = acp.getOrCreateACL(); ACE fryACE = new ACE("fry", WRITE, true); fryACE.putContextData(NOTIFY_KEY, true); fryACE.putContextData(COMMENT_KEY, "fry comment"); ACE leelaACE = new ACE("leela", READ, true); acl.add(fryACE); acl.add(leelaACE); acp.addACL(acl); doc.setACP(acp, true); try (Session session = directoryService.open(ACE_INFO_DIRECTORY)) { Map<String, Serializable> filter = new HashMap<>(); filter.put("docId", doc.getId()); DocumentModelList entries = session.query(filter); assertEquals(2, entries.size()); String id = PermissionHelper.computeDirectoryId(doc, ACL.LOCAL_ACL, fryACE.getId()); DocumentModel entry = session.getEntry(id); assertEquals(fryACE.getId(), entry.getPropertyValue("aceinfo:aceId")); assertTrue((Boolean) entry.getPropertyValue("aceinfo:notify")); assertEquals("fry comment", entry.getPropertyValue("aceinfo:comment")); id = PermissionHelper.computeDirectoryId(doc, ACL.LOCAL_ACL, leelaACE.getId()); entry = session.getEntry(id); assertEquals(leelaACE.getId(), entry.getPropertyValue("aceinfo:aceId")); assertFalse((Boolean) entry.getPropertyValue("aceinfo:notify")); assertNull(entry.getPropertyValue("aceinfo:comment")); } } @Test public void replacingAnACEShouldReplaceTheOldEntry() { DocumentModel doc = createTestDocument(); ACP acp = doc.getACP(); ACL acl = acp.getOrCreateACL(); ACE fryACE = new ACE("fry", WRITE, true); fryACE.putContextData(NOTIFY_KEY, true); fryACE.putContextData(COMMENT_KEY, "fry comment"); acl.add(fryACE); acp.addACL(acl); doc.setACP(acp, true); try (Session dirSession = directoryService.open(ACE_INFO_DIRECTORY)) { Map<String, Serializable> filter = new HashMap<>(); filter.put("docId", doc.getId()); DocumentModelList entries = dirSession.query(filter); assertEquals(1, entries.size()); String id = PermissionHelper.computeDirectoryId(doc, ACL.LOCAL_ACL, fryACE.getId()); DocumentModel entry = dirSession.getEntry(id); assertEquals(fryACE.getId(), entry.getPropertyValue("aceinfo:aceId")); assertTrue((Boolean) entry.getPropertyValue("aceinfo:notify")); assertEquals("fry comment", entry.getPropertyValue("aceinfo:comment")); } // replacing the ACE for fry ACE newFryACE = ACE.builder("fry", READ).build(); session.replaceACE(doc.getRef(), ACL.LOCAL_ACL, fryACE, newFryACE); try (Session dirSession = directoryService.open(ACE_INFO_DIRECTORY)) { Map<String, Serializable> filter = new HashMap<>(); filter.put("docId", doc.getId()); DocumentModelList entries = dirSession.query(filter); assertEquals(1, entries.size()); String id = PermissionHelper.computeDirectoryId(doc, ACL.LOCAL_ACL, newFryACE.getId()); DocumentModel entry = dirSession.getEntry(id); assertEquals(newFryACE.getId(), entry.getPropertyValue("aceinfo:aceId")); assertFalse((Boolean) entry.getPropertyValue("aceinfo:notify")); assertNull(entry.getPropertyValue("aceinfo:comment")); } ACE newFryACE2 = ACE.builder("fry", WRITE).build(); newFryACE2.putContextData(NOTIFY_KEY, true); session.replaceACE(doc.getRef(), ACL.LOCAL_ACL, newFryACE, newFryACE2); try (Session dirSession = directoryService.open(ACE_INFO_DIRECTORY)) { Map<String, Serializable> filter = new HashMap<>(); filter.put("docId", doc.getId()); DocumentModelList entries = dirSession.query(filter); assertEquals(1, entries.size()); String id = PermissionHelper.computeDirectoryId(doc, ACL.LOCAL_ACL, newFryACE2.getId()); DocumentModel entry = dirSession.getEntry(id); assertEquals(newFryACE2.getId(), entry.getPropertyValue("aceinfo:aceId")); assertTrue((Boolean) entry.getPropertyValue("aceinfo:notify")); assertNull(entry.getPropertyValue("aceinfo:comment")); } } }