Search in sources :

Example 1 with LdapDistributionList

use of com.zimbra.cs.account.ldap.entry.LdapDistributionList in project zm-mailbox by Zimbra.

the class LdapProvisioning method deleteDistributionList.

@Override
public void deleteDistributionList(String zimbraId) throws ServiceException {
    LdapDistributionList dl = (LdapDistributionList) getDistributionListByIdInternal(zimbraId);
    if (dl == null) {
        throw AccountServiceException.NO_SUCH_DISTRIBUTION_LIST(zimbraId);
    }
    deleteDistributionList(dl);
}
Also used : LdapDistributionList(com.zimbra.cs.account.ldap.entry.LdapDistributionList)

Example 2 with LdapDistributionList

use of com.zimbra.cs.account.ldap.entry.LdapDistributionList in project zm-mailbox by Zimbra.

the class LdapProvisioning method addDistributionListMembers.

private void addDistributionListMembers(DistributionList dl, String[] members) throws ServiceException {
    Set<String> existing = dl.getMultiAttrSet(Provisioning.A_zimbraMailForwardingAddress);
    Set<String> mods = new HashSet<String>();
    // all addrs of this DL
    AddrsOfEntry addrsOfDL = getAllAddressesOfEntry(dl.getName());
    String dlOU = null;
    if (dl.isHABGroup() && dl instanceof LdapDistributionList) {
        dlOU = getGroupOU(((LdapDistributionList) dl).getDN());
    }
    for (int i = 0; i < members.length; i++) {
        String memberName = members[i].toLowerCase();
        memberName = IDNUtil.toAsciiEmail(memberName);
        if (addrsOfDL.isIn(memberName))
            throw ServiceException.INVALID_REQUEST("Cannot add self as a member: " + memberName, null);
        if (dl.isHABGroup()) {
            Group memberGroup = getGroup(Key.DistributionListBy.name, memberName);
            if (memberGroup != null) {
                if (!memberGroup.isHABGroup()) {
                    throw ServiceException.INVALID_REQUEST(String.format("Cannot add non-hab group: %s as a member in hab group ", memberName), null);
                } else if (!isGroupInOU(memberGroup, dlOU)) {
                    throw ServiceException.INVALID_REQUEST(String.format("Cannot add group: %s as a member, since it belongs to different OU", memberName), null);
                }
            }
        }
        // cannot add a dynamic group as member in non-hab group
        DynamicGroup dynMember = getDynamicGroup(Key.DistributionListBy.name, memberName, null, Boolean.FALSE);
        if (dynMember != null) {
            if (dl.isHABGroup()) {
                if (dlIsInDynamicHABGroup(dynMember, addrsOfDL.getAll())) {
                    throw ServiceException.INVALID_REQUEST(String.format("Cannot add dynamic group: %s as a member, since it contains the parent", memberName), null);
                }
            } else {
                throw ServiceException.INVALID_REQUEST("Cannot add dynamic group as a member: " + memberName, null);
            }
        }
        if (!existing.contains(memberName)) {
            mods.add(memberName);
            // clear the DL cache on accounts/dl
            // can't do prov.getFromCache because it only caches by primary name
            Account acct = get(AccountBy.name, memberName);
            if (acct != null) {
                clearUpwardMembershipCache(acct);
            } else {
                // for DistributionList/ACLGroup, get it from cache because
                // if the dl is not in cache, after loading it prov.getAclGroup
                // always compute the upward membership.  Sounds silly if we are
                // about to clean the cache.  If memberName is indeed an alias
                // of one of the cached DL/ACLGroup, it will get expired after 15
                // mins, just like the multi-node case.
                // 
                // Note: do not call clearUpwardMembershipCache for AclGroup because
                // the upward membership cache for that is computed and cache only when
                // the entry is loaded/being cached, instead of lazily computed like we
                // do for account.
                removeGroupFromCache(Key.DistributionListBy.name, memberName);
            }
        }
    }
    if (mods.isEmpty()) {
        // nothing to do...
        return;
    }
    PermissionCache.invalidateCache();
    cleanGroupMembersCache(dl);
    Map<String, String[]> modmap = new HashMap<String, String[]>();
    modmap.put("+" + Provisioning.A_zimbraMailForwardingAddress, mods.toArray(new String[0]));
    modifyAttrs(dl, modmap, true);
}
Also used : Group(com.zimbra.cs.account.Group) DynamicGroup(com.zimbra.cs.account.DynamicGroup) LdapDynamicGroup(com.zimbra.cs.account.ldap.entry.LdapDynamicGroup) DynamicGroup(com.zimbra.cs.account.DynamicGroup) LdapDynamicGroup(com.zimbra.cs.account.ldap.entry.LdapDynamicGroup) Account(com.zimbra.cs.account.Account) GuestAccount(com.zimbra.cs.account.GuestAccount) LdapAccount(com.zimbra.cs.account.ldap.entry.LdapAccount) HashMap(java.util.HashMap) LdapDistributionList(com.zimbra.cs.account.ldap.entry.LdapDistributionList) HashSet(java.util.HashSet)

Example 3 with LdapDistributionList

use of com.zimbra.cs.account.ldap.entry.LdapDistributionList in project zm-mailbox by Zimbra.

the class LdapProvisioning method deleteDistributionList.

private void deleteDistributionList(LdapDistributionList dl, boolean cascadeDelete) throws ServiceException {
    // check if cascadeDelete is true. If it's true, delete all subgroups.
    if (dl.isHABGroup()) {
        if (cascadeDelete) {
            Set<String> members = dl.getAllMembersSet();
            for (String member : members) {
                LdapDistributionList subDl = (LdapDistributionList) getDistributionListByNameInternal(member);
                if (subDl != null && subDl.isHABGroup()) {
                    deleteDistributionList(subDl, cascadeDelete);
                } else {
                    DynamicGroup dg = getDynamicGroupBasic(DistributionListBy.name, member, LdapClient.getContext(LdapServerType.MASTER, LdapUsage.DELETE_DYNAMICGROUP));
                    if (dg != null && dg.isHABGroup()) {
                        deleteDynamicGroup((LdapDynamicGroup) dg);
                    }
                }
            }
        } else {
            if (dl.getAllMembers().length > 0) {
                throw ServiceException.INVALID_REQUEST("Can not delete hab group when members are present in group.", null);
            }
        }
    }
    String zimbraId = dl.getId();
    // make a copy of all addrs of this DL, after the delete all aliases on this dl
    // object will be gone, but we need to remove them from the all groups cache after the DL is deleted
    Set<String> addrs = new HashSet<String>(dl.getMultiAttrSet(Provisioning.A_mail));
    // remove the DL from all DLs
    // this doesn't throw any exceptions
    removeAddressFromAllDistributionLists(dl.getName());
    // delete all aliases of the DL
    String[] aliases = dl.getAliases();
    if (aliases != null) {
        String dlName = dl.getName();
        for (int i = 0; i < aliases.length; i++) {
            // this "alias" if it is the primary name, the entire entry will be deleted anyway.
            if (!dlName.equalsIgnoreCase(aliases[i])) {
                // this also removes each alias from any DLs
                removeAlias(dl, aliases[i]);
            }
        }
    }
    // delete all grants granted to the DL
    try {
        RightCommand.revokeAllRights(this, GranteeType.GT_GROUP, zimbraId);
    } catch (ServiceException e) {
        // eat the exception and continue
        ZimbraLog.account.warn("cannot revoke grants", e);
    }
    ZLdapContext zlc = null;
    try {
        zlc = LdapClient.getContext(LdapServerType.MASTER, LdapUsage.DELETE_DISTRIBUTIONLIST);
        zlc.deleteEntry(dl.getDN());
        groupCache.remove(dl);
        allDLs.removeGroup(addrs);
    } catch (ServiceException e) {
        throw ServiceException.FAILURE("unable to purge distribution list: " + zimbraId, e);
    } finally {
        LdapClient.closeContext(zlc);
    }
    PermissionCache.invalidateCache();
}
Also used : DynamicGroup(com.zimbra.cs.account.DynamicGroup) LdapDynamicGroup(com.zimbra.cs.account.ldap.entry.LdapDynamicGroup) AccountServiceException(com.zimbra.cs.account.AccountServiceException) AuthFailedServiceException(com.zimbra.cs.account.AccountServiceException.AuthFailedServiceException) ServiceException(com.zimbra.common.service.ServiceException) ZLdapContext(com.zimbra.cs.ldap.ZLdapContext) LdapDistributionList(com.zimbra.cs.account.ldap.entry.LdapDistributionList) HashSet(java.util.HashSet)

Example 4 with LdapDistributionList

use of com.zimbra.cs.account.ldap.entry.LdapDistributionList in project zm-mailbox by Zimbra.

the class LdapProvisioning method renameDistributionList.

@Override
public void renameDistributionList(String zimbraId, String newEmail) throws ServiceException {
    newEmail = IDNUtil.toAsciiEmail(newEmail);
    validEmailAddress(newEmail);
    boolean domainChanged = false;
    ZLdapContext zlc = null;
    try {
        zlc = LdapClient.getContext(LdapServerType.MASTER, LdapUsage.RENAME_DISTRIBUTIONLIST);
        LdapDistributionList dl = (LdapDistributionList) getDistributionListById(zimbraId, zlc);
        if (dl == null) {
            throw AccountServiceException.NO_SUCH_DISTRIBUTION_LIST(zimbraId);
        }
        groupCache.remove(dl);
        String oldEmail = dl.getName();
        String oldDomain = EmailUtil.getValidDomainPart(oldEmail);
        newEmail = newEmail.toLowerCase().trim();
        String[] parts = EmailUtil.getLocalPartAndDomain(newEmail);
        if (parts == null)
            throw ServiceException.INVALID_REQUEST("bad value for newName", null);
        String newLocal = parts[0];
        String newDomain = parts[1];
        domainChanged = !oldDomain.equals(newDomain);
        Domain domain = getDomainByAsciiName(newDomain, zlc);
        if (domain == null) {
            throw AccountServiceException.NO_SUCH_DOMAIN(newDomain);
        }
        if (domainChanged) {
            // make sure the new domain is a local domain
            if (!domain.isLocal()) {
                throw ServiceException.INVALID_REQUEST("domain type must be local", null);
            }
        }
        Map<String, Object> attrs = new HashMap<String, Object>();
        ReplaceAddressResult replacedMails = replaceMailAddresses(dl, Provisioning.A_mail, oldEmail, newEmail);
        if (replacedMails.newAddrs().length == 0) {
            // Set mail to newName if the account currently does not have a mail
            attrs.put(Provisioning.A_mail, newEmail);
        } else {
            attrs.put(Provisioning.A_mail, replacedMails.newAddrs());
        }
        ReplaceAddressResult replacedAliases = replaceMailAddresses(dl, Provisioning.A_zimbraMailAlias, oldEmail, newEmail);
        if (replacedAliases.newAddrs().length > 0) {
            attrs.put(Provisioning.A_zimbraMailAlias, replacedAliases.newAddrs());
            String newDomainDN = mDIT.domainToAccountSearchDN(newDomain);
            // check up front if any of renamed aliases already exists in the new domain (if domain also got changed)
            if (domainChanged && addressExistsUnderDN(zlc, newDomainDN, replacedAliases.newAddrs())) {
                throw AccountServiceException.DISTRIBUTION_LIST_EXISTS(newEmail);
            }
        }
        ReplaceAddressResult replacedAllowAddrForDelegatedSender = replaceMailAddresses(dl, Provisioning.A_zimbraPrefAllowAddressForDelegatedSender, oldEmail, newEmail);
        if (replacedAllowAddrForDelegatedSender.newAddrs().length > 0) {
            attrs.put(Provisioning.A_zimbraPrefAllowAddressForDelegatedSender, replacedAllowAddrForDelegatedSender.newAddrs());
        }
        String oldDn = dl.getDN();
        String newDn = mDIT.distributionListDNRename(oldDn, newLocal, domain.getName());
        boolean dnChanged = (!oldDn.equals(newDn));
        if (dnChanged) {
            // uid will be changed during renameEntry, so no need to modify it
            // OpenLDAP is OK modifying it, as long as it matches the new DN, but
            // InMemoryDirectoryServer does not like it.
            attrs.remove(A_uid);
        } else {
            /*
                 * always reset uid to the local part, because in non default DIT the naming RDN might not
                 * be uid, and ctxt.rename won't change the uid to the new localpart in that case.
                 */
            attrs.put(A_uid, newLocal);
        }
        // move over the distribution list entry
        if (dnChanged) {
            zlc.renameEntry(oldDn, newDn);
        }
        dl = (LdapDistributionList) getDistributionListById(zimbraId, zlc);
        // rename the distribution list and all it's renamed aliases to the new name
        // in all distribution lists.
        // Doesn't throw exceptions, just logs.
        renameAddressesInAllDistributionLists(oldEmail, newEmail, replacedAliases);
        // doesn't throw exceptions, just logs
        if (domainChanged) {
            String newUid = dl.getAttr(Provisioning.A_uid);
            moveAliases(zlc, replacedAliases, newDomain, newUid, oldDn, newDn, oldDomain, newDomain);
        }
        // could fail. So catch service exception here and log error
        try {
            modifyAttrsInternal(dl, zlc, attrs);
        } catch (ServiceException e) {
            ZimbraLog.account.error("distribution list renamed to " + newLocal + " but failed to move old name's LDAP attributes", e);
            throw e;
        }
        removeExternalAddrsFromAllDynamicGroups(dl.getAllAddrsSet(), zlc);
    } catch (LdapEntryAlreadyExistException nabe) {
        throw AccountServiceException.DISTRIBUTION_LIST_EXISTS(newEmail);
    } catch (LdapException e) {
        throw e;
    } catch (AccountServiceException e) {
        throw e;
    } catch (ServiceException e) {
        throw ServiceException.FAILURE("unable to rename distribution list: " + zimbraId, e);
    } finally {
        LdapClient.closeContext(zlc);
    }
    if (domainChanged) {
        PermissionCache.invalidateCache();
    }
}
Also used : LdapEntryAlreadyExistException(com.zimbra.cs.ldap.LdapException.LdapEntryAlreadyExistException) ZLdapContext(com.zimbra.cs.ldap.ZLdapContext) HashMap(java.util.HashMap) LdapDistributionList(com.zimbra.cs.account.ldap.entry.LdapDistributionList) AccountServiceException(com.zimbra.cs.account.AccountServiceException) AccountServiceException(com.zimbra.cs.account.AccountServiceException) AuthFailedServiceException(com.zimbra.cs.account.AccountServiceException.AuthFailedServiceException) ServiceException(com.zimbra.common.service.ServiceException) LdapDomain(com.zimbra.cs.account.ldap.entry.LdapDomain) Domain(com.zimbra.cs.account.Domain) LdapException(com.zimbra.cs.ldap.LdapException)

Example 5 with LdapDistributionList

use of com.zimbra.cs.account.ldap.entry.LdapDistributionList in project zm-mailbox by Zimbra.

the class LdapProvisioning method addMembers.

@Override
public void addMembers(DistributionList list, String[] members) throws ServiceException {
    LdapDistributionList ldl = (LdapDistributionList) list;
    addDistributionListMembers(ldl, members);
}
Also used : LdapDistributionList(com.zimbra.cs.account.ldap.entry.LdapDistributionList)

Aggregations

LdapDistributionList (com.zimbra.cs.account.ldap.entry.LdapDistributionList)7 ServiceException (com.zimbra.common.service.ServiceException)2 AccountServiceException (com.zimbra.cs.account.AccountServiceException)2 AuthFailedServiceException (com.zimbra.cs.account.AccountServiceException.AuthFailedServiceException)2 DynamicGroup (com.zimbra.cs.account.DynamicGroup)2 LdapDynamicGroup (com.zimbra.cs.account.ldap.entry.LdapDynamicGroup)2 ZLdapContext (com.zimbra.cs.ldap.ZLdapContext)2 HashMap (java.util.HashMap)2 HashSet (java.util.HashSet)2 Account (com.zimbra.cs.account.Account)1 DistributionList (com.zimbra.cs.account.DistributionList)1 Domain (com.zimbra.cs.account.Domain)1 Group (com.zimbra.cs.account.Group)1 GuestAccount (com.zimbra.cs.account.GuestAccount)1 LdapAccount (com.zimbra.cs.account.ldap.entry.LdapAccount)1 LdapDomain (com.zimbra.cs.account.ldap.entry.LdapDomain)1 LdapException (com.zimbra.cs.ldap.LdapException)1 LdapEntryAlreadyExistException (com.zimbra.cs.ldap.LdapException.LdapEntryAlreadyExistException)1