Skip to content

Commit

Permalink
Merge pull request #2647 from onaio/update-organization-serializer
Browse files Browse the repository at this point in the history
Add email field to the organization serializer
  • Loading branch information
FrankApiyo authored Jul 26, 2024
2 parents 98064d1 + a098af0 commit 1b6fb36
Show file tree
Hide file tree
Showing 5 changed files with 68 additions and 8 deletions.
5 changes: 5 additions & 0 deletions onadata/apps/api/models/organization_profile.py
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,11 @@ def __str__(self):
def save(self, *args, **kwargs): # pylint: disable=arguments-differ
super().save(*args, **kwargs)

@property
def email(self):
"organization email"
return self.user.email

def remove_user_from_organization(self, user):
"""Removes a user from all teams/groups in the organization.
Expand Down
2 changes: 2 additions & 0 deletions onadata/apps/api/tests/viewsets/test_abstract_viewset.py
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,7 @@ def _org_create(self, org_data=None):
response = view(request)
self.assertEqual(response.status_code, 200)
data = {
"email": "[email protected]",
"org": "denoinc",
"name": "Dennis",
"city": "Denoville",
Expand All @@ -224,6 +225,7 @@ def _org_create(self, org_data=None):
data["url"] = f"http://testserver/api/v1/orgs/{data['org']}"
data["user"] = f"http://testserver/api/v1/users/{data['org']}"
data["creator"] = "http://testserver/api/v1/users/bob"
data.pop("email")
self.assertDictContainsSubset(data, response.data)
# pylint: disable=attribute-defined-outside-init
self.company_data = response.data
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from builtins import str as text
from unittest.mock import patch

from django.contrib.auth.models import User, timezone
from django.contrib.auth.models import User, timezone, AnonymousUser
from django.core.cache import cache
from django.test.utils import override_settings

Expand Down Expand Up @@ -89,6 +89,7 @@ def test_orgs_list(self):
self.assertNotEqual(response.get("Cache-Control"), None)
self.assertEqual(response.status_code, 200)
del self.company_data["metadata"]
del self.company_data["email"]
self.assertEqual(response.data, [self.company_data])

# inactive organization
Expand All @@ -113,6 +114,7 @@ def test_orgs_list_for_authenticated_user(self):
self.assertNotEqual(response.get("Cache-Control"), None)
self.assertEqual(response.status_code, 200)
del self.company_data["metadata"]
del self.company_data["email"]
self.assertEqual(response.data, [self.company_data])

def test_orgs_list_shared_with_user(self):
Expand Down Expand Up @@ -194,6 +196,8 @@ def test_orgs_get_not_creator(self):
response = view(request, user="denoinc")
self.assertNotEqual(response.get("Cache-Control"), None)
self.assertEqual(response.status_code, 200)
del self.company_data['email']
del self.company_data['metadata']
self.assertEqual(response.data, self.company_data)
self.assertIn("users", list(response.data))
for user in response.data["users"]:
Expand All @@ -207,6 +211,8 @@ def test_orgs_get_anon(self):
response = view(request, user="denoinc")
self.assertNotEqual(response.get("Cache-Control"), None)
self.assertEqual(response.status_code, 200)
del self.company_data["email"]
del self.company_data['metadata']
self.assertEqual(response.data, self.company_data)
self.assertIn("users", list(response.data))
for user in response.data["users"]:
Expand All @@ -216,12 +222,14 @@ def test_orgs_get_anon(self):
def test_orgs_create(self):
self._org_create()
self.assertTrue(self.organization.user.is_active)
self.assertEqual(self.organization.user.email, "[email protected]")

def test_orgs_create_without_name(self):
data = {
"org": "denoinc",
"city": "Denoville",
"country": "US",
"email": "[email protected]",
"home_page": "deno.com",
"twitter": "denoinc",
"description": "",
Expand All @@ -235,6 +243,29 @@ def test_orgs_create_without_name(self):
response = self.view(request)
self.assertEqual(response.data, {"name": ["This field is required."]})

def test_org_create_and_fetch_by_admin_user(self):
org_email = "[email protected]"
data = {
"name": "denoinc",
"org": "denoinc",
"city": "Denoville",
"country": "US",
"home_page": "deno.com",
"twitter": "denoinc",
"email": org_email,
"description": "",
"address": "",
"phonenumber": "",
"require_auth": False,
}
request = self.factory.post(
"/", data=json.dumps(data), content_type="application/json"
)
request.user = self.user
response = self.view(request)
self.assertEqual(response.status_code, 201)
self.assertEqual(response.data['email'], org_email)

def test_org_create_with_anonymous_user(self):
data = {
"name": "denoinc",
Expand Down Expand Up @@ -389,6 +420,7 @@ def test_member_sees_orgs_added_to(self):
}
)
del expected_data["metadata"]
del expected_data['email']

request = self.factory.get("/", **self.extra)
response = view(request)
Expand Down Expand Up @@ -420,6 +452,8 @@ def test_role_for_org_non_owner(self):
request = self.factory.get("/", **self.extra)
response = view(request, user="denoinc")
self.assertEqual(response.status_code, 200)
self.assertTrue('email' in response.data)
self.assertEqual(response.data['email'], '[email protected]')
self.assertIn("users", list(response.data))

for user in response.data["users"]:
Expand All @@ -432,6 +466,21 @@ def test_role_for_org_non_owner(self):
)
self.assertEqual(role, expected_role)

# getting profile as a member
request = self.factory.get("/", **self.extra)
request.user = User.objects.get(username="aboy")
response = view(request, user="denoinc")
self.assertEqual(response.status_code, 200)

# get profile as a anonymous user
request = self.factory.get("/", **self.extra)
request.user = AnonymousUser()
request.headers = None
request.META['HTTP_AUTHORIZATION'] = ""
response = view(request, user="denoinc")
self.assertEqual(response.status_code, 200)
self.assertFalse('email' in response.data)

def test_add_members_to_org_with_anonymous_user(self):
self._org_create()
view = OrganizationProfileViewSet.as_view({"post": "members"})
Expand Down Expand Up @@ -561,6 +610,7 @@ def test_orgs_create_with_mixed_case(self):
"home_page": "deno.com",
"twitter": "denoinc",
"description": "",
"email": "[email protected]",
"address": "",
"phonenumber": "",
"require_auth": False,
Expand Down
14 changes: 8 additions & 6 deletions onadata/apps/api/viewsets/organization_profile_viewset.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,32 +66,34 @@ class OrganizationProfileViewSet(
def retrieve(self, request, *args, **kwargs):
"""Get organization from cache or db"""
username = kwargs.get("user")
cached_org = cache.get(f"{ORG_PROFILE_CACHE}{username}")
cache_key = f"{ORG_PROFILE_CACHE}{username}{request.user.username}"
cached_org = cache.get(cache_key)
if cached_org:
return Response(cached_org)
response = super().retrieve(request, *args, **kwargs)
cache.set(f"{ORG_PROFILE_CACHE}{username}", response.data)
cache.set(cache_key, response.data)
return response

def create(self, request, *args, **kwargs):
"""Create and cache organization"""
response = super().create(request, *args, **kwargs)
organization = response.data
username = organization.get("org")
cache.set(f"{ORG_PROFILE_CACHE}{username}", organization)
cache.set(f"{ORG_PROFILE_CACHE}{username}{request.user.username}", organization)
return response

def destroy(self, request, *args, **kwargs):
"""Clear cache and destroy organization"""
username = kwargs.get("user")
safe_delete(f"{ORG_PROFILE_CACHE}{username}")
safe_delete(f"{ORG_PROFILE_CACHE}{username}{request.user.username}")
return super().destroy(request, *args, **kwargs)

def update(self, request, *args, **kwargs):
"""Update org in cache and db"""
username = kwargs.get("user")
response = super().update(request, *args, **kwargs)
cache.set(f"{ORG_PROFILE_CACHE}{username}", response.data)
cache_key = f"{ORG_PROFILE_CACHE}{username}{request.user.username}"
cache.set(cache_key, response.data)
return response

@action(methods=["DELETE", "GET", "POST", "PUT"], detail=True)
Expand Down Expand Up @@ -120,7 +122,7 @@ def members(self, request, *args, **kwargs):
data = OrganizationSerializer(
organization, context={"request": request}
).data
cache.set(f"{ORG_PROFILE_CACHE}{username}", data)
cache.set(f"{ORG_PROFILE_CACHE}{username}{request.user.username}", data)
else:
return Response(data=serializer.errors, status=status.HTTP_400_BAD_REQUEST)

Expand Down
3 changes: 2 additions & 1 deletion onadata/libs/serializers/organization_serializer.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ class OrganizationSerializer(serializers.HyperlinkedModelSerializer):
user = serializers.HyperlinkedRelatedField(
view_name="user-detail", lookup_field="username", read_only=True
)
email = serializers.EmailField(allow_blank=True)
creator = serializers.HyperlinkedRelatedField(
view_name="user-detail", lookup_field="username", read_only=True
)
Expand All @@ -47,7 +48,7 @@ class OrganizationSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = OrganizationProfile
exclude = ("created_by", "is_organization", "organization")
owner_only_fields = ("metadata",)
owner_only_fields = ("metadata", "email")

def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
Expand Down

0 comments on commit 1b6fb36

Please sign in to comment.