-
Notifications
You must be signed in to change notification settings - Fork 283
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
send notification for put group membership decision (#2742)
Signed-off-by: craman <[email protected]> Co-authored-by: craman <[email protected]>
- Loading branch information
1 parent
901537a
commit caba2bf
Showing
17 changed files
with
2,236 additions
and
831 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
4 changes: 4 additions & 0 deletions
4
libs/java/server_common/src/test/resources/messages/ServerCommon.properties
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,7 @@ | ||
athenz.notification.email.role_member.expiry.subject=Athenz Role Member Expiration Notification | ||
|
||
athenz.notification.email.pending_role_membership.decision.reject.subject=Athenz Pending Role Member Rejected | ||
athenz.notification.email.pending_role_membership.decision.approval.subject=Athenz Pending Role Member Approved | ||
|
||
athenz.notification.email.pending_group_membership.decision.reject.subject=Athenz Pending Group Member Rejected | ||
athenz.notification.email.pending_group_membership.decision.approval.subject=Athenz Pending Group Member Approved |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
86 changes: 86 additions & 0 deletions
86
...src/main/java/com/yahoo/athenz/zms/notification/MembershipDecisionNotificationCommon.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
/* | ||
* Copyright The Athenz Authors | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
package com.yahoo.athenz.zms.notification; | ||
|
||
import com.yahoo.athenz.auth.AuthorityConsts; | ||
import com.yahoo.athenz.auth.util.AthenzUtils; | ||
import com.yahoo.athenz.common.server.notification.DomainRoleMembersFetcher; | ||
import com.yahoo.athenz.zms.DBService; | ||
import com.yahoo.athenz.zms.Group; | ||
import com.yahoo.athenz.zms.utils.ZMSUtils; | ||
import org.apache.commons.lang3.StringUtils; | ||
import org.eclipse.jetty.util.StringUtil; | ||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
|
||
import java.util.HashSet; | ||
import java.util.List; | ||
import java.util.Set; | ||
|
||
import static com.yahoo.athenz.common.ServerCommonConsts.ADMIN_ROLE_NAME; | ||
|
||
public class MembershipDecisionNotificationCommon { | ||
private static final Logger LOGGER = LoggerFactory.getLogger(MembershipDecisionNotificationCommon.class); | ||
private final DBService dbService; | ||
private final DomainRoleMembersFetcher domainRoleMembersFetcher; | ||
private final String userDomainPrefix; | ||
|
||
MembershipDecisionNotificationCommon(DBService dbService, DomainRoleMembersFetcher domainRoleMembersFetcher, String userDomainPrefix) { | ||
this.dbService = dbService; | ||
this.domainRoleMembersFetcher = domainRoleMembersFetcher; | ||
this.userDomainPrefix = userDomainPrefix; | ||
} | ||
|
||
public Set<String> getRecipients(List<String> members) { | ||
Set<String> notifyMembers = new HashSet<>(); | ||
for (String memberName : members) { | ||
if (StringUtils.isEmpty(memberName)) { | ||
continue; | ||
} | ||
int idx = memberName.indexOf(AuthorityConsts.GROUP_SEP); | ||
if (idx != -1) { | ||
final String domainName = memberName.substring(0, idx); | ||
final String groupName = memberName.substring(idx + AuthorityConsts.GROUP_SEP.length()); | ||
Group group = dbService.getGroup(domainName, groupName, Boolean.FALSE, Boolean.FALSE); | ||
if (group == null) { | ||
LOGGER.error("unable to retrieve group: {} in domain: {}", groupName, domainName); | ||
continue; | ||
} | ||
if (!StringUtil.isEmpty(group.getNotifyRoles())) { | ||
notifyMembers.addAll(NotificationUtils.extractNotifyRoleMembers(domainRoleMembersFetcher, | ||
domainName, group.getNotifyRoles())); | ||
} else { | ||
notifyMembers.addAll(domainRoleMembersFetcher.getDomainRoleMembers(domainName, ADMIN_ROLE_NAME)); | ||
} | ||
} else { | ||
final String domainName = AthenzUtils.extractPrincipalDomainName(memberName); | ||
if (userDomainPrefix.equals(domainName + ".")) { | ||
notifyMembers.add(memberName); | ||
} else { | ||
// domain role fetcher only returns the human users | ||
Set<String> domainAdminMembers = domainRoleMembersFetcher.getDomainRoleMembers(domainName, ADMIN_ROLE_NAME); | ||
if (!ZMSUtils.isCollectionEmpty(domainAdminMembers)) { | ||
for (String domainAdminMember : domainAdminMembers) { | ||
notifyMembers.add(domainAdminMember); | ||
} | ||
} | ||
} | ||
} | ||
} | ||
return notifyMembers; | ||
} | ||
} |
159 changes: 159 additions & 0 deletions
159
...in/java/com/yahoo/athenz/zms/notification/PutGroupMembershipDecisionNotificationTask.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,159 @@ | ||
/* | ||
* Copyright The Athenz Authors | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
package com.yahoo.athenz.zms.notification; | ||
|
||
import com.yahoo.athenz.common.server.notification.*; | ||
import com.yahoo.athenz.zms.DBService; | ||
import com.yahoo.rdl.Timestamp; | ||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
|
||
import java.text.MessageFormat; | ||
import java.util.*; | ||
|
||
import static com.yahoo.athenz.common.server.notification.NotificationServiceConstants.*; | ||
import static com.yahoo.athenz.common.server.notification.NotificationServiceConstants.NOTIFICATION_DETAILS_REQUESTER; | ||
import static com.yahoo.athenz.common.server.notification.impl.MetricNotificationService.*; | ||
import static com.yahoo.athenz.common.server.notification.impl.MetricNotificationService.METRIC_NOTIFICATION_REQUESTER_KEY; | ||
|
||
public class PutGroupMembershipDecisionNotificationTask implements NotificationTask { | ||
|
||
private static final Logger LOGGER = LoggerFactory.getLogger(PutRoleMembershipDecisionNotificationTask.class); | ||
|
||
private final Map<String, String> details; | ||
private final NotificationCommon notificationCommon; | ||
private final static String DESCRIPTION = "Pending Group Membership Decision Notification"; | ||
private final PutGroupMembershipDecisionNotificationToEmailConverter putMembershipNotificationToEmailConverter; | ||
private final PutGroupMembershipDecisionNotificationToMetricConverter putMembershipNotificationToMetricConverter; | ||
private final DBService dbService; | ||
private final DomainRoleMembersFetcher domainRoleMembersFetcher; | ||
private final String userDomainPrefix; | ||
|
||
public PutGroupMembershipDecisionNotificationTask(Map<String, String> details, Boolean approved, DBService dbService, String userDomainPrefix, NotificationToEmailConverterCommon notificationToEmailConverterCommon) { | ||
this.details = details; | ||
this.userDomainPrefix = userDomainPrefix; | ||
this.domainRoleMembersFetcher = new DomainRoleMembersFetcher(dbService, userDomainPrefix); | ||
this.notificationCommon = new NotificationCommon(domainRoleMembersFetcher, userDomainPrefix); | ||
this.putMembershipNotificationToEmailConverter = new PutGroupMembershipDecisionNotificationToEmailConverter(notificationToEmailConverterCommon, approved); | ||
this.putMembershipNotificationToMetricConverter = new PutGroupMembershipDecisionNotificationToMetricConverter(); | ||
this.dbService = dbService; | ||
} | ||
|
||
@Override | ||
public List<Notification> getNotifications() { | ||
if (details == null) { | ||
return new ArrayList<>(); | ||
} | ||
// we need to send the notification to both the member whose pending membership was approved or rejected | ||
// and also the member who requested the pending member | ||
List<String> members = new ArrayList<>(); | ||
members.add(details.getOrDefault(NOTIFICATION_DETAILS_MEMBER, "")); | ||
members.add(details.getOrDefault(NOTIFICATION_DETAILS_REQUESTER, "")); | ||
|
||
MembershipDecisionNotificationCommon membershipDecisionNotificationCommon = new MembershipDecisionNotificationCommon(dbService, domainRoleMembersFetcher, userDomainPrefix); | ||
Set<String> recipients = membershipDecisionNotificationCommon.getRecipients(members); | ||
|
||
return Collections.singletonList(notificationCommon.createNotification( | ||
Notification.Type.GROUP_MEMBER_DECISION, | ||
recipients, | ||
details, | ||
putMembershipNotificationToEmailConverter, | ||
putMembershipNotificationToMetricConverter)); | ||
} | ||
|
||
@Override | ||
public String getDescription() { | ||
return DESCRIPTION; | ||
} | ||
|
||
public static class PutGroupMembershipDecisionNotificationToEmailConverter implements NotificationToEmailConverter { | ||
private static final String EMAIL_TEMPLATE_NOTIFICATION_APPROVAL = "messages/pending-group-membership-approve.html"; | ||
private static final String PENDING_MEMBERSHIP_APPROVAL_SUBJECT = "athenz.notification.email.pending_group_membership.decision.approval.subject"; | ||
|
||
private static final String EMAIL_TEMPLATE_NOTIFICATION_REJECT = "messages/pending-group-membership-reject.html"; | ||
private static final String PENDING_MEMBERSHIP_REJECT_SUBJECT = "athenz.notification.email.pending_group_membership.decision.reject.subject"; | ||
|
||
private final NotificationToEmailConverterCommon notificationToEmailConverterCommon; | ||
private final String emailMembershipDecisionBody; | ||
private final boolean pendingMemberApproved; | ||
|
||
public PutGroupMembershipDecisionNotificationToEmailConverter(NotificationToEmailConverterCommon notificationToEmailConverterCommon, boolean approved) { | ||
this.notificationToEmailConverterCommon = notificationToEmailConverterCommon; | ||
pendingMemberApproved = approved; | ||
emailMembershipDecisionBody = getEmailBody(); | ||
} | ||
|
||
String getMembershipDecisionBody(Map<String, String> metaDetails) { | ||
if (metaDetails == null) { | ||
return null; | ||
} | ||
String athenzUIUrl = notificationToEmailConverterCommon.getAthenzUIUrl(); | ||
String body = MessageFormat.format(emailMembershipDecisionBody, metaDetails.get(NOTIFICATION_DETAILS_DOMAIN), | ||
metaDetails.get(NOTIFICATION_DETAILS_GROUP), metaDetails.get(NOTIFICATION_DETAILS_MEMBER), | ||
metaDetails.get(NOTIFICATION_DETAILS_REASON), metaDetails.get(NOTIFICATION_DETAILS_REQUESTER), | ||
metaDetails.get(NOTIFICATION_DETAILS_PENDING_MEMBERSHIP_STATE), | ||
metaDetails.get(NOTIFICATION_DETAILS_PENDING_MEMBERSHIP_DECISION_PRINCIPAL), | ||
athenzUIUrl); | ||
return notificationToEmailConverterCommon.addCssStyleToBody(body); | ||
} | ||
|
||
@Override | ||
public NotificationEmail getNotificationAsEmail(Notification notification) { | ||
String subject = notificationToEmailConverterCommon.getSubject(getNotificationSubjectProp()); | ||
String body = getMembershipDecisionBody(notification.getDetails()); | ||
Set<String> fullyQualifiedEmailAddresses = notificationToEmailConverterCommon.getFullyQualifiedEmailAddresses(notification.getRecipients()); | ||
return new NotificationEmail(subject, body, fullyQualifiedEmailAddresses); | ||
} | ||
|
||
String getEmailBody() { | ||
if (pendingMemberApproved) { | ||
return notificationToEmailConverterCommon.readContentFromFile(getClass().getClassLoader(), EMAIL_TEMPLATE_NOTIFICATION_APPROVAL); | ||
} else { | ||
return notificationToEmailConverterCommon.readContentFromFile(getClass().getClassLoader(), EMAIL_TEMPLATE_NOTIFICATION_REJECT); | ||
} | ||
} | ||
|
||
String getNotificationSubjectProp() { | ||
if (pendingMemberApproved) { | ||
return PENDING_MEMBERSHIP_APPROVAL_SUBJECT; | ||
} else { | ||
return PENDING_MEMBERSHIP_REJECT_SUBJECT; | ||
} | ||
} | ||
} | ||
|
||
public static class PutGroupMembershipDecisionNotificationToMetricConverter implements NotificationToMetricConverter { | ||
private final static String NOTIFICATION_TYPE = "pending_group_membership_decision"; | ||
|
||
@Override | ||
public NotificationMetric getNotificationAsMetrics(Notification notification, Timestamp currentTime) { | ||
String[] record = new String[] { | ||
METRIC_NOTIFICATION_TYPE_KEY, NOTIFICATION_TYPE, | ||
METRIC_NOTIFICATION_DOMAIN_KEY, notification.getDetails().get(NOTIFICATION_DETAILS_DOMAIN), | ||
METRIC_NOTIFICATION_GROUP_KEY, notification.getDetails().get(NOTIFICATION_DETAILS_GROUP), | ||
METRIC_NOTIFICATION_MEMBER_KEY, notification.getDetails().get(NOTIFICATION_DETAILS_MEMBER), | ||
METRIC_NOTIFICATION_REASON_KEY, notification.getDetails().get(NOTIFICATION_DETAILS_REASON), | ||
METRIC_NOTIFICATION_REQUESTER_KEY, notification.getDetails().get(NOTIFICATION_DETAILS_REQUESTER), | ||
METRIC_NOTIFICATION_MEMBERSHIP_DECISION, notification.getDetails().get(NOTIFICATION_DETAILS_PENDING_MEMBERSHIP_DECISION) | ||
}; | ||
|
||
List<String[]> attributes = new ArrayList<>(); | ||
attributes.add(record); | ||
return new NotificationMetric(attributes); | ||
} | ||
} | ||
} |
Oops, something went wrong.