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)
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, } )
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' )
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, })
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, } )
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, })
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, )
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)
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, } )
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, )
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}
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, })
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)
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)
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)
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)
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)