| /* |
| * 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; |
| } |
| } |
| } |