Search in sources :

Example 6 with CallbackContext

use of com.zimbra.cs.account.callback.CallbackContext in project zm-mailbox by Zimbra.

the class LdapProvisioning method createDataSource.

private DataSource createDataSource(Account account, DataSourceType dsType, String dsName, Map<String, Object> dataSourceAttrs, boolean passwdAlreadyEncrypted, boolean restoring) throws ServiceException {
    removeAttrIgnoreCase("objectclass", dataSourceAttrs);
    LdapEntry ldapEntry = (LdapEntry) (account instanceof LdapEntry ? account : getAccountById(account.getId()));
    if (ldapEntry == null) {
        throw AccountServiceException.NO_SUCH_ACCOUNT(account.getName());
    }
    List<DataSource> existing = getAllDataSources(account);
    if (existing.size() >= account.getLongAttr(A_zimbraDataSourceMaxNumEntries, 20)) {
        throw AccountServiceException.TOO_MANY_DATA_SOURCES();
    }
    String dsEmailAddr = (String) dataSourceAttrs.get(A_zimbraDataSourceEmailAddress);
    if (!StringUtil.isNullOrEmpty(dsEmailAddr)) {
        for (DataSource ds : existing) {
            if (dsEmailAddr.equals(ds.getEmailAddress())) {
                throw AccountServiceException.DATA_SOURCE_EXISTS(dsEmailAddr);
            }
        }
    }
    // must be the same
    dataSourceAttrs.put(A_zimbraDataSourceName, dsName);
    dataSourceAttrs.put(Provisioning.A_zimbraDataSourceType, dsType.toString());
    account.setCachedData(DATA_SOURCE_LIST_CACHE_KEY, null);
    boolean checkImmutable = !restoring;
    CallbackContext callbackContext = new CallbackContext(CallbackContext.Op.CREATE);
    AttributeManager.getInstance().preModify(dataSourceAttrs, null, callbackContext, checkImmutable);
    ZLdapContext zlc = null;
    try {
        zlc = LdapClient.getContext(LdapServerType.MASTER, LdapUsage.CREATE_DATASOURCE);
        String dn = getDataSourceDn(ldapEntry, dsName);
        ZMutableEntry entry = LdapClient.createMutableEntry();
        entry.setDN(dn);
        entry.mapToAttrs(dataSourceAttrs);
        entry.setAttr(A_objectClass, "zimbraDataSource");
        String extraOc = LdapDataSource.getObjectClass(dsType);
        if (extraOc != null) {
            entry.addAttr(A_objectClass, Sets.newHashSet(extraOc));
        }
        String dsId = entry.getAttrString(A_zimbraDataSourceId);
        if (dsId == null) {
            dsId = LdapUtil.generateUUID();
            entry.setAttr(A_zimbraDataSourceId, dsId);
        }
        String password = entry.getAttrString(A_zimbraDataSourcePassword);
        if (password != null) {
            String encrypted = passwdAlreadyEncrypted ? password : DataSource.encryptData(dsId, password);
            entry.setAttr(A_zimbraDataSourcePassword, encrypted);
        }
        String oauthToken = entry.getAttrString(A_zimbraDataSourceOAuthToken);
        if (oauthToken != null) {
            String encrypted = passwdAlreadyEncrypted ? oauthToken : DataSource.encryptData(dsId, oauthToken);
            entry.setAttr(A_zimbraDataSourceOAuthToken, encrypted);
        }
        String clientSecret = entry.getAttrString(A_zimbraDataSourceOAuthClientSecret);
        if (clientSecret != null) {
            String encrypted = passwdAlreadyEncrypted ? clientSecret : DataSource.encryptData(dsId, clientSecret);
            entry.setAttr(A_zimbraDataSourceOAuthClientSecret, encrypted);
        }
        String smtpPassword = entry.getAttrString(A_zimbraDataSourceSmtpAuthPassword);
        if (smtpPassword != null) {
            String encrypted = passwdAlreadyEncrypted ? smtpPassword : DataSource.encryptData(dsId, smtpPassword);
            entry.setAttr(A_zimbraDataSourceSmtpAuthPassword, encrypted);
        }
        entry.setAttr(Provisioning.A_zimbraCreateTimestamp, LdapDateUtil.toGeneralizedTime(new Date()));
        zlc.createEntry(entry);
        DataSource ds = getDataSourceById(ldapEntry, dsId, zlc);
        AttributeManager.getInstance().postModify(dataSourceAttrs, ds, callbackContext);
        return ds;
    } catch (LdapEntryAlreadyExistException nabe) {
        throw AccountServiceException.DATA_SOURCE_EXISTS(dsName);
    } catch (LdapException e) {
        throw e;
    } catch (AccountServiceException e) {
        throw e;
    } catch (ServiceException e) {
        throw ServiceException.FAILURE("unable to create data source: " + dsName, e);
    } finally {
        LdapClient.closeContext(zlc);
    }
}
Also used : ZMutableEntry(com.zimbra.cs.ldap.ZMutableEntry) LdapEntryAlreadyExistException(com.zimbra.cs.ldap.LdapException.LdapEntryAlreadyExistException) ZLdapContext(com.zimbra.cs.ldap.ZLdapContext) LdapEntry(com.zimbra.cs.account.ldap.entry.LdapEntry) Date(java.util.Date) DataSource(com.zimbra.cs.account.DataSource) LdapDataSource(com.zimbra.cs.account.ldap.entry.LdapDataSource) 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) CallbackContext(com.zimbra.cs.account.callback.CallbackContext) LdapException(com.zimbra.cs.ldap.LdapException)

Example 7 with CallbackContext

use of com.zimbra.cs.account.callback.CallbackContext in project zm-mailbox by Zimbra.

the class LdapProvisioning method createServer.

@Override
public Server createServer(String name, Map<String, Object> serverAttrs) throws ServiceException {
    name = name.toLowerCase().trim();
    CallbackContext callbackContext = new CallbackContext(CallbackContext.Op.CREATE);
    AttributeManager.getInstance().preModify(serverAttrs, null, callbackContext, true);
    ZLdapContext zlc = null;
    try {
        zlc = LdapClient.getContext(LdapServerType.MASTER, LdapUsage.CREATE_SERVER);
        ZMutableEntry entry = LdapClient.createMutableEntry();
        entry.mapToAttrs(serverAttrs);
        Set<String> ocs = LdapObjectClass.getServerObjectClasses(this);
        entry.addAttr(A_objectClass, ocs);
        String zimbraIdStr = LdapUtil.generateUUID();
        entry.setAttr(A_zimbraId, zimbraIdStr);
        entry.setAttr(A_zimbraCreateTimestamp, LdapDateUtil.toGeneralizedTime(new Date()));
        entry.setAttr(A_cn, name);
        String dn = mDIT.serverNameToDN(name);
        if (!entry.hasAttribute(Provisioning.A_zimbraServiceHostname)) {
            entry.setAttr(Provisioning.A_zimbraServiceHostname, name);
        }
        entry.setDN(dn);
        zlc.createEntry(entry);
        Server server = getServerById(zimbraIdStr, zlc, true);
        AttributeManager.getInstance().postModify(serverAttrs, server, callbackContext);
        return server;
    } catch (LdapEntryAlreadyExistException nabe) {
        throw AccountServiceException.SERVER_EXISTS(name);
    } catch (LdapException e) {
        throw e;
    } catch (AccountServiceException e) {
        throw e;
    } catch (ServiceException e) {
        throw ServiceException.FAILURE("unable to create server: " + name, e);
    } finally {
        LdapClient.closeContext(zlc);
    }
}
Also used : ZMutableEntry(com.zimbra.cs.ldap.ZMutableEntry) LdapEntryAlreadyExistException(com.zimbra.cs.ldap.LdapException.LdapEntryAlreadyExistException) AccountServiceException(com.zimbra.cs.account.AccountServiceException) ZLdapContext(com.zimbra.cs.ldap.ZLdapContext) InMemoryLdapServer(com.zimbra.cs.ldap.unboundid.InMemoryLdapServer) LdapServer(com.zimbra.cs.account.ldap.entry.LdapServer) Server(com.zimbra.cs.account.Server) AccountServiceException(com.zimbra.cs.account.AccountServiceException) AuthFailedServiceException(com.zimbra.cs.account.AccountServiceException.AuthFailedServiceException) ServiceException(com.zimbra.common.service.ServiceException) CallbackContext(com.zimbra.cs.account.callback.CallbackContext) LdapException(com.zimbra.cs.ldap.LdapException) Date(java.util.Date)

Example 8 with CallbackContext

use of com.zimbra.cs.account.callback.CallbackContext in project zm-mailbox by Zimbra.

the class LdapProvisioning method createDynamicGroup.

private DynamicGroup createDynamicGroup(String groupAddress, Map<String, Object> groupAttrs, Account creator) throws ServiceException {
    SpecialAttrs specialAttrs = mDIT.handleSpecialAttrs(groupAttrs);
    String baseDn = specialAttrs.getLdapBaseDn();
    groupAddress = groupAddress.toLowerCase().trim();
    EmailAddress addr = new EmailAddress(groupAddress);
    String localPart = addr.getLocalPart();
    String domainName = addr.getDomain();
    domainName = IDNUtil.toAsciiDomainName(domainName);
    groupAddress = EmailAddress.getAddress(localPart, domainName);
    validEmailAddress(groupAddress);
    CallbackContext callbackContext = new CallbackContext(CallbackContext.Op.CREATE);
    callbackContext.setCreatingEntryName(groupAddress);
    // remove zimbraIsACLGroup from attrs if provided, to avoid the immutable check
    Object providedZimbraIsACLGroup = groupAttrs.get(A_zimbraIsACLGroup);
    if (providedZimbraIsACLGroup != null) {
        groupAttrs.remove(A_zimbraIsACLGroup);
    }
    AttributeManager.getInstance().preModify(groupAttrs, null, callbackContext, true);
    // put zimbraIsACLGroup back
    if (providedZimbraIsACLGroup != null) {
        groupAttrs.put(A_zimbraIsACLGroup, providedZimbraIsACLGroup);
    }
    ZLdapContext zlc = null;
    try {
        zlc = LdapClient.getContext(LdapServerType.MASTER, LdapUsage.CREATE_DYNAMICGROUP);
        Domain domain = getDomainByAsciiName(domainName, zlc);
        if (domain == null) {
            throw AccountServiceException.NO_SUCH_DOMAIN(domainName);
        }
        if (!domain.isLocal()) {
            throw ServiceException.INVALID_REQUEST("domain type must be local", null);
        }
        String domainDN = ((LdapDomain) domain).getDN();
        /*
             * ====================================
             * create the main dynamic group entry
             * ====================================
             */
        ZMutableEntry entry = LdapClient.createMutableEntry();
        entry.mapToAttrs(groupAttrs);
        Set<String> ocs = LdapObjectClass.getGroupObjectClasses(this);
        entry.addAttr(A_objectClass, ocs);
        String zimbraId = LdapUtil.generateUUID();
        // create a UUID for the static unit entry
        String staticUnitZimbraId = LdapUtil.generateUUID();
        String createTimestamp = LdapDateUtil.toGeneralizedTime(new Date());
        entry.setAttr(A_zimbraId, zimbraId);
        entry.setAttr(A_zimbraCreateTimestamp, createTimestamp);
        entry.setAttr(A_mail, groupAddress);
        entry.setAttr(A_dgIdentity, LC.zimbra_ldap_userdn.value());
        // unlike accounts (which have a zimbraMailDeliveryAddress for the primary,
        // and zimbraMailAliases only for aliases), DLs use zimbraMailAlias for both.
        // Postfix uses these two attributes to route mail, and zimbraMailDeliveryAddress
        // indicates that something has a physical mailbox, which DLs don't.
        entry.setAttr(A_zimbraMailAlias, groupAddress);
        /*
            // allow only users in the same domain
            String memberURL = String.format("ldap:///%s??one?(zimbraMemberOf=%s)",
                    mDIT.domainDNToAccountBaseDN(domainDN), groupAddress);
            */
        String specifiedIsACLGroup = entry.getAttrString(A_zimbraIsACLGroup);
        boolean isACLGroup;
        if (!entry.hasAttribute(A_memberURL)) {
            String memberURL = LdapDynamicGroup.getDefaultMemberURL(zimbraId, staticUnitZimbraId);
            entry.setAttr(Provisioning.A_memberURL, memberURL);
            // or specified to be TRUE;
            if (specifiedIsACLGroup == null) {
                entry.setAttr(A_zimbraIsACLGroup, ProvisioningConstants.TRUE);
            } else if (ProvisioningConstants.FALSE.equals(specifiedIsACLGroup)) {
                throw ServiceException.INVALID_REQUEST("No custom " + A_memberURL + " is provided, " + A_zimbraIsACLGroup + " cannot be set to FALSE", null);
            }
            isACLGroup = true;
        } else {
            // We want to be able to use dynamic groups as ACLs, for instance when sharing a folder with a group
            // This used to be disallowed via a requirement that zimbraIsACLGroup be specified and set to FALSE.
            // That requirement has been dropped.
            isACLGroup = !ProvisioningConstants.FALSE.equals(specifiedIsACLGroup);
        }
        // by default a dynamic group is always created enabled
        if (!entry.hasAttribute(Provisioning.A_zimbraMailStatus)) {
            entry.setAttr(A_zimbraMailStatus, MAIL_STATUS_ENABLED);
        }
        String mailStatus = entry.getAttrString(A_zimbraMailStatus);
        entry.setAttr(A_cn, localPart);
        // entry.setAttr(A_uid, localPart); need to use uid if we move dynamic groups to the ou=people tree
        setGroupHomeServer(entry, creator);
        String dn = mDIT.dynamicGroupNameLocalPartToDN(localPart, domainDN);
        entry.setDN(dn);
        zlc.createEntry(entry);
        if (isACLGroup) {
            /*
                 * ===========================================================
                 * create the dynamic group unit entry, for internal addresses
                 * ===========================================================
                 */
            String dynamicUnitLocalpart = dynamicGroupDynamicUnitLocalpart(localPart);
            String dynamicUnitAddr = EmailAddress.getAddress(dynamicUnitLocalpart, domainName);
            entry = LdapClient.createMutableEntry();
            ocs = LdapObjectClass.getGroupDynamicUnitObjectClasses(this);
            entry.addAttr(A_objectClass, ocs);
            String dynamicUnitZimbraId = LdapUtil.generateUUID();
            entry.setAttr(A_cn, DYNAMIC_GROUP_DYNAMIC_UNIT_NAME);
            entry.setAttr(A_zimbraId, dynamicUnitZimbraId);
            // id of the main group
            entry.setAttr(A_zimbraGroupId, zimbraId);
            entry.setAttr(A_zimbraCreateTimestamp, createTimestamp);
            entry.setAttr(A_mail, dynamicUnitAddr);
            entry.setAttr(A_zimbraMailAlias, dynamicUnitAddr);
            entry.setAttr(A_zimbraMailStatus, mailStatus);
            entry.setAttr(A_dgIdentity, LC.zimbra_ldap_userdn.value());
            // id of the main group
            String memberURL = LdapDynamicGroup.getDefaultDynamicUnitMemberURL(zimbraId);
            entry.setAttr(Provisioning.A_memberURL, memberURL);
            String dynamicUnitDN = mDIT.dynamicGroupUnitNameToDN(DYNAMIC_GROUP_DYNAMIC_UNIT_NAME, dn);
            entry.setDN(dynamicUnitDN);
            zlc.createEntry(entry);
            /*
                 * ==========================================================
                 * create the static group unit entry, for external addresses
                 * ==========================================================
                 */
            entry = LdapClient.createMutableEntry();
            ocs = LdapObjectClass.getGroupStaticUnitObjectClasses(this);
            entry.addAttr(A_objectClass, ocs);
            entry.setAttr(A_cn, DYNAMIC_GROUP_STATIC_UNIT_NAME);
            entry.setAttr(A_zimbraId, staticUnitZimbraId);
            // id of the main group
            entry.setAttr(A_zimbraGroupId, zimbraId);
            entry.setAttr(A_zimbraCreateTimestamp, createTimestamp);
            String staticUnitDN = mDIT.dynamicGroupUnitNameToDN(DYNAMIC_GROUP_STATIC_UNIT_NAME, dn);
            entry.setDN(staticUnitDN);
            zlc.createEntry(entry);
        }
        /*
             * all is well, get the group by id
             */
        DynamicGroup group = getDynamicGroupBasic(DistributionListBy.id, zimbraId, zlc);
        if (group != null) {
            AttributeManager.getInstance().postModify(groupAttrs, group, callbackContext);
            removeExternalAddrsFromAllDynamicGroups(group.getAllAddrsSet(), zlc);
            allDLs.addGroup(group);
        } else {
            throw ServiceException.FAILURE("unable to get dynamic group after creating LDAP entry: " + groupAddress, null);
        }
        return group;
    } catch (LdapEntryAlreadyExistException nabe) {
        throw AccountServiceException.DISTRIBUTION_LIST_EXISTS(groupAddress);
    } catch (LdapException e) {
        throw e;
    } catch (AccountServiceException e) {
        throw e;
    } finally {
        LdapClient.closeContext(zlc);
    }
}
Also used : ZMutableEntry(com.zimbra.cs.ldap.ZMutableEntry) DynamicGroup(com.zimbra.cs.account.DynamicGroup) LdapDynamicGroup(com.zimbra.cs.account.ldap.entry.LdapDynamicGroup) LdapEntryAlreadyExistException(com.zimbra.cs.ldap.LdapException.LdapEntryAlreadyExistException) ZLdapContext(com.zimbra.cs.ldap.ZLdapContext) LdapDomain(com.zimbra.cs.account.ldap.entry.LdapDomain) EmailAddress(com.zimbra.cs.account.names.NameUtil.EmailAddress) Date(java.util.Date) AccountServiceException(com.zimbra.cs.account.AccountServiceException) CallbackContext(com.zimbra.cs.account.callback.CallbackContext) LdapDomain(com.zimbra.cs.account.ldap.entry.LdapDomain) Domain(com.zimbra.cs.account.Domain) LdapException(com.zimbra.cs.ldap.LdapException)

Example 9 with CallbackContext

use of com.zimbra.cs.account.callback.CallbackContext in project zm-mailbox by Zimbra.

the class LdapProvisioning method modifyAttrs.

/**
     * Modifies this entry.  <code>attrs</code> is a <code>Map</code> consisting of
     * keys that are <code>String</code>s, and values that are either
     * <ul>
     *   <li><code>null</code>, in which case the attr is removed</li>
     *   <li>a single <code>Object</code>, in which case the attr is modified
     *     based on the object's <code>toString()</code> value</li>
     *   <li>an <code>Object</code> array or <code>Collection</code>,
     *     in which case a multi-valued attr is updated</li>
     * </ul>
     */
@Override
public void modifyAttrs(Entry e, Map<String, ? extends Object> attrs, boolean checkImmutable, boolean allowCallback) throws ServiceException {
    CallbackContext callbackContext = new CallbackContext(CallbackContext.Op.MODIFY);
    AttributeManager.getInstance().preModify(attrs, e, callbackContext, checkImmutable, allowCallback);
    modifyAttrsInternal(e, null, attrs);
    AttributeManager.getInstance().postModify(attrs, e, callbackContext, allowCallback);
}
Also used : CallbackContext(com.zimbra.cs.account.callback.CallbackContext)

Example 10 with CallbackContext

use of com.zimbra.cs.account.callback.CallbackContext in project zm-mailbox by Zimbra.

the class LdapProvisioning method createAccount.

private Account createAccount(String emailAddress, String password, Map<String, Object> acctAttrs, SpecialAttrs specialAttrs, String[] additionalObjectClasses, boolean restoring, Map<String, Object> origAttrs) throws ServiceException {
    String uuid = specialAttrs.getZimbraId();
    String baseDn = specialAttrs.getLdapBaseDn();
    emailAddress = emailAddress.toLowerCase().trim();
    String[] parts = emailAddress.split("@");
    if (parts.length != 2) {
        throw ServiceException.INVALID_REQUEST("must be valid email address: " + emailAddress, null);
    }
    String localPart = parts[0];
    String domain = parts[1];
    domain = IDNUtil.toAsciiDomainName(domain);
    emailAddress = localPart + "@" + domain;
    validEmailAddress(emailAddress);
    if (restoring) {
        validate(ProvisioningValidator.CREATE_ACCOUNT, emailAddress, additionalObjectClasses, origAttrs);
        validate(ProvisioningValidator.CREATE_ACCOUNT_CHECK_DOMAIN_COS_AND_FEATURE, emailAddress, origAttrs);
    } else {
        validate(ProvisioningValidator.CREATE_ACCOUNT, emailAddress, additionalObjectClasses, acctAttrs);
        validate(ProvisioningValidator.CREATE_ACCOUNT_CHECK_DOMAIN_COS_AND_FEATURE, emailAddress, acctAttrs);
    }
    if (acctAttrs == null) {
        acctAttrs = new HashMap<String, Object>();
    }
    CallbackContext callbackContext = new CallbackContext(CallbackContext.Op.CREATE);
    callbackContext.setCreatingEntryName(emailAddress);
    AttributeManager.getInstance().preModify(acctAttrs, null, callbackContext, true);
    Account acct = null;
    String dn = null;
    ZLdapContext zlc = null;
    try {
        zlc = LdapClient.getContext(LdapServerType.MASTER, LdapUsage.CREATE_ACCOUNT);
        Domain d = getDomainByAsciiName(domain, zlc);
        if (d == null) {
            throw AccountServiceException.NO_SUCH_DOMAIN(domain);
        }
        if (!d.isLocal()) {
            throw ServiceException.INVALID_REQUEST("domain type must be local", null);
        }
        ZMutableEntry entry = LdapClient.createMutableEntry();
        entry.mapToAttrs(acctAttrs);
        for (int i = 0; i < sInvalidAccountCreateModifyAttrs.length; i++) {
            String a = sInvalidAccountCreateModifyAttrs[i];
            if (entry.hasAttribute(a))
                throw ServiceException.INVALID_REQUEST("invalid attribute for CreateAccount: " + a, null);
        }
        Set<String> ocs;
        if (additionalObjectClasses == null) {
            // We are creating a pure account object, get all object classes for account.
            //
            // If restoring, only add zimbra default object classes, do not add extra
            // ones configured.  After createAccount, the restore code will issue a
            // modifyAttrs call and all object classes in the backed up account will be
            // in the attr map passed to modifyAttrs.
            //
            ocs = LdapObjectClass.getAccountObjectClasses(this, restoring);
        } else {
            // We are creating a "subclass" of account (e.g. calendar resource), get just the
            // zimbra default object classes for account, then add extra object classes needed
            // by the subclass.  All object classes needed by the subclass (calendar resource)
            // were figured out in the createCalendarResource method: including the zimbra
            // default (zimbracalendarResource) and any extra ones configured via
            // globalconfig.zimbraCalendarResourceExtraObjectClass.
            //
            // It doesn't matter if the additionalObjectClasses already contains object classes
            // added by the getAccountObjectClasses(this, true).  When additional object classes
            // are added to the set, duplicated once will only appear once.
            //
            //
            // The "restoring" flag is ignored in this path.
            // When restoring a calendar a resource, the restoring code:
            //     - always calls createAccount, not createCalendarResource
            //     - always pass null for additionalObjectClasses
            //     - like restoring an account, it will call modifyAttrs after the
            //       entry is created, any object classes in the backed up data
            //       will be in the attr map passed to modifyAttrs.
            ocs = LdapObjectClass.getAccountObjectClasses(this, true);
            for (int i = 0; i < additionalObjectClasses.length; i++) ocs.add(additionalObjectClasses[i]);
        }
        boolean skipCountingLicenseQuota = false;
        /* bug 48226
             *
             * Check if any of the OCs in the backup is a structural OC that subclasses
             * our default OC (defined in ZIMBRA_DEFAULT_PERSON_OC).
             * If so, add that OC now while creating the account, because it cannot be modified later.
             */
        if (restoring && origAttrs != null) {
            Object ocsInBackupObj = origAttrs.get(A_objectClass);
            String[] ocsInBackup = StringUtil.toStringArray(ocsInBackupObj);
            String mostSpecificOC = LdapObjectClassHierarchy.getMostSpecificOC(this, ocsInBackup, LdapObjectClass.ZIMBRA_DEFAULT_PERSON_OC);
            if (!LdapObjectClass.ZIMBRA_DEFAULT_PERSON_OC.equalsIgnoreCase(mostSpecificOC)) {
                ocs.add(mostSpecificOC);
            }
            //calendar resource doesn't count against license quota
            if (origAttrs.get(A_zimbraCalResType) != null) {
                skipCountingLicenseQuota = true;
            }
            if (origAttrs.get(A_zimbraIsSystemResource) != null) {
                entry.setAttr(A_zimbraIsSystemResource, "TRUE");
                skipCountingLicenseQuota = true;
            }
            if (origAttrs.get(A_zimbraIsExternalVirtualAccount) != null) {
                entry.setAttr(A_zimbraIsExternalVirtualAccount, "TRUE");
                skipCountingLicenseQuota = true;
            }
        }
        entry.addAttr(A_objectClass, ocs);
        String zimbraIdStr;
        if (uuid == null) {
            zimbraIdStr = LdapUtil.generateUUID();
        } else {
            zimbraIdStr = uuid;
        }
        entry.setAttr(A_zimbraId, zimbraIdStr);
        entry.setAttr(A_zimbraCreateTimestamp, LdapDateUtil.toGeneralizedTime(new Date()));
        // default account status is active
        if (!entry.hasAttribute(Provisioning.A_zimbraAccountStatus)) {
            entry.setAttr(A_zimbraAccountStatus, Provisioning.ACCOUNT_STATUS_ACTIVE);
        }
        Cos cos = null;
        String cosId = entry.getAttrString(Provisioning.A_zimbraCOSId);
        if (cosId != null) {
            cos = lookupCos(cosId, zlc);
            if (!cos.getId().equals(cosId)) {
                cosId = cos.getId();
            }
            entry.setAttr(Provisioning.A_zimbraCOSId, cosId);
        } else {
            String domainCosId = domain != null ? isExternalVirtualAccount(entry) ? d.getDomainDefaultExternalUserCOSId() : d.getDomainDefaultCOSId() : null;
            if (domainCosId != null) {
                cos = get(Key.CosBy.id, domainCosId);
            }
            if (cos == null) {
                cos = getCosByName(isExternalVirtualAccount(entry) ? Provisioning.DEFAULT_EXTERNAL_COS_NAME : Provisioning.DEFAULT_COS_NAME, zlc);
            }
        }
        boolean hasMailTransport = entry.hasAttribute(Provisioning.A_zimbraMailTransport);
        // zimbraMailHost(and zimbraMailTransport) if it is not specified
        if (!hasMailTransport) {
            addMailHost(entry, cos, true);
        }
        // set all the mail-related attrs if zimbraMailHost or zimbraMailTransport was specified
        if (entry.hasAttribute(Provisioning.A_zimbraMailHost) || entry.hasAttribute(Provisioning.A_zimbraMailTransport)) {
            // default mail status is enabled
            if (!entry.hasAttribute(Provisioning.A_zimbraMailStatus)) {
                entry.setAttr(A_zimbraMailStatus, MAIL_STATUS_ENABLED);
            }
            // default account mail delivery address is email address
            if (!entry.hasAttribute(Provisioning.A_zimbraMailDeliveryAddress)) {
                entry.setAttr(A_zimbraMailDeliveryAddress, emailAddress);
            }
        } else {
            throw ServiceException.INVALID_REQUEST("missing " + Provisioning.A_zimbraMailHost + " or " + Provisioning.A_zimbraMailTransport + " for CreateAccount: " + emailAddress, null);
        }
        // amivisAccount requires the mail attr, so we always add it
        entry.setAttr(A_mail, emailAddress);
        // required for ZIMBRA_DEFAULT_PERSON_OC class
        if (!entry.hasAttribute(Provisioning.A_cn)) {
            String displayName = entry.getAttrString(Provisioning.A_displayName);
            if (displayName != null) {
                entry.setAttr(A_cn, displayName);
            } else {
                entry.setAttr(A_cn, localPart);
            }
        }
        // required for ZIMBRA_DEFAULT_PERSON_OC class
        if (!entry.hasAttribute(Provisioning.A_sn)) {
            entry.setAttr(A_sn, localPart);
        }
        entry.setAttr(A_uid, localPart);
        String entryPassword = entry.getAttrString(Provisioning.A_userPassword);
        if (entryPassword != null) {
            //password is a hash i.e. from autoprov; do not set with modify password
            password = null;
        } else if (password != null) {
            //user entered
            checkPasswordStrength(password, null, cos, entry);
        }
        entry.setAttr(Provisioning.A_zimbraPasswordModifiedTime, LdapDateUtil.toGeneralizedTime(new Date()));
        String ucPassword = entry.getAttrString(Provisioning.A_zimbraUCPassword);
        if (ucPassword != null) {
            String encryptedPassword = Account.encrypytUCPassword(entry.getAttrString(Provisioning.A_zimbraId), ucPassword);
            entry.setAttr(Provisioning.A_zimbraUCPassword, encryptedPassword);
        }
        dn = mDIT.accountDNCreate(baseDn, entry.getAttributes(), localPart, domain);
        entry.setDN(dn);
        zlc.createEntry(entry);
        acct = getAccountById(zimbraIdStr, zlc, true);
        if (acct == null) {
            throw ServiceException.FAILURE("unable to get account after creating LDAP account entry: " + emailAddress + ", check ldap log for possible error", null);
        }
        AttributeManager.getInstance().postModify(acctAttrs, acct, callbackContext);
        removeExternalAddrsFromAllDynamicGroups(acct.getAllAddrsSet(), zlc);
        validate(ProvisioningValidator.CREATE_ACCOUNT_SUCCEEDED, emailAddress, acct, skipCountingLicenseQuota);
        if (password != null) {
            setLdapPassword(acct, zlc, password);
        }
        return acct;
    } catch (LdapEntryAlreadyExistException e) {
        throw AccountServiceException.ACCOUNT_EXISTS(emailAddress, dn, e);
    } catch (LdapException e) {
        throw e;
    } catch (AccountServiceException e) {
        throw e;
    } catch (ServiceException e) {
        throw ServiceException.FAILURE("unable to create account: " + emailAddress, e);
    } finally {
        LdapClient.closeContext(zlc);
        if (!restoring && acct != null) {
            for (PostCreateAccountListener listener : ProvisioningExt.getPostCreateAccountListeners()) {
                if (listener.enabled()) {
                    listener.handle(acct);
                }
            }
        }
    }
}
Also used : Account(com.zimbra.cs.account.Account) GuestAccount(com.zimbra.cs.account.GuestAccount) LdapAccount(com.zimbra.cs.account.ldap.entry.LdapAccount) ZMutableEntry(com.zimbra.cs.ldap.ZMutableEntry) LdapEntryAlreadyExistException(com.zimbra.cs.ldap.LdapException.LdapEntryAlreadyExistException) ZLdapContext(com.zimbra.cs.ldap.ZLdapContext) LdapCos(com.zimbra.cs.account.ldap.entry.LdapCos) Cos(com.zimbra.cs.account.Cos) Date(java.util.Date) 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) CallbackContext(com.zimbra.cs.account.callback.CallbackContext) PostCreateAccountListener(com.zimbra.cs.account.ProvisioningExt.PostCreateAccountListener) LdapDomain(com.zimbra.cs.account.ldap.entry.LdapDomain) Domain(com.zimbra.cs.account.Domain) LdapException(com.zimbra.cs.ldap.LdapException)

Aggregations

CallbackContext (com.zimbra.cs.account.callback.CallbackContext)17 LdapEntryAlreadyExistException (com.zimbra.cs.ldap.LdapException.LdapEntryAlreadyExistException)14 ZLdapContext (com.zimbra.cs.ldap.ZLdapContext)14 ZMutableEntry (com.zimbra.cs.ldap.ZMutableEntry)14 AccountServiceException (com.zimbra.cs.account.AccountServiceException)13 LdapException (com.zimbra.cs.ldap.LdapException)13 Date (java.util.Date)13 ServiceException (com.zimbra.common.service.ServiceException)12 AuthFailedServiceException (com.zimbra.cs.account.AccountServiceException.AuthFailedServiceException)12 Domain (com.zimbra.cs.account.Domain)4 LdapDomain (com.zimbra.cs.account.ldap.entry.LdapDomain)4 LdapEntry (com.zimbra.cs.account.ldap.entry.LdapEntry)3 Account (com.zimbra.cs.account.Account)2 Cos (com.zimbra.cs.account.Cos)2 GuestAccount (com.zimbra.cs.account.GuestAccount)2 LdapAccount (com.zimbra.cs.account.ldap.entry.LdapAccount)2 LdapCos (com.zimbra.cs.account.ldap.entry.LdapCos)2 AlwaysOnCluster (com.zimbra.cs.account.AlwaysOnCluster)1 AttributeInfo (com.zimbra.cs.account.AttributeInfo)1 DataSource (com.zimbra.cs.account.DataSource)1