Skip to content

Commit

Permalink
Merge pull request #9318 from OpenMined/eelco/deny-reason
Browse files Browse the repository at this point in the history
add deny reason to email and table
  • Loading branch information
eelcovdw authored Sep 26, 2024
2 parents 7a50175 + 923262e commit cd62499
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 7 deletions.
29 changes: 25 additions & 4 deletions packages/syft/src/syft/service/notification/email_templates.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

if TYPE_CHECKING:
# relative
from ..request.request import Request
from .notifications import Notification


Expand Down Expand Up @@ -662,8 +663,11 @@ def email_title(notification: "Notification", context: AuthedServiceContext) ->

@staticmethod
def email_body(notification: "Notification", context: AuthedServiceContext) -> str:
# relative
from ..request.request import RequestStatus

notification.linked_obj = cast(LinkedObject, notification.linked_obj)
request_obj = notification.linked_obj.resolve_with_context(
request_obj: Request = notification.linked_obj.resolve_with_context(
context=context
).unwrap()
badge_color = "red" if request_obj.status.name == "REJECTED" else "green"
Expand All @@ -672,11 +676,26 @@ def email_body(notification: "Notification", context: AuthedServiceContext) -> s
request_name = request_obj.requesting_user_name
request_email = request_obj.requesting_user_email
request_time = request_obj.request_time
request_status = request_obj.status.name # fails in l0 check right now
request_status = request_obj.status
request_status_name = request_status.name # fails in l0 check right now
request_changes = ",".join(
[change.__class__.__name__ for change in request_obj.changes]
)

deny_reason_html = ""
if request_status == RequestStatus.REJECTED:
deny_reason_or_err = request_obj.get_deny_reason(context=context)
if deny_reason_or_err.is_err():
deny_reason = None
deny_reason = deny_reason_or_err.unwrap()

if not isinstance(deny_reason, str) or not len(deny_reason):
deny_reason = (
"No reason provided, please contact the admin for more information."
)

deny_reason_html = f"<p><strong>Deny Reason:</strong> {deny_reason}</p>"

head = """
<head>
<title>Access Request Notification</title>
Expand Down Expand Up @@ -792,8 +811,10 @@ def email_body(notification: "Notification", context: AuthedServiceContext) -> s
</p>
<p><strong>Date:</strong> {request_time}</p>
<div style="display: flex"><p><strong>Status:</strong><div class="badge {badge_color}">
{request_status}
</div></div>
{request_status_name}
</div>
</div>
{deny_reason_html}
<p>
<strong>Changes:</strong>
{request_changes}
Expand Down
40 changes: 37 additions & 3 deletions packages/syft/src/syft/service/request/request.py
Original file line number Diff line number Diff line change
Expand Up @@ -455,15 +455,47 @@ def html_description(self) -> str:

return desc

@property
def deny_reason(self) -> str | SyftError:
code = self.code
if isinstance(code, SyftError):
return code

code_status: UserCodeStatusCollection = code.status_link.resolve
return code_status.first_denial_reason

@as_result(SyftException)
def get_deny_reason(self, context: AuthedServiceContext) -> str | None:
code = self.get_user_code(context).unwrap()
if code is None:
return None

code_status = code.get_status(context).unwrap()
return code_status.first_denial_reason

def _coll_repr_(self) -> dict[str, str | dict[str, str]]:
# relative
from ...util.notebook_ui.components.sync import Badge

if self.status == RequestStatus.APPROVED:
badge_color = "badge-green"
elif self.status == RequestStatus.PENDING:
badge_color = "badge-gray"
else:
badge_color = "badge-red"

status_badge = {"value": self.status.name.capitalize(), "type": badge_color}
status_badge = Badge(
value=self.status.name.capitalize(),
badge_class=badge_color,
).to_html()

if self.status == RequestStatus.REJECTED:
deny_reason = self.deny_reason
if isinstance(deny_reason, str) and len(deny_reason) > 0:
status_badge += (
"<br><span style='margin-top: 8px; display: block;'>"
f"<strong>Deny Reason:</strong> {deny_reason}</span>"
)

user_data = [
self.requesting_user_name,
Expand Down Expand Up @@ -505,10 +537,11 @@ def codes(self) -> Any:
message="This type of request does not have code associated with it."
)

@as_result(SyftException)
def get_user_code(self, context: AuthedServiceContext) -> UserCode | None:
for change in self.changes:
if isinstance(change, UserCodeStatusChange):
return change.get_user_code(context)
return change.get_user_code(context).unwrap()
return None

@property
Expand Down Expand Up @@ -641,7 +674,7 @@ def is_l0_deployment(self) -> bool:
return bool(self.code) and self.code.is_l0_deployment

def get_is_l0_deployment(self, context: AuthedServiceContext) -> bool:
code = self.get_user_code(context)
code = self.get_user_code(context).unwrap()
if code:
return code.is_l0_deployment
else:
Expand Down Expand Up @@ -1355,6 +1388,7 @@ def code(self) -> UserCode:
return self.linked_user_code._resolve_cache
return self.linked_user_code.resolve

@as_result(SyftException)
def get_user_code(self, context: AuthedServiceContext) -> UserCode:
return self.linked_user_code.resolve_with_context(context).unwrap()

Expand Down

0 comments on commit cd62499

Please sign in to comment.