on 09-05-2005 7:30 AM
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.
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?
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
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.
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
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.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
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.
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.
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.
User | Count |
---|---|
93 | |
10 | |
10 | |
9 | |
9 | |
7 | |
6 | |
5 | |
5 | |
4 |
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.