From 689bb722d5fac0e943e64dc00a5e91f4bfdd6726 Mon Sep 17 00:00:00 2001 From: rendurama Date: Wed, 3 Jul 2024 18:07:29 +0530 Subject: [PATCH 1/2] zcs --- store/conf/attrs/zimbra-attrs.xml | 4 +++ .../com/zimbra/cs/account/ZAttrAccount.java | 30 +++++++++---------- .../java/com/zimbra/cs/account/ZAttrCos.java | 30 +++++++++---------- 3 files changed, 34 insertions(+), 30 deletions(-) diff --git a/store/conf/attrs/zimbra-attrs.xml b/store/conf/attrs/zimbra-attrs.xml index 5f3a74e1526..6378766c6b6 100644 --- a/store/conf/attrs/zimbra-attrs.xml +++ b/store/conf/attrs/zimbra-attrs.xml @@ -10555,4 +10555,8 @@ TODO: delete them permanently from here TRUE 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 + + + Option to hide/show alias in GAL + diff --git a/store/src/java/com/zimbra/cs/account/ZAttrAccount.java b/store/src/java/com/zimbra/cs/account/ZAttrAccount.java index fe6fcb38ec0..54e90ab4777 100644 --- a/store/src/java/com/zimbra/cs/account/ZAttrAccount.java +++ b/store/src/java/com/zimbra/cs/account/ZAttrAccount.java @@ -21018,9 +21018,9 @@ public Map unsetFeatureSearchHistoryEnabled(Map at } /** - * 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 * * @return zimbraFeatureSharedFolderMobileSyncEnabled, or true if unset @@ -21033,9 +21033,9 @@ public boolean isFeatureSharedFolderMobileSyncEnabled() { } /** - * 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 * * @param zimbraFeatureSharedFolderMobileSyncEnabled new value @@ -21051,9 +21051,9 @@ public void setFeatureSharedFolderMobileSyncEnabled(boolean zimbraFeatureSharedF } /** - * 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 * * @param zimbraFeatureSharedFolderMobileSyncEnabled new value @@ -21070,9 +21070,9 @@ public Map setFeatureSharedFolderMobileSyncEnabled(boolean zimbra } /** - * 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 * * @throws com.zimbra.common.service.ServiceException if error during update @@ -21087,9 +21087,9 @@ public void unsetFeatureSharedFolderMobileSyncEnabled() throws com.zimbra.common } /** - * 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 * * @param attrs existing map to populate, or null to create a new map diff --git a/store/src/java/com/zimbra/cs/account/ZAttrCos.java b/store/src/java/com/zimbra/cs/account/ZAttrCos.java index 1f6a8057025..8ab4f6954c4 100644 --- a/store/src/java/com/zimbra/cs/account/ZAttrCos.java +++ b/store/src/java/com/zimbra/cs/account/ZAttrCos.java @@ -15407,9 +15407,9 @@ public Map unsetFeatureSearchHistoryEnabled(Map at } /** - * 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 * * @return zimbraFeatureSharedFolderMobileSyncEnabled, or true if unset @@ -15422,9 +15422,9 @@ public boolean isFeatureSharedFolderMobileSyncEnabled() { } /** - * 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 * * @param zimbraFeatureSharedFolderMobileSyncEnabled new value @@ -15440,9 +15440,9 @@ public void setFeatureSharedFolderMobileSyncEnabled(boolean zimbraFeatureSharedF } /** - * 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 * * @param zimbraFeatureSharedFolderMobileSyncEnabled new value @@ -15459,9 +15459,9 @@ public Map setFeatureSharedFolderMobileSyncEnabled(boolean zimbra } /** - * 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 * * @throws com.zimbra.common.service.ServiceException if error during update @@ -15476,9 +15476,9 @@ public void unsetFeatureSharedFolderMobileSyncEnabled() throws com.zimbra.common } /** - * 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 * * @param attrs existing map to populate, or null to create a new map From f669f0738b617ed015eca2876d8547c7f0a92767 Mon Sep 17 00:00:00 2001 From: rendurama Date: Fri, 5 Jul 2024 13:09:44 +0530 Subject: [PATCH 2/2] ZCS-15079 POC | Hide alias in GAL --- .../common/account/ZAttrProvisioning.java | 14 ++- .../com/zimbra/common/util/Constants.java | 4 + store/conf/attrs/zimbra-attrs.xml | 7 +- .../zimbra/cs/account/MockProvisioning.java | 5 ++ .../com/zimbra/cs/account/Provisioning.java | 4 +- .../cs/account/ldap/LdapProvisioning.java | 29 ++++++ .../cs/account/soap/SoapProvisioning.java | 5 ++ .../cs/mailbox/ContactAutoComplete.java | 89 ++++++++++++------- 8 files changed, 120 insertions(+), 37 deletions(-) diff --git a/common/src/java/com/zimbra/common/account/ZAttrProvisioning.java b/common/src/java/com/zimbra/common/account/ZAttrProvisioning.java index ae40ee826f7..313b05cc879 100644 --- a/common/src/java/com/zimbra/common/account/ZAttrProvisioning.java +++ b/common/src/java/com/zimbra/common/account/ZAttrProvisioning.java @@ -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 @@ -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 */ diff --git a/common/src/java/com/zimbra/common/util/Constants.java b/common/src/java/com/zimbra/common/util/Constants.java index 56bc74cda85..49118b0015c 100644 --- a/common/src/java/com/zimbra/common/util/Constants.java +++ b/common/src/java/com/zimbra/common/util/Constants.java @@ -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"; + } diff --git a/store/conf/attrs/zimbra-attrs.xml b/store/conf/attrs/zimbra-attrs.xml index 6378766c6b6..a4b67ba8045 100644 --- a/store/conf/attrs/zimbra-attrs.xml +++ b/store/conf/attrs/zimbra-attrs.xml @@ -10474,7 +10474,7 @@ TODO: delete them permanently from here Define body: field for 2FA email in html format - + When set to True, all aliases will be hidden for particular account @@ -10556,7 +10556,8 @@ TODO: delete them permanently from here 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 - - Option to hide/show alias in GAL + + Option to hide/show alias in GAL + diff --git a/store/src/java-test/com/zimbra/cs/account/MockProvisioning.java b/store/src/java-test/com/zimbra/cs/account/MockProvisioning.java index bbf1bcaba03..54ed1ca0793 100644 --- a/store/src/java-test/com/zimbra/cs/account/MockProvisioning.java +++ b/store/src/java-test/com/zimbra/cs/account/MockProvisioning.java @@ -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 email) throws ServiceException { + //Not yet implemenmted + } } diff --git a/store/src/java/com/zimbra/cs/account/Provisioning.java b/store/src/java/com/zimbra/cs/account/Provisioning.java index 2055484c37c..476f27e0428 100644 --- a/store/src/java/com/zimbra/cs/account/Provisioning.java +++ b/store/src/java/com/zimbra/cs/account/Provisioning.java @@ -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; @@ -2795,4 +2794,7 @@ public String createAddressList(Domain domain, String name, String desc, Map email) throws ServiceException; + } diff --git a/store/src/java/com/zimbra/cs/account/ldap/LdapProvisioning.java b/store/src/java/com/zimbra/cs/account/ldap/LdapProvisioning.java index 81e3909e8ee..3a77926ece3 100644 --- a/store/src/java/com/zimbra/cs/account/ldap/LdapProvisioning.java +++ b/store/src/java/com/zimbra/cs/account/ldap/LdapProvisioning.java @@ -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) { @@ -11726,4 +11727,32 @@ public void modifyAddressList(AddressList addressList, String name, Map 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)); + } + } + } } + diff --git a/store/src/java/com/zimbra/cs/account/soap/SoapProvisioning.java b/store/src/java/com/zimbra/cs/account/soap/SoapProvisioning.java index be7eec340bd..ec8ca4d635d 100644 --- a/store/src/java/com/zimbra/cs/account/soap/SoapProvisioning.java +++ b/store/src/java/com/zimbra/cs/account/soap/SoapProvisioning.java @@ -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 email) throws ServiceException { + //not yet implemented + } } \ No newline at end of file diff --git a/store/src/java/com/zimbra/cs/mailbox/ContactAutoComplete.java b/store/src/java/com/zimbra/cs/mailbox/ContactAutoComplete.java index 9de314d3d3f..982ac0fff85 100644 --- a/store/src/java/com/zimbra/cs/mailbox/ContactAutoComplete.java +++ b/store/src/java/com/zimbra/cs/mailbox/ContactAutoComplete.java @@ -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; @@ -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 folders, int limit) throws ServiceException { ZimbraLog.gal.debug("AutoComplete querying: %s", str); @@ -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); @@ -504,7 +503,7 @@ public AutoCompleteCallback(String str, AutoCompleteResult result, GalSearchPara this.str = str; } - public void handleContactAttrs(Map attrs) { + public void handleContactAttrs(Map attrs) throws ServiceException { addMatchedContacts(str, attrs, FOLDER_ID_GAL, null, result); } @@ -600,8 +599,7 @@ private boolean matchesName(List tokens, Map 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; } } @@ -634,8 +632,8 @@ private boolean matchesName(List tokens, Map 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; @@ -669,7 +667,7 @@ private Pattern toPattern(List tokens) { } public void addMatchedContacts(String query, Map attrs, int folderId, ItemId id, - AutoCompleteResult result) { + AutoCompleteResult result) throws ServiceException { if (!result.canBeCached) { return; } @@ -680,10 +678,10 @@ public void addMatchedContacts(String query, Map 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 @@ -708,21 +706,22 @@ public void addMatchedContacts(String query, Map attrs displayName = Joiner.on(' ').skipNulls().join(first, middle, last); } - for (String emailKey : mEmailKeys) { - String email = getFieldAsString(attrs, emailKey); + List 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) { @@ -734,10 +733,11 @@ public void addMatchedContacts(String query, Map 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. */ } @@ -756,6 +756,35 @@ public void addMatchedContacts(String query, Map attrs } } + private List extractAllowedEmailsListForAccount(Map attrs, String fullName) throws ServiceException { + List 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, Map> getLocalRemoteContactFolders(Collection folderIDs) throws ServiceException { List folders = new ArrayList(); Map mountpoints = new HashMap(); @@ -931,4 +960,4 @@ private void addExistingContactsFromRankingTable(String str, String folderBasicQ queryFolders(str, queryRanking, mountpoints, limit, result); } } -} +} \ No newline at end of file