org.netxilia.api.impl.user.AclServiceImpl.java Source code

Java tutorial

Introduction

Here is the source code for org.netxilia.api.impl.user.AclServiceImpl.java

Source

/*******************************************************************************
 * 
 * Copyright 2010 Alexandru Craciun, and individual contributors as indicated
 * by the @authors tag. 
 * 
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 3 of
 * the License, or (at your option) any later version.
 * 
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 ******************************************************************************/
package org.netxilia.api.impl.user;

import java.security.AccessControlException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.netxilia.api.INetxiliaSystem;
import org.netxilia.api.command.CellCommands;
import org.netxilia.api.exception.AlreadyExistsException;
import org.netxilia.api.exception.NetxiliaBusinessException;
import org.netxilia.api.exception.NetxiliaResourceException;
import org.netxilia.api.exception.NotFoundException;
import org.netxilia.api.exception.StorageException;
import org.netxilia.api.formula.Formula;
import org.netxilia.api.impl.model.SheetNames;
import org.netxilia.api.model.CellData;
import org.netxilia.api.model.ISheet;
import org.netxilia.api.model.SheetFullName;
import org.netxilia.api.model.SheetType;
import org.netxilia.api.model.WorkbookId;
import org.netxilia.api.operation.ISheetOperations;
import org.netxilia.api.reference.AreaReference;
import org.netxilia.api.user.AclObjectType;
import org.netxilia.api.user.AclPrivilegedMode;
import org.netxilia.api.user.IAclService;
import org.netxilia.api.user.IUserService;
import org.netxilia.api.user.Permission;
import org.netxilia.api.user.User;
import org.netxilia.api.utils.Matrix;
import org.netxilia.api.value.IGenericValue;
import org.netxilia.api.value.StringValue;
import org.springframework.beans.factory.annotation.Autowired;

/**
 * 
 * @author <a href='mailto:ax.craciun@gmail.com'>Alexandru Craciun</a>
 * 
 */
public class AclServiceImpl implements IAclService {
    private static org.apache.log4j.Logger log = org.apache.log4j.Logger.getLogger(AclServiceImpl.class);

    private String permissionSheet = SheetNames.PERMISSIONS;

    private static final Map<String, IGenericValue> HEADERS = new HashMap<String, IGenericValue>();

    private static final String ANY_USER = "*";
    private static final String ANY_SHEET = "*";

    static {
        HEADERS.put("A", new StringValue("Object type"));
        HEADERS.put("B", new StringValue("User"));
        HEADERS.put("C", new StringValue("Object name"));
        HEADERS.put("D", new StringValue("Permission"));
    }
    @Autowired
    private INetxiliaSystem workbookProcessor;

    @Autowired
    private IUserService userService;

    @Autowired
    private ISheetOperations sheetOperations;

    public INetxiliaSystem getWorkbookProcessor() {
        return workbookProcessor;
    }

    public void setWorkbookProcessor(INetxiliaSystem workbookProcessor) {
        this.workbookProcessor = workbookProcessor;
    }

    public IUserService getUserService() {
        return userService;
    }

    public void setUserService(IUserService userService) {
        this.userService = userService;
    }

    public ISheetOperations getSheetOperations() {
        return sheetOperations;
    }

    public void setSheetOperations(ISheetOperations sheetOperations) {
        this.sheetOperations = sheetOperations;
    }

    protected ISheet getAclSheet(WorkbookId workbookId) throws StorageException, NotFoundException {
        try {
            return workbookProcessor.getWorkbook(workbookId).getSheet(permissionSheet);
        } catch (NotFoundException e) {
            ISheet aclSheet = null;
            try {
                aclSheet = workbookProcessor.getWorkbook(workbookId).addNewSheet(permissionSheet, SheetType.normal);
            } catch (AlreadyExistsException e1) {
                // nothing to do
            }
            aclSheet.sendCommand(CellCommands.mapValues(AreaReference.lastRow(0, 3), HEADERS));
            return aclSheet;
        }
    }

    private boolean checkPermission(INetxiliaSystem workbookProcessor, ISheet aclSheet, AclObjectType objectType,
            String userSpec, String sheetName, Permission permission)
            throws NetxiliaResourceException, NetxiliaBusinessException {

        // A=object type => sheet
        // B=username
        // C=object name => sheet name
        // D=permissions comma delimited

        List<Integer> rows;
        String formulaText = "=AND(A1=\"" + objectType.name() + "\", B1=\"" + userSpec + "\"";
        if (sheetName != null) {
            formulaText += ",C1=\"" + sheetName + "\"";
        }
        formulaText += ")";
        rows = sheetOperations.filter(aclSheet, new Formula(formulaText)).getNonBlocking();
        // NO AND YET
        if (rows == null || rows.size() == 0) {
            return false;
        }

        int row = rows.get(0);
        Matrix<CellData> cells = aclSheet.receiveCells(new AreaReference(null, row, 0, row, 3)).getNonBlocking();

        String permissions = cells.get(0, 3).getValue().getStringValue();
        String[] permissionsArray = StringUtils.split(permissions, ",");
        for (int i = 0; i < permissionsArray.length; ++i) {
            Permission p = Permission.valueOf(permissionsArray[i]);
            if (p == permission) {
                return true;
            }
        }
        return false;
    }

    @Override
    public void checkPermission(SheetFullName sheetFullName, Permission permission) throws AccessControlException {
        if (log.isDebugEnabled()) {
            log.debug("Check for " + sheetFullName + " " + permission + " isSet:" + AclPrivilegedMode.isSet());
        }
        if (AclPrivilegedMode.isSet()) {
            return;
        }

        ISheet aclSheet = null;

        boolean wasSet = AclPrivilegedMode.set();
        try {

            aclSheet = getAclSheet(new WorkbookId(sheetFullName.getWorkbookName()));

            User user = userService.getCurrentUser();
            if (user == null) {
                throw new AccessControlException("No current user");
            }
            if (user.isAdmin()) {
                return;
            }
            // sheet.summary has the same permissions as sheet itself
            String sheetName = SheetFullName.sheetSimpleName(sheetFullName.getSheetName(), user);
            // if it's the user's private sheet, all access is allowed
            if (sheetName.equals(SheetFullName.privateSheetName(sheetFullName, user))) {
                return;
            }

            // check user
            if (checkPermission(workbookProcessor, aclSheet, AclObjectType.sheet, user.getLogin(), sheetName,
                    permission)) {
                return;
            }
            // TODO: check groups
            // check all
            if (checkPermission(workbookProcessor, aclSheet, AclObjectType.sheet, ANY_USER, sheetName,
                    permission)) {
                return;
            }

            if (checkPermission(workbookProcessor, aclSheet, AclObjectType.sheet, user.getLogin(), ANY_SHEET,
                    permission)) {
                return;
            }

            throw new AccessControlException("Operation not permitted");
        } catch (NotFoundException e) {
            // only happens if somebody deleted the sheet right before the filtering
            throw new AccessControlException("Cannot check permissions. Reason: " + e);
        } catch (NetxiliaResourceException e) {
            throw new AccessControlException("Cannot check permissions. Reason: " + e);
        } catch (NetxiliaBusinessException e) {
            throw new AccessControlException("Cannot check permissions. Reason: " + e);
        } finally {
            if (!wasSet) {
                AclPrivilegedMode.clear();
            }
            if (log.isDebugEnabled()) {
                log.debug("<-- done for " + sheetFullName + " " + permission);
            }
        }

    }

    @Override
    public void setPermissions(SheetFullName sheetFullName, User grantee, Permission... permissions)
            throws AccessControlException, StorageException {

        // sheet.summary has the same permissions as sheet itself
        if (sheetFullName.getType() != SheetType.normal) {
            return;
        }
        setPermissions(AclObjectType.sheet, new WorkbookId(sheetFullName.getWorkbookName()),
                sheetFullName.getSheetName(), grantee, permissions);
    }

    @Override
    public void checkPermission(WorkbookId workbookId, Permission permission) throws AccessControlException {
        if (log.isDebugEnabled()) {
            log.debug("Check for " + workbookId + " " + permission + " isSet:" + AclPrivilegedMode.isSet());
        }
        if (AclPrivilegedMode.isSet()) {
            return;
        }

        ISheet aclSheet = null;
        boolean wasSet = AclPrivilegedMode.set();
        try {

            aclSheet = getAclSheet(workbookId);

            User user = userService.getCurrentUser();
            if (user == null) {
                throw new AccessControlException("No current user");
            }
            if (user.isAdmin()) {
                return;
            }

            // check user
            if (checkPermission(workbookProcessor, aclSheet, AclObjectType.workbook, user.getLogin(), null,
                    permission)) {
                return;
            }
            // TODO: check groups
            // check all
            if (checkPermission(workbookProcessor, aclSheet, AclObjectType.workbook, ANY_USER, null, permission)) {
                return;
            }

            throw new AccessControlException("Operation not permitted");
        } catch (NotFoundException e) {
            // only happens if somebody deleted the sheet right before the filtering
            throw new AccessControlException("Cannot check permissions. Reason: " + e);
        } catch (NetxiliaResourceException e) {
            throw new AccessControlException("Cannot check permissions. Reason: " + e);
        } catch (NetxiliaBusinessException e) {
            throw new AccessControlException("Cannot check permissions. Reason: " + e);
        } finally {
            if (!wasSet) {
                AclPrivilegedMode.clear();
            }
            if (log.isDebugEnabled()) {
                log.debug("<-- done for " + workbookId + " " + permission);
            }
        }

    }

    @Override
    public void setPermissions(WorkbookId id, User grantee, Permission... permissions)
            throws AccessControlException, StorageException {
        setPermissions(AclObjectType.workbook, id, null, grantee, permissions);

    }

    private void setPermissions(AclObjectType objectType, WorkbookId workbookId, String sheetName, User grantee,
            Permission... permissions) throws StorageException {

        // A=object type => sheet
        // B=username
        // C=object name => sheet name
        // D=permissions comma delimited
        ISheet aclSheet = null;
        boolean wasSet = AclPrivilegedMode.set();
        try {

            aclSheet = getAclSheet(workbookId);

            User user = userService.getCurrentUser();
            if (user == null) {
                throw new AccessControlException("No current user");
            }
            if (user.isAdmin()) {
                return;
            }

            Map<String, IGenericValue> row = new HashMap<String, IGenericValue>();
            row.put("A", new StringValue(objectType.name()));
            row.put("B", new StringValue(user.getLogin()));
            row.put("C", new StringValue(sheetName));
            StringBuilder permString = new StringBuilder();
            for (Permission perm : permissions) {
                if (permString.length() > 0) {
                    permString.append(",");
                }
                permString.append(perm.name());
            }
            row.put("D", new StringValue(permString.toString()));

            aclSheet.sendCommand(CellCommands.mapValues(AreaReference.lastRow(0, 3), row));
        } catch (NotFoundException e) {
            // only happens if somebody deleted the sheet right before the filtering
            throw new StorageException(e);
        } finally {
            if (!wasSet) {
                AclPrivilegedMode.clear();
            }
        }
    }
}