cancel
Showing results for 
Search instead for 
Did you mean: 

Repository Service auto change resource permissions

Former Member
0 Kudos

Hello all,

This is something I was working on a whiles back and I've come back to it. The idea is that users can create some XML form in a given folder. When this happens my repository service comes into play and changes the permissions so that only admin and owner have FULL_CONTROL while Everyone has READ access.

It all works great when the logged on user has the ContentManager role but regular users throw a NotAuthorizedException and don't change the ACL. Obviously I can't give hundreds of users content admin privilages so..... any ideas?

Here is the received method in my repository service:

  public void received(IEvent event) {
	IResource resource = (IResource)event.getParameter();
	try{
		String rid = resource.getRID().toString();
		if(rid.equals("/documents/corkBoard/"+resource.getName())){
			ISecurityManager sm = resource.getRepositoryManager().getSecurityManager(resource);
			if(sm != null && sm instanceof IAclSecurityManager){
				IAclSecurityManager asm = (IAclSecurityManager)sm;
				IResourceAclManager ram = asm.getAclManager();
				ram.removeAcl(resource);
				IResourceAcl ra = ram.createAcl(resource);
				IUMPrincipal everyone = WPUMFactory.getGroupFactory().getGroup("Everyone");
				IUMPrincipal newsManager = WPUMFactory.getRoleFactory().getRole("com.sapro.KM_News_Manager");
				IUMPrincipal owner = WPUMFactory.getUserFactory().getUser(resource.getCreatedBy());
				IResourceAclEntryList rel = ra.getEntries();
				IResourceAclEntryListIterator it = rel.iterator();
				while(it.hasNext()){
					ra.removeEntry(it.next());
				}
				ra.addEntry(ram.createAclEntry(everyone, false, ram.getPermission(IAclPermission.ACL_PERMISSION_READ), 0));
				ra.addEntry(ram.createAclEntry(newsManager, false, ram.getPermission(IAclPermission.ACL_PERMISSION_FULL_CONTROL), 1));
				ra.addEntry(ram.createAclEntry(owner, false, ram.getPermission(IAclPermission.ACL_PERMISSION_FULL_CONTROL), 2));
			}
		}
	}catch(AclPersistenceException e){
		LOCATION.errorT("I raised an AclPersistenceException @"+(new Date()).toString()+": " + LoggingFormatter.extractCallstack(e));
	}catch(ResourceException e){
		LOCATION.errorT("I raised a ResourceException @"+(new Date()).toString()+": " + LoggingFormatter.extractCallstack(e));
	}catch(NotAuthorizedException e){
		LOCATION.errorT("I raised a NotAuthorizedException @"+(new Date()).toString()+": " +e.getMessage() + "**" + LoggingFormatter.extractCallstack(e));
	}catch(AclExistsException e){
		LOCATION.errorT("I raised an AclExistsException @"+(new Date()).toString()+": " + LoggingFormatter.extractCallstack(e));
	}catch(UserManagementException e){
		LOCATION.errorT("I raised a UserManagementException @"+(new Date()).toString()+": " + LoggingFormatter.extractCallstack(e));
	}catch(InvalidClassException e){
		LOCATION.errorT("I raised an InvalidClassException @"+(new Date()).toString()+": " + LoggingFormatter.extractCallstack(e));
	}catch(AlreadyAssignedToAclException e){
		LOCATION.errorT("I raised an AlreadyAssignedToAclException @"+(new Date()).toString()+": " + LoggingFormatter.extractCallstack(e));
	}catch(PermissionNotSupportedException e){
		LOCATION.errorT("I raised a PermissionNotSupportedException @"+(new Date()).toString()+": " + LoggingFormatter.extractCallstack(e));
	}
  }

When a resource is created I check to see if it's in the folder that interests me, if so I remove the current ACL so's not to inherit from the parent folder, I grab the role, group and user that interest me and set the permissions that I want.

Again, when I run this as myself it works great. Other users, not having the same permissions as me in KM, throw the NotAuthorizedException. Is there any way around this?

I look forward to any response/help.

Yours,

Patrick.

Accepted Solutions (0)

Answers (2)

Answers (2)

Former Member
0 Kudos

Hi Patrick

Thanks for the code all seems ok - however I have one question:

When I create the Par file and import it I get an error when I try to access KM content. I have looked in the trace file and it says:

Could not retrieve resource for given uri /alias/userhome/<user.id>/favorites com.sapportals.wcm.repository.InvalidUriException: Invalid RID: No repository manager found for prefix: /alias

any ideas?

Former Member
0 Kudos

After a bit of fidilling is all working!! Thanks a lot!!

Former Member
0 Kudos

Good stuff Phil, I'm glad it's working.

It's a nice first repository service to work on, it covers a bunch of stuff and leaves you in a good position for writing others.

Patrick.

Former Member
0 Kudos

Thanks, Speaking of which - you don't by any chance know if it is possible to write a service to move a documnent when it has been authorised?

I can move a document when it is created but it would be easier if it was possible when it has been authorised?

Any help would be great!

Former Member
0 Kudos

I haven't tackled that myself although I imagine that there is an event raised when a doc is authorised. So instead of listening for the CREATE_CHILD event you'd just register for the authorisation event:

  protected void addRepositoryAssignment(IRepositoryManager mgr) throws ServiceNotAvailableException {
	// Implement this method: Usually the service registers itself for certain events at the repository manager.
	try{
		mgr.getEventBroker().register(this, new ResourceEvent(ResourceEvent.CREATE_CHILD, null));
	}catch(WcmException e){
	}
  }

That's the code we used before, so find out if there is an event at authorisation, find out its name and register your interest in it.

Regards,

Patrick.

Former Member
0 Kudos

Hi Patrick,

I have a similar requirement to assign permission for documents to the users at runtime. I have used your code for the same. Thanks for that.

However I am facing a small problem -

I have configured a CM repository in FSDB mode. When I upload the documents in this repository from KM, eveything works fine and the repository service gets executed.

But when I physically put the documents in the file server to which the CM repository has been configured, the service does not execute.

Can you please help me out with this.

I have also opened another thread for my query.Yhe link for the new thread is

Thanks in advance,

Vivek

Former Member
0 Kudos

Hi Vivek,

I'm glad that you found the code useful.

I did read your thread earlier but I'm afraid that I don't have a solution for you. My requirements were to write a repository service to work only from inside the portal.

Sorry I can't help,

Patrick.

Former Member
0 Kudos

Hi Patrick,

Thanks for the reply.

I just hope someone replies to my query, I am totally stuck :-(.

Actually I am facing the same problem with some other repository service (service for document count) also which I have deployed.

Thanks again,

Vivek

Former Member
0 Kudos

It was the line

IResourceAcl ra = ram.createAcl(resource);

that was causing the exception.

I added 'Everyone' as 'Permission Owner' to the parent folder.... now users can create ACL's for resources inside that folder.

Patrick.

Former Member
0 Kudos

Hi Patrick,

I fear that "permission owner" should not be assigned to "everyone" as anybody can do anything in that case.

Better is to execute the application with "Content Admin" or "super admin" user.

best regds,

Alagammai.

Former Member
0 Kudos

I tend to agree with you there.

(Most)users will only be able to see the folder through the NewsExplorer layout set so they won't have access to KM commands over the folder anyhoos. Anyone who can see the folder in KM navigation will have been assigned ContentManagement so they'll already have full control.

I can limit the ownership to particular roles or groups of users... it's just easier to say 'Everyone'.

The ACL manager is accessed automaticaly through the logged in user, I don't have the option of pulling the cmadmin service user and using that so I'll just leave it the way that it is. Everyone should have read/write/delete access to the folder in question anyhoos so I think that giving them permission ownership should be OK.

Also it's not a critical folder, it's to be used as a notice board for folks buying/selling stuff informaly throughout the office so even if things go wrong in this folder it won't really matter, there's no business data there.

In a more important folder I would absolutely agree with you though.

Patrick.

Former Member
0 Kudos

Hi Patrick,

Now I understood the context. Thank you for your explanation.

best regds,

Alagammai.

Former Member
0 Kudos

Hi Patrick

Did you manage to get this working, as I am currently trying to do something very similar? (with little success)

Would you mind posting your completed code it would be most appreciated.

Thanks in advance

Phil

Former Member
0 Kudos

I did indeed get this working.

I'm not at that site though today and don't have access to that code. I'll get it though and post before the end of the week, OK?

Patrick.

EDIT:

Here is the link to the original thread that I started about this whole process. You may find something of interest there.

I hope it helps.

Former Member
0 Kudos

Thanks Patrick that is most appreciated.

Cheers

Phil

Former Member
0 Kudos

Hi Phil,

Here's the full code for the repository filter that I use. Most of the code is generated by NWDS from the template;

package com.sapro.km.repository.service;

import java.util.Collection;
import java.util.Iterator;

import com.sap.tc.logging.Location;
import com.sapportals.wcm.util.logging.LoggingFormatter;
import java.util.Date;

import com.sapportals.portal.security.usermanagement.IUMPrincipal;
import com.sapportals.portal.security.usermanagement.UserManagementException;
import com.sapportals.wcm.WcmException;
import com.sapportals.wcm.crt.component.IReconfigurable;
import com.sapportals.wcm.crt.component.StartupException;
import com.sapportals.wcm.crt.configuration.ConfigurationException;
import com.sapportals.wcm.crt.configuration.IConfiguration;
import com.sapportals.wcm.repository.IResource;
import com.sapportals.wcm.repository.ResourceException;
import com.sapportals.wcm.repository.manager.IAclSecurityManager;
import com.sapportals.wcm.repository.manager.IRepositoryManager;
import com.sapportals.wcm.repository.manager.IResourceEventReceiver;
import com.sapportals.wcm.repository.manager.ISecurityManager;
import com.sapportals.wcm.repository.manager.ResourceEvent;
import com.sapportals.wcm.repository.security.IResourceAcl;
import com.sapportals.wcm.repository.security.IResourceAclEntryList;
import com.sapportals.wcm.repository.security.IResourceAclEntryListIterator;
import com.sapportals.wcm.repository.security.IResourceAclManager;
import com.sapportals.wcm.repository.service.AbstractRepositoryService;
import com.sapportals.wcm.repository.service.ServiceNotAvailableException;
import com.sapportals.wcm.util.acl.AclExistsException;
import com.sapportals.wcm.util.acl.AclPersistenceException;
import com.sapportals.wcm.util.acl.AlreadyAssignedToAclException;
import com.sapportals.wcm.util.acl.IAclPermission;
import com.sapportals.wcm.util.acl.InvalidClassException;
import com.sapportals.wcm.util.acl.NotAuthorizedException;
import com.sapportals.wcm.util.acl.PermissionNotSupportedException;
import com.sapportals.wcm.util.events.IEvent;
import com.sapportals.wcm.util.usermanagement.WPUMFactory;

 // implements IMyNewRepositoryService interface
 /*
  Note: IReconfigurable and IResourceEventReceiver interfaces are optional 
 */

public class PermissionsClassifiedAds extends AbstractRepositoryService implements IReconfigurable, IResourceEventReceiver {

  private static final String TYPE = "PermissionsClassifiedAds";
  private Collection repositoryManagers;
  
  /**************************************/
  private static final Location LOCATION = Location.getLocation(com.sapro.km.repository.service.PermissionsClassifiedAds.class);
  /**************************************/
  
  public PermissionsClassifiedAds() {
	super();
	// Do not add code here. Add it to startUpImpl() instead 
  }

  public String getServiceType() {
	return PermissionsClassifiedAds.TYPE;
  }

  protected void startUpImpl(Collection repositoryManagers) throws ConfigurationException, StartupException {
	// implement this method as follows:
	// - Verify configuration data
	// - Get references to other needed (global) services
	// - Check whether other repository services (this service depends on) are also assigned to the repository managers
	// - Usually the service registers itself for certain events at all repository managers
	//
	/*
	try  {
	}
	catch (Exception e) {
	  throw new StartupException(e.getMessage(), e);
	}
	*/
	this.repositoryManagers = repositoryManagers;
	Iterator it = repositoryManagers.iterator();
	while (it.hasNext()){
	  try {
		addRepositoryAssignment((IRepositoryManager) it.next());
	  } catch (ServiceNotAvailableException e) {
		e.printStackTrace();
	  }
	}
  }

  protected void shutDownImpl() {
	Iterator it = repositoryManagers.iterator();
	while (it.hasNext()){
	  try {
		removeRepositoryAssignment((IRepositoryManager) it.next());
	  } catch (WcmException e) {
		e.printStackTrace();
	  }
	}
  }

  protected void addRepositoryAssignment(IRepositoryManager mgr) throws ServiceNotAvailableException {
	// Implement this method: Usually the service registers itself for certain events at the repository manager.
	try{
		mgr.getEventBroker().register(this, new ResourceEvent(ResourceEvent.CREATE_CHILD, null));
	}catch(WcmException e){
	}
  }

  protected void removeRepositoryAssignment(IRepositoryManager mgr) throws WcmException {
	// Implement this method: Usually the service must unregister itself as an event handler.
	mgr.getEventBroker().unregister(this, new ResourceEvent(ResourceEvent.CREATE_CHILD, null));
  }

  public void reconfigure(IConfiguration config) throws ConfigurationException {
	this.stateHandler.preReconfigure();
	// check the new configuration data
	/*
	try {
	}
	catch (ConfigurationException ex) {
	  this.stateHandler.postReconfigure(ex);
	  throw ex;
	}*/

	this.config = config;
	this.stateHandler.postReconfigure();
  }

  public void received(IEvent event) {
	IResource resource = (IResource)event.getParameter();
	try{
		String rid = resource.getRID().toString();
		if(rid.equals("/documents/corkboard/"+resource.getName())){
			ISecurityManager sm = resource.getRepositoryManager().getSecurityManager(resource);
			if(sm != null && sm instanceof IAclSecurityManager){
				IAclSecurityManager asm = (IAclSecurityManager)sm;
				IResourceAclManager ram = asm.getAclManager();
				ram.removeAcl(resource);
				IResourceAcl ra = ram.createAcl(resource);
				IUMPrincipal everyone = WPUMFactory.getGroupFactory().getGroup("Everyone");
				IUMPrincipal newsManager = WPUMFactory.getRoleFactory().getRole("com.sapro.KM_News_Manager");
				IUMPrincipal owner = WPUMFactory.getUserFactory().getUser(resource.getCreatedBy());
				IResourceAclEntryList rel = ra.getEntries();
				IResourceAclEntryListIterator it = rel.iterator();
				while(it.hasNext()){
					ra.removeEntry(it.next());
				}
				ra.addEntry(ram.createAclEntry(everyone, false, ram.getPermission(IAclPermission.ACL_PERMISSION_READ), 0));
				ra.addEntry(ram.createAclEntry(newsManager, false, ram.getPermission(IAclPermission.ACL_PERMISSION_FULL_CONTROL), 1));
				ra.addEntry(ram.createAclEntry(owner, false, ram.getPermission(IAclPermission.ACL_PERMISSION_FULL_CONTROL), 2));
			}
		}
	}catch(AclPersistenceException e){
		LOCATION.errorT("I raised an AclPersistenceException @"+(new Date()).toString()+": " + LoggingFormatter.extractCallstack(e));
	}catch(ResourceException e){
		LOCATION.errorT("I raised a ResourceException @"+(new Date()).toString()+": " + LoggingFormatter.extractCallstack(e));
	}catch(NotAuthorizedException e){
		LOCATION.errorT("I raised a NotAuthorizedException @"+(new Date()).toString()+": " +e.getMessage() + "**" + LoggingFormatter.extractCallstack(e));
	}catch(AclExistsException e){
		LOCATION.errorT("I raised an AclExistsException @"+(new Date()).toString()+": " + LoggingFormatter.extractCallstack(e));
	}catch(UserManagementException e){
		LOCATION.errorT("I raised a UserManagementException @"+(new Date()).toString()+": " + LoggingFormatter.extractCallstack(e));
	}catch(InvalidClassException e){
		LOCATION.errorT("I raised an InvalidClassException @"+(new Date()).toString()+": " + LoggingFormatter.extractCallstack(e));
	}catch(AlreadyAssignedToAclException e){
		LOCATION.errorT("I raised an AlreadyAssignedToAclException @"+(new Date()).toString()+": " + LoggingFormatter.extractCallstack(e));
	}catch(PermissionNotSupportedException e){
		LOCATION.errorT("I raised a PermissionNotSupportedException @"+(new Date()).toString()+": " + LoggingFormatter.extractCallstack(e));
	}
  }
}

I hope that it helps you. It's been a long time since I even looked at this code but I think that once I had a few questions answered (in the other thread that I've linked to) things went fairly smoothly.

If you have any questions just post them,

Patrick.