Skip to content

Commit

Permalink
ZCS-15079 POC | Hide alias in GAL
Browse files Browse the repository at this point in the history
  • Loading branch information
rendurama committed Jul 8, 2024
1 parent 689bb72 commit f669f07
Show file tree
Hide file tree
Showing 8 changed files with 120 additions and 37 deletions.
14 changes: 11 additions & 3 deletions common/src/java/com/zimbra/common/account/ZAttrProvisioning.java
Original file line number Diff line number Diff line change
Expand Up @@ -7508,9 +7508,9 @@ public static TwoFactorAuthSecretEncoding fromString(String s) throws ServiceExc
public static final String A_zimbraFeatureSearchHistoryEnabled = "zimbraFeatureSearchHistoryEnabled";

/**
* Feature to enable/disable the mobile sync for shared folders. Default
* value is TRUE. The option to sync the shared folders to the Mobile
* will be enabled for the users in the webclient. The option will only
* Feature to enable/disable the mobile sync for shared folders. Default
* value is TRUE. The option to sync the shared folders to the Mobile
* will be enabled for the users in the webclient. The option will only
* be enabled for shared folders having Admin or Manager permission
*
* @since ZCS 10.1.0
Expand Down Expand Up @@ -8586,6 +8586,14 @@ public static TwoFactorAuthSecretEncoding fromString(String s) throws ServiceExc
@ZAttr(id=4116)
public static final String A_zimbraHideAliasesInGal = "zimbraHideAliasesInGal";

/**
* Option to hide/show alias in GAL
*
* @since ZCS 10.1.1
*/
@ZAttr(id=4135)
public static final String A_zimbraHideAliasInGal = "zimbraHideAliasInGal";

/**
* hide entry in Global Address List
*/
Expand Down
4 changes: 4 additions & 0 deletions common/src/java/com/zimbra/common/util/Constants.java
Original file line number Diff line number Diff line change
Expand Up @@ -50,4 +50,8 @@ public class Constants {
public static final String BEARER= "Bearer";
public static final String JWT_SALT_SEPARATOR = "|";

public static final String PRIMARY_EMAIL = "email";

public static final String TRUE_VALUE = "TRUE";

}
7 changes: 4 additions & 3 deletions store/conf/attrs/zimbra-attrs.xml
Original file line number Diff line number Diff line change
Expand Up @@ -10474,7 +10474,7 @@ TODO: delete them permanently from here
<desc>Define body: field for 2FA email in html format</desc>
</attr>

<attr id="4116" name="zimbraHideAliasesInGal" type="boolean" cardinality="single" optionalIn="account" flags="accountInfo" since="10.1.0">
<attr id="4116" name="zimbraHideAliasesInGal" type="boolean" cardinality="single" optionalIn="account,cos,domain" flags="accountInfo" since="10.1.0">
<desc>When set to True, all aliases will be hidden for particular account</desc>
</attr>

Expand Down Expand Up @@ -10556,7 +10556,8 @@ TODO: delete them permanently from here
<desc>Feature to enable/disable the mobile sync for shared folders. Default value is TRUE. The option to sync the shared folders to the Mobile will be enabled for the users in the webclient. The option will only be enabled for shared folders having Admin or Manager permission</desc>
</attr>

<attr id="4135" name="zimbraHideAliasInGal" type="boolean" cardinality="single" requiredIn="alias" since="10.1.1">
<desc>Option to hide/show alias in GAL</desc>
<attr id="4135" name="zimbraHideAliasInGal" type="boolean" cardinality="single" requiredIn="alias" since="10.1.1">
<desc> Option to hide/show alias in GAL</desc>

</attr>
</attrs>
Original file line number Diff line number Diff line change
Expand Up @@ -970,4 +970,9 @@ public void resetPassword(Account acct, String newPassword, boolean dryRun) thro
public String sendMdmEmail(String status, String timeInterval) throws ServiceException {
return null;
}

@Override
public void excludePrivateAliases(NamedEntry entry, List<String> email) throws ServiceException {
//Not yet implemenmted
}
}
4 changes: 3 additions & 1 deletion store/src/java/com/zimbra/cs/account/Provisioning.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@
import com.zimbra.common.service.ServiceException;
import com.zimbra.common.util.ExceptionToString;
import com.zimbra.common.util.L10nUtil;
import com.zimbra.common.util.Pair;
import com.zimbra.common.util.StringUtil;
import com.zimbra.common.util.ZimbraLog;
import com.zimbra.cs.account.accesscontrol.Right;
Expand Down Expand Up @@ -2795,4 +2794,7 @@ public String createAddressList(Domain domain, String name, String desc, Map<Str
}

public abstract String sendMdmEmail(String status, String timeInterval) throws ServiceException;

public abstract void excludePrivateAliases(NamedEntry entry, List<String> email) throws ServiceException;

}
29 changes: 29 additions & 0 deletions store/src/java/com/zimbra/cs/account/ldap/LdapProvisioning.java
Original file line number Diff line number Diff line change
Expand Up @@ -2497,6 +2497,7 @@ private void addAliasInternal(NamedEntry entry, String alias) throws ServiceExce
zlc.createEntry(aliasDn, "zimbraAlias",
new String[] { Provisioning.A_uid, aliasName,
Provisioning.A_zimbraId, aliasUuid,
Provisioning.A_zimbraHideAliasInGal, String.valueOf(new Random().nextBoolean()).toUpperCase(),// to be modified
Provisioning.A_zimbraCreateTimestamp, LdapDateUtil.toGeneralizedTime(new Date()),
Provisioning.A_zimbraAliasTargetId, targetEntryId} );
} catch (LdapEntryAlreadyExistException e) {
Expand Down Expand Up @@ -11726,4 +11727,32 @@ public void modifyAddressList(AddressList addressList, String name, Map<String,
public String sendMdmEmail(String status, String timeInterval) throws ServiceException {
return L10nUtil.getMessage(L10nUtil.MsgKey.sendMDMNotificationEmailFailure);
}


@Override
public void excludePrivateAliases(NamedEntry entry, List<String> emailAndAliases) throws ServiceException {
LdapUsage ldapUsage = LdapUsage.GAL_SEARCH;
ZLdapContext zlc = LdapClient.getContext(LdapServerType.MASTER, ldapUsage);
for (String alias : new ArrayList<>(
emailAndAliases.subList(1, emailAndAliases.size()))) { // exclude primay email here
if (null != alias) {
String parts[] = alias.split("@");
String aliasName = parts[0];
String aliasDomain = parts[1];
String targetDomainName = ((Account) entry).getDomainName();
String aliasDn = mDIT.aliasDN(((LdapEntry) entry).getDN(), targetDomainName, aliasName, aliasDomain);
ZimbraLog.mailbox.info(
"excludePrivateAliases alias - %s , aliasname - %s ,aliasDomain %s ,Target Domain - %s , aliasDn -%s ",
alias, aliasName, aliasDomain, targetDomainName, aliasDn);
ZAttributes attrs = helper.getAttributes(zlc, aliasDn);
Alias aliasEntry = makeAlias(aliasDn, attrs);
if (Constants.TRUE_VALUE.equalsIgnoreCase(aliasEntry.getAttr(Provisioning.A_zimbraHideAliasInGal))) {
emailAndAliases.remove(alias);
}
ZimbraLog.mailbox.info("alias attribute for %s is %s", alias,
aliasEntry.getAttr(Provisioning.A_zimbraHideAliasInGal));
}
}
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -3312,4 +3312,9 @@ public String sendMdmEmail(String status, String timeInterval) throws ServiceExc

return L10nUtil.getMessage(L10nUtil.MsgKey.sendMDMNotificationEmailSuccess);
}

@Override
public void excludePrivateAliases(NamedEntry entry, List<String> email) throws ServiceException {
//not yet implemented
}
}
89 changes: 59 additions & 30 deletions store/src/java/com/zimbra/cs/mailbox/ContactAutoComplete.java
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,11 @@
import com.zimbra.common.soap.Element;
import com.zimbra.common.soap.MailConstants;
import com.zimbra.common.soap.SoapProtocol;
import com.zimbra.common.util.Constants;
import com.zimbra.common.util.Pair;
import com.zimbra.common.util.StringUtil;
import com.zimbra.common.util.ZimbraLog;
import com.zimbra.cs.account.Account;
import com.zimbra.cs.account.GalContact;
import com.zimbra.cs.account.Provisioning;
import com.zimbra.cs.account.*;
import com.zimbra.cs.gal.GalGroup;
import com.zimbra.cs.gal.GalGroupInfoProvider;
import com.zimbra.cs.gal.GalSearchControl;
Expand Down Expand Up @@ -397,17 +396,17 @@ public void setSearchType(GalSearchType type) {
}

public AutoCompleteResult resolveEmailAddr(String str) throws ServiceException {
AutoCompleteResult result = new AutoCompleteResult(1);
result.rankings = new ContactRankings(getRequestedAcctId());
for (String addr : mRequestedAcct.getAllAddrsSet()) {
if (addr.equals(str)) {
ContactEntry entry = new ContactEntry();
entry.mEmail = addr;
result.addEntry(entry);
break;
}
}
return result;
AutoCompleteResult result = new AutoCompleteResult(1);
result.rankings = new ContactRankings(getRequestedAcctId());
for (String addr : mRequestedAcct.getAllAddrsSet()) {
if (addr.equals(str)) {
ContactEntry entry = new ContactEntry();
entry.mEmail = addr;
result.addEntry(entry);
break;
}
}
return result;
}
public AutoCompleteResult query(String str, Collection<Integer> folders, int limit) throws ServiceException {
ZimbraLog.gal.debug("AutoComplete querying: %s", str);
Expand Down Expand Up @@ -470,7 +469,7 @@ private void resolveGroupInfo(ContactEntry entry, String email) {
}

private void queryGal(String str, AutoCompleteResult result) {
ZimbraLog.gal.debug("querying gal");
ZimbraLog.gal.info("querying gal");
GalSearchParams params = new GalSearchParams(mRequestedAcct, mZsc);
params.setQuery(str);
params.setType(mSearchType);
Expand Down Expand Up @@ -504,7 +503,7 @@ public AutoCompleteCallback(String str, AutoCompleteResult result, GalSearchPara
this.str = str;
}

public void handleContactAttrs(Map<String, ? extends Object> attrs) {
public void handleContactAttrs(Map<String, ? extends Object> attrs) throws ServiceException {
addMatchedContacts(str, attrs, FOLDER_ID_GAL, null, result);
}

Expand Down Expand Up @@ -600,8 +599,7 @@ private boolean matchesName(List<String> tokens, Map<String, ? extends Object> a
String fullName = getFieldAsString(attrs, ContactConstants.A_fullName);
if (!Strings.isNullOrEmpty(fullName)) {
for (String fullNameToken : TOKEN_SPLITTER.split(fullName)) {
if (!Strings.isNullOrEmpty(fullNameToken) &&
fullNameToken.toLowerCase().startsWith(token)) {
if (!Strings.isNullOrEmpty(fullNameToken) && fullNameToken.toLowerCase().startsWith(token)) {
return true;
}
}
Expand Down Expand Up @@ -634,8 +632,8 @@ private boolean matchesName(List<String> tokens, Map<String, ? extends Object> a
if (pattern.matcher(Joiner.on(' ').skipNulls().join(lastName, firstName, middleName)).matches()) {
return true;
}


String fullName = getFieldAsString(attrs, ContactConstants.A_fullName);
if (!Strings.isNullOrEmpty(fullName) && pattern.matcher(fullName).matches()) {
return true;
Expand Down Expand Up @@ -669,7 +667,7 @@ private Pattern toPattern(List<String> tokens) {
}

public void addMatchedContacts(String query, Map<String, ? extends Object> attrs, int folderId, ItemId id,
AutoCompleteResult result) {
AutoCompleteResult result) throws ServiceException {
if (!result.canBeCached) {
return;
}
Expand All @@ -680,10 +678,10 @@ public void addMatchedContacts(String query, Map<String, ? extends Object> attrs
}

if (!Contact.isGroup(attrs) || folderId == FOLDER_ID_GAL) {
//
//
// either a GAL entry or a non-contact-group contact entry
//

boolean nameMatches = matchesName(tokens, attrs);

// matching algorithm is slightly different between matching
Expand All @@ -708,21 +706,22 @@ public void addMatchedContacts(String query, Map<String, ? extends Object> attrs
displayName = Joiner.on(' ').skipNulls().join(first, middle, last);
}

for (String emailKey : mEmailKeys) {
String email = getFieldAsString(attrs, emailKey);
List<String> allowedEmailsListInGalAutocomplete = extractAllowedEmailsListForAccount(attrs, fullName);

for (String email : allowedEmailsListInGalAutocomplete) {
if (email != null && (nameMatches || matchesEmail(tokens, email))) {
ContactEntry entry = new ContactEntry();
entry.mEmail = email;
entry.setName(displayName);
entry.mId = id;
entry.mFolderId = folderId;
entry.mFirstName = first;
entry.mFirstName = first;
entry.mMiddleName = middle;
entry.mLastName = last;
entry.mFullName = fullName;
entry.mNickname = nick;
entry.mCompany = company;
entry.mFileAs = fileas;
entry.mCompany = company;
entry.mFileAs = fileas;
if (Contact.isGroup(attrs)) {
entry.setIsGalGroup(email, attrs, mAuthedAcct, mNeedCanExpand);
} else if (entry.mFolderId != FOLDER_ID_GAL) {
Expand All @@ -734,10 +733,11 @@ public void addMatchedContacts(String query, Map<String, ? extends Object> attrs
if (returnFullContactData) {
entry.mAttrs = attrs;
}

addEntry(entry, result);
ZimbraLog.gal.debug("adding %s", entry.getEmail());
/*
Previously stopped at first matching email address for GAL contact.
Previously stopped at first matching email address for GAL contact.
See ZBUG-1838.
*/
}
Expand All @@ -756,6 +756,35 @@ public void addMatchedContacts(String query, Map<String, ? extends Object> attrs
}
}

private List<String> extractAllowedEmailsListForAccount(Map<String, ?> attrs, String fullName) throws ServiceException {
List<String> allowedEmailsListInGalAutocomplete = new ArrayList<>();

Account account = Provisioning.getInstance().get(Key.AccountBy.name, fullName);
boolean isCosHidden = ("TRUE".equalsIgnoreCase(account.getCOS().getAttr(Provisioning.A_zimbraHideAliasesInGal)));
boolean isDomainHidden = ("TRUE".equalsIgnoreCase(account.getProvisioning().getDomain(account).getAttr(Provisioning.A_zimbraHideAliasesInGal)));

ZimbraLog.mailbox.info("Values for isCosHidden is %s and isDomain Hidden is %s", isCosHidden, isDomainHidden);

for(String emailKey: mEmailKeys) {
if (!emailKey.equals(Constants.PRIMARY_EMAIL)) {
//check if all aliases of an account need to be bypassed
if (account.isHideAliasesInGal() || isCosHidden || isDomainHidden) {
break;
}
}
String email = getFieldAsString(attrs, emailKey);
if(null != email) {
allowedEmailsListInGalAutocomplete.add(email);
}
}
ZimbraLog.mailbox.info("allowed list 1 is %s", allowedEmailsListInGalAutocomplete);

Provisioning.getInstance().excludePrivateAliases(account, allowedEmailsListInGalAutocomplete);

ZimbraLog.mailbox.info("allowed list 2 is %s", allowedEmailsListInGalAutocomplete);
return allowedEmailsListInGalAutocomplete;
}

private Pair<List<Folder>, Map<ItemId, Mountpoint>> getLocalRemoteContactFolders(Collection<Integer> folderIDs) throws ServiceException {
List<Folder> folders = new ArrayList<Folder>();
Map<ItemId, Mountpoint> mountpoints = new HashMap<ItemId, Mountpoint>();
Expand Down Expand Up @@ -931,4 +960,4 @@ private void addExistingContactsFromRankingTable(String str, String folderBasicQ
queryFolders(str, queryRanking, mountpoints, limit, result);
}
}
}
}

0 comments on commit f669f07

Please sign in to comment.