Skip to content

Commit

Permalink
Update flow to allow the registration of other NGO users
Browse files Browse the repository at this point in the history
  • Loading branch information
tudoramariei committed Nov 12, 2024
1 parent e81658f commit 174f29f
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 48 deletions.
1 change: 1 addition & 0 deletions backend/accounts/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
COMMITTEE_GROUP = "Comisie Electorala"
SUPPORT_GROUP = "Support Staff"
NGO_GROUP = "ONG"
NGO_USERS_GROUP = "ONG Users"


class User(AbstractUser, TimeStampedModel):
Expand Down
7 changes: 6 additions & 1 deletion backend/hub/management/commands/init.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from django.core.management.base import BaseCommand
from guardian.shortcuts import assign_perm

from accounts.models import COMMITTEE_GROUP, NGO_GROUP, STAFF_GROUP, SUPPORT_GROUP
from accounts.models import COMMITTEE_GROUP, NGO_GROUP, NGO_USERS_GROUP, STAFF_GROUP, SUPPORT_GROUP
from hub.models import City, FLAG_CHOICES, FeatureFlag


Expand Down Expand Up @@ -41,6 +41,11 @@ def _initialize_groups_permissions(self):
assign_perm("hub.vote_candidate", ngo_group)
assign_perm("hub.change_organization", ngo_group)

ngo_users_group: Group = Group.objects.get_or_create(name=NGO_USERS_GROUP)[0]
assign_perm("hub.support_candidate", ngo_users_group)
assign_perm("hub.vote_candidate", ngo_users_group)
assign_perm("hub.change_organization", ngo_users_group)

def _initialize_feature_flags(self):
self.stdout.write(self.style.NOTICE("Initializing feature flags..."))

Expand Down
13 changes: 8 additions & 5 deletions backend/hub/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -824,6 +824,13 @@ def count_confirmations(self):
unique_confirmations = confirmations.values("user").distinct()
return unique_confirmations.count()

def update_users_permissions(self):
for org_user in self.org.users.all():
assign_perm("view_candidate", org_user, self)
assign_perm("change_candidate", org_user, self)
assign_perm("delete_candidate", org_user, self)
assign_perm("view_data_candidate", org_user, self)

def save(self, *args, **kwargs):
create = False if self.id else True

Expand All @@ -845,11 +852,7 @@ def save(self, *args, **kwargs):
super().save(*args, **kwargs)

if create:
for org_user in self.org.users.all():
assign_perm("view_candidate", org_user, self)
assign_perm("change_candidate", org_user, self)
assign_perm("delete_candidate", org_user, self)
assign_perm("view_data_candidate", org_user, self)
self.update_users_permissions()


class CandidateVote(TimeStampedModel):
Expand Down
81 changes: 41 additions & 40 deletions backend/hub/social_adapters.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,9 @@
from django.urls import reverse
from django.utils.translation import gettext as _

from accounts.models import NGO_GROUP, STAFF_GROUP, User
from accounts.models import NGO_GROUP, NGO_USERS_GROUP, STAFF_GROUP, User
from hub.exceptions import (
ClosedRegistrationException,
DuplicateOrganizationException,
MissingOrganizationException,
NGOHubHTTPException,
)
Expand All @@ -43,7 +42,7 @@ def ngohub_api_get(path: str, token: str):
return response.json()


def update_user_org(org: Organization, token: str, *, in_auth_flow: bool = False) -> None:
def update_user_org(user, org: Organization, token: str, *, in_auth_flow: bool = False) -> None:
"""
Update an Organization by pulling data from NGO Hub.
Expand All @@ -52,7 +51,7 @@ def update_user_org(org: Organization, token: str, *, in_auth_flow: bool = False
"""

# Check if the new organization registration is still open
if org.status == Organization.STATUS.draft and not FeatureFlag.flag_enabled("enable_org_registration"):
if not org and not FeatureFlag.flag_enabled("enable_org_registration"):
if in_auth_flow:
raise ImmediateHttpResponse(redirect(reverse("error-org-registration-closed")))
else:
Expand All @@ -61,7 +60,7 @@ def update_user_org(org: Organization, token: str, *, in_auth_flow: bool = False
)

# If the current organization is not already linked to NGO Hub, check the NGO Hub API for the data
if not org.ngohub_org_id:
if not org:
ngohub_org = ngohub_api_get("organization-profile/", token)

# Check that an NGO Hub organization appears only once in VotONG
Expand All @@ -72,17 +71,19 @@ def update_user_org(org: Organization, token: str, *, in_auth_flow: bool = False
else:
raise MissingOrganizationException(_("There is no NGO Hub organization for this VotONG user."))

# Check that the current user has an NGO Hub organization
if Organization.objects.filter(ngohub_org_id=ngohub_id).exclude(pk=org.pk).count():
if in_auth_flow:
raise ImmediateHttpResponse(redirect(reverse("error-org-duplicate")))
else:
raise DuplicateOrganizationException(
_("This NGO Hub organization already exists for another VotONG user.")
)
# Check that the user's organization doesn't already exist in VotONG
if Organization.objects.filter(ngohub_org_id=ngohub_id).exists():
org = Organization.objects.get(ngohub_org_id=ngohub_id)
user.organization = org
user.save()

if org.candidate:
org.candidate.update_users_permissions()
else:
org = create_user_org(user)

org.ngohub_org_id = ngohub_id
org.save()
org.ngohub_org_id = ngohub_id
org.save()

update_organization(org.id, token)

Expand Down Expand Up @@ -118,6 +119,27 @@ def create_user_org(user: User) -> Organization:
return org


def get_user_for_org(user, user_token: str, user_role: str):
if not check_app_enabled_in_ngohub(user_token):
if user.is_active:
user.is_active = False
user.save()

raise ImmediateHttpResponse(redirect(reverse("error-app-missing")))
elif not user.is_active:
user.is_active = True
user.save()

# Add the user to the NGO group
ngo_group: Group = Group.objects.get(name=user_role)
user.groups.add(ngo_group)

if not (org := user.organization):
org = None

return org


def update_user_information(user: User, token: str):
try:
user_profile: Dict = ngohub_api_get("profile/", token)
Expand All @@ -140,32 +162,15 @@ def update_user_information(user: User, token: str):

user.groups.add(Group.objects.get(name=STAFF_GROUP))
user.groups.remove(Group.objects.get(name=NGO_GROUP))
user.groups.remove(Group.objects.get(name=NGO_USERS_GROUP))

return None

elif user_role == settings.NGOHUB_ROLE_NGO_ADMIN:
if not check_app_enabled_in_ngohub(token):
if user.is_active:
user.is_active = False
user.save()

raise ImmediateHttpResponse(redirect(reverse("error-app-missing")))
elif not user.is_active:
user.is_active = True
user.save()

# Add the user to the NGO group
ngo_group: Group = Group.objects.get(name=NGO_GROUP)
user.groups.add(ngo_group)

if not (org := user.organization):
org = None

return org
return get_user_for_org(user, token, NGO_GROUP)

elif user_role == settings.NGOHUB_ROLE_NGO_EMPLOYEE:
# Employees cannot have organizations
raise ImmediateHttpResponse(redirect(reverse("error-user-role")))
return get_user_for_org(user, token, NGO_USERS_GROUP)

else:
# Unknown user role
Expand All @@ -182,11 +187,7 @@ def common_user_init(sociallogin: SocialLogin) -> User:
if user.groups.filter(name=STAFF_GROUP).exists():
return user

# Start the import of initial data from NGO Hub
if not org:
org = create_user_org(user)

update_user_org(org, sociallogin.token.token, in_auth_flow=True)
update_user_org(user, org, sociallogin.token.token, in_auth_flow=True)

return user

Expand Down
4 changes: 2 additions & 2 deletions backend/hub/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
from guardian.mixins import LoginRequiredMixin, PermissionRequiredMixin
from sentry_sdk import capture_message

from accounts.models import COMMITTEE_GROUP, NGO_GROUP, STAFF_GROUP, SUPPORT_GROUP, User
from accounts.models import COMMITTEE_GROUP, NGO_GROUP, NGO_USERS_GROUP, STAFF_GROUP, SUPPORT_GROUP, User
from civil_society_vote.common.messaging import send_email
from hub.forms import (
CandidateRegisterForm,
Expand Down Expand Up @@ -244,7 +244,7 @@ class ElectorCandidatesListView(LoginRequiredMixin, SearchMixin):
template_name = "hub/ngo/votes.html"

def get_queryset(self):
if not self.request.user.groups.filter(name__in=[NGO_GROUP]).exists():
if not self.request.user.groups.filter(name__in=[NGO_GROUP, NGO_USERS_GROUP]).exists():
raise PermissionDenied

voted_candidates = CandidateVote.objects.filter(user=self.request.user)
Expand Down

0 comments on commit 174f29f

Please sign in to comment.