use of com.zimbra.cs.account.Cos in project zm-mailbox by Zimbra.
the class LdapProvisioning method removeServerFromAllCOSes.
private void removeServerFromAllCOSes(String serverId, String serverName, ZLdapContext initZlc) {
List<Cos> coses = null;
try {
coses = searchCOS(filterFactory.cosesByMailHostPool(serverId), initZlc);
for (Cos cos : coses) {
Map<String, String> attrs = new HashMap<String, String>();
attrs.put("-" + Provisioning.A_zimbraMailHostPool, serverId);
ZimbraLog.account.info("Removing " + Provisioning.A_zimbraMailHostPool + " " + serverId + "(" + serverName + ") from cos " + cos.getName());
modifyAttrs(cos, attrs);
// invalidate cached cos
cosCache.remove((LdapCos) cos);
}
} catch (ServiceException se) {
ZimbraLog.account.warn("unable to remove " + serverId + " from all COSes ", se);
return;
}
}
use of com.zimbra.cs.account.Cos in project zm-mailbox by Zimbra.
the class LdapProvisioning method searchCOS.
private List<Cos> searchCOS(ZLdapFilter filter, ZLdapContext initZlc) throws ServiceException {
List<Cos> result = new ArrayList<Cos>();
try {
ZSearchResultEnumeration ne = helper.searchDir(mDIT.cosBaseDN(), filter, ZSearchControls.SEARCH_CTLS_SUBTREE(), initZlc, LdapServerType.REPLICA);
while (ne.hasMore()) {
ZSearchResultEntry sr = ne.next();
result.add(new LdapCos(sr.getDN(), sr.getAttributes(), this));
}
ne.close();
} catch (ServiceException e) {
throw ServiceException.FAILURE("unable to lookup cos via query: " + filter.toFilterString() + " message: " + e.getMessage(), e);
}
return result;
}
use of com.zimbra.cs.account.Cos in project zm-mailbox by Zimbra.
the class LdapProvisioning method refreshEntry.
void refreshEntry(Entry entry, ZLdapContext initZlc) throws ServiceException {
try {
String dn = ((LdapEntry) entry).getDN();
ZAttributes attributes = helper.getAttributes(initZlc, dn);
Map<String, Object> attrs = attributes.getAttrs();
Map<String, Object> defaults = null;
Map<String, Object> secondaryDefaults = null;
Map<String, Object> overrideDefaults = null;
if (entry instanceof Account) {
//
// We can get here from either modifyAttrsInternal or reload path.
//
// If we got here from modifyAttrsInternal, zimbraCOSId on account
// might have been changed, added, removed, but entry now still contains
// the old attrs. Create a temp Account object from the new attrs, and then
// use the same cos of the temp Account object for our entry object.
//
// If we got here from reload, attrs are likely not changed, the callsites
// just want a refreshed object. For this case it's best if we still
// always resolve the COS correctly. makeAccount is a cheap call and won't
// add any overhead like loading cos/domain from LDAP: even if cos/domain
// has to be loaded (because not in cache) in the getCOS(temp) call, it's
// just the same as calling (buggy) getCOS(entry) before.
//
// We only need the temp object for the getCOS call, don't need to setup
// primary/secondary defaults on the temp object because:
// zimbraCOSId is only on account(of course), and that's all needed
// for determining the COS for the account in the getCOS call: if
// zimbraCOSId is not set on account, it will fallback to the domain
// default COS, then fallback to the system default COS.
//
Account temp = makeAccountNoDefaults(dn, attributes);
Cos cos = getCOS(temp);
if (cos != null)
defaults = cos.getAccountDefaults();
Domain domain = getDomain((Account) entry);
if (domain != null)
secondaryDefaults = domain.getAccountDefaults();
} else if (entry instanceof Domain) {
defaults = getConfig().getDomainDefaults();
} else if (entry instanceof Server) {
defaults = getConfig().getServerDefaults();
AlwaysOnCluster aoc = getAlwaysOnCluster((Server) entry);
if (aoc != null) {
overrideDefaults = aoc.getServerOverrides();
}
}
if (defaults == null && secondaryDefaults == null)
entry.setAttrs(attrs);
else
entry.setAttrs(attrs, defaults, secondaryDefaults, overrideDefaults);
extendLifeInCacheOrFlush(entry);
} catch (ServiceException e) {
throw ServiceException.FAILURE("unable to refresh entry", e);
}
}
use of com.zimbra.cs.account.Cos in project zm-mailbox by Zimbra.
the class LdapProvisioning method flushCache.
@Override
public void flushCache(CacheEntryType type, CacheEntry[] entries) throws ServiceException {
switch(type) {
case all:
if (entries != null) {
throw ServiceException.INVALID_REQUEST("cannot specify entry for flushing all", null);
}
ZimbraLog.account.info("Flushing all LDAP entry caches");
flushCache(CacheEntryType.account, null);
flushCache(CacheEntryType.group, null);
flushCache(CacheEntryType.config, null);
flushCache(CacheEntryType.globalgrant, null);
flushCache(CacheEntryType.cos, null);
flushCache(CacheEntryType.domain, null);
flushCache(CacheEntryType.mime, null);
flushCache(CacheEntryType.server, null);
flushCache(CacheEntryType.alwaysOnCluster, null);
flushCache(CacheEntryType.zimlet, null);
break;
case account:
if (entries != null) {
for (CacheEntry entry : entries) {
AccountBy accountBy = (entry.mEntryBy == Key.CacheEntryBy.id) ? AccountBy.id : AccountBy.name;
Account account = getFromCache(accountBy, entry.mEntryIdentity);
/*
* We now call removeFromCache instead of reload for flushing an account
* from cache. This change was originally for bug 25028, but that would still
* need an extrat step to flush cache after the account's zimbraCOSId changed.
* (if we call reload insteasd of removeFromCache, flush cache of the account would
* not clear the mDefaults for inherited attrs, that was the bug.)
* Bug 25028 is now taken care of by the callback. We still call removeFromCache
* for flushing account cache, because that does a cleaner flush.
*
* Note, we only call removeFromCache for account.
* We should *NOT* do removeFromCache when flushing global config and cos caches.
*
* Because the "mDefaults" Map(contains a ref to the old instance of COS.mAccountDefaults for
* all the accountInherited COS attrs) stored in all the cached accounts. Same for the
* inherited attrs of server/domain from global config. If we do removeFromCache for flushing
* cos/global config, then after FlushCache(cos) if you do a ga on a cached account, it still
* shows the old COS value for values that are inherited from COS. Although, for newly loaded
* accounts or when a cached account is going thru auth(that'll trigger a reload) they will get
* the new COS values(refreshed as a result of FlushCache(cos)).
*/
if (account != null) {
removeFromCache(account);
}
}
} else {
accountCache.clear();
}
return;
case group:
if (entries != null) {
for (CacheEntry entry : entries) {
Key.DistributionListBy dlBy = (entry.mEntryBy == Key.CacheEntryBy.id) ? Key.DistributionListBy.id : Key.DistributionListBy.name;
removeGroupFromCache(dlBy, entry.mEntryIdentity);
}
} else {
allDLs.clear();
groupCache.clear();
}
return;
case config:
if (entries != null) {
throw ServiceException.INVALID_REQUEST("cannot specify entry for flushing global config", null);
}
Config config = getConfig();
reload(config, false);
EphemeralStore.clearFactory();
return;
case globalgrant:
if (entries != null) {
throw ServiceException.INVALID_REQUEST("cannot specify entry for flushing global grant", null);
}
GlobalGrant globalGrant = getGlobalGrant();
reload(globalGrant, false);
return;
case cos:
if (entries != null) {
for (CacheEntry entry : entries) {
Key.CosBy cosBy = (entry.mEntryBy == Key.CacheEntryBy.id) ? Key.CosBy.id : Key.CosBy.name;
Cos cos = getFromCache(cosBy, entry.mEntryIdentity);
if (cos != null)
reload(cos, false);
}
} else
cosCache.clear();
return;
case domain:
if (entries != null) {
for (CacheEntry entry : entries) {
Key.DomainBy domainBy = (entry.mEntryBy == Key.CacheEntryBy.id) ? Key.DomainBy.id : Key.DomainBy.name;
Domain domain = getFromCache(domainBy, entry.mEntryIdentity, GetFromDomainCacheOption.BOTH);
if (domain != null) {
if (domain instanceof DomainCache.NonExistingDomain)
domainCache.removeFromNegativeCache(domainBy, entry.mEntryIdentity);
else
reload(domain, false);
}
}
} else
domainCache.clear();
return;
case mime:
mimeTypeCache.flushCache(this);
return;
case server:
if (entries != null) {
for (CacheEntry entry : entries) {
Key.ServerBy serverBy = (entry.mEntryBy == Key.CacheEntryBy.id) ? Key.ServerBy.id : Key.ServerBy.name;
Server server = get(serverBy, entry.mEntryIdentity);
if (server != null)
reload(server, false);
}
} else
serverCache.clear();
return;
case alwaysOnCluster:
if (entries != null) {
for (CacheEntry entry : entries) {
Key.AlwaysOnClusterBy clusterBy = Key.AlwaysOnClusterBy.id;
AlwaysOnCluster cluster = get(clusterBy, entry.mEntryIdentity);
if (cluster != null)
reload(cluster, false);
}
} else
alwaysOnClusterCache.clear();
return;
case zimlet:
if (entries != null) {
for (CacheEntry entry : entries) {
Key.ZimletBy zimletBy = (entry.mEntryBy == Key.CacheEntryBy.id) ? Key.ZimletBy.id : Key.ZimletBy.name;
Zimlet zimlet = getFromCache(zimletBy, entry.mEntryIdentity);
if (zimlet != null)
reload(zimlet, false);
}
} else
zimletCache.clear();
return;
default:
throw ServiceException.INVALID_REQUEST("invalid cache type " + type, null);
}
}
use of com.zimbra.cs.account.Cos 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);
}
}
}
}
}
Aggregations