com.zimbra.cs.account.accesscontrol.ACLUtil.java Source code

Java tutorial

Introduction

Here is the source code for com.zimbra.cs.account.accesscontrol.ACLUtil.java

Source

/*
 * ***** BEGIN LICENSE BLOCK *****
 * Zimbra Collaboration Suite Server
 * Copyright (C) 2008, 2009, 2010, 2011, 2013, 2014, 2015, 2016 Synacor, Inc.
 *
 * This program is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software Foundation,
 * version 2 of the License.
 *
 * This program 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 General Public License for more details.
 * You should have received a copy of the GNU General Public License along with this program.
 * If not, see <https://www.gnu.org/licenses/>.
 * ***** END LICENSE BLOCK *****
 */
package com.zimbra.cs.account.accesscontrol;

import java.util.ArrayList;
import java.util.Collections;
import java.util.EnumSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import com.google.common.base.Objects;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Multimap;
import com.zimbra.common.service.ServiceException;
import com.zimbra.cs.account.Account;
import com.zimbra.cs.account.AttributeClass;
import com.zimbra.cs.account.Entry;
import com.zimbra.cs.account.Identity;
import com.zimbra.cs.account.Provisioning;
import com.zimbra.cs.account.accesscontrol.generated.UserRights;

public final class ACLUtil {
    private static final String ACL_CACHE_KEY = "ENTRY.ACL_CACHE";

    private ACLUtil() {
    }

    /**
     * Returns all ACEs granted on the entry.
     *
     * @param entry the entry on which rights are granted
     * @return all ACEs granted on the entry.
     */
    public static List<ZimbraACE> getAllACEs(Entry entry) throws ServiceException {
        ZimbraACL acl = getACL(entry);
        return acl != null ? acl.getAllACEs() : null;
    }

    public static Set<ZimbraACE> getAllowedNotDelegableACEs(Entry entry) throws ServiceException {
        ZimbraACL acl = getACL(entry);
        return acl != null ? acl.getAllowedNotDelegableACEs() : null;
    }

    public static Set<ZimbraACE> getAllowedDelegableACEs(Entry entry) throws ServiceException {
        ZimbraACL acl = getACL(entry);
        return acl != null ? acl.getAllowedDelegableACEs() : null;
    }

    public static Set<ZimbraACE> getDeniedACEs(Entry entry) throws ServiceException {
        ZimbraACL acl = getACL(entry);
        return acl != null ? acl.getDeniedACEs() : null;
    }

    /**
     * Returns a Set of ACEs with the specified rights granted on the entry.
     *
     * @param entry the entry on which rights are granted
     * @param rights rights of interest
     * @return a Set of ACEs with the specified rights granted on the entry.
     */
    public static List<ZimbraACE> getACEs(Entry entry, Set<? extends Right> rights) throws ServiceException {
        ZimbraACL acl = getACL(entry);
        return acl != null ? acl.getACEs(rights) : null;
    }

    private static Multimap<Right, Entry> getGrantedRights(Account grantee, Set<String> fetchAttrs)
            throws ServiceException {
        SearchGrants search = new SearchGrants(grantee.getProvisioning(), EnumSet.of(TargetType.account),
                RightBearer.Grantee.getGrantee(grantee, false).getIdAndGroupIds());
        search.addFetchAttribute(fetchAttrs);
        Set<SearchGrants.GrantsOnTarget> results = search.doSearch().getResults();
        Multimap<Right, Entry> map = HashMultimap.create();
        for (SearchGrants.GrantsOnTarget grants : results) {
            ZimbraACL acl = grants.getAcl();
            for (ZimbraACE ace : acl.getAllACEs()) {
                if (ace.getGrantee().equals(grantee.getId())) {
                    map.put(ace.getRight(), grants.getTargetEntry());
                }
            }
        }
        return map;
    }

    /**
     * Returns {@link UserRights#R_sendOnBehalfOf} rights granted to the grantee.
     */
    public static List<Identity> getSendOnBehalfOf(Account grantee) throws ServiceException {
        Multimap<Right, Entry> rights = getGrantedRights(grantee,
                Collections.singleton(Provisioning.A_displayName));
        ImmutableList.Builder<Identity> result = ImmutableList.<Identity>builder();
        for (Entry entry : rights.get(UserRights.R_sendOnBehalfOf)) {
            Account grantor = (Account) entry;
            String mail = grantor.getName();
            String name = Objects.firstNonNull(grantor.getDisplayName(), mail);
            Map<String, Object> attrs = ImmutableMap.<String, Object>builder()
                    .put(Provisioning.A_zimbraPrefIdentityId, grantor.getId())
                    .put(Provisioning.A_zimbraPrefIdentityName, name)
                    .put(Provisioning.A_zimbraPrefFromDisplay, name).put(Provisioning.A_zimbraPrefFromAddress, mail)
                    .put(Provisioning.A_objectClass, AttributeClass.OC_zimbraAclTarget).build();
            result.add(new Identity(grantee, name, grantor.getId(), attrs, grantee.getProvisioning()));
        }
        return result.build();
    }

    /**
     * Grant rights on a target entry.
     */
    public static List<ZimbraACE> grantRight(Provisioning prov, Entry target, Set<ZimbraACE> aces)
            throws ServiceException {
        for (ZimbraACE ace : aces) {
            ZimbraACE.validate(ace);
        }
        ZimbraACL acl = getACL(target);
        List<ZimbraACE> granted = null;

        if (acl == null) {
            acl = new ZimbraACL(aces);
            granted = acl.getAllACEs();
        } else {
            // Make a copy so we don't interfere with others that are using the acl.
            // This instance of acl will never be used in any AccessManager code path.
            // It only lives within this method for serialization.
            // serialize will erase the cached ZimbraACL object on the target object.
            // The new ACL will be loaded when it is needed.
            acl = acl.clone();
            granted = acl.grantAccess(aces);
        }

        serialize(prov, target, acl);

        PermissionCache.invalidateCache(target);

        return granted;
    }

    /**
     * Revoke(remove) rights from a target entry.
     * If a right was not previously granted on the target, NO error is thrown.
     * @return a Set of grants that are actually revoked by this call
     */
    public static List<ZimbraACE> revokeRight(Provisioning prov, Entry target, Set<ZimbraACE> aces)
            throws ServiceException {
        ZimbraACL acl = getACL(target);
        if (acl == null) {
            return new ArrayList<ZimbraACE>(); // return empty list
        }
        // Make a copy so we don't interfere with others that are using the acl.
        // This instance of acl will never be used in any AccessManager code path.
        // It only lives within this method for serialization.
        // serialize will erase the cached ZimbraACL object on the target object.
        // The new ACL will be loaded when it is needed.
        acl = acl.clone();
        List<ZimbraACE> revoked = acl.revokeAccess(aces);
        serialize(prov, target, acl);

        PermissionCache.invalidateCache(target);

        return revoked;
    }

    /**
     * Persists grants in LDAP
     */
    private static void serialize(Provisioning prov, Entry entry, ZimbraACL acl) throws ServiceException {
        // modifyAttrs will erase cached ACL and permission cache on the target
        prov.modifyAttrs(entry, Collections.singletonMap(Provisioning.A_zimbraACE, acl.serialize()));
    }

    /**
     * Get cached grants, if not in cache, load from LDAP.
     *
     * @param entry
     * @return
     * @throws ServiceException
     */
    static ZimbraACL getACL(Entry entry) throws ServiceException {
        ZimbraACL acl = (ZimbraACL) entry.getCachedData(ACL_CACHE_KEY);
        if (acl != null) {
            return acl;
        } else {
            String[] aces = entry.getMultiAttr(Provisioning.A_zimbraACE);
            if (aces.length == 0) {
                return null;
            } else {
                acl = new ZimbraACL(aces, TargetType.getTargetType(entry), entry.getLabel());
                entry.setCachedData(ACL_CACHE_KEY, acl);
            }
        }
        return acl;
    }

}