예제 #1
0
def send_return_for_revision_email(update):
    user_id = update.user_id
    indicator = update.period.indicator
    project = indicator.result.project
    project_id = project.id
    context = dict(
        title=project.title,
        indicator_title=indicator.title,
        enumerator=update.user,
        results_url=
        f'https://{settings.RSR_DOMAIN}/my-rsr/projects/{project_id}/results',
    )

    assigned_user = update.period.indicator.enumerators.filter(
        id=user_id).exists()
    if assigned_user:
        token = _update_user_token(user_id, project_id)
        jwt = token.jwt()
        results_url = context['results_url']
        context['results_url'] = f"{results_url}/?rt={jwt}"

    rsr_send_mail([update.user.email],
                  subject='enumerators/returned_for_revision_subject.txt',
                  message='enumerators/returned_for_revision_message.txt',
                  subject_context=context,
                  msg_context=context)
예제 #2
0
def employment_pre_save(sender, **kwargs):
    """
    Send a mail to the user when his/her account has been approved.
    """
    employment = kwargs.get("instance", False)
    try:
        obj = sender.objects.get(pk=employment.pk)
    except sender.DoesNotExist:
        # Object is new
        pass
    else:
        if not obj.is_approved and employment.is_approved:
            # Employment is approved, send mail
            rsr_send_mail(
                [employment.user.email],
                subject='registration/approved_email_subject.txt',
                message='registration/approved_email_message.txt',
                subject_context={
                    'organisation': employment.organisation,
                },
                msg_context={
                    'user': employment.user,
                    'organisation': employment.organisation,
                }
            )
예제 #3
0
    def send_mail(self):
        """
        Send an email to the RSR admins (gathered from settings) and the user linked to the
        IATI import instance.
        """
        email_addresses = [email for _name, email in settings.ADMINS]
        email_addresses.append(self.user.email)

        rsr_send_mail(
            email_addresses,
            subject='iati_import/import_done_subject.txt',
            message='iati_import/import_done_message.txt',
            subject_context={
                'iati_import': self.iati_import
            },
            msg_context={
                'iati_import': self.iati_import,
                'project_count': self.iati_import.iati_project_imports.count(),
                'projects_created': self.iati_import.iati_project_imports.filter(
                    action=IatiProjectImport.CREATE_ACTION
                ).count(),
                'projects_updated': self.iati_import.iati_project_imports.filter(
                    action=IatiProjectImport.UPDATE_ACTION
                ).count(),
                'projects_published': self.iati_import.projects.published().count(),
                'critical_errors_log': self.iati_import.iati_import_logs.filter(
                    severity=IatiImportLog.CRITICAL_ERROR
                ),
                'warnings_log': self.iati_import.iati_import_logs.filter(severity__in=[
                    IatiImportLog.VALUE_PARTLY_SAVED, IatiImportLog.VALUE_NOT_SAVED
                ]),
                'projects_log': self.iati_import.iati_project_imports.all()
            },
            html_message='iati_import/import_done_message.html'
        )
예제 #4
0
    def approve_employment(invitee, invited, empl):
        """
        Approves the employment and sends a mail to the user that has invited the new user.

        :param invitee: the invitee user's instance
        :param invited: the invited user's instance
        :param empl: the employment's instance
        """
        empl.approve(invitee)

        if invitee:
            # Send notification email to inviting user
            rsr_send_mail(
                [invitee.email],
                subject='registration/inviting_user_notification_subject.txt',
                message='registration/inviting_user_notification_message.txt',
                html_message=
                'registration/inviting_user_notification_message.html',
                subject_context={
                    'user': invited,
                },
                msg_context={
                    'invited_user': invited,
                    'inviting_user': invitee,
                    'organisation': empl.organisation,
                })
예제 #5
0
    def approve_employment(invitee, invited, empl):
        """
        Approves the employment and sends a mail to the user that has invited the new user.

        :param invitee: the invitee user's instance
        :param invited: the invited user's instance
        :param empl: the employment's instance
        """
        empl.approve(invitee)

        if invitee:
            # Send notification email to inviting user
            rsr_send_mail(
                [invitee.email],
                subject='registration/inviting_user_notification_subject.txt',
                message='registration/inviting_user_notification_message.txt',
                html_message='registration/inviting_user_notification_message.html',
                subject_context={
                    'user': invited,
                },
                msg_context={
                    'invited_user': invited,
                    'inviting_user': invitee,
                    'organisation': empl.organisation,
                }
            )
예제 #6
0
파일: signals.py 프로젝트: zuhdil/akvo-rsr
def employment_pre_save(sender, **kwargs):
    """
    This signal intends to send a mail to the user when his/her account has been approved.

    This signal also sets 'Users' Group for the employment if no group has been set

    A mail will be sent when:

    - A new employment is created with is_approved = True.
      * We assume this happens when an existing user is invited for a new organisation.
    - An existing employment is updated from is_approved = False changed to True.
      * We assume this happens when an existing user has requested to join an organisation himself.
    """
    # FIXME: The actual save may fail. Why are emails being sent pre_save?!
    employment = kwargs.get("instance", None)

    if not employment:
        return

    # If this is an employment with a shadow org, don't send email
    if employment.organisation.original is not None:
        return

    # Set the group to 'Users' when no group has been specified
    if not employment.group:
        employment.group = Group.objects.get(name='Users')

    try:
        obj = sender.objects.get(pk=employment.pk)
    except sender.DoesNotExist:
        # Employment is new, send mail when it is also approved
        if employment.is_approved:
            rsr_send_mail(
                [employment.user.email],
                subject='registration/approved_added_email_subject.txt',
                message='registration/approved_added_email_message.txt',
                subject_context={
                    'organisation': employment.organisation,
                },
                msg_context={
                    'user': employment.user,
                    'organisation': employment.organisation,
                })
    else:
        # Employment already exists, send mail when it wasn't approved before, but is approved now.
        if not obj.is_approved and employment.is_approved:
            rsr_send_mail(
                [employment.user.email],
                subject='registration/approved_request_email_subject.txt',
                message='registration/approved_request_email_message.txt',
                subject_context={
                    'organisation': employment.organisation,
                },
                msg_context={
                    'user': employment.user,
                    'organisation': employment.organisation,
                })
예제 #7
0
    def send_mail(self):
        """
        Send an email to the RSR admins (gathered from settings) and the user linked to the
        IATI import instance.
        """

        email_addresses = [email for _name, email in settings.ADMINS]
        email_addresses.append(self.iati_import.user.email)

        attachments = []
        attachments.extend(self.get_log_csv(self.CRITICAL_LOG))
        attachments.extend(self.get_log_csv(self.WARNINGS_LOG))
        attachments.extend(self.get_log_csv(self.FULL_LOG))

        rsr_send_mail(
            email_addresses,
            subject='iati_import/import_done_subject.txt',
            message='iati_import/import_done_message.txt',
            subject_context={
                'iati_import_job': self,
            },
            msg_context={
                'iati_import_job':
                self,
                'project_count':
                self.projects.count(),
                'projects_created':
                self.iati_import_logs.filter(
                    message_type=LOG_ENTRY_TYPE.ACTION_CREATE).count(),
                'projects_updated':
                self.iati_import_logs.filter(
                    message_type=LOG_ENTRY_TYPE.ACTION_UPDATE).count(),
                'projects_published':
                self.projects.all().published().count(),
                'critical_errors_log':
                self.iati_import_logs.filter(
                    message_type=LOG_ENTRY_TYPE.CRITICAL_ERROR),
                'warnings_log':
                self.iati_import_logs.filter(message_type__in=[
                    LOG_ENTRY_TYPE.VALUE_PARTLY_SAVED,
                    LOG_ENTRY_TYPE.VALUE_NOT_SAVED
                ]),
                'projects_log':
                self.iati_import_logs.filter(message_type__in=[
                    LOG_ENTRY_TYPE.ACTION_CREATE, LOG_ENTRY_TYPE.ACTION_UPDATE
                ]),
                'full_log':
                self.iati_import_logs.filter(iati_import_job=self),
                'LOG_ENTRY_TYPE':
                LOG_ENTRY_TYPE,
            },
            html_message='iati_import/import_done_message.html',
            attachments=attachments,
        )
예제 #8
0
    def send_eutf_error_email(error_type, attachments):
        recipients = getattr(settings, 'EUTF_HIERARCHY_ERROR_RECIPIENTS', [
            '*****@*****.**',
        ])

        rsr_send_mail(
            recipients,
            subject='results_framework/eutf_hierarchy_error_subject.txt',
            message='results_framework/eutf_hierarchy_error_message.txt',
            msg_context={'error_type': error_type},
            html_message='results_framework/eutf_hierarchy_error_message.html',
            attachments=attachments)
예제 #9
0
def employment_pre_save(sender, **kwargs):
    """
    This signal intends to send a mail to the user when his/her account has been approved.

    This signal also sets 'Users' Group for the employment if no group has been set

    A mail will be sent when:

    - A new employment is created with is_approved = True.
      * We assume this happens when an existing user is invited for a new organisation.
    - An existing employment is updated from is_approved = False changed to True.
      * We assume this happens when an existing user has requested to join an organisation himself.
    """
    # FIXME: The actual save may fail. Why are emails being sent pre_save?!
    employment = kwargs.get("instance", None)

    # Set the group to 'Users' when no group has been specified
    if not employment.group:
        employment.group = Group.objects.get(name='Users')

    try:
        obj = sender.objects.get(pk=employment.pk)
    except sender.DoesNotExist:
        # Employment is new, send mail when it is also approved
        if employment.is_approved:
            rsr_send_mail(
                [employment.user.email],
                subject='registration/approved_added_email_subject.txt',
                message='registration/approved_added_email_message.txt',
                subject_context={
                    'organisation': employment.organisation,
                },
                msg_context={
                    'user': employment.user,
                    'organisation': employment.organisation,
                }
            )
    else:
        # Employment already exists, send mail when it wasn't approved before, but is approved now.
        if not obj.is_approved and employment.is_approved:
            rsr_send_mail(
                [employment.user.email],
                subject='registration/approved_request_email_subject.txt',
                message='registration/approved_request_email_message.txt',
                subject_context={
                    'organisation': employment.organisation,
                },
                msg_context={
                    'user': employment.user,
                    'organisation': employment.organisation,
                }
            )
예제 #10
0
    def send_mail(self):
        """
        Send an email to the RSR admins (gathered from settings) and the user linked to the
        IATI import instance.
        """

        email_addresses = [email for _name, email in settings.ADMINS]
        email_addresses.append(self.iati_import.user.email)

        attachments = []
        attachments.extend(self.get_log_csv(self.CRITICAL_LOG))
        attachments.extend(self.get_log_csv(self.WARNINGS_LOG))
        attachments.extend(self.get_log_csv(self.FULL_LOG))

        rsr_send_mail(
            email_addresses,
            subject='iati_import/import_done_subject.txt',
            message='iati_import/import_done_message.txt',
            subject_context={
                'iati_import_job': self,
            },
            msg_context={
                'iati_import_job': self,
                'project_count': self.projects.count(),
                'projects_created': self.iati_import_logs.filter(
                    message_type=LOG_ENTRY_TYPE.ACTION_CREATE).count(),
                'projects_updated': self.iati_import_logs.filter(
                    message_type=LOG_ENTRY_TYPE.ACTION_UPDATE).count(),
                'projects_published': self.projects.all().published().count(),
                'critical_errors_log': self.iati_import_logs.filter(
                    message_type=LOG_ENTRY_TYPE.CRITICAL_ERROR),
                'warnings_log': self.iati_import_logs.filter(
                    message_type__in=[LOG_ENTRY_TYPE.VALUE_PARTLY_SAVED,
                                      LOG_ENTRY_TYPE.VALUE_NOT_SAVED]
                ),
                'projects_log': self.iati_import_logs.filter(
                    message_type__in=[LOG_ENTRY_TYPE.ACTION_CREATE,
                                      LOG_ENTRY_TYPE.ACTION_UPDATE]
                ),
                'full_log': self.iati_import_logs.filter(iati_import_job=self),
                'LOG_ENTRY_TYPE': LOG_ENTRY_TYPE,
            },
            html_message='iati_import/import_done_message.html',
            attachments=attachments,
        )
예제 #11
0
def _send_assignment_email(user_id, project, email, context, dry_run=True):
    token = _update_user_token(user_id, project.id, preview=dry_run)
    jwt = token.jwt()
    results_url = context['results_url']
    extra_context = {
        'url': f"{results_url}/?rt={jwt}",
        'enumerator': token.user,
    }
    context.update(extra_context)
    if not dry_run:
        is_a4a = project.reporting_org and project.reporting_org.id == settings.A4A_ORG_ID
        rsr_send_mail(
            [email],
            subject='enumerators/assignment_subject.txt',
            message=('enumerators/a4a_assignment_message.txt'
                     if is_a4a else 'enumerators/assignment_message.txt'),
            subject_context=context,
            msg_context=context)

    return {'token': jwt, 'email': email}
예제 #12
0
def employment_pre_save(sender, **kwargs):
    """
    Send a mail to the user when his/her account has been approved.
    """
    employment = kwargs.get("instance", False)
    try:
        obj = sender.objects.get(pk=employment.pk)
    except sender.DoesNotExist:
        # Object is new
        pass
    else:
        if not obj.is_approved and employment.is_approved:
            # Employment is approved, send mail
            rsr_send_mail([employment.user.email],
                          subject='registration/approved_email_subject.txt',
                          message='registration/approved_email_message.txt',
                          subject_context={
                              'organisation': employment.organisation,
                          },
                          msg_context={
                              'user': employment.user,
                              'organisation': employment.organisation,
                          })
예제 #13
0
    def save(self, *args, **kwargs):
        """
        Process approved data updates.
        """
        # Always copy the period's actual value to the period_actual_value field.
        self.period_actual_value = str(self.period.actual_value or '0')

        if not self.pk:
            # Newly added data update
            if self.status == self.STATUS_APPROVED_CODE:
                # Update is immediately approved. Scenario that probably does not happen very often.
                self.period.update_actual_value(self.data, self.relative_data)
        else:
            orig = IndicatorPeriodData.objects.get(pk=self.pk)

            # Mail admins of a paying partner when an update needs to be approved
            if orig.status != self.STATUS_PENDING_CODE and \
                    self.status == self.STATUS_PENDING_CODE:
                me_managers_group = Group.objects.get(name='M&E Managers')
                me_managers = self.period.indicator.result.project.publishing_orgs.employments().\
                    approved().filter(group=me_managers_group)

                rsr_send_mail(
                    [empl.user.email for empl in me_managers],
                    subject='results_framework/approve_update_subject.txt',
                    message='results_framework/approve_update_message.txt',
                    html_message='results_framework/approve_update_message.html',
                    msg_context={'update': self}
                )

            # Mail the user that created the update when an update needs revision
            elif orig.status != self.STATUS_REVISION_CODE and \
                    self.status == self.STATUS_REVISION_CODE:
                rsr_send_mail(
                    [self.user.email],
                    subject='results_framework/revise_update_subject.txt',
                    message='results_framework/revise_update_message.txt',
                    html_message='results_framework/revise_update_message.html',
                    msg_context={'update': self}
                )

            # Process data when the update has been approved and mail the user about it
            elif orig.status != self.STATUS_APPROVED_CODE and \
                    self.status == self.STATUS_APPROVED_CODE:
                self.period.update_actual_value(self.data, self.relative_data)
                rsr_send_mail(
                    [self.user.email],
                    subject='results_framework/approved_subject.txt',
                    message='results_framework/approved_message.txt',
                    html_message='results_framework/approved_message.html',
                    msg_context={'update': self}
                )

        super(IndicatorPeriodData, self).save(*args, **kwargs)
예제 #14
0
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.append('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)

    User = get_user_model()

    # Check if the user already exists, based on the email address
    try:
        invited_user = User.objects.get(email=email)
    except User.DoesNotExist:
        try:
            invited_user = User.objects.create_user(username=email,
                                                    email=email)
        except IntegrityError:
            return Response(
                {'error': 'Trying to create a user that already exists'},
                status=status.HTTP_500_INTERNAL_SERVER_ERROR)

    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(user)

        elif not employment.is_approved:
            # Approve the existing unapproved employment
            employment.approve(user)

        else:
            return Response('Employment already exists',
                            status=status.HTTP_200_OK)

    else:
        # Create an unapproved employment for inactive users
        employment, _ = Employment.objects.get_or_create(
            user=invited_user,
            organisation=organisation,
            group=group,
        )

        # Send an activation email
        _, token_date, token = TimestampSigner().sign(email).split(':')

        rsr_send_mail(
            [email],
            subject='registration/invited_user_subject.txt',
            message='registration/invited_user_message.txt',
            html_message='registration/invited_user_message.html',
            msg_context={
                'user': user,
                'invited_user': invited_user,
                'employment': employment,
                'token': token,
                'token_date': token_date,
            })

    return Response('User invited', status=status.HTTP_201_CREATED)
예제 #15
0
def invite_user(request):
    """
    Invite a new user to RSR.

    :param request; request.DATA is a JSON string containing email, organisation and group data
    """
    def valid_email(email_address):
        try:
            validate_email(email_address)
            return True
        except ValidationError:
            return False

    user, group, organisation = request.user, None, None
    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:
        return Response({'missing_data': missing_data.append(['email', 'organisation', 'group'])},
                        status=status.HTTP_400_BAD_REQUEST)
    else:
        data = json.loads(data)

    # Check email
    email = data['email'].lower().strip()
    if not (email and valid_email(email) and user.email != email):
        missing_data.append('email')

    # Check organisation
    try:
        organisation = Organisation.objects.get(pk=int(data['organisation']))
    except (Organisation.DoesNotExist, ValueError):
        missing_data.append('organisation')

    # 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)

    # Check if the user already exists, based on the email address
    try:
        invited_user = get_user_model().objects.get(email=email)
    except get_user_model().DoesNotExist:
        try:
            invited_user = get_user_model().objects.create_user(username=email, email=email)
        except IntegrityError:
            return Response({'error': 'Trying to create a user that already exists'},
                            status=status.HTTP_500_INTERNAL_SERVER_ERROR)

    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.
        if Employment.objects.filter(user=invited_user,
                                     organisation=organisation,
                                     group=group).exists():
            employment = Employment.objects.get(user=invited_user, organisation=organisation,
                                                group=group)
            if not employment.is_approved:
                # Approve the employment
                employment.approve(user)
            else:
                # Employment already exists and is already approved
                return Response('Employment already exists', status=status.HTTP_200_OK)

        else:
            employment = Employment.objects.create(
                user=invited_user, organisation=organisation, group=group, is_approved=True
            )

            # Manual log the approval.
            # We can't use approve(), since then we would first need to create an employment that
            # is not approved, which will in turn send a 'organisation request' email.
            LogEntry.objects.log_action(
                user_id=user.pk,
                content_type_id=ContentType.objects.get_for_model(Employment).pk,
                object_id=employment.pk,
                object_repr=force_unicode(employment),
                action_flag=CHANGE,
                change_message=u'Changed is_approved, outside of admin.'
            )
    else:
        # Inactive users, need an activation email.
        employment, empl_created = Employment.objects.get_or_create(
            user=invited_user, organisation=organisation
        )
        employment.group = group
        employment.save()

        expiration_days = getattr(settings, 'ACCOUNT_ACTIVATION_DAYS', 7)
        token_value = TimestampSigner().sign(email)
        token = token_value.split(':')[2]
        token_date = token_value.split(':')[1]

        rsr_send_mail(
            [email],
            subject='registration/invited_user_subject.txt',
            message='registration/invited_user_message.txt',
            html_message='registration/invited_user_message.html',
            msg_context={
                'user': user,
                'invited_user': invited_user,
                'employment': employment,
                'token': token,
                'token_date': token_date,
                'expiration_days': expiration_days
            }
        )

    return Response('User invited', status=status.HTTP_201_CREATED)
예제 #16
0
def invite_user(request):
    """
    Invite a new user to RSR.

    :param request; request.data is a JSON string containing email, organisation and group data
    """
    def valid_email(email_address):
        try:
            validate_email(email_address)
            return True
        except ValidationError:
            return False

    user, group, organisation = request.user, None, None
    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:
        return Response(
            {
                'missing_data':
                missing_data.append(['email', 'organisation', 'group'])
            },
            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)

    # Check if the user already exists, based on the email address
    try:
        invited_user = get_user_model().objects.get(email=email)
    except get_user_model().DoesNotExist:
        try:
            invited_user = get_user_model().objects.create_user(username=email,
                                                                email=email)
        except IntegrityError:
            return Response(
                {'error': 'Trying to create a user that already exists'},
                status=status.HTTP_500_INTERNAL_SERVER_ERROR)

    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.
        if Employment.objects.filter(user=invited_user,
                                     organisation=organisation,
                                     group=group).exists():
            employment = Employment.objects.get(user=invited_user,
                                                organisation=organisation,
                                                group=group)
            if not employment.is_approved:
                # Approve the employment
                employment.approve(user)
            else:
                # Employment already exists and is already approved
                return Response('Employment already exists',
                                status=status.HTTP_200_OK)

        else:
            employment = Employment.objects.create(user=invited_user,
                                                   organisation=organisation,
                                                   group=group,
                                                   is_approved=True)

            # Manual log the approval.
            # We can't use approve(), since then we would first need to create an employment that
            # is not approved, which will in turn send a 'organisation request' email.
            LogEntry.objects.log_action(
                user_id=user.pk,
                content_type_id=ContentType.objects.get_for_model(
                    Employment).pk,
                object_id=employment.pk,
                object_repr=force_unicode(employment),
                action_flag=CHANGE,
                change_message=u'Changed is_approved, outside of admin.')
    else:
        # Inactive users, need an activation email.
        employment, empl_created = Employment.objects.get_or_create(
            user=invited_user, organisation=organisation)
        employment.group = group
        employment.save()

        token_value = TimestampSigner().sign(email)
        token = token_value.split(':')[2]
        token_date = token_value.split(':')[1]

        rsr_send_mail(
            [email],
            subject='registration/invited_user_subject.txt',
            message='registration/invited_user_message.txt',
            html_message='registration/invited_user_message.html',
            msg_context={
                'user': user,
                'invited_user': invited_user,
                'employment': employment,
                'token': token,
                'token_date': token_date,
            })

    return Response('User invited', status=status.HTTP_201_CREATED)
예제 #17
0
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.append('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)

    User = get_user_model()

    # Check if the user already exists, based on the email address
    try:
        invited_user = User.objects.get(email=email)
    except User.DoesNotExist:
        try:
            invited_user = User.objects.create_user(username=email, email=email)
        except IntegrityError:
            return Response({'error': 'Trying to create a user that already exists'},
                            status=status.HTTP_500_INTERNAL_SERVER_ERROR)

    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(user)

        elif not employment.is_approved:
            # Approve the existing unapproved employment
            employment.approve(user)

        else:
            return Response('Employment already exists', status=status.HTTP_200_OK)

    else:
        # Create an unapproved employment for inactive users
        employment, _ = Employment.objects.get_or_create(
            user=invited_user,
            organisation=organisation,
            group=group,
        )

        # Send an activation email
        _, token_date, token = TimestampSigner().sign(email).split(':')

        rsr_send_mail(
            [email],
            subject='registration/invited_user_subject.txt',
            message='registration/invited_user_message.txt',
            html_message='registration/invited_user_message.html',
            msg_context={
                'user': user,
                'invited_user': invited_user,
                'employment': employment,
                'token': token,
                'token_date': token_date,
            }
        )

    return Response('User invited', status=status.HTTP_201_CREATED)