Skip to content

Commit

Permalink
Add access_overview as context variable to get the status of all in…
Browse files Browse the repository at this point in the history
…tegrations for a user (#385)
  • Loading branch information
GDay authored Nov 7, 2023
1 parent 3165850 commit 531a8ba
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 6 deletions.
34 changes: 32 additions & 2 deletions back/users/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from django.db.models import CheckConstraint, Q
from django.template import Context, Template
from django.utils.crypto import get_random_string
from django.utils.functional import cached_property
from django.utils.functional import cached_property, lazy
from django.utils.translation import gettext_lazy as _

from admin.appointments.models import Appointment
Expand Down Expand Up @@ -431,7 +431,9 @@ def get_local_time(self, date=None):
)
return us_tz.normalize(local.astimezone(us_tz))

def personalize(self, text, extra_values={}):
def personalize(self, text, extra_values=None):
if extra_values is None:
extra_values = {}
t = Template(text)
department = ""
manager = ""
Expand All @@ -456,14 +458,42 @@ def personalize(self, text, extra_values={}):
"start": self.start_day,
"buddy_email": buddy_email,
"manager_email": manager_email,
"access_overview": lazy(self.get_access_overview, str),
"department": department,
}

text = t.render(Context(new_hire_context | extra_values))
# Remove non breakable space html code (if any). These could show up in the
# Slack bot.
text = text.replace(" ", " ")
return text

def get_access_overview(self):
all_access = []
for integration, access in self.check_integration_access().items():
if access is None:
access_str = _("(unknown)")
elif access:
access_str = _("(has access)")
else:
access_str = _("(no access)")

all_access.append(f"{integration} {access_str}")

return ", ".join(all_access)

def check_integration_access(self):
from admin.integrations.models import Integration

items = {}
for integration_user in IntegrationUser.objects.filter(user=self):
items[integration_user.integration.name] = not integration_user.revoked

for integration in Integration.objects.filter(manifest__exists__isnull=False):
items[integration.name] = integration.user_exists(self)

return items

def reset_otp_recovery_keys(self):
self.user_otp.all().delete()
newItems = [OTPRecoveryKey(user=self) for x in range(10)]
Expand Down
56 changes: 52 additions & 4 deletions back/users/tests.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import datetime

import pytest
from unittest.mock import Mock, patch
from django.contrib.auth import get_user_model
from freezegun import freeze_time

Expand Down Expand Up @@ -199,7 +200,13 @@ def test_days_before_starting(date, daybefore, new_hire_factory):


@pytest.mark.django_db
def test_personalize(manager_factory, new_hire_factory, department_factory):
def test_personalize(
manager_factory,
new_hire_factory,
department_factory,
custom_integration_factory,
integration_user_factory,
):
department = department_factory(name="IT")
manager = manager_factory(first_name="jane", last_name="smith")
buddy = manager_factory(email="cat@chiefonboarding.com")
Expand All @@ -211,11 +218,16 @@ def test_personalize(manager_factory, new_hire_factory, department_factory):
position="developer",
department=department,
)
# add integrations
i_u1 = integration_user_factory(user=new_hire, revoked=True)
i_u2 = integration_user_factory(user=new_hire, revoked=False)

integration = custom_integration_factory()

text = (
"Hello {{ first_name }} {{ last_name }}, your manager is {{ manager }} and "
"you can reach your buddy through {{ buddy_email }}, you will be our "
"{{ position }} in {{ department }}"
"{{ position }} in {{ department }}. He has access to: {{ access_overview }}"
)
text_without_spaces = (
"Hello {{first_name}} {{last_name}}, your manager is {{manager}} and you can "
Expand All @@ -224,12 +236,48 @@ def test_personalize(manager_factory, new_hire_factory, department_factory):
)

expected_output = (
"Hello john smith, your manager is jane smith and you can reach your buddy "
"through cat@chiefonboarding.com, you will be our developer in IT. He has "
f"access to: {i_u1.integration.name} (no access), {i_u2.integration.name} (has "
f"access), {integration.name} (unknown)"
)

expected_output_without_spaces = (
"Hello john smith, your manager is jane smith and you can reach your buddy "
"through cat@chiefonboarding.com, you will be our developer in IT"
)

assert new_hire.personalize(text) == expected_output
assert new_hire.personalize(text_without_spaces) == expected_output
# Service errored
with patch(
"admin.integrations.models.Integration.user_exists",
Mock(return_value=(None)),
):
assert new_hire.personalize(text) == expected_output
assert (
new_hire.personalize(text_without_spaces) == expected_output_without_spaces
)


@pytest.mark.django_db
def test_check_integration_access(
new_hire_factory, custom_integration_factory, integration_user_factory
):
new_hire = new_hire_factory()
integration_user1 = integration_user_factory(user=new_hire, revoked=True)
integration_user2 = integration_user_factory(user=new_hire, revoked=False)

integration = custom_integration_factory()

# integration service errored
with patch(
"admin.integrations.models.Integration.user_exists",
Mock(return_value=(None)),
):
access = new_hire.check_integration_access()

assert access[integration_user1.integration.name] is False
assert access[integration_user2.integration.name] is True
assert access[integration.name] is None


@pytest.mark.django_db
Expand Down
2 changes: 2 additions & 0 deletions docs/Integrations.md
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,8 @@ Throughout the manifest you can use the variables that you have defined in the `

`start`: New hire's start date

`access_overview`: This will be a list of all the access the user could have access to. This includes previously assigned manual access and automated access (all of the automated items). It will result in a string like this: `Asana (no access), Google (has access), Teams (unknown)`. `unknown` is used when we couldn't reach the service.

!!!
Please do not overwrite these with your own ids
!!!
Expand Down

0 comments on commit 531a8ba

Please sign in to comment.