Source code for akvo.rest.views.user_management

# -*- coding: utf-8 -*-
"""Akvo RSR is covered by the GNU Affero General Public License.

See more details in the license.txt file located at the root folder of the Akvo RSR module.
For additional details on the GNU license please see < http://www.gnu.org/licenses/agpl.html >.
"""

import json

from django.contrib.auth.models import Group
from django.core.exceptions import ValidationError
from django.core.validators import validate_email
from django.utils.translation import gettext_lazy as _

from rest_framework import status
from rest_framework.decorators import api_view, permission_classes
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response

from .utils import create_invited_user
from akvo.utils import send_user_invitation
from ...rsr.models import Employment, Organisation


[docs]def valid_email(email_address): try: validate_email(email_address) return True except ValidationError: return False
[docs]@api_view(['POST']) @permission_classes((IsAuthenticated, )) def invite_user(request): """ Invite a new user to RSR. :param request; request.data is a JSON string containing email, organisation and group data """ user = request.user if not user.has_perm('rsr.user_management'): return Response('Request not allowed', status=status.HTTP_403_FORBIDDEN) # Check if all information is present, and if the organisation and group exist data, missing_data = request.data.get('user_data'), [] if not data: missing_data.extend(['email', 'organisation', 'group']) return Response({'missing_data': missing_data}, status=status.HTTP_400_BAD_REQUEST) else: data = json.loads(data) # Check organisation try: organisation = Organisation.objects.get(pk=int(data['organisation'])) except (Organisation.DoesNotExist, ValueError): missing_data.append('organisation') # Check email email = data['email'].lower().strip() if not (email and valid_email(email)): missing_data.append('email') elif user.email == email and organisation: # Only superusers, RSR admins and organisation admins can invite themselves if not (user.is_admin or user.is_superuser): admin_group = Group.objects.get(name='Admins') content_owned = [] for empl in Employment.objects.filter(user=user, group=admin_group).exclude( organisation=None): content_owned += empl.organisation.content_owned_organisations() if organisation not in content_owned: missing_data.append('email') # Check group try: group = Group.objects.get(pk=int(data['group'])) except (Group.DoesNotExist, ValueError): missing_data.append('group') if missing_data: return Response({'missing_data': missing_data}, status=status.HTTP_400_BAD_REQUEST) invited_user = create_invited_user(email) if invited_user is None: return Response({'error': _('Trying to create a user that already exists')}, status=status.HTTP_500_INTERNAL_SERVER_ERROR) if employ_user(invited_user, organisation, group, user): return Response('User invited', status=status.HTTP_201_CREATED) else: return Response('Employment already exists', status=status.HTTP_200_OK)
[docs]def employ_user(invited_user, organisation, group, inviting_user): if invited_user.is_active: # For active users, we know their email address is correct so we approve their new # employment immediately. They'll get a mail that their employment is approved. employment, created = Employment.objects.get_or_create( user=invited_user, organisation=organisation, group=group, # NOTE: Create approved employment to avoid sending 'organisation request' mail defaults=dict(is_approved=True) ) if created: # HACK: We force approve to log, instead of manually logging. # Creating an unapproved employment, to start with, isn't ideal # since this would send approval requests to a bunch of users with # the permissions to approve. employment.is_approved = False employment.approve(inviting_user) elif not employment.is_approved: # Approve the existing unapproved employment employment.approve(inviting_user) else: return False else: # Create an unapproved employment for inactive users employment, __ = Employment.objects.get_or_create( user=invited_user, organisation=organisation, group=group, ) send_user_invitation(invited_user.email, inviting_user, invited_user, employment) return True