/*
* (C) Copyright 2006-2016 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:
* Radu Darlea
* Florent Guillaume
*/
package org.nuxeo.ecm.platform.tag;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.junit.Assume.assumeTrue;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import javax.inject.Inject;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.junit.Before;
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.DocumentRef;
import org.nuxeo.ecm.core.api.DocumentSecurityException;
import org.nuxeo.ecm.core.api.LifeCycleConstants;
import org.nuxeo.ecm.core.api.security.ACE;
import org.nuxeo.ecm.core.api.security.ACL;
import org.nuxeo.ecm.core.api.security.SecurityConstants;
import org.nuxeo.ecm.core.api.security.impl.ACPImpl;
import org.nuxeo.ecm.core.event.EventService;
import org.nuxeo.ecm.core.test.CoreFeature;
import org.nuxeo.ecm.core.test.StorageConfiguration;
import org.nuxeo.ecm.core.test.annotations.Granularity;
import org.nuxeo.ecm.core.test.annotations.RepositoryConfig;
import org.nuxeo.ecm.core.trash.TrashService;
import org.nuxeo.ecm.platform.api.ws.DocumentProperty;
import org.nuxeo.ecm.platform.api.ws.DocumentSnapshot;
import org.nuxeo.ecm.platform.ws.NuxeoRemotingBean;
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 org.nuxeo.runtime.test.runner.LocalDeploy;
import org.nuxeo.runtime.transaction.TransactionHelper;
@RunWith(FeaturesRunner.class)
@Features(CoreFeature.class)
@RepositoryConfig(cleanup = Granularity.METHOD)
@Deploy({ "org.nuxeo.runtime.datasource", "org.nuxeo.ecm.platform.tag", "org.nuxeo.ecm.platform.query.api",
"org.nuxeo.ecm.platform.ws" })
@LocalDeploy("org.nuxeo.ecm.platform.tag:login-config.xml")
public class TestTagService {
protected static final Log log = LogFactory.getLog(TestTagService.class);
@Inject
protected CoreFeature coreFeature;
@Inject
protected CoreSession session;
@Inject
protected TagService tagService;
@Inject
protected TrashService trashService;
@Before
public void checkTagsSupported() {
assumeTrue("DBS does not support tags", !coreFeature.getStorageConfiguration().isDBS());
}
// Oracle fails if we do too many connections in a short time, sleep
// here to prevent this.
public void maybeSleep() throws Exception {
StorageConfiguration storageConfiguration = coreFeature.getStorageConfiguration();
if (storageConfiguration.isVCSOracle() || storageConfiguration.isVCSSQLServer()) {
Thread.sleep(5 * 1000);
}
}
@Test
public void testTags() throws Exception {
DocumentModel fold = session.createDocumentModel("/", "fold", "Folder");
fold = session.createDocument(fold);
DocumentModel file1 = session.createDocumentModel("/", "foo", "File");
file1.setPropertyValue("dc:title", "File1");
file1 = session.createDocument(file1);
DocumentModel file2 = session.createDocumentModel("/fold", "bar", "File");
file2.setPropertyValue("dc:title", "File2");
file2 = session.createDocument(file2);
session.save();
String file1Id = file1.getId();
String file2Id = file2.getId();
Set<String> file1set = new HashSet<>(Collections.singleton(file1Id));
Set<String> twofiles = new HashSet<>(Arrays.asList(file1Id, file2Id));
// add tag
tagService.tag(session, file1Id, "mytag", "Administrator");
tagService.tag(session, file1Id, "othertag", "Administrator");
tagService.tag(session, file2Id, "mytag", "Administrator");
session.save();
Set<String> mytag = new HashSet<>(Collections.singleton("mytag"));
Set<String> twotags = new HashSet<>(Arrays.asList("mytag", "othertag"));
// find tags for doc
List<Tag> tags;
// file 1
tags = tagService.getDocumentTags(session, file1Id, null);
assertEquals(twotags, labels(tags));
tags = tagService.getDocumentTags(session, file1Id, "Administrator");
assertEquals(twotags, labels(tags));
tags = tagService.getDocumentTags(session, file1Id, "bob");
assertTrue(tags.isEmpty());
// file 2
tags = tagService.getDocumentTags(session, file2Id, null);
assertEquals(mytag, labels(tags));
tags = tagService.getDocumentTags(session, file2Id, "Administrator");
assertEquals(mytag, labels(tags));
tags = tagService.getDocumentTags(session, file2Id, "bob");
assertTrue(tags.isEmpty());
maybeSleep();
// find docs for tag
List<String> docIds;
// tag 1
docIds = tagService.getTagDocumentIds(session, "mytag", null);
assertEquals(twofiles, new HashSet<>(docIds));
docIds = tagService.getTagDocumentIds(session, "mytag", "Administrator");
assertEquals(twofiles, new HashSet<>(docIds));
docIds = tagService.getTagDocumentIds(session, "mytag", "bob");
assertTrue(docIds.isEmpty());
// tag 2
docIds = tagService.getTagDocumentIds(session, "othertag", null);
assertEquals(file1set, new HashSet<>(docIds));
docIds = tagService.getTagDocumentIds(session, "othertag", "Administrator");
assertEquals(file1set, new HashSet<>(docIds));
docIds = tagService.getTagDocumentIds(session, "othertag", "bob");
assertTrue(docIds.isEmpty());
maybeSleep();
// global cloud
List<Tag> cloud = tagService.getTagCloud(session, null, null, null);
assertEquals(cloud.toString(), 2, cloud.size());
Collections.sort(cloud, Tag.LABEL_COMPARATOR);
Tag tag1 = cloud.get(0);
assertEquals("mytag", tag1.getLabel());
assertEquals(2, tag1.getWeight());
Tag tag2 = cloud.get(1);
assertEquals("othertag", tag2.getLabel());
assertEquals(1, tag2.getWeight());
// specific tagging user
cloud = tagService.getTagCloud(session, null, "bob", null);
assertEquals(0, cloud.size());
// cloud per folder
cloud = tagService.getTagCloud(session, fold.getId(), null, null);
assertEquals(1, cloud.size()); // only file2 under fold
Collections.sort(cloud, Tag.LABEL_COMPARATOR);
tag1 = cloud.get(0);
assertEquals("mytag", tag1.getLabel());
assertEquals(1, tag1.getWeight());
// cloud under root folder
cloud = tagService.getTagCloud(session, session.getRootDocument().getId(), null, null);
assertEquals(2, cloud.size());
Collections.sort(cloud, Tag.LABEL_COMPARATOR);
tag1 = cloud.get(0);
assertEquals("mytag", tag1.getLabel());
assertEquals(2, tag1.getWeight());
tag2 = cloud.get(1);
assertEquals("othertag", tag2.getLabel());
assertEquals(1, tag2.getWeight());
// suggestions
List<Tag> suggestions = tagService.getSuggestions(session, "my", null);
assertEquals(mytag, labels(suggestions));
suggestions = tagService.getSuggestions(session, "%tag", null);
assertEquals(twotags, labels(suggestions));
maybeSleep();
// ws loader
NuxeoRemotingBean remoting = new NuxeoRemotingBean();
String sid = remoting.connect("Administrator", "Administrator");
DocumentSnapshot snapshot = remoting.getDocumentSnapshot(sid, file1Id);
DocumentProperty[] props = snapshot.getNoBlobProperties();
Comparator<DocumentProperty> propsComparator = (o1, o2) -> o1.getName().compareTo(o2.getName());
Arrays.sort(props, propsComparator);
int ti = Arrays.binarySearch(props, new DocumentProperty("tags", null), propsComparator);
assertTrue(ti > 0);
String expected = "tags:othertag,mytag";
String prop = props[ti].toString();
if (!expected.equals(prop)) {
// order depends on database
expected = "tags:mytag,othertag";
}
assertEquals(expected, prop);
// remove explicit tagging
tagService.untag(session, file2Id, "mytag", null);
tags = tagService.getDocumentTags(session, file2Id, null);
assertTrue(tags.isEmpty());
docIds = tagService.getTagDocumentIds(session, "mytag", "Administrator");
assertEquals(file1set, new HashSet<>(docIds));
// remove all taggings on doc
tagService.untag(session, file1Id, null, null);
tags = tagService.getDocumentTags(session, file1Id, null);
assertTrue(tags.isEmpty());
// close remote session
remoting.disconnect(sid);
}
protected static Set<String> labels(List<Tag> tags) {
return tags.stream().map(Tag::getLabel).collect(Collectors.toSet());
}
@Test
public void testUntagOnDelete() throws Exception {
DocumentModel file = session.createDocumentModel("/", "foo", "File");
file.setPropertyValue("dc:title", "File1");
file = session.createDocument(file);
String file1Id = file.getId();
List<Tag> tags;
tagService.tag(session, file1Id, "mytag", "Administrator");
// check tag present
tags = tagService.getDocumentTags(session, file1Id, null);
assertEquals(Collections.singleton("mytag"), labels(tags));
// delete doc
session.removeDocument(file.getRef());
TransactionHelper.commitOrRollbackTransaction();
// wait for async tag removal
Framework.getService(EventService.class).waitForAsyncCompletion();
// check no more tag
TransactionHelper.startTransaction();
tags = tagService.getDocumentTags(session, file1Id, null);
assertEquals(Collections.emptySet(), labels(tags));
}
@Test
public void testUntagOnTrash() throws Exception {
DocumentModel file = session.createDocumentModel("/", "foo", "File");
file.setPropertyValue("dc:title", "File1");
file = session.createDocument(file);
String file1Id = file.getId();
List<Tag> tags;
tagService.tag(session, file1Id, "mytag", "Administrator");
// check tag present
tags = tagService.getDocumentTags(session, file1Id, null);
assertEquals(Collections.singleton("mytag"), labels(tags));
// trash doc
file.followTransition(LifeCycleConstants.DELETE_TRANSITION);
TransactionHelper.commitOrRollbackTransaction();
// wait for async tag removal
Framework.getService(EventService.class).waitForAsyncCompletion();
// check no more tag
TransactionHelper.startTransaction();
tags = tagService.getDocumentTags(session, file1Id, null);
assertEquals(Collections.emptySet(), labels(tags));
}
@Test
public void testRemoveTags() {
DocumentModel file = session.createDocumentModel("/", "foo", "File");
file.setPropertyValue("dc:title", "File1");
file = session.createDocument(file);
session.save();
String fileId = file.getId();
tagService.tag(session, fileId, "foo", "Administrator");
tagService.tag(session, fileId, "bar", "leela");
tagService.tag(session, fileId, "foo", "bender");
assertEquals(2, tagService.getDocumentTags(session, fileId, null).size());
tagService.removeTags(session, fileId);
assertEquals(0, tagService.getDocumentTags(session, fileId, null).size());
}
@Test
public void testRemoveDoc() {
DocumentModel file = session.createDocumentModel("/", "foo", "File");
file.setPropertyValue("dc:title", "File1");
file = session.createDocument(file);
session.save();
String fileId = file.getId();
tagService.tag(session, fileId, "foo", "Administrator");
tagService.tag(session, fileId, "bar", "leela");
tagService.tag(session, fileId, "foo", "bender");
assertEquals(2, tagService.getDocumentTags(session, fileId, null).size());
session.removeDocument(file.getRef());
// wait for async tag removal
TransactionHelper.commitOrRollbackTransaction();
Framework.getService(EventService.class).waitForAsyncCompletion();
TransactionHelper.startTransaction();
// check no more tag
assertEquals(0, tagService.getDocumentTags(session, fileId, null).size());
}
@Test
public void testCopyTags() {
DocumentModel srcFile = session.createDocumentModel("/", "srcFile", "File");
srcFile.setPropertyValue("dc:title", "File1");
srcFile = session.createDocument(srcFile);
session.save();
String srcDocId = srcFile.getId();
DocumentModel dstFile = session.createDocumentModel("/", "dstFile", "File");
dstFile.setPropertyValue("dc:title", "File1");
dstFile = session.createDocument(dstFile);
session.save();
String dstDocId = dstFile.getId();
tagService.tag(session, srcDocId, "foo", "Administrator");
tagService.tag(session, srcDocId, "foo", "leela");
tagService.tag(session, srcDocId, "foo", "bender");
tagService.tag(session, srcDocId, "bar", "fry");
tagService.tag(session, srcDocId, "bar", "leela");
tagService.tag(session, srcDocId, "baz", "bender");
assertEquals(3, tagService.getDocumentTags(session, srcDocId, null).size());
assertEquals(0, tagService.getDocumentTags(session, dstDocId, null).size());
tagService.copyTags(session, srcDocId, dstDocId);
session.save();
assertEquals(3, tagService.getDocumentTags(session, srcDocId, null).size());
List<Tag> tags = tagService.getDocumentTags(session, dstDocId, null);
assertEquals(3, tags.size());
assertTrue(tags.contains(new Tag("foo", 0)));
assertTrue(tags.contains(new Tag("bar", 0)));
assertTrue(tags.contains(new Tag("baz", 0)));
assertEquals(1, tagService.getDocumentTags(session, dstDocId, "Administrator").size());
assertEquals(2, tagService.getDocumentTags(session, dstDocId, "leela").size());
assertEquals(2, tagService.getDocumentTags(session, dstDocId, "bender").size());
}
@Test
public void testReplaceTags() {
DocumentModel srcFile = session.createDocumentModel("/", "srcFile", "File");
srcFile.setPropertyValue("dc:title", "File1");
srcFile = session.createDocument(srcFile);
String srcDocId = srcFile.getId();
DocumentModel dstFile = session.createDocumentModel("/", "dstFile", "File");
dstFile.setPropertyValue("dc:title", "File1");
dstFile = session.createDocument(dstFile);
String dstDocId = dstFile.getId();
session.save();
tagService.tag(session, srcDocId, "foo", "Administrator");
tagService.tag(session, srcDocId, "foo", "leela");
tagService.tag(session, srcDocId, "foo", "bender");
tagService.tag(session, srcDocId, "bar", "fry");
tagService.tag(session, srcDocId, "bar", "leela");
tagService.tag(session, srcDocId, "baz", "bender");
tagService.tag(session, dstDocId, "tag1", "Administrator");
tagService.tag(session, dstDocId, "tag1", "fry");
tagService.tag(session, dstDocId, "tag2", "leela");
tagService.tag(session, dstDocId, "tag2", "bender");
assertEquals(3, tagService.getDocumentTags(session, srcDocId, null).size());
assertEquals(2, tagService.getDocumentTags(session, dstDocId, null).size());
tagService.replaceTags(session, srcDocId, dstDocId);
session.save();
assertEquals(3, tagService.getDocumentTags(session, srcDocId, null).size());
List<Tag> tags = tagService.getDocumentTags(session, dstDocId, null);
assertEquals(3, tags.size());
assertTrue(tags.contains(new Tag("foo", 0)));
assertTrue(tags.contains(new Tag("bar", 0)));
assertTrue(tags.contains(new Tag("baz", 0)));
assertEquals(1, tagService.getDocumentTags(session, dstDocId, "Administrator").size());
assertEquals(2, tagService.getDocumentTags(session, dstDocId, "leela").size());
assertEquals(2, tagService.getDocumentTags(session, dstDocId, "bender").size());
}
@Test
public void testCopyTagsOnVersion() {
DocumentModel doc;
doc = session.createDocumentModel("/", "doc", "File");
doc.setPropertyValue("dc:title", "File1");
doc = session.createDocument(doc);
String docId = doc.getId();
tagService.tag(session, docId, "foo", "Administrator");
tagService.tag(session, docId, "foo", "leela");
tagService.tag(session, docId, "foo", "bender");
tagService.tag(session, docId, "bar", "fry");
tagService.tag(session, docId, "bar", "leela");
tagService.tag(session, docId, "baz", "bender");
assertEquals(3, tagService.getDocumentTags(session, docId, null).size());
DocumentRef versionRef = checkIn(doc.getRef());
DocumentModel version = session.getDocument(versionRef);
String versionId = version.getId();
List<Tag> tags = tagService.getDocumentTags(session, versionId, null);
assertEquals(3, tags.size());
assertTrue(tags.contains(new Tag("foo", 0)));
assertTrue(tags.contains(new Tag("bar", 0)));
assertTrue(tags.contains(new Tag("baz", 0)));
assertEquals(1, tagService.getDocumentTags(session, versionId, "Administrator").size());
assertEquals(2, tagService.getDocumentTags(session, versionId, "leela").size());
assertEquals(2, tagService.getDocumentTags(session, versionId, "bender").size());
// prevents NXP-14608 NXP-14441
tagService.removeTags(session, versionId);
tagService.removeTags(session, docId);
}
@Test
public void testCopyTagsOnProxy() {
DocumentModel doc;
doc = session.createDocumentModel("/", "doc", "File");
doc.setPropertyValue("dc:title", "File1");
doc = session.createDocument(doc);
String docId = doc.getId();
tagService.tag(session, docId, "foo", "Administrator");
tagService.tag(session, docId, "foo", "leela");
tagService.tag(session, docId, "foo", "bender");
tagService.tag(session, docId, "bar", "fry");
tagService.tag(session, docId, "bar", "leela");
tagService.tag(session, docId, "baz", "bender");
assertEquals(3, tagService.getDocumentTags(session, docId, null).size());
DocumentModel proxy = publishDocument(doc);
String proxyId = proxy.getId();
List<Tag> tags = tagService.getDocumentTags(session, proxyId, null);
assertEquals(3, tags.size());
assertTrue(tags.contains(new Tag("foo", 0)));
assertTrue(tags.contains(new Tag("bar", 0)));
assertTrue(tags.contains(new Tag("baz", 0)));
assertEquals(1, tagService.getDocumentTags(session, proxyId, "Administrator").size());
assertEquals(2, tagService.getDocumentTags(session, proxyId, "leela").size());
assertEquals(2, tagService.getDocumentTags(session, proxyId, "bender").size());
// prevents NXP-14608 NXP-14441
tagService.removeTags(session, proxy.getId());
tagService.removeTags(session, docId);
}
@Test
public void testCopyTagsOnRestoredVersion() {
DocumentModel doc;
doc = session.createDocumentModel("/", "doc", "File");
doc.setPropertyValue("dc:title", "File1");
doc = session.createDocument(doc);
String docId = doc.getId();
tagService.tag(session, docId, "foo", "Administrator");
tagService.tag(session, docId, "foo", "leela");
tagService.tag(session, docId, "foo", "bender");
tagService.tag(session, docId, "bar", "fry");
tagService.tag(session, docId, "bar", "leela");
tagService.tag(session, docId, "baz", "bender");
DocumentRef versionRef = checkIn(doc.getRef());
DocumentModel version = session.getDocument(versionRef);
String versionId = version.getId();
assertEquals(3, tagService.getDocumentTags(session, docId, null).size());
assertEquals(3, tagService.getDocumentTags(session, versionId, null).size());
// put new tags on the version
tagService.removeTags(session, versionId);
tagService.tag(session, versionId, "tag1", "leela");
tagService.tag(session, versionId, "tag2", "fry");
restoreToVersion(doc.getRef(), version.getRef());
List<Tag> tags = tagService.getDocumentTags(session, docId, null);
assertEquals(2, tags.size());
assertTrue(tags.contains(new Tag("tag1", 0)));
assertTrue(tags.contains(new Tag("tag2", 0)));
// prevents NXP-14608 NXP-14441
tagService.removeTags(session, versionId);
tagService.removeTags(session, docId);
}
protected DocumentRef checkIn(DocumentRef ref) {
DocumentRef versionRef = session.checkIn(ref, null, null);
TransactionHelper.commitOrRollbackTransaction();
Framework.getLocalService(EventService.class).waitForAsyncCompletion();
TransactionHelper.startTransaction();
return versionRef;
}
protected DocumentModel publishDocument(DocumentModel doc) {
DocumentModel proxy = session.publishDocument(doc, session.getRootDocument());
TransactionHelper.commitOrRollbackTransaction();
Framework.getLocalService(EventService.class).waitForAsyncCompletion();
TransactionHelper.startTransaction();
return proxy;
}
protected DocumentModel restoreToVersion(DocumentRef docRef, DocumentRef versionRef) {
DocumentModel docModel = session.restoreToVersion(docRef, versionRef);
TransactionHelper.commitOrRollbackTransaction();
Framework.getLocalService(EventService.class).waitForAsyncCompletion();
TransactionHelper.startTransaction();
return docModel;
}
@Test
public void testCloudNormalization() throws Exception {
List<Tag> cloud;
cloud = new ArrayList<>();
TagServiceImpl.normalizeCloud(cloud, 0, 0, true);
// linear
cloud.add(new Tag("a", 3));
TagServiceImpl.normalizeCloud(cloud, 3, 3, true);
assertEquals(100, cloud.get(0).getWeight());
// logarithmic
cloud.add(new Tag("a", 3));
TagServiceImpl.normalizeCloud(cloud, 3, 3, false);
assertEquals(100, cloud.get(0).getWeight());
// linear
cloud = new ArrayList<>();
cloud.add(new Tag("a", 1));
cloud.add(new Tag("b", 5));
TagServiceImpl.normalizeCloud(cloud, 1, 5, true);
assertEquals(0, cloud.get(0).getWeight());
assertEquals(100, cloud.get(1).getWeight());
// logarithmic
cloud = new ArrayList<>();
cloud.add(new Tag("a", 1));
cloud.add(new Tag("b", 5));
TagServiceImpl.normalizeCloud(cloud, 1, 5, false);
assertEquals(0, cloud.get(0).getWeight());
assertEquals(100, cloud.get(1).getWeight());
// linear
cloud = new ArrayList<>();
cloud.add(new Tag("a", 1));
cloud.add(new Tag("b", 2));
cloud.add(new Tag("c", 5));
TagServiceImpl.normalizeCloud(cloud, 1, 5, true);
assertEquals(0, cloud.get(0).getWeight());
assertEquals(25, cloud.get(1).getWeight());
assertEquals(100, cloud.get(2).getWeight());
// logarithmic
cloud = new ArrayList<>();
cloud.add(new Tag("a", 1));
cloud.add(new Tag("b", 2));
cloud.add(new Tag("c", 5));
TagServiceImpl.normalizeCloud(cloud, 1, 5, false);
assertEquals(0, cloud.get(0).getWeight());
assertEquals(43, cloud.get(1).getWeight());
assertEquals(100, cloud.get(2).getWeight());
// linear
cloud = new ArrayList<>();
cloud.add(new Tag("a", 1));
cloud.add(new Tag("b", 2));
cloud.add(new Tag("c", 5));
cloud.add(new Tag("d", 12));
TagServiceImpl.normalizeCloud(cloud, 1, 12, true);
assertEquals(0, cloud.get(0).getWeight());
assertEquals(9, cloud.get(1).getWeight());
assertEquals(36, cloud.get(2).getWeight());
assertEquals(100, cloud.get(3).getWeight());
// logarithmic
cloud = new ArrayList<>();
cloud.add(new Tag("a", 1));
cloud.add(new Tag("b", 2));
cloud.add(new Tag("c", 5));
cloud.add(new Tag("d", 12));
TagServiceImpl.normalizeCloud(cloud, 1, 12, false);
assertEquals(0, cloud.get(0).getWeight());
assertEquals(28, cloud.get(1).getWeight());
assertEquals(65, cloud.get(2).getWeight());
assertEquals(100, cloud.get(3).getWeight());
}
@Test
public void testTag() throws Exception {
int count = buildDocWithProxiesAndTags();
log.debug("before commit");
TransactionHelper.commitOrRollbackTransaction();
Framework.getService(EventService.class).waitForAsyncCompletion();
TransactionHelper.startTransaction();
String nxql = "SELECT * FROM Document, Relation order by ecm:uuid";
DocumentModelList docs = session.query(nxql);
// Due NXP-16154 this gives a random number of docs
String digest = getDigest(docs);
assertEquals(digest, count, docs.totalSize());
}
private int buildDocWithProxiesAndTags() {
int count = 0;
DocumentModel folder = session.createDocumentModel("/", "section", "Folder");
session.createDocument(folder);
folder = session.saveDocument(folder);
count += 1; // folder
for (int i = 0; i < 5; i++) {
DocumentModel doc = session.createDocumentModel("/", "testDoc" + i, "File");
doc.setPropertyValue("dc:title", "TestMe" + i);
doc = session.createDocument(doc);
session.saveDocument(doc);
count += 1; // doc
tagService.tag(session, doc.getId(), "mytag" + i, "Administrator");
count += 2; // tagging + tag
session.publishDocument(doc, folder);
count += 2; // proxy + tagging
count += 2; // version + tagging
trashService.trashDocuments(Collections.singletonList(doc));
count -= 1; // tagging
}
return count;
}
protected String getDigest(DocumentModelList docs) throws Exception {
StringBuilder sb = new StringBuilder();
for (DocumentModel doc : docs) {
String nameOrTitle = doc.getName();
if (nameOrTitle == null || nameOrTitle.isEmpty()) {
nameOrTitle = doc.getTitle();
}
sb.append(String.format("%s %s proxy:%s %s", doc.getId(), doc.getType(), doc.isProxy(), nameOrTitle));
sb.append("\n");
}
return sb.toString();
}
/*
* NXP-19047
*/
@Test
public void testUntagAllowed() {
DocumentModel file1 = session.createDocumentModel("/", "foo", "File");
file1.setPropertyValue("dc:title", "File1");
file1 = session.createDocument(file1);
session.save();
String file1Id = file1.getId();
ACPImpl acp = new ACPImpl();
ACL acl = acp.getOrCreateACL();
acl.add(new ACE("bob", SecurityConstants.WRITE, true));
acl.add(new ACE("bender", SecurityConstants.READ, true));
session.setACP(file1.getRef(), acp, false);
session.save();
// Test untag for user with write permission
try (CoreSession bobSession = CoreInstance.openCoreSession(session.getRepositoryName(), "bob")) {
// Tag document
tagService.tag(bobSession, file1Id, "mytag", "bob");
// Test tag present
List<Tag> tags = tagService.getDocumentTags(bobSession, file1Id, "bob");
assertEquals(1, tags.size());
assertEquals("mytag", tags.get(0).getLabel());
// Untag
tagService.untag(bobSession, file1Id, "mytag", "bob");
// Test tag absent
tags = tagService.getDocumentTags(bobSession, file1Id, "bob");
assertTrue(tags.isEmpty());
}
// Test untag for user which created tag
try (CoreSession bobSession = CoreInstance.openCoreSession(session.getRepositoryName(), "bender")) {
// Tag document
tagService.tag(bobSession, file1Id, "othertag", "bender");
// Test tag present
List<Tag> tags = tagService.getDocumentTags(bobSession, file1Id, "bender");
assertEquals(1, tags.size());
assertEquals("othertag", tags.get(0).getLabel());
// Untag
tagService.untag(bobSession, file1Id, "othertag", "bender");
// Test tag absent
tags = tagService.getDocumentTags(bobSession, file1Id, "bender");
assertTrue(tags.isEmpty());
}
}
/*
* NXP-19047
*/
@Test
public void testUntagForbidden() {
DocumentModel file1 = session.createDocumentModel("/", "foo", "File");
file1.setPropertyValue("dc:title", "File1");
file1 = session.createDocument(file1);
session.save();
String file1Id = file1.getId();
ACPImpl acp = new ACPImpl();
ACL acl = acp.getOrCreateACL();
acl.add(new ACE("bob", SecurityConstants.READ, true));
acl.add(new ACE("bender", SecurityConstants.WRITE, true));
session.setACP(file1.getRef(), acp, false);
session.save();
try (CoreSession benderSession = CoreInstance.openCoreSession(session.getRepositoryName(), "bender")) {
// Tag document
tagService.tag(benderSession, file1Id, "mytag", "bender");
// Test tag present
List<Tag> tags = tagService.getDocumentTags(benderSession, file1Id, "bender");
assertEquals(1, tags.size());
assertEquals("mytag", tags.get(0).getLabel());
try (CoreSession bobSession = CoreInstance.openCoreSession(session.getRepositoryName(), "bob")) {
// Untag with bob user
tagService.untag(bobSession, file1Id, "mytag", "bender");
fail("bob is not allowed to untag document file1 tagged by bender");
} catch (DocumentSecurityException e) {
assertEquals("User 'bob' is not allowed to remove tag 'mytag' on document '" + file1Id + "'",
e.getMessage());
}
// Test tag present
tags = tagService.getDocumentTags(benderSession, file1Id, "bender");
assertEquals(1, tags.size());
assertEquals("mytag", tags.get(0).getLabel());
}
}
}