(contacts) list profile contacts from same org

Allow the contact API to list "profile" contacts for
user of the same organization.
This commit is contained in:
Quentin BEY
2024-12-04 16:54:10 +01:00
committed by BEY Quentin
parent c54f010989
commit 579aac264e
4 changed files with 69 additions and 24 deletions

View File

@@ -12,8 +12,9 @@ and this project adheres to
### Added
- ✨(contacts) return profile contact from same organization
- ✨(dimail) automate allows requests to dimail
- ✨(contacts) add notes & force full_name #565
- ✨(contacts) add notes & force full_name #565
### Changed

View File

@@ -139,19 +139,21 @@ class ContactViewSet(
queryset = models.Contact.objects.all()
serializer_class = serializers.ContactSerializer
throttle_classes = [BurstRateThrottle, SustainedRateThrottle]
ordering_fields = ["full_name", "short_name", "created_at"]
ordering = ["full_name"]
def list(self, request, *args, **kwargs):
"""Limit listed users by a query with throttle protection."""
user = self.request.user
queryset = self.filter_queryset(self.get_queryset())
# Exclude contacts that:
# List only contacts that:
queryset = queryset.filter(
# - belong to another user (keep public and owned contacts)
Q(owner__isnull=True) | Q(owner=user),
# - are profile contacts for a user
user__isnull=True,
# - are overriden base contacts
# - are owned by the user
Q(owner=user)
# - are profile contacts for a user from the same organization
| Q(user__organization_id=user.organization_id),
# - are not overriden by another contact
overridden_by__isnull=True,
)

View File

@@ -118,6 +118,16 @@ class ContactFactory(BaseContactFactory):
owner = factory.SubFactory("core.factories.UserFactory")
class ProfileContactFactory(BaseContactFactory):
"""A factory to create profile contacts for a user"""
class Meta:
model = models.Contact
owner = factory.SelfAttribute(".user")
user = factory.SubFactory("core.factories.UserFactory")
class OverrideContactFactory(BaseContactFactory):
"""A factory to create contacts for a user"""

View File

@@ -27,18 +27,32 @@ def test_api_contacts_list_authenticated_no_query():
Authenticated users should be able to list contacts without applying a query.
Profile and overridden contacts should be excluded.
"""
user = factories.UserFactory()
factories.ContactFactory(owner=user, user=user)
organization = factories.OrganizationFactory(with_registration_id=True)
user = factories.UserFactory(organization=organization)
# Let's have 5 contacts in database:
assert user.profile_contact is not None # Excluded because profile contact
base_contact = factories.BaseContactFactory() # Excluded because overridden
factories.ContactFactory(
override=base_contact
) # Excluded because belongs to other user
contact2 = factories.ContactFactory(
override=base_contact, owner=user, full_name="Bernard"
) # Included
# The user's profile contact should be listed (why not)
user_profile_contact = factories.ContactFactory(
owner=user, user=user, full_name="Dave Bowman"
)
# A contact that belongs to another user should not be listed
factories.ContactFactory()
# even if from the same organization
factories.ContactFactory(owner__organization=organization)
# A profile contact should not be listed if from another organization
factories.ProfileContactFactory()
# A profile contact for someone in the same organization should be listed
profile_contact = factories.ProfileContactFactory(
user__organization=organization, full_name="Frank Poole"
)
# An overridden contact should not be listed, but the override must be
overriden_contact = factories.ProfileContactFactory(user__organization=organization)
override_contact = factories.ContactFactory(
owner=user, override=overriden_contact, full_name="Nicole Foole"
)
client = APIClient()
client.force_login(user)
@@ -48,13 +62,31 @@ def test_api_contacts_list_authenticated_no_query():
assert response.status_code == 200
assert response.json() == [
{
"id": str(contact2.id),
"override": str(base_contact.id),
"owner": str(contact2.owner.id),
"data": contact2.data,
"full_name": contact2.full_name,
"id": str(user_profile_contact.pk),
"override": None,
"owner": str(user.pk),
"data": user_profile_contact.data,
"full_name": user_profile_contact.full_name,
"notes": "",
"short_name": contact2.short_name,
"short_name": user_profile_contact.short_name,
},
{
"id": str(profile_contact.pk),
"override": None,
"owner": str(profile_contact.user.pk),
"data": profile_contact.data,
"full_name": profile_contact.full_name,
"notes": "",
"short_name": profile_contact.short_name,
},
{
"id": str(override_contact.pk),
"override": str(overriden_contact.pk),
"owner": str(user.pk),
"data": override_contact.data,
"full_name": override_contact.full_name,
"notes": "",
"short_name": override_contact.short_name,
},
]