use of com.zimbra.cs.account.ldap.entry.LdapEntry in project zm-mailbox by Zimbra.
the class LdapProvisioning method modifySignature.
@Override
public void modifySignature(Account account, String signatureId, Map<String, Object> signatureAttrs) throws ServiceException {
removeAttrIgnoreCase("objectclass", signatureAttrs);
validateSignatureAttrs(signatureAttrs);
LdapEntry ldapEntry = (LdapEntry) (account instanceof LdapEntry ? account : getAccountById(account.getId()));
if (ldapEntry == null)
throw AccountServiceException.NO_SUCH_ACCOUNT(account.getName());
String newName = (String) signatureAttrs.get(A_zimbraSignatureName);
if (newName != null) {
newName = newName.trim();
// do not allow name to be wiped
if (newName.length() == 0)
throw ServiceException.INVALID_REQUEST("empty signature name is not allowed", null);
// check for duplicate names
List<Signature> sigs = getAllSignatures(account);
for (Signature sig : sigs) {
if (sig.getName().equalsIgnoreCase(newName) && !sig.getId().equals(signatureId))
throw AccountServiceException.SIGNATURE_EXISTS(newName);
}
}
// clear cache
account.setCachedData(SIGNATURE_LIST_CACHE_KEY, null);
if (LdapSignature.isAccountSignature(account, signatureId)) {
LdapSignature.modifyAccountSignature(this, account, signatureAttrs);
} else {
LdapSignature signature = (LdapSignature) getSignatureById(account, ldapEntry, signatureId, null);
if (signature == null)
throw AccountServiceException.NO_SUCH_SIGNATURE(signatureId);
boolean nameChanged = (newName != null && !newName.equals(signature.getName()));
if (nameChanged)
signatureAttrs.remove(A_zimbraSignatureName);
modifyAttrs(signature, signatureAttrs, true);
if (nameChanged) {
// the signature cache could've been loaded again if getAllSignatures
// were called in pre/poseModify callback, so we clear it again
account.setCachedData(SIGNATURE_LIST_CACHE_KEY, null);
renameSignature(ldapEntry, signature, newName);
}
}
}
use of com.zimbra.cs.account.ldap.entry.LdapEntry in project zm-mailbox by Zimbra.
the class LdapProvisioning method getAllSignatures.
@Override
public List<Signature> getAllSignatures(Account account) throws ServiceException {
LdapEntry ldapEntry = (LdapEntry) (account instanceof LdapEntry ? account : getAccountById(account.getId()));
if (ldapEntry == null)
throw AccountServiceException.NO_SUCH_ACCOUNT(account.getName());
@SuppressWarnings("unchecked") List<Signature> result = (List<Signature>) account.getCachedData(SIGNATURE_LIST_CACHE_KEY);
if (result != null) {
return result;
}
result = new ArrayList<Signature>();
Signature acctSig = LdapSignature.getAccountSignature(this, account);
if (acctSig != null)
result.add(acctSig);
result = getSignaturesByQuery(account, ldapEntry, filterFactory.allSignatures(), null, result);
result = Collections.unmodifiableList(result);
account.setCachedData(SIGNATURE_LIST_CACHE_KEY, result);
return result;
}
use of com.zimbra.cs.account.ldap.entry.LdapEntry in project zm-mailbox by Zimbra.
the class LdapProvisioning method addAliasInternal.
private void addAliasInternal(NamedEntry entry, String alias) throws ServiceException {
LdapUsage ldapUsage = null;
String targetDomainName = null;
AliasedEntry aliasedEntry = null;
if (entry instanceof Account) {
aliasedEntry = (AliasedEntry) entry;
targetDomainName = ((Account) entry).getDomainName();
ldapUsage = LdapUsage.ADD_ALIAS_ACCOUNT;
} else if (entry instanceof Group) {
aliasedEntry = (AliasedEntry) entry;
ldapUsage = LdapUsage.ADD_ALIAS_DL;
targetDomainName = ((Group) entry).getDomainName();
} else {
throw ServiceException.FAILURE("invalid entry type for alias", null);
}
alias = alias.toLowerCase().trim();
alias = IDNUtil.toAsciiEmail(alias);
validEmailAddress(alias);
String[] parts = alias.split("@");
String aliasName = parts[0];
String aliasDomain = parts[1];
ZLdapContext zlc = null;
String aliasDn = null;
try {
zlc = LdapClient.getContext(LdapServerType.MASTER, ldapUsage);
Domain domain = getDomainByAsciiName(aliasDomain, zlc);
if (domain == null)
throw AccountServiceException.NO_SUCH_DOMAIN(aliasDomain);
aliasDn = mDIT.aliasDN(((LdapEntry) entry).getDN(), targetDomainName, aliasName, aliasDomain);
// the create and addAttr ideally would be in the same transaction
String aliasUuid = LdapUtil.generateUUID();
String targetEntryId = entry.getId();
try {
zlc.createEntry(aliasDn, "zimbraAlias", new String[] { Provisioning.A_uid, aliasName, Provisioning.A_zimbraId, aliasUuid, Provisioning.A_zimbraCreateTimestamp, LdapDateUtil.toGeneralizedTime(new Date()), Provisioning.A_zimbraAliasTargetId, targetEntryId });
} catch (LdapEntryAlreadyExistException e) {
/*
* check if the alias is a dangling alias. If so remove the dangling alias
* and create a new one.
*/
ZAttributes attrs = helper.getAttributes(zlc, aliasDn);
// see if the entry is an alias
if (!isEntryAlias(attrs))
throw e;
Alias aliasEntry = makeAlias(aliasDn, attrs);
NamedEntry targetEntry = searchAliasTarget(aliasEntry, false);
if (targetEntry == null) {
// remove the dangling alias
try {
removeAliasInternal(null, alias);
} catch (ServiceException se) {
// ignore
}
// try creating the alias again
zlc.createEntry(aliasDn, "zimbraAlias", new String[] { Provisioning.A_uid, aliasName, Provisioning.A_zimbraId, aliasUuid, Provisioning.A_zimbraCreateTimestamp, LdapDateUtil.toGeneralizedTime(new Date()), Provisioning.A_zimbraAliasTargetId, targetEntryId });
} else if (targetEntryId.equals(targetEntry.getId())) {
// the alias target points to this account/DL
Set<String> mailAliases = entry.getMultiAttrSet(Provisioning.A_zimbraMailAlias);
Set<String> mails = entry.getMultiAttrSet(Provisioning.A_mail);
if (mailAliases != null && mailAliases.contains(alias) && mails != null && mails.contains(alias)) {
throw e;
} else {
ZimbraLog.account.warn("alias entry exists at " + aliasDn + ", but either mail or zimbraMailAlias of the target does not contain " + alias + ", adding " + alias + " to entry " + entry.getName());
}
} else {
// for which the alias is being added for, rethrow the naming exception
throw e;
}
}
HashMap<String, String> attrs = new HashMap<String, String>();
attrs.put("+" + Provisioning.A_zimbraMailAlias, alias);
attrs.put("+" + Provisioning.A_mail, alias);
// UGH
modifyAttrsInternal(entry, zlc, attrs);
removeExternalAddrsFromAllDynamicGroups(aliasedEntry.getAllAddrsSet(), zlc);
} catch (LdapEntryAlreadyExistException nabe) {
throw AccountServiceException.ACCOUNT_EXISTS(alias, aliasDn, nabe);
} catch (LdapException e) {
throw e;
} catch (AccountServiceException e) {
throw e;
} catch (ServiceException e) {
throw ServiceException.FAILURE("unable to create alias: " + e.getMessage(), e);
} finally {
LdapClient.closeContext(zlc);
}
}
use of com.zimbra.cs.account.ldap.entry.LdapEntry in project zm-mailbox by Zimbra.
the class LdapProvisioning method createSignature.
private Signature createSignature(Account account, String signatureName, Map<String, Object> signatureAttrs, boolean restoring) throws ServiceException {
signatureName = signatureName.trim();
removeAttrIgnoreCase("objectclass", signatureAttrs);
validateSignatureAttrs(signatureAttrs);
LdapEntry ldapEntry = (LdapEntry) (account instanceof LdapEntry ? account : getAccountById(account.getId()));
if (ldapEntry == null)
throw AccountServiceException.NO_SUCH_ACCOUNT(account.getName());
/*
* check if the signature name already exists
*
* We check if the signatureName is the same as the signature on the account.
* For signatures that are in the signature LDAP entries, JNDI will throw
* NameAlreadyBoundException for duplicate names.
*
*/
Signature acctSig = LdapSignature.getAccountSignature(this, account);
if (acctSig != null && signatureName.equalsIgnoreCase(acctSig.getName()))
throw AccountServiceException.SIGNATURE_EXISTS(signatureName);
boolean setAsDefault = false;
List<Signature> existing = getAllSignatures(account);
// If the signature id is supplied with the request, check that it
// is not associated with an existing signature
String signatureId = (String) signatureAttrs.get(Provisioning.A_zimbraSignatureId);
if (signatureId != null) {
for (Signature signature : existing) {
if (signatureId.equals(signature.getAttr(Provisioning.A_zimbraSignatureId))) {
throw AccountServiceException.SIGNATURE_EXISTS(signatureId);
}
}
}
int numSigs = existing.size();
if (numSigs >= account.getLongAttr(A_zimbraSignatureMaxNumEntries, 20))
throw AccountServiceException.TOO_MANY_SIGNATURES();
else if (numSigs == 0)
setAsDefault = true;
account.setCachedData(SIGNATURE_LIST_CACHE_KEY, null);
boolean checkImmutable = !restoring;
CallbackContext callbackContext = new CallbackContext(CallbackContext.Op.CREATE);
callbackContext.setData(DataKey.MAX_SIGNATURE_LEN, String.valueOf(account.getMailSignatureMaxLength()));
AttributeManager.getInstance().preModify(signatureAttrs, null, callbackContext, checkImmutable);
if (signatureId == null) {
signatureId = LdapUtil.generateUUID();
signatureAttrs.put(Provisioning.A_zimbraSignatureId, signatureId);
}
if (acctSig == null) {
// the slot on the account is not occupied, use it
signatureAttrs.put(Provisioning.A_zimbraSignatureName, signatureName);
// pass in setAsDefault as an optimization, since we are updating the account
// entry, we can update the default attr in one LDAP write
LdapSignature.createAccountSignature(this, account, signatureAttrs, setAsDefault);
return LdapSignature.getAccountSignature(this, account);
}
ZLdapContext zlc = null;
try {
zlc = LdapClient.getContext(LdapServerType.MASTER, LdapUsage.CREATE_SIGNATURE);
String dn = getSignatureDn(ldapEntry, signatureName);
ZMutableEntry entry = LdapClient.createMutableEntry();
entry.mapToAttrs(signatureAttrs);
entry.setAttr(A_objectClass, "zimbraSignature");
entry.setAttr(Provisioning.A_zimbraCreateTimestamp, LdapDateUtil.toGeneralizedTime(new Date()));
entry.setDN(dn);
zlc.createEntry(entry);
Signature signature = getSignatureById(account, ldapEntry, signatureId, zlc);
AttributeManager.getInstance().postModify(signatureAttrs, signature, callbackContext);
if (setAsDefault)
setDefaultSignature(account, signatureId);
return signature;
} catch (LdapEntryAlreadyExistException nabe) {
throw AccountServiceException.SIGNATURE_EXISTS(signatureName);
} catch (LdapException e) {
throw e;
} catch (AccountServiceException e) {
throw e;
} catch (ServiceException e) {
throw ServiceException.FAILURE("unable to create signature: " + signatureName, e);
} finally {
LdapClient.closeContext(zlc);
}
}
use of com.zimbra.cs.account.ldap.entry.LdapEntry in project zm-mailbox by Zimbra.
the class TestProvAlias method testRemoveAlias_entryExist_aliasExist_aliasPointToOtherEntry.
//
// A - alias points to other existing entry
//
@Test
public void testRemoveAlias_entryExist_aliasExist_aliasPointToOtherEntry() throws Exception {
String testName = getTestName();
// create the domain
String domainName = "EE-AE-aliasPointToOtherEntry" + "." + BASE_DOMAIN_NAME;
domainName = domainName.toLowerCase();
Map<String, Object> attrs = new HashMap<String, Object>();
attrs.put(Provisioning.A_zimbraDomainType, Provisioning.DomainType.local.name());
Domain domain = prov.createDomain(domainName, attrs);
// create the account the alias points to
String acctName = getEmail("acct-1", domainName);
Account acct = prov.createAccount(acctName, PASSWORD, new HashMap<String, Object>());
// add an alias to the account
String aliasName = getEmail("alias-1", domainName);
prov.addAlias(acct, aliasName);
// create 2 DLs
String dl1Name = getEmail("dl-1", domainName);
DistributionList dl1 = prov.createDistributionList(dl1Name, new HashMap<String, Object>());
String dl2Name = getEmail("dl-2", domainName);
DistributionList dl2 = prov.createDistributionList(dl2Name, new HashMap<String, Object>());
// add the alias to the two DLs
prov.addMembers(dl1, new String[] { aliasName });
prov.addMembers(dl2, new String[] { aliasName });
// create another account
String otherAcctName = getEmail("acct-other", domainName);
Account otherAcct = prov.createAccount(otherAcctName, PASSWORD, new HashMap<String, Object>());
// and hack the other account to also contain the alias in it's mail/zimbraMailAlias attrs
// the hacked attrs should be removed after the removeAlais call
{
Map<String, Object> attributes = new HashMap<String, Object>();
// can no long do this, we now have an unique constraint on mail
// attributes.put(Provisioning.A_mail, aliasName);
attributes.put(Provisioning.A_zimbraMailAlias, aliasName);
LdapEntry ldapAccount = (LdapEntry) otherAcct;
((LdapProv) prov).getHelper().modifyEntry(ldapAccount.getDN(), attributes, (Entry) ldapAccount, LdapUsage.UNITTEST);
// make sure the attrs did get hacked in
prov.reload(otherAcct);
Set<String> values;
// values = otherAcct.getMultiAttrSet(Provisioning.A_mail);
// assertTrue(values.contains(aliasName));
values = otherAcct.getMultiAttrSet(Provisioning.A_zimbraMailAlias);
assertTrue(values.contains(aliasName));
}
// remove the alias, on the "other" account, which is *not* the target for the alias we are removing
// ensure we *do* get a NO_SUCH_ALIAS exception
boolean good = false;
try {
prov.removeAlias(otherAcct, aliasName);
} catch (ServiceException e) {
assertEquals(e.getCode(), (AccountServiceException.NO_SUCH_ALIAS));
good = true;
}
assertTrue(good);
// reload all entries
prov.reload(acct);
prov.reload(otherAcct);
prov.reload(dl1);
prov.reload(dl2);
Set<String> values;
// ensure the alias is still on the account
values = acct.getMultiAttrSet(Provisioning.A_mail);
assertTrue(values.contains(aliasName));
values = acct.getMultiAttrSet(Provisioning.A_zimbraMailAlias);
assertTrue(values.contains(aliasName));
// ensure the hacked in attrs are removed from the other account
values = otherAcct.getMultiAttrSet(Provisioning.A_mail);
assertFalse(values.contains(aliasName));
values = otherAcct.getMultiAttrSet(Provisioning.A_zimbraMailAlias);
assertFalse(values.contains(aliasName));
// ensure the alias is *not* removed from any the DLs
values = dl1.getMultiAttrSet(Provisioning.A_zimbraMailForwardingAddress);
assertTrue(values.contains(aliasName));
values = dl2.getMultiAttrSet(Provisioning.A_zimbraMailForwardingAddress);
assertTrue(values.contains(aliasName));
// ensure the alias entry is *not* removed
List<NamedEntry> aliases = searchAliasesInDomain(domain);
assertEquals(aliases.size(), 1);
assertTrue(aliases.get(0).getName().equals(aliasName));
}
Aggregations