blob: 09738b6cfb5715894a3d96b502dcf4497aa5a5ff [file] [log] [blame]
/*
* Copyright (c) 2013, 2014 Eike Stepper (Berlin, Germany) and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Eike Stepper - initial API and implementation
*/
package org.eclipse.emf.cdo.server.spi.security;
import org.eclipse.emf.cdo.security.Access;
import org.eclipse.emf.cdo.security.PatternStyle;
import org.eclipse.emf.cdo.security.Realm;
import org.eclipse.emf.cdo.security.Role;
import org.eclipse.emf.cdo.security.SecurityFactory;
import org.eclipse.emf.cdo.security.SecurityPackage;
import org.eclipse.emf.cdo.security.User;
import org.eclipse.emf.cdo.server.IStoreAccessor.CommitContext;
import org.eclipse.emf.cdo.server.internal.security.bundle.OM;
import org.eclipse.emf.cdo.server.security.ISecurityManager.RealmOperation;
import org.eclipse.emf.cdo.server.spi.security.InternalSecurityManager.CommitHandler;
import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision;
import org.eclipse.emf.cdo.transaction.CDOTransaction;
import org.eclipse.emf.cdo.view.CDOView;
import org.eclipse.net4j.util.concurrent.ExecutorServiceFactory;
import org.eclipse.net4j.util.container.IManagedContainer;
import org.eclipse.net4j.util.container.IManagedContainer.ContainerAware;
import org.eclipse.net4j.util.factory.ProductCreationException;
import org.eclipse.emf.common.util.BasicEList;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EClass;
import java.util.List;
import java.util.concurrent.ExecutorService;
/**
* If the meaning of this type isn't clear, there really should be more of a description here...
*
* @author Eike Stepper
* @since 4.3
*/
public class HomeFolderHandler implements InternalSecurityManager.CommitHandler2
{
public static final String DEFAULT_HOME_FOLDER = "/home";
private static final SecurityFactory SF = SecurityFactory.eINSTANCE;
private final String homeFolder;
private ExecutorService executorService;
public HomeFolderHandler(String homeFolder)
{
this.homeFolder = homeFolder == null || homeFolder.length() == 0 ? DEFAULT_HOME_FOLDER : homeFolder;
}
public HomeFolderHandler()
{
this(null);
}
public String getHomeFolder()
{
return homeFolder;
}
public ExecutorService getExecutorService()
{
return executorService;
}
public void setExecutorService(ExecutorService executorService)
{
this.executorService = executorService;
}
public void init(InternalSecurityManager securityManager, boolean firstTime)
{
if (firstTime)
{
EList<User> users = securityManager.getRealm().getAllUsers();
if (!users.isEmpty())
{
List<String> userIDs = new BasicEList<String>();
for (User user : users)
{
userIDs.add(user.getId());
}
handleUsers(securityManager, userIDs, true);
}
}
}
protected void initRole(Role role)
{
role.getPermissions().add(SF.createFilterPermission(Access.WRITE, //
SF.createResourceFilter(homeFolder + "/${user}", PatternStyle.TREE, false)));
role.getPermissions().add(SF.createFilterPermission(Access.READ, //
SF.createResourceFilter(homeFolder, PatternStyle.EXACT, true)));
}
public void handleCommit(final InternalSecurityManager securityManager, CommitContext commitContext, User user)
{
// Do nothing
}
public void handleCommitted(final InternalSecurityManager securityManager, CommitContext commitContext)
{
List<String> userIDs = null;
InternalCDORevision[] newObjects = commitContext.getNewObjects();
for (int i = 0; i < newObjects.length; i++)
{
InternalCDORevision newObject = newObjects[i];
EClass eClass = newObject.getEClass();
if (eClass == SecurityPackage.Literals.USER)
{
String userID = (String)newObject.getValue(SecurityPackage.Literals.ASSIGNEE__ID);
if (userID != null)
{
if (userIDs == null)
{
userIDs = new BasicEList<String>();
}
userIDs.add(userID);
}
}
}
if (userIDs != null)
{
final List<String> list = userIDs;
long commitTime = commitContext.getBranchPoint().getTimeStamp();
CDOView view = securityManager.getRealm().cdoView();
view.runAfterUpdate(commitTime, new Runnable()
{
public void run()
{
handleUsers(securityManager, list, false);
}
});
}
}
protected void handleUsers(final InternalSecurityManager securityManager, final List<String> userIDs,
final boolean init)
{
executorService.submit(new Runnable()
{
public void run()
{
securityManager.modify(new RealmOperation()
{
public void execute(Realm realm)
{
String roleID = "Home Folder " + homeFolder;
Role role;
if (init)
{
role = realm.addRole(roleID);
initRole(role);
}
else
{
role = realm.getRole(roleID);
if (role == null)
{
OM.LOG.warn("Role '" + roleID + "' not found in " + HomeFolderHandler.this);
return;
}
}
CDOTransaction transaction = (CDOTransaction)realm.cdoView();
for (String userID : userIDs)
{
try
{
User user = realm.getUser(userID);
if (user == null)
{
OM.LOG.warn("User '" + userID + "' not found in " + HomeFolderHandler.this);
}
else
{
handleUser(transaction, realm, role, user);
}
}
catch (Exception ex)
{
OM.LOG.error(ex);
}
}
}
});
}
});
}
protected void handleUser(CDOTransaction transaction, Realm realm, Role role, User user) throws Exception
{
EList<Role> roles = user.getRoles();
roles.add(role);
String path = getHomeFolder() + "/" + user.getId();
transaction.getOrCreateResourceFolder(path);
}
@Override
public String toString()
{
return getClass().getSimpleName() + "[" + homeFolder + "]";
}
/**
* Creates {@link CommitHandler} instances.
*
* @author Eike Stepper
*/
public static class Factory extends InternalSecurityManager.CommitHandler.Factory implements ContainerAware
{
private IManagedContainer container;
public Factory()
{
super("home");
}
public void setManagedContainer(IManagedContainer container)
{
this.container = container;
}
@Override
public CommitHandler create(String homeFolder) throws ProductCreationException
{
ExecutorService executorService = ExecutorServiceFactory.get(container);
HomeFolderHandler handler = new HomeFolderHandler(homeFolder);
handler.setExecutorService(executorService);
return handler;
}
}
}