Exemplo n.º 1
0
    def post(self, request, *args, **kwargs):
        """
        Post form for emailing participants.
        """
        retval = super().get(request, *args, **kwargs)
        email_form = self.request.POST

        sender = email_form['sender']
        subject = email_form['subject']
        message = email_form['message']
        recipients = list(
            User.objects.filter(
                pk__in=email_form.getlist('recipients')).values_list(
                    'username', flat=True))
        try:
            context = {'custom_message': message}
            send_mail.delay('custom_email',
                            subject,
                            settings.EMAIL_FROM_ADDRESS,
                            bcc=recipients,
                            from_email=sender,
                            **context)
            messages.success(self.request, "Your message has been sent.")
            self.create_email_log(recipients, message, subject)
            return HttpResponseRedirect(self.get_success_url())
        except BadHeaderError:
            messages.error(self.request, "Invalid header found.")
        return HttpResponseRedirect(reverse('exp:study-participant-email'))
Exemplo n.º 2
0
def send_email_when_receive_groups(sender, instance, created, **kwargs):
    """
    If researcher is given groups for the first time, send an email letting them know.
    """
    if instance.is_researcher and hasattr(instance, "__original_groups"):
        original_groups = getattr(instance, "__original_groups")
        if not original_groups and set(instance.groups.all()) != set(
            instance.__original_groups
        ):
            if instance.is_org_admin:
                permission = "admin"
            elif instance.is_org_read:
                permission = "read"
            else:
                permission = "researcher"

            context = {
                "researcher_name": instance.get_short_name(),
                "org_name": instance.organization.name,
                "permission": permission,
            }
            send_mail.delay(
                "notify_researcher_of_org_permissions",
                f"Invitation to access studies on {instance.organization.name}",
                instance.username,
                from_address=EMAIL_FROM_ADDRESS,
                **context,
            )
Exemplo n.º 3
0
    def send_as_email(self):
        context = {
            "base_url": settings.BASE_URL,
            "osf_url": settings.OSF_URL,
            "custom_message": mark_safe(self.body),
        }

        lab_email = self.related_study.lab.contact_email

        recipient_email_list = list(
            self.recipients.values_list("username", flat=True))
        if len(recipient_email_list) == 1:
            to_email_list = recipient_email_list
            bcc_email_list = []
        else:
            to_email_list = []
            bcc_email_list = recipient_email_list

        send_mail.delay(
            "custom_email",
            self.subject,
            to_email_list,
            bcc=bcc_email_list,
            from_email=lab_email,
            **context,
        )

        self.email_sent_timestamp = now(
        )  # will use UTC now (see USE_TZ in settings)
        self.save()
Exemplo n.º 4
0
 def notify_submitter_of_recission(self, ev):
     context = {"study_name": self.name}
     send_mail.delay(
         "notify_researchers_of_approval_rescission",
         "{} Rescinded Notification".format(self.name),
         settings.EMAIL_FROM_ADDRESS,
         bcc=list(
             self.users_with_study_perms(
                 StudyPermission.CHANGE_STUDY_STATUS).values_list(
                     "username", flat=True)),
         **context,
     )
Exemplo n.º 5
0
 def send_reset_password_email(self):
     """
     Send reset_password email to researcher
     """
     context = {
         'researcher_name': self.object.get_short_name(),
         'org_name': self.request.user.organization.name,
         'login_url': login_url
     }
     subject = 'Reset OSF password to login to Experimenter'
     send_mail.delay('reset_password', subject, self.object.username, **context)
     messages.success(self.request, f'Reset password email sent to {self.object.username}.')
     return
Exemplo n.º 6
0
 def send_resend_confirmation_email(self):
     """
     Send resend_confirmation_email to researcher
     """
     context = {
         'researcher_name': self.object.get_short_name(),
         'org_name': self.request.user.organization.name,
         'login_url': login_url
     }
     subject = 'Confirm OSF account to login to Experimenter'
     send_mail.delay('resend_confirmation', subject, self.object.username, **context)
     messages.success(self.request, f'Confirmation email resent to {self.object.username}.')
     return
Exemplo n.º 7
0
 def send_resend_confirmation_email(self):
     """
     Send resend_confirmation_email to researcher
     """
     context = {
         "researcher_name": self.object.get_short_name(),
         "org_name": self.request.user.organization.name,
         "login_url": login_url,
     }
     subject = "Confirm OSF account to login to Experimenter"
     send_mail.delay("resend_confirmation", subject, self.object.username, **context)
     messages.success(
         self.request, f"Confirmation email resent to {self.object.username}."
     )
     return
Exemplo n.º 8
0
 def send_reset_password_email(self):
     """
     Send reset_password email to researcher
     """
     context = {
         "researcher_name": self.object.get_short_name(),
         "org_name": self.request.user.organization.name,
         "login_url": login_url,
     }
     subject = "Reset OSF password to login to Experimenter"
     send_mail.delay("reset_password", subject, self.object.username, **context)
     messages.success(
         self.request, f"Reset password email sent to {self.object.username}."
     )
     return
Exemplo n.º 9
0
 def send_study_email(self, user, permission):
     study = self.get_object()
     context = {
         'permission': permission,
         'study_name': study.name,
         'study_id': study.id,
         'org_name': user.organization.name,
         'researcher_name': user.get_short_name()
     }
     send_mail.delay(
         'notify_researcher_of_study_permissions',
         f' Invitation to collaborate on {self.get_object().name}',
         user.username,
         from_address=settings.EMAIL_FROM_ADDRESS,
         **context)
Exemplo n.º 10
0
 def notify_admins_of_lab_submission(self):
     email_context = {
         "lab_name": self.object.name,
         "researcher_name": self.request.user.get_short_name(),
         "lab_id": self.object.id,
     }
     send_mail.delay(
         "notify_admins_of_lab_creation",
         "Lab Submission Notification",
         settings.EMAIL_FROM_ADDRESS,
         bcc=list(
             Group.objects.get(name=SiteAdminGroup.LOOKIT_ADMIN.name).
             user_set.values_list("username", flat=True)),
         **email_context,
     )
Exemplo n.º 11
0
 def send_reset_password_email(self, researcher):
     """
     Send reset_password email to researcher./
     """
     context = {
         "researcher_name": researcher.get_short_name(),
         "lab_name": self.get_object().name,
         "login_url": self.login_url,
     }
     subject = "Reset password to login to Lookit"
     send_mail.delay("reset_password", subject, researcher.username,
                     **context)
     messages.success(
         self.request,
         f"Reset password email sent to {researcher.username}.")
Exemplo n.º 12
0
 def send_study_email(self, user, permission):
     study = self.get_object()
     context = {
         "permission": permission,
         "study_name": study.name,
         "study_id": study.id,
         "lab_name": study.lab.name,
         "researcher_name": user.get_short_name(),
     }
     send_mail.delay(
         "notify_researcher_of_study_permissions",
         f"New access granted for study {self.get_object().name}",
         user.username,
         from_email=study.lab.contact_email,
         **context,
     )
Exemplo n.º 13
0
 def notify_submitter_of_rejection(self, ev):
     context = {
         "study_name": self.name,
         "study_id": self.pk,
         "approved": False,
         "comments": self.comments,
     }
     send_mail.delay(
         "notify_researchers_of_approval_decision",
         "{}: Changes requested notification".format(self.name),
         settings.EMAIL_FROM_ADDRESS,
         bcc=list(
             self.users_with_study_perms(
                 StudyPermission.CHANGE_STUDY_STATUS).values_list(
                     "username", flat=True)),
         **context,
     )
Exemplo n.º 14
0
 def send_resend_confirmation_email(self, researcher):
     """
     Send resend_confirmation_email to researcher (not a real confirmation email,
     just directs to OSF).
     """
     context = {
         "researcher_name": researcher.get_short_name(),
         "lab_name": self.get_object().name,
         "login_url": self.login_url,
     }
     subject = "Confirm OSF account to login to Lookit"
     send_mail.delay("resend_confirmation", subject, researcher.username,
                     **context)
     messages.success(
         self.request,
         f"Confirmation email resent to {researcher.username}.")
     return
Exemplo n.º 15
0
 def notify_administrators_of_deactivation(self, ev):
     context = {
         "lab_name": self.lab.name,
         "study_name": self.name,
         "study_id": self.pk,
         "study_uuid": str(self.uuid),
         "researcher_name": ev.kwargs.get("user").get_short_name(),
         "action": ev.transition.dest,
     }
     send_mail.delay(
         "notify_admins_of_study_action",
         "Study Deactivation Notification",
         settings.EMAIL_FROM_ADDRESS,
         bcc=list(
             Group.objects.get(name=SiteAdminGroup.LOOKIT_ADMIN.name).
             user_set.values_list("username", flat=True)),
         **context,
     )
Exemplo n.º 16
0
def notify_lab_of_approval(sender, instance, **kwargs):
    """
    If lab is approved, email the lab admins to let them know.
    """
    lab_in_db = Lab.objects.filter(pk=instance.id).first()
    if not lab_in_db:
        return
    if (not lab_in_db.approved_to_test) and instance.approved_to_test:
        context = {"lab_name": instance.name, "lab_id": instance.pk}
        send_mail.delay(
            "notify_lab_admins_of_approval",
            "Lab Approval Notification",
            settings.EMAIL_FROM_ADDRESS,
            bcc=list(
                instance.admin_group.user_set.values_list("username",
                                                          flat=True)),
            **context,
        )
Exemplo n.º 17
0
def send_email_when_receive_groups(sender, instance, created, **kwargs):
    """
    If researcher is given groups for the first time, send an email letting them know.
    """
    if instance.is_researcher and hasattr(instance, '__original_groups'):
        original_groups = getattr(instance, '__original_groups')
        if not original_groups and set(instance.groups.all()) != set(instance.__original_groups):
            if instance.is_org_admin:
                permission = 'admin'
            elif instance.is_org_read:
                permission = 'read'
            else:
                permission = 'researcher'

            context = {
                'researcher_name': instance.get_short_name(),
                'org_name': instance.organization.name,
                'permission': permission,
            }
            send_mail.delay('notify_researcher_of_org_permissions', f'Invitation to access studies on {instance.organization.name}', instance.username, from_address=EMAIL_FROM_ADDRESS, **context)
Exemplo n.º 18
0
def notify_involved_parties_of_build_status(study,
                                            failure_stage=None,
                                            log_output=None):
    lab = study.lab
    lab_name = lab.name if lab else None
    email_context = {
        "lab_name": lab_name,
        "study_name": study.name,
        "study_id": study.pk,
        "study_uuid": str(study.uuid),
    }

    success = failure_stage is None

    if success:
        email_context["action"] = "deployed"

        send_mail.delay(
            "notify_admins_of_study_action",
            "Study Deployed",
            settings.EMAIL_FROM_ADDRESS,
            bcc=list(
                study.admin_group.user_set.values_list("username", flat=True)),
            **email_context,
        )
        subject_line = f"Experiment runner built"
        researcher_notification_template = "notify_researchers_of_deployment"
    else:
        email_context["failure_stage"] = failure_stage
        email_context["log_output"] = log_output
        subject_line = f"Experiment runner failed to build."
        researcher_notification_template = "notify_researchers_of_build_failure"

    send_mail.delay(
        researcher_notification_template,
        subject_line,
        settings.EMAIL_FROM_ADDRESS,
        bcc=list(study.admin_group.user_set.values_list("username",
                                                        flat=True)),
        **email_context,
    )
Exemplo n.º 19
0
    def post(self, request, *args, **kwargs):
        user = self.request.user
        lab = self.get_object()

        # Technically allow re-requesting if already in a lab; won't have any effect
        # but will re-notify lab admins.
        if lab not in user.labs.all():
            # Add the request to the user/lab
            user.requested_labs.add(lab)
            user.save()
            # Notify lab admins so they can go approve the request.
            # TODO: could also handle this via m2m post-add signals on Lab model
            # (see https://docs.djangoproject.com/en/3.0/ref/signals/#m2m-changed)
            researcher_name = user.get_full_name()
            context = {
                "researcher_name": researcher_name,
                "lab_name": lab.name,
                "url": reverse("exp:lab-members", kwargs={"pk": lab.pk}),
            }
            send_mail.delay(
                "notify_lab_admins_of_request_to_join",
                "Researcher {} has requested access to {}".format(
                    researcher_name, lab.name),
                settings.EMAIL_FROM_ADDRESS,
                bcc=list(
                    lab.admin_group.user_set.values_list("username",
                                                         flat=True)),
                **context,
            )
            messages.success(
                request,
                f"Requested to join {lab.name}. The lab admins have been notified and you will receive an email when your request is approved.",
            )
        else:
            messages.warning(request,
                             f"You are already a member of {lab.name}.")
        return super().post(request, *args, **kwargs)
Exemplo n.º 20
0
def build_experiment(self, study_uuid, researcher_uuid, preview=True):
    ex = None
    try:
        from studies.models import Study, StudyLog
        from accounts.models import User

        save_versions = preview
        now = timezone.now()
        try:
            study = Study.objects.get(uuid=study_uuid)
        except Study.DoesNotExist as ex:
            logger.error(f'Study with uuid {study_uuid} does not exist. {ex}')
            raise

        try:
            researcher = User.objects.get(uuid=researcher_uuid)
        except User.DoesNotExist as ex:
            logger.error(
                f'User with uuid {researcher_uuid} does not exist. {ex}')
            raise

        destination_directory = f'{study_uuid}'

        player_sha = study.metadata.get('last_known_player_sha', None)
        addons_sha = study.metadata.get('last_known_addons_sha', None)
        addons_repo_url = study.metadata.get('addons_repo_url',
                                             settings.EMBER_ADDONS_REPO)
        logger.debug(
            f"Got {addons_repo_url} from {study.metadata.get('addons_repo_url')}"
        )

        if preview:
            current_state = study.state
            study.state = 'previewing'
            study.save()
            if player_sha is None and addons_sha is None:
                # if they're previewing and the sha's on their study aren't set
                # save the latest master sha of both repos
                save_versions = True

        checkout_directory, addons_sha, player_sha = download_repos(
            addons_repo_url, addons_sha=addons_sha, player_sha=player_sha)

        if save_versions:
            study.metadata['last_known_addons_sha'] = addons_sha
            study.metadata['last_known_player_sha'] = player_sha
            study.save()

        container_checkout_directory = os.path.join('/checkouts/',
                                                    checkout_directory)
        container_destination_directory = os.path.join('/deployments/',
                                                       destination_directory)

        build_image_comp_process = build_docker_image()
        local_checkout_path = os.path.join(settings.EMBER_BUILD_ROOT_PATH,
                                           'checkouts')
        local_deployments_path = os.path.join(settings.EMBER_BUILD_ROOT_PATH,
                                              'deployments')

        replacement_string = f"prepend: '/studies/{study_uuid}/'"

        build_command = [
            'docker', 'run', '--rm', '-e',
            f'CHECKOUT_DIR={container_checkout_directory}', '-e',
            f'REPLACEMENT={re.escape(replacement_string)}', '-e',
            f'STUDY_OUTPUT_DIR={container_destination_directory}', '-e',
            f"SENTRY_DSN={os.environ.get('SENTRY_DSN_JS', None)}", '-e',
            f"PIPE_ACCOUNT_HASH={os.environ.get('PIPE_ACCOUNT_HASH', None)}",
            '-e',
            f"PIPE_ENVIRONMENT={os.environ.get('PIPE_ENVIRONMENT', None)}",
            '-v', f'{local_checkout_path}:/checkouts', '-v',
            f'{local_deployments_path}:/deployments', 'ember_build'
        ]

        logger.debug(f'Running build.sh for {container_checkout_directory}...')
        ember_build_comp_process = subprocess.run(
            build_command,
            cwd=settings.EMBER_BUILD_ROOT_PATH,
            stdout=subprocess.PIPE,
            stderr=subprocess.STDOUT)

        if preview:
            # if they're previewing put things in the preview directory
            storage = storages.LookitPreviewExperimentStorage()
        else:
            # otherwise put them in the experiment directory
            storage = storages.LookitExperimentStorage()

        cloud_deployment_directory = os.path.join(local_deployments_path,
                                                  destination_directory)

        deploy_to_remote(cloud_deployment_directory, storage)

        context = {
            'org_name': study.organization.name,
            'study_name': study.name,
            'study_id': study.pk,
            'study_uuid': str(study.uuid),
            'action': 'previewed' if preview else 'deployed'
        }
        send_mail.delay(
            'notify_admins_of_study_action',
            'Study Previewed' if preview else 'Study Deployed',
            settings.EMAIL_FROM_ADDRESS,
            bcc=list(
                study.study_organization_admin_group.user_set.values_list(
                    'username', flat=True)),
            **context)
        send_mail.delay('notify_researchers_of_deployment',
                        'Study Previewed' if preview else 'Study Deployed',
                        settings.EMAIL_FROM_ADDRESS,
                        bcc=list(
                            study.study_admin_group.user_set.values_list(
                                'username', flat=True)),
                        **context)
        if not preview:
            study.state = 'active'
        else:
            study.previewed = True
            study.state = current_state

        study.save()
    except Exception as e:
        ex = e
        logger.error(e)
    finally:
        StudyLog.objects.create(study=study,
                                action='preview' if preview else 'deploy',
                                user=researcher,
                                extra={
                                    'ember_build':
                                    str(ember_build_comp_process.stdout),
                                    'image_build':
                                    str(build_image_comp_process.stdout),
                                    'ex':
                                    str(ex),
                                    'log':
                                    log_buffer.getvalue(),
                                })
        log_buffer.close()
    if ex:
        raise self.retry(exc=ex, countdown=30)
Exemplo n.º 21
0
    def post(self, request, *args, **kwargs):
        """
        Post form for changing researcher permissions.
        """
        retval = super().get(request, *args, **kwargs)
        action = self.request.POST.get("user_action", "")
        if not action:
            return retval
        researcher = get_object_or_404(User,
                                       pk=self.request.POST.get("user_id", ""))
        lab = self.get_object()

        # First check we are not trying to remove the only admin
        if (action in ["make_guest", "make_member", "remove_researcher"]
                and researcher in lab.admin_group.user_set.all()
                and lab.admin_group.user_set.count() == 1):
            messages.error(
                self.request,
                "Could not change permissions for this researcher. There must be at least one lab admin.",
            )
            return retval

        if action == "make_guest":
            lab.requested_researchers.remove(researcher)
            lab.researchers.add(researcher)
            lab.guest_group.user_set.add(researcher)
            lab.readonly_group.user_set.remove(researcher)
            lab.member_group.user_set.remove(researcher)
            lab.admin_group.user_set.remove(researcher)
            messages.success(
                self.request,
                f"Changed {researcher.get_full_name()} to a guest of {lab.name}.",
            )
            context = {
                "permission": "Guest",
                "lab_id": lab.pk,
                "lab_name": lab.name,
                "researcher_name": researcher.get_short_name(),
            }
            send_mail.delay(
                "notify_researcher_of_lab_permissions",
                f"You are now part of the Lookit lab {lab.name}",
                researcher.username,
                from_email=lab.contact_email,
                **context,
            )
        if action == "make_member":
            lab.requested_researchers.remove(researcher)
            lab.researchers.add(researcher)
            lab.guest_group.user_set.remove(researcher)
            lab.readonly_group.user_set.remove(researcher)
            lab.member_group.user_set.add(researcher)
            lab.admin_group.user_set.remove(researcher)
            messages.success(
                self.request,
                f"Changed {researcher.get_full_name()} to have lab member permissions for {lab.name}.",
            )
            context = {
                "permission":
                "View all studies (you will still need to be added to individual studies to view data)",
                "lab_id": lab.pk,
                "lab_name": lab.name,
                "researcher_name": researcher.get_short_name(),
            }
            send_mail.delay(
                "notify_researcher_of_lab_permissions",
                f"You now have lab member permissions for the Lookit lab {lab.name}",
                researcher.username,
                from_email=lab.contact_email,
                **context,
            )
        if action == "make_admin":
            lab.requested_researchers.remove(researcher)
            lab.researchers.add(researcher)
            lab.guest_group.user_set.remove(researcher)
            lab.readonly_group.user_set.remove(researcher)
            lab.member_group.user_set.remove(researcher)
            lab.admin_group.user_set.add(researcher)
            messages.success(
                self.request,
                f"Changed {researcher.get_full_name()} to have admin permissions for {lab.name}.",
            )
            context = {
                "permission":
                "Admin (view and manage all studies, and manage lab members' permissions). You will still need to be added to individual studies to view data.",
                "lab_id": lab.pk,
                "lab_name": lab.name,
                "researcher_name": researcher.get_short_name(),
            }
            send_mail.delay(
                "notify_researcher_of_lab_permissions",
                f"You are now an admin of the Lookit lab {lab.name}",
                researcher.username,
                from_email=lab.contact_email,
                **context,
            )
        if action == "remove_researcher":
            lab.requested_researchers.remove(researcher)
            lab.researchers.remove(researcher)
            lab.guest_group.user_set.remove(researcher)
            lab.readonly_group.user_set.remove(researcher)
            lab.member_group.user_set.remove(researcher)
            lab.admin_group.user_set.remove(researcher)
            # Remove from all lab study groups. Note that this could
            # remove the sole study admin, but we're enforcing that there's at least
            # one lab admin, who could give someone else access.
            for study in Study.objects.filter(lab=lab):
                for gr in study.all_study_groups():
                    gr.user_set.remove(researcher)
                    gr.save()
                study.save()
            messages.success(
                self.request,
                f"Removed {researcher.get_full_name()} from {lab.name} and from all of this lab's studies.",
            )
            context = {
                "permission": "None",
                "lab_id": lab.pk,
                "lab_name": lab.name,
                "researcher_name": researcher.get_short_name(),
            }
            send_mail.delay(
                "notify_researcher_of_lab_permissions",
                f"You have been removed from the Lookit lab {lab.name}",
                researcher.username,
                from_email=lab.contact_email,
                **context,
            )
        if action == "reset_password":
            self.send_reset_password_email(researcher)
        if action == "resend_confirmation":
            self.send_resend_confirmation_email(researcher)

        return HttpResponseRedirect(
            reverse("exp:lab-members", kwargs={"pk": self.object.id}))