diff --git a/python/lib/sift_py/rule/config.py b/python/lib/sift_py/rule/config.py index d2cad7d60..895e655f1 100644 --- a/python/lib/sift_py/rule/config.py +++ b/python/lib/sift_py/rule/config.py @@ -112,6 +112,11 @@ def as_json(self) -> Any: if self.action.tags is not None and len(self.action.tags) > 0: hash_map["tags"] = self.action.tags + elif isinstance(self.action, RuleActionCreateNotification): + hash_map["type"] = RuleActionKindStrRep.NOTIFICATION.value + + if self.action.recipients is not None and len(self.action.recipients) > 0: + hash_map["recipients"] = self.action.recipients else: kind = self.action.kind() if self.action else self.action raise TypeError(f"Unsupported rule action '{kind}'.") @@ -177,6 +182,24 @@ def kind(self) -> RuleActionKind: return RuleActionKind.ANNOTATION +class RuleActionCreateNotification(RuleAction): + """ + Action to send a notification to one or more users when a rule evaluates to a truthy value. + + - `recipients`: List of emails of users in the organization to notify. + """ + + recipients: List[str] + tags: Optional[List[str]] + + def __init__(self, recipients: List[str]): + self.recipients = recipients + self.tags = None + + def kind(self) -> RuleActionKind: + return RuleActionKind.NOTIFICATION + + class RuleActionKind(Enum): NOTIFICATION = ActionKind.NOTIFICATION ANNOTATION = ActionKind.ANNOTATION diff --git a/python/lib/sift_py/rule/service.py b/python/lib/sift_py/rule/service.py index 76dd965b2..067bfcc2b 100644 --- a/python/lib/sift_py/rule/service.py +++ b/python/lib/sift_py/rule/service.py @@ -18,6 +18,7 @@ from sift.common.type.v1.user_pb2 import User as UserPb from sift.rules.v1.rules_pb2 import ( ANNOTATION, + NOTIFICATION, AnnotationActionConfiguration, BatchUpdateRulesRequest, BatchUpdateRulesResponse, @@ -26,6 +27,7 @@ CreateRuleRequest, GetRuleRequest, GetRuleResponse, + NotificationActionConfiguration, Rule, RuleActionConfiguration, RuleAssetConfiguration, @@ -53,6 +55,7 @@ RuleAction, RuleActionAnnotationKind, RuleActionCreateDataReviewAnnotation, + RuleActionCreateNotification, RuleActionCreatePhaseAnnotation, RuleActionKind, RuleConfig, @@ -425,10 +428,30 @@ def _update_req_from_rule_config( actions = [] if config.action.kind() == RuleActionKind.NOTIFICATION: - raise NotImplementedError( - "Notification actions are not yet supported." - "Please contact the Sift team for assistance." + if not isinstance(config.action, RuleActionCreateNotification): + raise TypeError( + f"Expected RuleActionCreateNotification for notification action, " + f"got {type(config.action).__name__}." + ) + + recipient_user_ids: List[str] = [] + for email in config.action.recipients: + users = self._get_active_users(filter=f"name=='{email}'") + if not users: + raise ValueError(f"Cannot find user '{email}'.") + if len(users) > 1: + raise ValueError(f"Multiple users found with name '{email}'.") + recipient_user_ids.append(users[0].user_id) + + action_config = UpdateActionRequest( + action_type=NOTIFICATION, + configuration=RuleActionConfiguration( + notification=NotificationActionConfiguration( + recipient_user_ids=recipient_user_ids, + ) + ), ) + actions.append(action_config) elif config.action.kind() == RuleActionKind.ANNOTATION: annotation_tag_ids = ( [tag.tag_id for tag in annotation_tags] if annotation_tags else None