Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tableau de bord : ne pas afficher GPS aux orienteurs #4318

Merged
merged 1 commit into from
Jun 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions itou/templates/dashboard/dashboard.html
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@
</div>
{% endif %}

{% if user.is_prescriber or user.is_employer %}
{% if can_view_gps_card %}
<div class="alert alert-info alert-dismissible-once fade show d-none" role="status" id="GPS_banner">
<p class="mb-0">
Une nouvelle entrée dans votre tableau de bord vous permet de visualiser l’ensemble des intervenants auprès des personnes pour lesquelles vous avez réalisé une action. Il s’agit de l’encart GPS (Guide de Partage et de Suivi).
Expand Down Expand Up @@ -338,7 +338,9 @@ <h2>Vue d’ensemble</h2>
{% if user.is_employer or user.is_prescriber %}
<h2>Services partenaires</h2>
<div class="row row-cols-1 row-cols-md-2 mt-3 mt-md-4">
{% include "dashboard/includes/gps_card.html" %}
{% if can_view_gps_card %}
{% include "dashboard/includes/gps_card.html" %}
{% endif %}
{% include "dashboard/includes/dora_card.html" with siret=request.current_organization.siret|default:"" tracker="mtm_campaign=LesEmplois&mtm_kwd=Dashboard" %}
</div>
{% endif %}
Expand Down
3 changes: 2 additions & 1 deletion itou/www/autocomplete/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
from itou.cities.models import City
from itou.jobs.models import Appellation
from itou.users.models import User
from itou.www.gps.views import is_allowed_to_use_gps


# Consider that after 50 matches the user should refine its search.
Expand Down Expand Up @@ -156,7 +157,7 @@ def communes_autocomplete(request):


@login_required
@user_passes_test(lambda u: not u.is_job_seeker, login_url=reverse_lazy("dashboard:index"), redirect_field_name=None)
@user_passes_test(is_allowed_to_use_gps, login_url=reverse_lazy("dashboard:index"), redirect_field_name=None)
def gps_users_autocomplete(request):
"""
Returns JSON data compliant with Select2
Expand Down
3 changes: 3 additions & 0 deletions itou/www/dashboard/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ def _employer_dashboard_context(request):
"evaluated_job_applications__evaluated_administrative_criteria",
)
),
"can_view_gps_card": True,
"can_create_siae_antenna": request.user.can_create_siae_antenna(parent_siae=current_org),
"can_show_employee_records": current_org.can_use_employee_record,
"can_show_financial_annexes": current_org.convention_can_be_accessed_by(request.user),
Expand Down Expand Up @@ -131,6 +132,7 @@ def dashboard(request, template_name="dashboard/dashboard.html"):
"can_create_siae_antenna": False,
"can_show_financial_annexes": False,
"can_show_employee_records": False,
"can_view_gps_card": False,
"can_view_stats_dashboard_widget": stats_utils.can_view_stats_dashboard_widget(request),
"can_view_stats_siae": stats_utils.can_view_stats_siae(request),
"can_view_stats_siae_aci": stats_utils.can_view_stats_siae_aci(request),
Expand Down Expand Up @@ -202,6 +204,7 @@ def dashboard(request, template_name="dashboard/dashboard.html"):
}
)
if current_org.is_authorized:
context["can_view_gps_card"] = True
context["pending_prolongation_requests"] = ProlongationRequest.objects.filter(
prescriber_organization=current_org,
status=ProlongationRequestStatus.PENDING,
Expand Down
12 changes: 8 additions & 4 deletions itou/www/gps/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,13 @@
from itou.www.gps.forms import GpsUserSearchForm


def is_allowed_to_use_gps(user):
return user.is_employer or user.is_prescriber_with_authorized_org


@login_required
@user_passes_test(
lambda u: not u.is_job_seeker,
is_allowed_to_use_gps,
login_url=reverse_lazy("dashboard:index"),
redirect_field_name=None,
)
Expand Down Expand Up @@ -39,7 +43,7 @@ def my_groups(request, template_name="gps/my_groups.html"):

@login_required
@user_passes_test(
lambda u: not u.is_job_seeker,
is_allowed_to_use_gps,
login_url=reverse_lazy("dashboard:index"),
redirect_field_name=None,
)
Expand Down Expand Up @@ -69,7 +73,7 @@ def join_group(request, template_name="gps/join_group.html"):

@login_required
@user_passes_test(
lambda u: not u.is_job_seeker,
is_allowed_to_use_gps,
login_url=reverse_lazy("dashboard:index"),
redirect_field_name=None,
)
Expand All @@ -87,7 +91,7 @@ def leave_group(request, group_id):

@login_required
@user_passes_test(
lambda u: not u.is_job_seeker,
is_allowed_to_use_gps,
login_url=reverse_lazy("dashboard:index"),
redirect_field_name=None,
)
Expand Down
7 changes: 7 additions & 0 deletions itou/www/users_views/views.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
from django.contrib.auth.mixins import LoginRequiredMixin
from django.core.exceptions import PermissionDenied
from django.urls import reverse
from django.views.generic import DetailView

from itou.gps.models import FollowUpGroupMembership
from itou.users.models import User
from itou.www.gps.views import is_allowed_to_use_gps


class UserDetailsView(LoginRequiredMixin, DetailView):
Expand All @@ -16,6 +18,11 @@ class UserDetailsView(LoginRequiredMixin, DetailView):
slug_url_kwarg = "public_id"
context_object_name = "beneficiary"

def setup(self, request, *args, **kwargs):
if request.user.is_authenticated and not is_allowed_to_use_gps(request.user):
raise PermissionDenied("Votre utilisateur n'est pas autorisé à accéder à ces informations.")
super().setup(request, *args, **kwargs)

def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context["gps_memberships"] = (
Expand Down
2 changes: 1 addition & 1 deletion tests/gps/__snapshots__/test_views.ambr
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@
</a>
</li>
<li class="d-flex justify-content-between align-items-center mb-3">
<a aria-label="Inviter un partenaire." class="btn-link btn-ico" data-matomo-action="clic" data-matomo-category="gps" data-matomo-event="true" data-matomo-option="tdb_inviter_partenaire" href="https://hello-tally.so/r/w5kLqM?user_public_id=03580247-b036-4578-bf9d-f92c9c2f68cd&amp;user_first_name=Pierre&amp;user_last_name=Dupont&amp;" rel="noopener" target="_blank">
<a aria-label="Inviter un partenaire." class="btn-link btn-ico" data-matomo-action="clic" data-matomo-category="gps" data-matomo-event="true" data-matomo-option="tdb_inviter_partenaire" href="https://hello-tally.so/r/w5kLqM?user_public_id=03580247-b036-4578-bf9d-f92c9c2f68cd&amp;user_first_name=Pierre&amp;user_last_name=Dupont&amp;&amp;user_organization_uid=0260ad4f-2008-48bd-88cc-b41c0211e219&amp;user_organization_name=Pres. Org." rel="noopener" target="_blank">
<i class="ri-mail-send-line ri-lg font-weight-normal align-self-start"></i>
<span>Inviter un partenaire</span>
<i class="ri-external-link-line font-weight-normal ms-2"></i>
Expand Down
19 changes: 12 additions & 7 deletions tests/gps/test_create_beneficiary.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ def test_create_job_seeker(_mock, client):
[city] = create_test_cities(["67"], num_per_department=1)
singleton = Company.unfiltered_objects.get(siret=companies_enums.POLE_EMPLOI_SIRET)

prescriber_organization = PrescriberOrganizationWithMembershipFactory(with_pending_authorization=True)
prescriber_organization = PrescriberOrganizationWithMembershipFactory(authorized=True)
user = prescriber_organization.members.first()
client.force_login(user)

Expand Down Expand Up @@ -337,21 +337,26 @@ def test_existing_user_with_nir(client):


@pytest.mark.parametrize(
"UserFactory, factory_args",
"UserFactory, factory_args, expected_access",
[
(PrescriberFactory, {"membership": True}),
(PrescriberFactory, {"membership": False}),
(EmployerFactory, {"with_company": True}),
(PrescriberFactory, {"membership": False}, False),
(PrescriberFactory, {"membership": True}, False),
(PrescriberFactory, {"membership__organization__authorized": True}, True),
(EmployerFactory, {"with_company": True}, True),
],
)
def test_creation_by_user_kind(client, UserFactory, factory_args):
def test_creation_by_user_kind(client, UserFactory, factory_args, expected_access):
singleton = Company.unfiltered_objects.get(siret=companies_enums.POLE_EMPLOI_SIRET)
user = UserFactory(**factory_args)
client.force_login(user)
# Assert contains link.
create_beneficiary_url = reverse("apply:start", kwargs={"company_pk": singleton.pk}) + "?gps=true"
response = client.get(reverse("gps:join_group"))
assertContains(response, create_beneficiary_url)
if expected_access:
assertContains(response, create_beneficiary_url)
else:
assertRedirects(response, reverse("dashboard:index"))

response = client.get(create_beneficiary_url)
assert response.status_code == 302
assert (
Expand Down
65 changes: 55 additions & 10 deletions tests/gps/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from django.conf import settings
from django.test.utils import override_settings
from django.urls import reverse
from pytest_django.asserts import assertContains
from pytest_django.asserts import assertContains, assertRedirects

from itou.gps.models import FollowUpGroup, FollowUpGroupMembership
from itou.users.enums import UserKind
Expand All @@ -20,6 +20,41 @@
from tests.utils.test import TestCase, parse_response_to_soup


def test_job_seeker_cannot_use_gps(client):
job_seeker = JobSeekerFactory()
client.force_login(job_seeker)
group = FollowUpGroupFactory(beneficiary=job_seeker)

for route, kwargs in [
("gps:my_groups", {}),
("gps:join_group", {}),
("gps:leave_group", {"group_id": group.pk}),
("gps:toggle_referent", {"group_id": group.pk}),
]:
response = client.get(reverse(route, kwargs=kwargs))
assertRedirects(response, reverse("dashboard:index"), fetch_redirect_response=False)
response = client.get(reverse("users:details", kwargs={"public_id": job_seeker.public_id}))
assert response.status_code == 403


def test_orienter_cannot_use_gps(client):
prescriber = PrescriberFactory()
job_seeker = JobSeekerFactory()
client.force_login(prescriber)
group = FollowUpGroupFactory(beneficiary=job_seeker, memberships__member=prescriber)

for route, kwargs in [
("gps:my_groups", {}),
("gps:join_group", {}),
("gps:leave_group", {"group_id": group.pk}),
("gps:toggle_referent", {"group_id": group.pk}),
Comment on lines +47 to +50
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Une assertion sur la longueur des URL patterns de gps ?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On commence à avoir des URLs en dehors de l'app donc je laisserai le soin à celui qui ajoute la prochaine vue de faire les tests appropriés :)

]:
response = client.get(reverse(route, kwargs=kwargs))
assertRedirects(response, reverse("dashboard:index"), fetch_redirect_response=False)
response = client.get(reverse("users:details", kwargs={"public_id": job_seeker.public_id}))
assert response.status_code == 403


# To be able to use assertCountEqual
class GpsTest(TestCase):
def test_user_autocomplete(self):
Expand Down Expand Up @@ -68,7 +103,7 @@ def test_user_autocomplete(self):
],
)
def test_join_group_of_a_job_seeker(is_referent, client, snapshot):
prescriber = PrescriberFactory(membership=True)
prescriber = PrescriberFactory(membership__organization__authorized=True)
job_seeker = JobSeekerFactory()

client.force_login(prescriber)
Expand Down Expand Up @@ -96,7 +131,7 @@ def test_join_group_of_a_job_seeker(is_referent, client, snapshot):
assert membership.is_referent == is_referent

# Login with another prescriber and join the same follow_up_group
other_prescriber = PrescriberFactory(membership=True)
other_prescriber = PrescriberFactory(membership__organization__authorized=True)

client.force_login(other_prescriber)

Expand All @@ -117,7 +152,7 @@ def test_join_group_of_a_job_seeker(is_referent, client, snapshot):


def test_join_group_of_a_prescriber(client):
prescriber = PrescriberFactory(membership=True)
prescriber = PrescriberFactory(membership__organization__authorized=True)
another_prescriber = PrescriberFactory(membership=True)

client.force_login(prescriber)
Expand All @@ -144,15 +179,20 @@ def test_join_group_of_a_prescriber(client):

@override_settings(TALLY_URL="https://hello-tally.so")
def test_dashboard_card(snapshot, client):
member = PrescriberFactory(for_snapshot=True)
member = PrescriberFactory(
for_snapshot=True,
membership=True,
membership__organization__authorized=True,
membership__organization__for_snapshot=True,
)
client.force_login(member)
response = client.get(reverse("dashboard:index"))
assert str(parse_response_to_soup(response, "#gps-card")) == snapshot


@freezegun.freeze_time("2024-06-21", tick=True)
def test_my_groups(snapshot, client):
user = PrescriberFactory()
user = PrescriberFactory(membership__organization__authorized=True, membership__organization__for_snapshot=True)
client.force_login(user)

# Was created in bulk.
Expand Down Expand Up @@ -207,7 +247,7 @@ def test_access_as_jobseeker(client):


def test_leave_group(client):
member = PrescriberFactory(membership=True)
member = PrescriberFactory(membership__organization__authorized=True)
another_member = PrescriberFactory(membership=True)

beneficiary = JobSeekerFactory()
Expand Down Expand Up @@ -243,7 +283,7 @@ def test_leave_group(client):


def test_referent_group(client):
prescriber = PrescriberFactory(membership=True)
prescriber = PrescriberFactory(membership__organization__authorized=True)

beneficiary = JobSeekerFactory()

Expand All @@ -264,7 +304,12 @@ def test_referent_group(client):

@freezegun.freeze_time("2024-06-21")
def test_beneficiary_details(client, snapshot):
prescriber = PrescriberFactory(membership=True, for_snapshot=True, membership__organization__name="Les Olivades")
prescriber = PrescriberFactory(
membership=True,
for_snapshot=True,
membership__organization__name="Les Olivades",
membership__organization__authorized=True,
)
beneficiary = JobSeekerFactory(for_snapshot=True)
FollowUpGroupFactory(beneficiary=beneficiary, memberships=1, memberships__member=prescriber)

Expand All @@ -281,7 +326,7 @@ def test_beneficiary_details(client, snapshot):


def test_remove_members_from_group(client):
prescriber = PrescriberFactory(membership=True)
prescriber = PrescriberFactory(membership__organization__authorized=True)

beneficiary = JobSeekerFactory()

Expand Down
1 change: 1 addition & 0 deletions tests/prescribers/factories.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ class Params:
authorization_status=PrescriberAuthorizationStatus.NOT_SET,
)
for_snapshot = factory.Trait(
uid="0260ad4f-2008-48bd-88cc-b41c0211e219",
name="Pres. Org.",
address_line_1="39 rue d'Artois",
post_code="75008",
Expand Down
9 changes: 8 additions & 1 deletion tests/www/dashboard/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -631,12 +631,19 @@ def test_gps_card_is_shown_for_employer(self):
self.client.get(reverse("dashboard:index"))

def test_gps_card_is_shown_for_prescriber(self):
prescriber_organization = prescribers_factories.PrescriberOrganizationWithMembershipFactory()
prescriber_organization = prescribers_factories.PrescriberOrganizationWithMembershipFactory(authorized=True)
self.client.force_login(prescriber_organization.members.first())

with self.assertTemplateUsed("dashboard/includes/gps_card.html"):
self.client.get(reverse("dashboard:index"))

def test_gps_card_is_not_shown_for_orienter(self):
prescriber_organization = prescribers_factories.PrescriberOrganizationWithMembershipFactory()
self.client.force_login(prescriber_organization.members.first())

with self.assertTemplateNotUsed("dashboard/includes/gps_card.html"):
self.client.get(reverse("dashboard:index"))

def test_dashboard_prescriber_without_organization_message(self):
# An orienter is a prescriber without prescriber organization
orienter = PrescriberFactory()
Expand Down