Home

CMIS ACL problem/question [SOLVED]

You are here

3 posts / 0 new
Last post
CMIS ACL problem/question [SOLVED]

Hi

I'm trying to figure out how to use the CMIS Java API, in particular ACLs, but I run into a "CmisPermissionDeniedException: Forbidden" when I try to manipulate a document as a non-Administrator user.

I have an Alfresco Community v4.2.0 (4428) schema 6019 running with an extra user called "user". I'm using version 0.8.0 of Chemistry.

In the JUnit test below I create, as administrator, a text file in the rootfolder and add a write permission to it for the normal user. When I try to check out the document as a normal user I get CmisPermissionDeniedException: Forbidden.

Over at the Chemistry mailing list they suggested using permissions.add("{http://www.alfresco.org/model/content/1.0}cmobject.Collaborator"); instead of permissions.add(BasicPermissions.WRITE);
And indeed the test completes without errors.

But using the Alfresco specific permission instead of the CMIS basic permission, defeats the purpose of using CMIS to become vendor agnostic.

At this moment I'm just testing against Alfresco but the goal is the replace the Documentum Foundation Classes with CMIS in our applications. Eventually we'll want to replace Documentum, probably with Alfresco, but we also want to do automated testing with the OpenCMIS InMemory repository. And by using CMIS we thought we could do that easily without further code changes.

So is there a way to use CMIS permissions with Alfresco?

Yours,
Nick

CmisTests.java:

public class CmisTests {
 
@Test
public void test() throws IOException {
SessionFactory sessionFactory = SessionFactoryImpl.newInstance();
Map<String, String> parameters = new HashMap<String, String>();
parameters.put(SessionParameter.USER, "admin");
parameters.put(SessionParameter.PASSWORD, "admin");
parameters.put(SessionParameter.BINDING_TYPE, BindingType.ATOMPUB.value());
parameters.put(SessionParameter.ATOMPUB_URL, "http://localhost:8080/alfresco/cmisatom");
Session session = sessionFactory.getRepositories(parameters).get(0).createSession();
 
Document document = FileUtils.createTextDocument("/", "test.txt", "Some text", BaseTypeId.CMIS_DOCUMENT.value(), VersioningState.MAJOR, session);
String id = document.getId();
 
OperationContext operationContext = new OperationContextImpl();
operationContext.setIncludeAcls(true);
document = (Document) session.getObject(id, operationContext);
 
System.out.println("Acl:");
Acl acl = document.getAcl();
for (Ace ace : acl.getAces()) {
System.out.println(ace);
}
 
parameters.put(SessionParameter.USER, "user");
parameters.put(SessionParameter.PASSWORD, "user");
session = sessionFactory.getRepositories(parameters).get(0).createSession();
 
document = (Document) session.getObject(id);
String content = IOUtils.toString(document.getContentStream().getStream());
System.out.println("Content: " + content);
 
ObjectId checkedOutDocumentObjectId = null;
try {
checkedOutDocumentObjectId = document.checkOut();
} catch (CmisPermissionDeniedException e) {
System.out.println("No permission to check out");
}
 
parameters.put(SessionParameter.USER, "admin");
parameters.put(SessionParameter.PASSWORD, "admin");
session = sessionFactory.getRepositories(parameters).get(0).createSession();
 
document = (Document) session.getObject(id, operationContext);
String principal = "user";
List<String> permissions = new LinkedList<String>();
permissions.add(BasicPermissions.WRITE);
Ace addAce = session.getObjectFactory().createAce(principal, permissions);
List<Ace> addAces = new LinkedList<Ace>();
addAces.add(addAce);
document.addAcl(addAces, AclPropagation.REPOSITORYDETERMINED);
 
System.out.println("Acl:");
acl = document.getAcl();
for (Ace ace : acl.getAces()) {
System.out.println(ace);
}
 
parameters.put(SessionParameter.USER, "user");
parameters.put(SessionParameter.PASSWORD, "user");
session = sessionFactory.getRepositories(parameters).get(0).createSession();
 
document = (Document) session.getObject(id);
// CmisPermissionDeniedException: Forbidden below
checkedOutDocumentObjectId = document.checkOut();
 
Document checkedOutDocument = (Document) session.getObject(checkedOutDocumentObjectId);
String newContent = "New text.";
boolean major = false;
Map<String, String> properties = null;
String filename = document.getName();
BigInteger length = BigInteger.valueOf(newContent.length());
String mimeType = document.getContentStreamMimeType();
InputStream stream = IOUtils.toInputStream(newContent);
ContentStream updatedContentStream = new ContentStreamImpl(filename, length, mimeType, stream);
String checkinComment = "Text is updated";
checkedOutDocument.checkIn(major, properties, updatedContentStream, checkinComment);
 
document = document.getObjectOfLatestVersion(false);
content = IOUtils.toString(document.getContentStream().getStream());
System.out.println("Content: " + content);
}
 
@Test
public void t() {
SessionFactory sessionFactory = SessionFactoryImpl.newInstance();
Map<String, String> parameters = new HashMap<String, String>();
parameters.put(SessionParameter.USER, "admin");
parameters.put(SessionParameter.PASSWORD, "admin");
parameters.put(SessionParameter.BINDING_TYPE, BindingType.ATOMPUB.value());
parameters.put(SessionParameter.ATOMPUB_URL, "http://localhost:8080/alfresco/cmisatom");
Session session = sessionFactory.getRepositories(parameters).get(0).createSession();
Document document = (Document) session.getObjectByPath("/test.txt");
OperationContext operationContext = new OperationContextImpl();
operationContext.setIncludeAcls(true);
document = (Document) session.getObject(document, operationContext);
Acl acl = document.getAcl();
for (Ace ace : acl.getAces()) {
System.out.println(ace);
}
}
 
@Before
public void init() {
SessionFactory sessionFactory = SessionFactoryImpl.newInstance();
Map<String, String> parameters = new HashMap<String, String>();
parameters.put(SessionParameter.USER, "admin");
parameters.put(SessionParameter.PASSWORD, "admin");
parameters.put(SessionParameter.BINDING_TYPE, BindingType.ATOMPUB.value());
parameters.put(SessionParameter.ATOMPUB_URL, "http://localhost:8080/alfresco/cmisatom");
Session session = sessionFactory.getRepositories(parameters).get(0).createSession();
session.delete(session.getObjectByPath("/test.txt"));
}
 
}

Re: CMIS ACL problem/question

If you look at the permission mapping in the result of calling getRepositoryInfo, you'll see something like this:

<cmis:mapping>
<cmis:key>canCheckout.Document</cmis:key>
<cmis:permission>cmis:all</cmis:permission>
<cmis:permission>{http://www.alfresco.org/model/content/1.0}lockable.CheckOut</cmis:permission>
</cmis:mapping>

This tells you that if you want your test user to be able to check out a document, you need to assign the "cmis:all" permission. If you do that, your user will be able to successfully perform a checkout.

So if you are writing an interoperable client, before setting the ACL, check the permission mapping, then set the ACL to the correct CMIS permission.

Jeff

Chief Community Officer
Alfresco Software
Blog: ecmarchitect.com | Twitter: jeffpotts01
CMIS APIs: Apache Chemistry | CMIS and Apache Chemistry in Action
Alfresco tutorials: Alfresco Developer Series

Re: CMIS ACL problem/question

Thanks for the help.

I was able to do it like this:

RepositoryInfo repositoryInfo = session.getRepositoryInfo();
AclCapabilities aclCapabilities = repositoryInfo.getAclCapabilities();
Map<String, PermissionMapping> permissionMappings = aclCapabilities.getPermissionMapping();
PermissionMapping permissionMapping = permissionMappings.get(PermissionMapping.CAN_CHECKOUT_DOCUMENT);
List<String> permissions = permissionMapping.getPermissions();
Ace addAce = session.getObjectFactory().createAce(principal, permissions);
List<Ace> addAces = new LinkedList<Ace>();
addAces.add(addAce);
document.addAcl(addAces, AclPropagation.REPOSITORYDETERMINED);