Esempio n. 1
0
def assert_can_fully_view_sample(user, sample):
    """Tests whether the user can view the sample fully, i.e. without needing
    a clearance.

    :param user: the user whose permission should be checked
    :param sample: the sample to be shown

    :type user: django.contrib.auth.models.User
    :type sample: `samples.models.Sample`

    :raises PermissionError: if the user is not allowed to fully view the
        sample.
    """
    currently_responsible_person = sample.currently_responsible_person
    sample_department = currently_responsible_person.jb_user_details.department or NoDepartment()
    user_department = user.jb_user_details.department or NoDepartment()
    if not sample.topic and sample_department != user_department and not user.is_superuser:
        description = _("You are not allowed to view the sample since the sample doesn't belong to your department.")
        raise PermissionError(user, description, new_topic_would_help=True)
    if sample.topic and user not in sample.topic.members.all() and currently_responsible_person != user and \
            not user.is_superuser:
        if sample_department != user_department:
            description = _("You are not allowed to view the sample since you are not in the sample's topic, nor belongs the "
                            "sample to your department.")
            raise PermissionError(user, description, new_topic_would_help=True)
        elif sample.topic.confidential:
            description = _("You are not allowed to view the sample since you are not in the sample's topic, nor are you "
                            "its currently responsible person ({name})."). \
                            format(name=utils.get_really_full_name(currently_responsible_person))
            raise PermissionError(user, description, new_topic_would_help=True)
        elif not user.has_perm("samples.view_every_sample"):
            description = _("You are not allowed to view the sample since you are not in the sample's topic, nor are you "
                            "its currently responsible person ({name}), nor can you view all samples."). \
                            format(name=utils.get_really_full_name(currently_responsible_person))
            raise PermissionError(user, description, new_topic_would_help=True)
Esempio n. 2
0
def assert_can_fully_view_sample(user, sample):
    """Tests whether the user can view the sample fully, i.e. without needing
    a clearance.

    :param user: the user whose permission should be checked
    :param sample: the sample to be shown

    :type user: django.contrib.auth.models.User
    :type sample: `samples.models.Sample`

    :raises PermissionError: if the user is not allowed to fully view the
        sample.
    """
    currently_responsible_person = sample.currently_responsible_person
    sample_department = currently_responsible_person.jb_user_details.department or NoDepartment()
    user_department = user.jb_user_details.department or NoDepartment()
    if not sample.topic and sample_department != user_department and not user.is_superuser:
        description = _("You are not allowed to view the sample since the sample doesn't belong to your department.")
        raise PermissionError(user, description, new_topic_would_help=True)
    if sample.topic and user not in sample.topic.members.all() and currently_responsible_person != user and \
            not user.is_superuser:
        if sample_department != user_department:
            description = _("You are not allowed to view the sample since you are not in the sample's topic, nor belongs the "
                            "sample to your department.")
            raise PermissionError(user, description, new_topic_would_help=True)
        elif sample.topic.confidential:
            description = _("You are not allowed to view the sample since you are not in the sample's topic, nor are you "
                            "its currently responsible person ({name})."). \
                            format(name=utils.get_really_full_name(currently_responsible_person))
            raise PermissionError(user, description, new_topic_would_help=True)
        elif not user.has_perm("samples.view_every_sample"):
            description = _("You are not allowed to view the sample since you are not in the sample's topic, nor are you "
                            "its currently responsible person ({name}), nor can you view all samples."). \
                            format(name=utils.get_really_full_name(currently_responsible_person))
            raise PermissionError(user, description, new_topic_would_help=True)
Esempio n. 3
0
def add(request, username):
    """View for adding a new claim.  The ``username`` parameter is actually
    superfluous because it must be the currently logged-in user anyway.  But
    this way, we don't get into trouble if a user happens to be called
    ``"add"``.  Additionally, the URLs become RESTful.

    :param request: the current HTTP Request object
    :param username: the name of the user whose claim this will be; it must be
        the currently logged-in user

    :type request: HttpRequest
    :type username: unicode

    :return:
      the HTTP response object

    :rtype: HttpResponse
    """
    _ = ugettext
    user = get_object_or_404(django.contrib.auth.models.User, username=username)
    if user != request.user:
        raise permissions.PermissionError(request.user, _("You are not allowed to add a claim in another user's name."))
    if request.method == "POST":
        samples_form = SamplesForm(user, request.POST)
        reviewer_form = ReviewerForm(request.POST)
        if samples_form.is_valid() and reviewer_form.is_valid():
            reviewer = reviewer_form.cleaned_data["reviewer"]
            claim = models.SampleClaim(requester=user, reviewer=reviewer)
            claim.save()
            _ = lambda x: x
            send_email(_("Sample request from {requester}"),
                       _("""Hello {reviewer},

{requester} wants to become the new “currently responsible person”
of one or more samples.  Please visit

    {url}

for reviewing this request.  If you don't want or cannot approve
the request, please contact {requester} directly and ask him or her
to withdraw the request.

JuliaBase.
"""), reviewer, {"reviewer": get_really_full_name(reviewer), "requester": get_really_full_name(user),
                 "url": request.build_absolute_uri(django.core.urlresolvers.reverse(show, kwargs={"claim_id": claim.pk}))})
            _ = ugettext
            claim.samples = samples_form.cleaned_data["samples"]
            return utils.successful_response(request,
                                             _("Sample claim {id_} was successfully submitted.").format(id_=claim.pk),
                                             show, kwargs={"claim_id": claim.pk})
    else:
        samples_form = SamplesForm(user)
        reviewer_form = ReviewerForm()
    return render(request, "samples/add_claim.html", {"title": _("Assert claim"), "samples": samples_form,
                                                      "reviewer": reviewer_form})
Esempio n. 4
0
def edit(request, username):
    """View for editing user permissions.  You can change two kinds of user
    permissions here: The “add”, “view all”, and “edit permissions”
    permissions, as well as whether the user is a so-called “topic manager”.
    See `list_` for further information.

    :param request: the current HTTP Request object
    :param username: the username of the user whose permissions should be
        changed

    :type request: HttpRequest
    :type username: unicode

    :return:
      the HTTP response object

    :rtype: HttpResponse
    """
    edited_user = get_object_or_404(User, username=username)
    user = request.user
    has_global_edit_permission = user.has_perm("samples.edit_permissions_for_all_physical_processes")
    addable_models = get_addable_models(user)
    permissions_list = []
    for model in addable_models:
        if model.add_permission or model.view_all_permission or model.edit_all_permission or \
                model.edit_permissions_permission:
            if user in model.permission_editors or has_global_edit_permission:
                if request.method == "POST":
                    permissions_list.append((model, PermissionsForm(edited_user, model, request.POST,
                                                                      prefix=model.codename)))
                else:
                    permissions_list.append((model, PermissionsForm(edited_user, model, prefix=model.codename)))
    if request.method == "POST":
        if all(permission[1].is_valid() for permission in permissions_list):
            for model, permissions_form in permissions_list:
                cleaned_data = permissions_form.cleaned_data
                def model_permission(form_key, attribute_name, permission):
                    if permission:
                        if cleaned_data[form_key]:
                            if edited_user not in getattr(model, attribute_name):
                                edited_user.user_permissions.add(permission)
                        else:
                            if edited_user in getattr(model, attribute_name):
                                edited_user.user_permissions.remove(permission)
                model_permission("can_add", "adders", model.add_permission)
                model_permission("can_view_all", "full_viewers", model.view_all_permission)
                model_permission("can_edit_all", "full_editors", model.edit_all_permission)
                model_permission("can_edit_permissions", "permission_editors", model.edit_permissions_permission)
            return utils.successful_response(request, _("The permissions of {name} were successfully changed."). \
                                                 format(name=get_really_full_name(edited_user)), list_)
    return render(request, "samples/edit_permissions.html",
                  {"title": _("Change permissions of {name}").format(name=get_really_full_name(edited_user)),
                   "permissions_list": permissions_list})
Esempio n. 5
0
    def set_choices(self, user, old_process):
        """Set the operator list shown in the widget.  It combines selectable users and
        external operators.  You must call this method in the constructor of
        the form in which you use this field, otherwise the selection box will
        remain emtpy.  The selectable operators are:

        - the former operator of the process (if any)
        - the current user
        - the former external operator (if any)
        - all external operators for which the current user is the contact person.

        It works also for staff users, which can choose from *all* users and
        external operators (including inactive users such as “nobody”).

        :param user: the currently logged-in user.
        :param old_process: if the process is to be edited, the former instance
            of the process; otherwise, ``None``

        :type operator: django.contrib.auth.models.User
        :type old_process: `samples.models.Process`
        """
        self.user = user
        if user.is_superuser:
            self.choices = django.contrib.auth.models.User.objects.values_list(
                "pk", "username")
            external_operators = set(models.ExternalOperator.objects.all())
        else:
            self.choices = []
            if old_process:
                if old_process.operator != user:
                    self.choices.append(
                        (old_process.operator.pk,
                         get_really_full_name(old_process.operator)))
                external_operators = {
                    old_process.external_operator
                } if old_process.external_operator else set()
            else:
                external_operators = set()
            self.choices.append((user.pk, get_really_full_name(user)))
            external_operators |= set(user.external_contacts.all())
        if old_process:
            self.initial = "extern-{0}".format(old_process.external_operator.pk) if old_process.external_operator else \
                old_process.operator.pk
        else:
            self.initial = user.pk
        for external_operator in sorted(
                external_operators,
                key=lambda external_operator: external_operator.name):
            self.choices.append(("extern-{0}".format(external_operator.pk),
                                 external_operator.name))
Esempio n. 6
0
def list_(request, username):
    """View for listing claim, both those with you being the requester and the
    reviewer.  The ``username`` parameter is actually superfluous because it
    must be the currently logged-in user anyway.  But this way, it is more
    consistent and more RESTful.

    :param request: the current HTTP Request object
    :param username: the name of the user whose claims will be listed; it must
        be the currently logged-in user

    :type request: HttpRequest
    :type username: unicode

    :return:
      the HTTP response object

    :rtype: HttpResponse
    """
    user = get_object_or_404(django.contrib.auth.models.User,
                             username=username)
    if user != request.user and not user.is_staff:
        raise permissions.PermissionError(
            request.user,
            _("You are not allowed to see claims of another user."))
    return render(
        request, "samples/list_claims.html", {
            "title":
            _("Claims for {user}").format(user=get_really_full_name(user)),
            "claims": user.claims.filter(closed=False),
            "claims_as_reviewer": user.claims_as_reviewer.filter(closed=False)
        })
Esempio n. 7
0
def inform_process_supervisors(sender, instance, **kwargs):
    """Send an email to the supervisors of an apparatus when a user creates
    his or her first process of this apparatus.  If no supervisors are found,
    the administrators are emailed.
    """
    # FixMe: The following line is only necessary as long as
    # http://code.djangoproject.com/ticket/9318 is not fixed.  When it is
    # fixed, this function must be connected only with senders of
    # ``PhysicalProcess``.  If this is not possible because ``PhysicalProcess``
    # is abstract, this line must stay, and this function must be connected
    # with senders of ``Process`` only.  The check ``raw==False`` must stay,
    # though.
    _ = ugettext
    if not kwargs.get("raw") and isinstance(instance, PhysicalProcess) and instance.finished:
        user = instance.operator
        process_class = instance.__class__
        if not process_class.objects.filter(operator=user).exists():
            try:
                permission = django.contrib.auth.models.Permission.objects.get(
                    codename="edit_permissions_for_{0}".format(process_class.__name__.lower()),
                    content_type=ContentType.objects.get_for_model(process_class))
            except django.contrib.auth.models.Permission.DoesNotExist:
                return
            recipients = list(django.contrib.auth.models.User.objects.filter(user_permissions=permission)) or \
                list(django.contrib.auth.models.User.objects.filter(is_superuser=True).exclude(email=""))
            if recipients:
                _ = lambda x: x
                utils.send_email(_(u"{user_name} uses {apparatus}"),
                                 _(u"Dear supervisors of {apparatus_plural},\n\n{user_name} has "
                                   u"created their first {apparatus}.\n"), recipients,
                                 {"apparatus_plural": process_class._meta.verbose_name_plural,
                                  "apparatus": process_class._meta.verbose_name,
                                  "user_name": utils.get_really_full_name(user)})
Esempio n. 8
0
def get_really_full_name(user, anchor_type="http"):
    """Unfortunately, Django's get_full_name method for users returns the empty
    string if the user has no first and surname set. However, it'd be sensible
    to use the login name as a fallback then. This is realised here.  See also
    `jb_common.utils.get_really_full_name`.

    The optional parameter to this filter determines whether the name should be
    linked or not, and if so, how.  There are three possible parameter values:

    ``"http"`` (default)
        The user's name should be linked with his web page on JuliaBase

    ``"mailto"``
        The user's name should be linked with his email address

    ``"plain"``
        There should be no link, the name is just printed as plain unformatted
        text.
    """
    full_name = utils.get_really_full_name(user)
    if anchor_type == "mailto" and not user.email:
        anchor_type = "plain"
    if anchor_type == "plain" or not user.jb_user_details.department:
        return full_name
    elif anchor_type == "http":
        return format_html('<a href="{0}">{1}</a>', mark_safe(django.core.urlresolvers.reverse(
            "jb_common:show_user", kwargs={"login_name": user.username})), full_name)
    elif anchor_type == "mailto":
        return format_html('<a href="mailto:{0}">{1}</a>', user.email, full_name)
    else:
        return ""
Esempio n. 9
0
 def get_metadata(self):
     metadata = {}
     metadata["title"] = _("{name} copied samples to you").format(
         name=get_really_full_name(self.originator))
     metadata["category term"] = "copied samples"
     metadata["category label"] = "copied My Samples"
     return metadata
Esempio n. 10
0
def show_user(request, login_name):
    """View for showing basic information about a user, like the email address.
    This could be fleshed out with phone number, picture, position, and field
    of interest by overriding this view in the institute app.

    :param request: the current HTTP Request object
    :param login_name: the login name of the user to be shown

    :type request: HttpRequest
    :type login_name: str

    :return:
      the HTTP response object

    :rtype: HttpResponse
    """
    try:
        user = django.contrib.auth.models.User.objects.filter(username=login_name). \
               exclude(jb_user_details__department=None)[0]
    except IndexError:
        raise Http404('No User matches the given query.')
    department = user.jb_user_details.department
    username = get_really_full_name(user)
    return render(request, "jb_common/show_user.html", {
        "title": username,
        "shown_user": user,
        "department": department
    })
Esempio n. 11
0
def list_(request, username):
    """View for listing claim, both those with you being the requester and the
    reviewer.  The ``username`` parameter is actually superfluous because it
    must be the currently logged-in user anyway.  But this way, it is more
    consistent and more RESTful.

    :param request: the current HTTP Request object
    :param username: the name of the user whose claims will be listed; it must
        be the currently logged-in user

    :type request: HttpRequest
    :type username: unicode

    :return:
      the HTTP response object

    :rtype: HttpResponse
    """
    user = get_object_or_404(django.contrib.auth.models.User, username=username)
    if user != request.user and not user.is_superuser:
        raise permissions.PermissionError(request.user, _("You are not allowed to see claims of another user."))
    return render(request, "samples/list_claims.html",
                  {"title": _("Claims for {user}").format(user=get_really_full_name(user)),
                   "claims": user.claims.filter(closed=False),
                   "claims_as_reviewer": user.claims_as_reviewer.filter(closed=False)})
Esempio n. 12
0
def edit_user_details(request, username):
    user = get_object_or_404(django.contrib.auth.models.User,
                             username=username)
    if not request.user.is_staff and request.user != user:
        raise Http404("You can't access the user details of another user.")
    user_details = user.kicker_user_details
    if request.method == "POST":
        user_details_form = UserDetailsForm(user,
                                            request.POST,
                                            instance=user_details)
        if user_details_form.is_valid():
            user_details_form.save()
            return successful_response(
                request, _("The preferences were successfully updated."),
                summary)
    else:
        user_details_form = UserDetailsForm(user, instance=user_details)
    return render(
        request, "kicker/user_details.html", {
            "title":
            _("Change preferences for {user_name}").format(
                user_name=get_really_full_name(user)),
            "user_details":
            user_details_form
        })
Esempio n. 13
0
def get_really_full_name(user, anchor_type="http", autoescape=False):
    """Unfortunately, Django's get_full_name method for users returns the
    empty string if the user has no first and surname set. However, it'd be
    sensible to use the login name as a fallback then. This is realised here.
    See also `jb_common.utils.get_really_full_name`.

    The optional parameter to this filter determines whether the name should be
    linked or not, and if so, how.  There are three possible parameter values:

    ``"http"`` (default)
        The user's name should be linked with his web page on JuliaBase

    ``"mailto"``
        The user's name should be linked with his email address

    ``"plain"``
        There should be no link, the name is just printed as plain unformatted
        text.

    """
    full_name = utils.get_really_full_name(user)
    if autoescape:
        full_name = conditional_escape(full_name)
    if anchor_type == "mailto" and not user.email:
        anchor_type = "plain"
    if anchor_type == "plain" or not user.jb_user_details.department:
        return mark_safe(full_name)
    elif anchor_type == "http":
        # FixMe: The view should be one of jb_common.
        return mark_safe('<a href="{0}">{1}</a>'.format(django.core.urlresolvers.reverse(
                    "jb_common.views.show_user", kwargs={"login_name": user.username}), full_name))
    elif anchor_type == "mailto":
        return mark_safe('<a href="mailto:{0}">{1}</a>'.format(user.email, full_name))
    else:
        return ""
Esempio n. 14
0
def edit(request, username):
    """View for doing various things with the samples listed under “My
    Samples”.  For example, copying them to the “My Samples” list of another
    user, or simply removing them from the list.

    Note that there are two different user variables in this view and its
    associated functions.  ``current_user`` is the same as ``request.user``.
    Thus, it is the currently logged-in user.  However, ``user`` is the user
    whose “My Samples” are to be processed.  Almost always both are the same,
    especially because you are not allowed to see or change the “My Samples” of
    another user.  However, staff users *are* allowed to change them, so then
    both are different.

    :param request: the current HTTP Request object
    :param username: the login name of the user whose “My Samples” should be
        changed

    :type request: HttpRequest
    :type username: unicode

    :return:
      the HTTP response object

    :rtype: HttpResponse
    """
    user = get_object_or_404(django.contrib.auth.models.User,
                             username=username)
    if not request.user.is_superuser and request.user != user:
        raise permissions.PermissionError(
            request.user,
            _("You can't access the “My Samples” section of another user."))
    if request.method == "POST":
        my_samples_form = MySamplesForm(user, request.POST)
        action_form = ActionForm(user, request.POST)
        referentially_valid = is_referentially_valid(request.user,
                                                     my_samples_form,
                                                     action_form)
        if my_samples_form.is_valid() and action_form.is_valid(
        ) and referentially_valid:
            save_to_database(user, my_samples_form, action_form)
            return utils.successful_response(
                request, _("Successfully processed “My Samples”."))
    else:
        if is_json_requested(request):
            return respond_in_json(
                request.user.my_samples.values_list("id", flat=True))
        my_samples_form = MySamplesForm(user)
        action_form = ActionForm(user)
    return render(
        request, "samples/edit_my_samples.html", {
            "title":
            _("Manage “My Samples” of {user_name}").format(
                user_name=get_really_full_name(user)),
            "my_samples":
            my_samples_form,
            "action":
            action_form
        })
Esempio n. 15
0
 def __init__(self, user, data=None, **kwargs):
     self.task = kwargs.get("instance")
     self.user = user
     self.fixed_fields = set()
     if self.task:
         eligible_operators = set(permissions.get_all_adders(self.task.process_class.model_class()))
         if self.task.operator:
             eligible_operators.add(self.task.operator)
         self.fixed_fields.add("process_class")
         if self.task.status == "1 new":
             self.fixed_fields.add("finished_process")
             if self.user not in eligible_operators:
                 self.fixed_fields.update(["operator", "status"])
         elif self.task.status in ["2 accepted", "3 in progress"]:
             if self.user != self.task.operator:
                 self.fixed_fields.update(["status", "priority", "finished_process", "operator"])
                 if self.user != self.task.customer:
                     self.fixed_fields.add("comments")
         else:
             self.fixed_fields.update(["priority", "finished_process", "operator"])
             if self.user != self.task.operator:
                 self.fixed_fields.add("status")
                 if self.user != self.task.customer:
                     self.fixed_fields.add("comments")
     else:
         self.fixed_fields.update(["status", "finished_process", "operator"])
     if data is not None:
         data = data.copy()
         if self.task:
             data.update(forms.model_to_dict(self.task, self.fixed_fields))
         else:
             initial = kwargs.get("initial", {})
             initial.update({"status": "1 new"})
             data.update(initial)
     super(TaskForm, self).__init__(data, **kwargs)
     self.fields["customer"].required = False
     self.fields["operator"].choices = [("", "---------")]
     if self.task:
         self.fields["operator"].choices.extend((user.pk, common_utils.get_really_full_name(user))
                                                for user in common_utils.sorted_users_by_first_name(eligible_operators))
     self.fields["process_class"].choices = utils.choices_of_content_types(
         permissions.get_all_addable_physical_process_models())
     self.fields["finished_process"].choices = [("", "---------")]
     if self.task:
         old_finished_process_id = self.task.finished_process.id if self.task.finished_process else None
         if self.user == self.task.operator:
             self.fields["finished_process"].choices.extend(
                 [(process.id, process.actual_instance)
                  for process in Process.objects.filter(
                         Q(operator=self.user, content_type=self.task.process_class) |
                         Q(id=old_finished_process_id)).filter(finished=True).order_by("-timestamp")[:10]])
         elif old_finished_process_id:
             self.fields["finished_process"].choices.append((old_finished_process_id, self.task.finished_process))
     self.fields["comments"].widget.attrs["cols"] = 30
     self.fields["comments"].widget.attrs["rows"] = 5
     for field_name in self.fixed_fields:
         self.fields[field_name].widget.attrs["disabled"] = "disabled"
         self.fields[field_name].required = False
Esempio n. 16
0
    def build_menu(self, menu, request):
        """Contribute to the menu.  See :py:mod:`jb_common.nav_menu` for further
        information.
        """
        import jb_common.utils.base as utils

        if request.user.is_authenticated():
            user_menu = menu.get_or_create(MenuItem(utils.get_really_full_name(request.user), position="right"))
            user_menu.prepend(MenuItem(_("my topics and permissions"),
                                       reverse("samples:topics_and_permissions",
                                               kwargs={"login_name": request.user.username})))
            add_menu = menu.get_or_create(_("add"))
            add_menu.add(_("samples"), reverse(settings.ADD_SAMPLES_VIEW), "stop")
            add_menu.add(_("sample series"), reverse("samples:add_sample_series"), "th")
            add_menu.add(_("result"), reverse("samples:add_result"), "scale")
            add_menu.add_separator()
            permissions = importlib.import_module("samples.permissions")
            for physical_process in permissions.get_allowed_physical_processes(request.user):
                add_menu.add(physical_process["label"], physical_process["url"])
            explore_menu = menu.get_or_create(pgettext("top-level menu item", "explore"))
            explore_menu.add(_("advanced search"), reverse("samples:advanced_search"), "search")
            explore_menu.add(_("samples by name"), reverse("samples:sample_search"), "stop")
            explore_menu.add_separator()
            lab_notebooks = permissions.get_lab_notebooks(request.user)
            if lab_notebooks:
                explore_menu.add_heading(_("lab notebooks"))
                for lab_notebook in lab_notebooks:
                    explore_menu.add(lab_notebook["label"], lab_notebook["url"], "book")
            manage_menu = menu.get_or_create(_("manage"))
            manage_menu.add(_("manage “My Samples”"), reverse("samples:edit_my_samples",
                                                              kwargs={"username": request.user.username}))
            if request.user.has_perm("samples.rename_samples"):
                manage_menu.add(_("rename sample"), reverse("samples:rename_sample"))
            manage_menu.add(_("merge samples"), reverse("samples:merge_samples"))
            manage_menu.add(_("sample claims"), reverse("samples:list_claims", kwargs={"username": request.user.username}))
            manage_menu.add_separator()
            if permissions.has_permission_to_edit_users_topics(request.user):
                manage_menu.add(_("add new topic"), reverse("samples:add_topic"))
            if permissions.can_edit_any_topics(request.user):
                manage_menu.add(_("change topic memberships"), reverse("samples:list_topics"))
            manage_menu.add_separator()
            if permissions.has_permission_to_add_external_operator(request.user):
                manage_menu.add(_("add external operator"), reverse("samples:add_external_operator"))
            if permissions.can_edit_any_external_contacts(request.user):
                manage_menu.add(_("edit external operator"), reverse("samples:list_external_operators"))
            manage_menu.add_separator()
            manage_menu.add(_("permissions"), reverse("samples:list_permissions"))
            manage_menu.add(_("task lists"), reverse("samples:show_task_lists"))
            manage_menu.add(_("newsfeed"),
                            reverse("samples:show_feed", kwargs={"username": request.user,
                                                                 "user_hash": permissions.get_user_hash(request.user)}))
            manage_menu.add(_("status messages"), reverse("samples:show_status"))
            manage_menu.add(_("inspect crawler logs"), reverse("samples:list_log_viewers"))
            if request.user.is_superuser:
                manage_menu.add(_("administration"), reverse("admin:index"))
Esempio n. 17
0
    def set_choices(self, user, old_process):
        """Set the operator list shown in the widget.  It combines selectable users and
        external operators.  You must call this method in the constructor of
        the form in which you use this field, otherwise the selection box will
        remain emtpy.  The selectable operators are:

        - the former operator of the process (if any)
        - the current user
        - the former external operator (if any)
        - all external operators for which the current user is the contact person.

        It works also for staff users, which can choose from *all* users and
        external operators (including inactive users such as “nobody”).

        :param user: the currently logged-in user.
        :param old_process: if the process is to be edited, the former instance
            of the process; otherwise, ``None``

        :type operator: django.contrib.auth.models.User
        :type old_process: `samples.models.Process`
        """
        self.user = user
        if user.is_superuser:
            self.choices = django.contrib.auth.models.User.objects.values_list("pk", "username")
            external_operators = set(models.ExternalOperator.objects.all())
        else:
            self.choices = []
            if old_process:
                if old_process.operator != user:
                    self.choices.append((old_process.operator.pk, get_really_full_name(old_process.operator)))
                external_operators = {old_process.external_operator} if old_process.external_operator else set()
            else:
                external_operators = set()
            self.choices.append((user.pk, get_really_full_name(user)))
            external_operators |= set(user.external_contacts.all())
        if old_process:
            self.initial = "extern-{0}".format(old_process.external_operator.pk) if old_process.external_operator else \
                old_process.operator.pk
        else:
            self.initial = user.pk
        for external_operator in sorted(external_operators, key=lambda external_operator: external_operator.name):
            self.choices.append(("extern-{0}".format(external_operator.pk), external_operator.name))
Esempio n. 18
0
 def build_menu(self, menu, request):
     """Contribute to the menu.  See :py:mod:`jb_common.nav_menu` for further
     information.
     """
     if request.user.is_authenticated():
         user_menu = menu.get_or_create(MenuItem(utils.get_really_full_name(request.user), position="right"))
         user_menu.prepend(MenuItem(_("my topics and permissions"),
                                    reverse("samples.views.user_details.topics_and_permissions",
                                            kwargs={"login_name": request.user.username})))
         add_menu = menu.get_or_create(_("add"))
         add_menu.add(_("samples"), reverse(settings.ADD_SAMPLES_VIEW), "stop")
         add_menu.add(_("sample series"), reverse("samples.views.sample_series.new"), "th")
         add_menu.add(_("result"), reverse("add_result"), "scale")
         add_menu.add_separator()
         permissions = importlib.import_module("samples.permissions")
         for physical_process in permissions.get_allowed_physical_processes(request.user):
             add_menu.add(physical_process["label"], physical_process["url"])
         explore_menu = menu.get_or_create(pgettext("top-level menu item", "explore"))
         explore_menu.add(_("advanced search"), reverse("samples.views.sample.advanced_search"), "search")
         explore_menu.add(_("samples by name"), reverse("samples.views.sample.search"), "stop")
         explore_menu.add_separator()
         lab_notebooks = permissions.get_lab_notebooks(request.user)
         if lab_notebooks:
             explore_menu.add_heading(_("lab notebooks"))
             for lab_notebook in lab_notebooks:
                 explore_menu.add(lab_notebook["label"], lab_notebook["url"], "book")
         manage_menu = menu.get_or_create(_("manage"))
         manage_menu.add(_("manage “My Samples”"), reverse("samples.views.my_samples.edit",
                                                           kwargs={"username": request.user.username}))
         if request.user.has_perm("samples.rename_samples"):
             manage_menu.add(_("rename sample"), reverse("samples.views.sample.rename_sample"))
         manage_menu.add(_("merge samples"), reverse("samples.views.merge_samples.merge"))
         manage_menu.add(_("sample claims"), reverse("samples.views.claim.list_",
                                                     kwargs={"username": request.user.username}))
         manage_menu.add_separator()
         if permissions.has_permission_to_edit_users_topics(request.user):
             manage_menu.add(_("add new topic"), reverse("samples.views.topic.add"))
         if permissions.can_edit_any_topics(request.user):
             manage_menu.add(_("change topic memberships"), reverse("samples.views.topic.list_"))
         manage_menu.add_separator()
         if permissions.has_permission_to_add_external_operator(request.user):
             manage_menu.add(_("add external operator"), reverse("samples.views.external_operator.new"))
         if permissions.can_edit_any_external_contacts(request.user):
             manage_menu.add(_("edit external operator"), reverse("samples.views.external_operator.list_"))
         manage_menu.add_separator()
         manage_menu.add(_("permissions"), reverse("samples.views.permissions.list_"))
         manage_menu.add(_("task lists"), reverse("samples.views.task_lists.show"))
         manage_menu.add(_("newsfeed"),
                         reverse("samples.views.feed.show", kwargs={"username": request.user,
                                                                    "user_hash": permissions.get_user_hash(request.user)}))
         manage_menu.add(_("status messages"), reverse("samples.views.status.show"))
         manage_menu.add(_("inspect crawler logs"), reverse("samples.views.log_viewer.list"))
         if request.user.is_superuser:
             manage_menu.add(_("administration"), reverse("admin:index"))
Esempio n. 19
0
def topics_and_permissions(request, login_name):
    user = get_object_or_404(django.contrib.auth.models.User, username=login_name)
    if not request.user.is_staff and request.user != user:
        raise permissions.PermissionError(
            request.user, _("You can't access the list of topics and permissions of another user."))
    return render(request, "samples/topics_and_permissions.html",
                  {"title": _("Topics and permissions for {user_name}").format(user_name=get_really_full_name(request.user)),
                   "topics": user.topics.all(), "managed_topics": user.managed_topics.all(),
                   "permissions": permissions.get_user_permissions(user),
                   "full_user_name": get_really_full_name(request.user),
                   "permissions_url": django.core.urlresolvers.reverse("samples.views.permissions.list_")})
Esempio n. 20
0
def _user_choices_by_department(user, include=(), exclude=()):
    """Returns a choices list ready-to-be-used in multiple- and single-selection
    widgets.  Basically, it consists of all users in the departments that the
    user wants to see accorint to the `show_users_from_departments` field.  It
    collapses the list automatically if only one department is present.  Note
    that no entry for “empty choice” is added.  This must be done by the
    caller, if necessary.

    :param user: the currently logged-in user
    :param include: list of users to be included additionally
    :param exclude: list of users to be excluded

    :type user: django.contrib.auth.models.User
    :type include: list of django.contrib.auth.models.User
    :type exclude: list of django.contrib.auth.models.User

    :return:
      list of choices, ready to be used in a `ChoiceField` or
      `MultipleChoiceField`

    :rtype: list of (int, str) or list of (str, list of (int, str))
    """
    choices = []
    for department in Department.objects.all():
        users_from_department = set(user for user in include if user.jb_user_details.department == department)
        if department in user.samples_user_details.show_users_from_departments.all():
            users_from_department |= set(django.contrib.auth.models.User.objects.
                                         filter(is_active=True, jb_user_details__department=department))
        users_from_department -= set(user for user in exclude if user.jb_user_details.department == department)
        if users_from_department:
            choices.append((department.name, [(user.pk, get_really_full_name(user))
                                              for user in sorted_users_by_first_name(users_from_department)]))
    departmentless_users = [user for user in include
                            if user in django.contrib.auth.models.User.objects.filter(jb_user_details__department=None)]
    if departmentless_users:
        choices.append(("", [(user.pk, get_really_full_name(user))
                             for user in sorted_users_by_first_name(departmentless_users)]))
    if len(choices) == 1:
        choices = choices[0][1]
    return choices
Esempio n. 21
0
    def build_menu(self, menu, request):
        """Contribute to the menu.  See :py:mod:`jb_common.nav_menu` for further
        information.
        """
        import jb_common.utils.base as utils

        menu.get_or_create(_("add"))
        menu.get_or_create(pgettext("top-level menu item", "explore"))
        menu.get_or_create(_("manage"))
        if request.user.is_authenticated():
            user_menu = menu.get_or_create(
                MenuItem(utils.get_really_full_name(request.user),
                         position="right"))
            user_menu.add(
                _("edit preferences"),
                reverse("samples:edit_preferences",
                        kwargs={"login_name": request.user.username}),
                "wrench")
            if request.user.has_usable_password():
                user_menu.add(_("change password"), reverse("password_change"),
                              "option-horizontal")
            user_menu.add(_("logout"), reverse("logout"), "log-out")
        jb_menu = menu.get_or_create("JuliaBase")
        jb_menu.add(_("main menu"), reverse("samples:main_menu"), "home")
        try:
            help_link = request.juliabase_help_link
        except AttributeError:
            pass
        else:
            jb_menu.add(_("help"), settings.HELP_LINK_PREFIX + help_link,
                        "question-sign")
        jb_menu.add(_("statistics"), reverse("samples:statistics"), "stats")
        jb_menu.add(_("about"), reverse("samples:about"), "info-sign")
        if request.user.is_authenticated(
        ) and request.method == "GET" and settings.LANGUAGES:
            jb_menu.add_separator()
            for code, name in settings.LANGUAGES:
                back_url = request.path
                if request.GET:
                    back_url += "?" + request.GET.urlencode()
                jb_menu.add(name,
                            "{}?lang={}&amp;next={}".format(
                                reverse("jb_common:switch_language"), code,
                                urllib.parse.quote_plus(back_url)),
                            icon_url=urllib.parse.urljoin(
                                settings.STATIC_URL,
                                "juliabase/flags/{}.png".format(code)),
                            icon_description=_("switch to {language}").format(
                                language=name))
Esempio n. 22
0
def topics_and_permissions(request, login_name):
    user = get_object_or_404(django.contrib.auth.models.User, username=login_name)
    if not request.user.is_superuser and request.user != user:
        raise permissions.PermissionError(
            request.user, _("You can't access the list of topics and permissions of another user."))
    if jb_common_utils.is_json_requested(request):
        return jb_common_utils.respond_in_json((user.topics.values_list("pk", flat=True),
                                                user.managed_topics.values_list("pk", flat=True),
                                                user.get_all_permissions()))
    return render(request, "samples/topics_and_permissions.html",
                  {"title": _("Topics and permissions for {user_name}").format(user_name=get_really_full_name(request.user)),
                   "topics": user.topics.all(), "managed_topics": user.managed_topics.all(),
                   "permissions": permissions.get_user_permissions(user),
                   "full_user_name": get_really_full_name(request.user),
                   "permissions_url": django.core.urlresolvers.reverse("samples:list_permissions")})
Esempio n. 23
0
def topics_and_permissions(request, login_name):
    user = get_object_or_404(django.contrib.auth.models.User, username=login_name)
    if not request.user.is_superuser and request.user != user:
        raise permissions.PermissionError(
            request.user, _("You can't access the list of topics and permissions of another user."))
    if jb_common_utils.is_json_requested(request):
        return jb_common_utils.respond_in_json((user.topics.values_list("pk", flat=True),
                                                user.managed_topics.values_list("pk", flat=True),
                                                user.get_all_permissions()))
    return render(request, "samples/topics_and_permissions.html",
                  {"title": _("Topics and permissions for {user_name}").format(user_name=get_really_full_name(request.user)),
                   "topics": user.topics.all(), "managed_topics": user.managed_topics.all(),
                   "permissions": permissions.get_user_permissions(user),
                   "full_user_name": get_really_full_name(request.user),
                   "permissions_url": django.core.urlresolvers.reverse("samples.views.permissions.list_")})
Esempio n. 24
0
 def __init__(self, user, data=None, **kwargs):
     super(AddSamplesForm, self).__init__(data, **kwargs)
     self.fields["timestamp"].initial = datetime.datetime.now()
     self.fields["topic"].set_topics(user)
     self.fields["substrate_comments"].help_text = \
         """<span class="markdown-hint">""" + _("""with {markdown_link} syntax""").format(
         markdown_link="""<a href="{0}">Markdown</a>""".format(
                 django.core.urlresolvers.reverse("jb_common.views.markdown_sandbox"))) + "</span>"
     self.fields["substrate_originator"].choices = [("<>", get_really_full_name(user))]
     external_contacts = user.external_contacts.all()
     if external_contacts:
         for external_operator in external_contacts:
             self.fields["substrate_originator"].choices.append((external_operator.pk, external_operator.name))
         self.fields["substrate_originator"].required = True
     self.user = user
Esempio n. 25
0
def edit_user_details(request, username):
    user = get_object_or_404(django.contrib.auth.models.User, username=username)
    if not request.user.is_superuser and request.user != user:
        raise Http404("You can't access the user details of another user.")
    user_details = user.kicker_user_details
    if request.method == "POST":
        user_details_form = UserDetailsForm(user, request.POST, instance=user_details)
        if user_details_form.is_valid():
            user_details_form.save()
            return successful_response(request, _("The preferences were successfully updated."), summary)
    else:
        user_details_form = UserDetailsForm(user, instance=user_details)
    return render(request, "kicker/user_details.html", {
        "title": _("Change preferences for {user_name}").format(user_name=get_really_full_name(user)),
        "user_details": user_details_form,
        "shortkeys": " ".join(models.UserDetails.objects.exclude(shortkey="").values_list("shortkey", flat=True))})
Esempio n. 26
0
    def __init__(self, user, *args, **kwargs):
        """
        :param user: the user whose “My Samples” list should be generated

        :type user: django.contrib.auth.models.User
        """
        super(ActionForm, self).__init__(*args, **kwargs)
        self.fields["new_currently_responsible_person"].set_users(user, user)
        self.fields["copy_to_user"].set_users(user)
        try:
            self.fields["copy_to_user"].choices.remove((user.id, get_really_full_name(user)))
        except ValueError:
            pass
        self.fields["new_topic"].set_topics(user)
        self.fields["clearance"].choices = [("", "---------"), ("0", _("sample only")),
                                            ("1", _("all processes up to now"))]
        self.clearance_choices = {"": None, "0": (), "1": "all"}
Esempio n. 27
0
 def __init__(self, user, data=None, **kwargs):
     super(AddSamplesForm, self).__init__(data, **kwargs)
     self.fields["timestamp"].initial = django.utils.timezone.now()
     self.fields["topic"].set_topics(user)
     self.fields["substrate_comments"].help_text = \
         """<span class="markdown-hint">""" + _("""with {markdown_link} syntax""").format(
         markdown_link="""<a href="{0}">Markdown</a>""".format(
                 django.core.urlresolvers.reverse("jb_common:markdown_sandbox"))) + "</span>"
     self.fields["substrate_originator"].choices = [
         ("<>", get_really_full_name(user))
     ]
     external_contacts = user.external_contacts.all()
     if external_contacts:
         for external_operator in external_contacts:
             self.fields["substrate_originator"].choices.append(
                 (external_operator.pk, external_operator.name))
         self.fields["substrate_originator"].required = True
     self.user = user
Esempio n. 28
0
def edit(request, username):
    """View for doing various things with the samples listed under “My
    Samples”.  For example, copying them to the “My Samples” list of another
    user, or simply removing them from the list.

    Note that there are two different user variables in this view and its
    associated functions.  ``current_user`` is the same as ``request.user``.
    Thus, it is the currently logged-in user.  However, ``user`` is the user
    whose “My Samples” are to be processed.  Almost always both are the same,
    especially because you are not allowed to see or change the “My Samples” of
    another user.  However, staff users *are* allowed to change them, so then
    both are different.

    :param request: the current HTTP Request object
    :param username: the login name of the user whose “My Samples” should be
        changed

    :type request: HttpRequest
    :type username: unicode

    :return:
      the HTTP response object

    :rtype: HttpResponse
    """
    user = get_object_or_404(django.contrib.auth.models.User, username=username)
    if not request.user.is_superuser and request.user != user:
        raise permissions.PermissionError(request.user, _("You can't access the “My Samples” section of another user."))
    if request.method == "POST":
        my_samples_form = MySamplesForm(user, request.POST)
        action_form = ActionForm(user, request.POST)
        referentially_valid = is_referentially_valid(request.user, my_samples_form, action_form)
        if my_samples_form.is_valid() and action_form.is_valid() and referentially_valid:
            save_to_database(user, my_samples_form, action_form)
            return utils.successful_response(request, _("Successfully processed “My Samples”."))
    else:
        if is_json_requested(request):
            return respond_in_json(request.user.my_samples.values_list("id", flat=True))
        my_samples_form = MySamplesForm(user)
        action_form = ActionForm(user)
    return render(request, "samples/edit_my_samples.html",
                  {"title": _("Manage “My Samples” of {user_name}").format(user_name=get_really_full_name(user)),
                   "my_samples": my_samples_form, "action": action_form})
Esempio n. 29
0
    def __init__(self, user, *args, **kwargs):
        """
        :param user: the user whose “My Samples” list should be generated

        :type user: django.contrib.auth.models.User
        """
        super(ActionForm, self).__init__(*args, **kwargs)
        self.fields["new_currently_responsible_person"].set_users(user, user)
        self.fields["copy_to_user"].set_users(user)
        try:
            self.fields["copy_to_user"].choices.remove(
                (user.id, get_really_full_name(user)))
        except ValueError:
            pass
        self.fields["new_topic"].set_topics(user)
        self.fields["clearance"].choices = [("", "---------"),
                                            ("0", _("sample only")),
                                            ("1", _("all processes up to now"))
                                            ]
        self.clearance_choices = {"": None, "0": (), "1": "all"}
Esempio n. 30
0
def inform_process_supervisors(sender, instance, **kwargs):
    """Send an email to the supervisors of an apparatus when a user creates
    his or her first process of this apparatus.  If no supervisors are found,
    the administrators are emailed.
    """
    # FixMe: The following line is only necessary as long as
    # http://code.djangoproject.com/ticket/9318 is not fixed.  When it is
    # fixed, this function must be connected only with senders of
    # ``PhysicalProcess``.  If this is not possible because ``PhysicalProcess``
    # is abstract, this line must stay, and this function must be connected
    # with senders of ``Process`` only.  The check ``raw==False`` must stay,
    # though.
    _ = ugettext
    if not kwargs.get("raw") and isinstance(
            instance, PhysicalProcess) and instance.finished:
        user = instance.operator
        process_class = instance.__class__
        if not process_class.objects.filter(operator=user).exists():
            try:
                permission = django.contrib.auth.models.Permission.objects.get(
                    codename="edit_permissions_for_{0}".format(
                        process_class.__name__.lower()),
                    content_type=ContentType.objects.get_for_model(
                        process_class))
            except django.contrib.auth.models.Permission.DoesNotExist:
                return
            recipients = list(django.contrib.auth.models.User.objects.filter(user_permissions=permission)) or \
                list(django.contrib.auth.models.User.objects.filter(is_staff=True).exclude(email=""))
            if recipients:
                _ = lambda x: x
                utils.send_email(
                    _(u"{user_name} uses {apparatus}"),
                    _(u"Dear supervisors of {apparatus_plural},\n\n{user_name} has "
                      u"created their first {apparatus}.\n"), recipients, {
                          "apparatus_plural":
                          process_class._meta.verbose_name_plural,
                          "apparatus": process_class._meta.verbose_name,
                          "user_name": utils.get_really_full_name(user)
                      })
Esempio n. 31
0
def show_user(request, login_name):
    """View for showing basic information about a user, like the email address.
    This could be fleshed out with phone number, picture, position, and field
    of interest by overriding this view in the institute app.

    :param request: the current HTTP Request object
    :param login_name: the login name of the user to be shown

    :type request: HttpRequest
    :type login_name: str

    :return:
      the HTTP response object

    :rtype: HttpResponse
    """
    try:
        user = django.contrib.auth.models.User.objects.filter(username=login_name). \
               exclude(jb_user_details__department=None)[0]
    except IndexError:
        raise Http404('No User matches the given query.')
    department = user.jb_user_details.department
    username = get_really_full_name(user)
    return render(request, "jb_common/show_user.html", {"title": username, "shown_user": user, "department": department})
Esempio n. 32
0
 def build_menu(self, menu, request):
     """Contribute to the menu.  See :py:mod:`jb_common.nav_menu` for further
     information.
     """
     menu.get_or_create(_("add"))
     menu.get_or_create(pgettext("top-level menu item", "explore"))
     menu.get_or_create(_("manage"))
     if request.user.is_authenticated():
         user_menu = menu.get_or_create(MenuItem(utils.get_really_full_name(request.user), position="right"))
         user_menu.add(
             _("edit preferences"),
             reverse("samples.views.user_details.edit_preferences", kwargs={"login_name": request.user.username}),
             "wrench")
         if request.user.has_usable_password():
             user_menu.add(_("change password"), reverse("django.contrib.auth.views.password_change"), "option-horizontal")
         user_menu.add(_("logout"), reverse("django.contrib.auth.views.logout"), "log-out")
     jb_menu = menu.get_or_create("JuliaBase")
     jb_menu.add(_("main menu"), reverse("samples.views.main.main_menu"), "home")
     try:
         help_link = request.juliabase_help_link
     except AttributeError:
         pass
     else:
         jb_menu.add(_("help"), help_link, "question-sign")
     jb_menu.add(_("statistics"), reverse("samples.views.statistics.statistics"), "stats")
     jb_menu.add(_("about"), reverse("samples.views.statistics.about"), "info-sign")
     if request.user.is_authenticated() and request.method == "GET" and settings.LANGUAGES:
         jb_menu.add_separator()
         for code, name in settings.LANGUAGES:
             back_url = request.path
             if request.GET:
                 back_url += "?" + request.GET.urlencode()
             jb_menu.add(name, "{}?lang={}&amp;next={}".format(reverse("jb_common.views.switch_language"), code,
                                                               urllib.parse.quote_plus(back_url)),
                         icon_url=urllib.parse.urljoin(settings.STATIC_URL, "juliabase/flags/{}.png".format(code)),
                         icon_description=_("switch to {language}").format(language=name))
Esempio n. 33
0
def edit_preferences(request, login_name):
    """View for editing preferences of a user.  Note that by giving the
    ``login_name`` explicitly, it is possible to edit the preferences of
    another user.  However, this is only allowed to staff.  The main reason for
    this explicitness is to be more “RESTful”.

    You can't switch the prefered language here because there are the flags
    anyway.

    Moreover, for good reason, you can't change your real name here.  This is
    taken automatically from the domain database through LDAP.  I want to give
    as few options as possible in order to avoid misbehaviour.

    :param request: the current HTTP Request object
    :param login_name: the login name of the user who's preferences should be
        edited.

    :type request: HttpRequest
    :type login_name: unicode

    :return:
      the HTTP response object

    :rtype: HttpResponse
    """
    def __change_folded_processes(default_folded_process_classes, user):
        """Creates the new exceptional processes dictionary and saves it into the user details.
        """
        old_default_classes = set(cls.id for cls in ContentType.objects.filter(dont_show_to_user=user.samples_user_details))
        new_default_classes = set(int(class_id) for class_id in default_folded_process_classes if class_id)
        differences = old_default_classes ^ new_default_classes
        exceptional_processes_dict = json.loads(user.samples_user_details.folded_processes)
        for process_id_list in exceptional_processes_dict.values():
            for process_id in copy.copy(process_id_list):
                try:
                    if models.Process.objects.get(pk=process_id).content_type.id in differences:
                        process_id_list.remove(process_id)
                except models.Process.DoesNotExist:
                    # FixMe: the missing process should be removed from the exceptional_processes_dict
                    pass
        user.samples_user_details.folded_processes = json.dumps(exceptional_processes_dict)
        user.samples_user_details.save()

    user = get_object_or_404(django.contrib.auth.models.User, username=login_name)
    if not request.user.is_superuser and request.user != user:
        raise permissions.PermissionError(request.user, _("You can't access the preferences of another user."))
    initials_mandatory = request.GET.get("initials_mandatory") == "True"
    user_details = user.samples_user_details
    if request.method == "POST":
        user_details_form = UserDetailsForm(user, request.POST, instance=user_details)
        initials_form = utils.InitialsForm(user, initials_mandatory, request.POST)
        if user_details_form.is_valid() and initials_form.is_valid():
            __change_folded_processes(user_details_form.cleaned_data["default_folded_process_classes"], user)
            user_details = user_details_form.save(commit=False)
            user_details.show_users_from_departments = Department.objects.filter(id__in=
                                                        user_details_form.cleaned_data["show_users_from_departments"])
            user_details.default_folded_process_classes = [ContentType.objects.get_for_id(int(id_))
                 for id_ in user_details_form.cleaned_data["default_folded_process_classes"]]
            user_details.save()
            initials_form.save()
            return utils.successful_response(request, _("The preferences were successfully updated."))
    else:
        user_details_form = UserDetailsForm(user, instance=user_details)
        initials_form = utils.InitialsForm(user, initials_mandatory)
    return render(request, "samples/edit_preferences.html",
                  {"title": _("Change preferences for {user_name}").format(user_name=get_really_full_name(request.user)),
                   "user_details": user_details_form, "initials": initials_form,
                   "has_topics": user.topics.exists()})
Esempio n. 34
0
def show(request, claim_id):
    """View for reviewing a claim.

    :param request: the current HTTP Request object
    :param claim_id: the primary key of the claim to be viewed

    :type request: HttpRequest
    :type claim_id: unicode

    :return:
      the HTTP response object

    :rtype: HttpResponse
    """
    _ = ugettext
    claim = get_object_or_404(models.SampleClaim,
                              pk=utils.convert_id_to_int(claim_id))
    is_reviewer = request.user == claim.reviewer or request.user.is_staff
    is_requester = request.user == claim.requester
    if not is_reviewer and not is_requester:
        raise permissions.PermissionError(
            request.user,
            _("You are neither the requester nor the reviewer of this claim."))
    if request.method == "POST" and not claim.closed:
        withdraw_form = CloseForm(_("withdraw claim"),
                                  request.POST,
                                  prefix="withdraw") if is_requester else None
        approve_form = CloseForm(_("approve claim"),
                                 request.POST,
                                 prefix="approve") if is_reviewer else None
        all_valid = (withdraw_form is None or withdraw_form.is_valid()) and (
            approve_form is None or approve_form.is_valid())
        referencially_valid = is_referentially_valid(withdraw_form,
                                                     approve_form)
        if all_valid and referencially_valid:
            approved = approve_form and approve_form.cleaned_data["close"]
            closed = approved or (withdraw_form
                                  and withdraw_form.cleaned_data["close"])
            response = None
            if approved:
                sample_list = list(claim.samples.all())
                for sample in sample_list:
                    sample.currently_responsible_person = claim.requester
                    sample.save()
                sample_enumeration = "    " + ",\n    ".join(
                    six.text_type(sample) for sample in sample_list)
                _ = lambda x: x
                send_email(
                    _("Sample request approved"),
                    _("""Hello {requester},

your sample claim was approved.  You are now the “currently
responsible person” of the following samples:

{samples}

JuliaBase.
"""), claim.requester, {
                        "requester": get_really_full_name(claim.requester),
                        "samples": sample_enumeration
                    })
                _ = ugettext
                response = \
                    utils.successful_response(request,
                                              _("Sample claim {id_} was successfully approved.").format(id_=claim.pk))
            if closed:
                claim.closed = True
                claim.save()
                response = response or \
                    utils.successful_response(request,
                                              _("Sample claim {id_} was successfully withdrawn.").format(id_=claim.pk))
            return response
    else:
        withdraw_form = CloseForm(_("withdraw claim"),
                                  prefix="withdraw") if is_requester else None
        approve_form = CloseForm(_("approve claim"),
                                 prefix="approve") if is_reviewer else None
    return render(
        request, "samples/show_claim.html", {
            "title": _("Claim #{number}").format(number=claim_id),
            "claim": claim,
            "is_reviewer": is_reviewer,
            "is_requester": is_requester,
            "withdraw": withdraw_form,
            "approve": approve_form
        })
Esempio n. 35
0
def add_oldstyle(request, username):
    """View for adding a new claim to old-style sample names.  This is a nice
    example of a view of the app “samples” which is *extended* in the institute
    app.  The template – in this case,
    :file:`institute/templates/samples/list_claims.html` – overrides and extends the
    default one, and adds a link to a URL listed in institute's URLconf and pointing
    to this view function.

    The important step is the template.  This is the hook for your extensions.
    You override the template from “samples” by creating a file called the same
    in :file:`institute/templates/samples/`.  Because ``TEMPLATE_DIRS`` and
    ``TEMPLATE_LOADERS`` are defined as recommended in
    :doc:`/programming/settings`, it shadows its counterpart.  By giving the
    full path, you can still access the original.  Thus, you may start your
    template with

    ::

        {% extends "samples/templates/samples/list_claims.html" %}

    in order to extend it.

    The `username` parameter of this view function is actually superfluous
    because it must be the currently logged-in user anyway.  But this way, we
    don't get into trouble if a user happens to be called ``"add"``.
    Additionally, the URLs become RESTful.

    :param request: the current HTTP Request object
    :param username: the name of the user whose claim this will be; it must be
        the currently logged-in user

    :type request: HttpRequest
    :type username: unicode

    :return:
      the HTTP response object

    :rtype: HttpResponse
    """
    _ = ugettext
    user = get_object_or_404(django.contrib.auth.models.User,
                             username=username)
    if user != request.user:
        raise permissions.PermissionError(
            request.user,
            _("You are not allowed to add a claim in another user's name."))
    if request.method == "POST":
        samples_form = SamplesForm(request.POST)
        substrate_form = SubstrateForm(request.POST)
        reviewer_form = ReviewerForm(request.POST)
        if samples_form.is_valid() and substrate_form.is_valid(
        ) and reviewer_form.is_valid():
            reviewer = reviewer_form.cleaned_data["reviewer"]
            claim = SampleClaim(requester=user, reviewer=reviewer)
            claim.save()
            _ = lambda x: x
            send_email(
                _("Sample request from {requester}"),
                _("""Hello {reviewer},

{requester} wants to become the new “currently responsible person”
of one or more samples.  Please visit

    {url}

for reviewing this request.  If you don't want or cannot approve
the request, please contact {requester} directly and ask him or her
to withdraw the request.

JuliaBase.
"""), reviewer, {
                    "reviewer":
                    get_really_full_name(reviewer),
                    "requester":
                    get_really_full_name(user),
                    "url":
                    request.build_absolute_uri(
                        django.core.urlresolvers.reverse(
                            "samples.views.claim.show",
                            kwargs={"claim_id": claim.pk}))
                })
            _ = ugettext
            samples = []
            nobody = django.contrib.auth.models.User.objects.get(
                username="******")
            legacy = Topic.objects.get(name="Legacy")
            now = datetime.datetime.now()
            material, substrate_comments = substrate_form.cleaned_data[
                "material"], substrate_form.cleaned_data["comments"]
            for name in samples_form.cleaned_data["samples"]:
                substrate = models.Substrate(operator=nobody,
                                             timestamp=now,
                                             material=material,
                                             comments=substrate_comments)
                substrate.save()
                sample = Sample(name=name,
                                current_location="unknown",
                                currently_responsible_person=nobody,
                                topic=legacy)
                sample.save()
                sample.processes.add(substrate)
                samples.append(sample)
            claim.samples = samples
            return utils.successful_response(
                request,
                _("Sample claim {id_} was successfully submitted.").format(
                    id_=claim.pk),
                "samples.views.claim.show",
                kwargs={"claim_id": claim.pk})
    else:
        samples_form = SamplesForm()
        substrate_form = SubstrateForm()
        reviewer_form = ReviewerForm()
    return render(
        request, "samples/add_claim_oldstyle.html", {
            "title": _("Assert claim"),
            "samples": samples_form,
            "substrate": substrate_form,
            "reviewer": reviewer_form
        })
Esempio n. 36
0
def show(request, claim_id):
    """View for reviewing a claim.

    :param request: the current HTTP Request object
    :param claim_id: the primary key of the claim to be viewed

    :type request: HttpRequest
    :type claim_id: unicode

    :return:
      the HTTP response object

    :rtype: HttpResponse
    """
    _ = ugettext
    claim = get_object_or_404(models.SampleClaim, pk=utils.convert_id_to_int(claim_id))
    is_reviewer = request.user == claim.reviewer or request.user.is_superuser
    is_requester = request.user == claim.requester
    if not is_reviewer and not is_requester:
        raise permissions.PermissionError(request.user, _("You are neither the requester nor the reviewer of this claim."))
    if request.method == "POST" and not claim.closed:
        withdraw_form = CloseForm(_("withdraw claim"), request.POST, prefix="withdraw") if is_requester else None
        approve_form = CloseForm(_("approve claim"), request.POST, prefix="approve") if is_reviewer else None
        all_valid = (withdraw_form is None or withdraw_form.is_valid()) and (approve_form is None or approve_form.is_valid())
        referencially_valid = is_referentially_valid(withdraw_form, approve_form)
        if all_valid and referencially_valid:
            approved = approve_form and approve_form.cleaned_data["close"]
            closed = approved or (withdraw_form and withdraw_form.cleaned_data["close"])
            response = None
            if approved:
                sample_list = list(claim.samples.all())
                for sample in sample_list:
                    sample.currently_responsible_person = claim.requester
                    sample.save()
                sample_enumeration = "    " + ",\n    ".join(six.text_type(sample) for sample in sample_list)
                _ = lambda x: x
                send_email(_("Sample request approved"),
                       _("""Hello {requester},

your sample claim was approved.  You are now the “currently
responsible person” of the following samples:

{samples}

JuliaBase.
"""), claim.requester, {"requester": get_really_full_name(claim.requester), "samples": sample_enumeration})
                _ = ugettext
                response = \
                    utils.successful_response(request,
                                              _("Sample claim {id_} was successfully approved.").format(id_=claim.pk))
            if closed:
                claim.closed = True
                claim.save()
                response = response or \
                    utils.successful_response(request,
                                              _("Sample claim {id_} was successfully withdrawn.").format(id_=claim.pk))
            return response
    else:
        withdraw_form = CloseForm(_("withdraw claim"), prefix="withdraw") if is_requester else None
        approve_form = CloseForm(_("approve claim"), prefix="approve") if is_reviewer else None
    return render(request, "samples/show_claim.html", {"title": _("Claim #{number}").format(number=claim_id),
                                                       "claim": claim, "is_reviewer": is_reviewer,
                                                       "is_requester": is_requester,
                                                       "withdraw": withdraw_form, "approve": approve_form})
Esempio n. 37
0
def nickname(user):
    return user.kicker_user_details.nickname or utils.get_really_full_name(user)
Esempio n. 38
0
def show(request, username, user_hash):
    """View which doesn't generate an HTML page but an Atom 1.0 feed with
    current news for the user.

    The problem we have to deal with here is that the feed-reading program
    cannot login.  Therefore, it must be possible to fetch the feed without
    being logged-in.  The username is no problem, it is part of the path.
    Additionally, a secret hash (see `permissions.get_user_hash`) is appended
    to the URL in the query string.  This should be enough security for this
    purpose.

    :param request: the current HTTP Request object
    :param username: the login name of the user for which the news should be
        delivered
    :param user_hash: the secret user hash, which works as an ersatz password
        because the feed clients can't login.

    :type request: HttpRequest
    :type username: str
    :type user_hash: str

    :return:
      the HTTP response object

    :rtype: HttpResponse
    """
    user = get_object_or_404(django.contrib.auth.models.User, username=username)
    permissions.assert_can_view_feed(user_hash, user)
    feed_absolute_url = request.build_absolute_uri(django.core.urlresolvers.reverse(
        show, kwargs={"username": username, "user_hash": user_hash}))
    feed = ElementTree.Element("feed", xmlns="http://www.w3.org/2005/Atom")
    feed.attrib["xml:base"] = request.build_absolute_uri("/")
    ElementTree.SubElement(feed, "id").text = feed_absolute_url
    ElementTree.SubElement(feed, "title").text = \
        _("JuliaBase news for {user_name}").format(user_name=get_really_full_name(user))
    entries = [entry.actual_instance for entry in user.feed_entries.all()]
    if entries:
        ElementTree.SubElement(feed, "updated").text = format_timestamp(entries[0].timestamp)
    else:
        ElementTree.SubElement(feed, "updated").text = format_timestamp(datetime.datetime.now())
    author = ElementTree.SubElement(feed, "author")
    if settings.ADMINS:
        ElementTree.SubElement(author, "name").text, ElementTree.SubElement(author, "email").text = settings.ADMINS[0]
    ElementTree.SubElement(feed, "link", rel="self", href=feed_absolute_url)
    ElementTree.SubElement(feed, "generator", version=__version__).text = "JuliaBase"
    ElementTree.SubElement(feed, "icon").text = request.build_absolute_uri("/static/juliabase/juliabase_logo.png")
    only_important = user.samples_user_details.only_important_news
    for entry in entries:
        if only_important and not entry.important:
            continue
        if isinstance(entry, (models.FeedNewSamples, models.FeedMovedSamples, models.FeedCopiedMySamples,
                              models.FeedEditedSamples)):
            # Remove orphaned entries (i.e. whose samples have been deleted)
            # because they are a) phony and b) cause tracebacks.
            if entry.samples.count() == 0:
                entry.delete()
                continue
        entry_element = ElementTree.SubElement(feed, "entry")
        ElementTree.SubElement(entry_element, "id").text = \
            "tag:{0},{1}:{2}".format(request.build_absolute_uri("/").partition("//")[2][:-1],
                                     entry.timestamp.strftime("%Y-%m-%d"), entry.sha1_hash)
        metadata = entry.get_metadata()
        ElementTree.SubElement(entry_element, "title").text = metadata["title"]
        ElementTree.SubElement(entry_element, "updated").text = format_timestamp(entry.timestamp)
        author = ElementTree.SubElement(entry_element, "author")
        ElementTree.SubElement(author, "name").text = get_really_full_name(entry.originator)
        if entry.originator.email:
            ElementTree.SubElement(author, "email").text = entry.originator.email
        category = ElementTree.SubElement(
            entry_element, "category", term=metadata["category term"], label=metadata["category label"])
        if "link" in metadata:
            ElementTree.SubElement(entry_element, "link", rel="alternate", href=request.build_absolute_uri(metadata["link"]))
        template = loader.get_template("samples/" + camel_case_to_underscores(entry.__class__.__name__) + ".html")
        content = ElementTree.SubElement(entry_element, "content")
        context_dict = {"entry": entry}
        context_dict.update(entry.get_additional_template_context(user))
        content.text = template.render(Context(context_dict))
        content.attrib["type"] = "html"
#    indent(feed)
    return HttpResponse("""<?xml version="1.0"?>\n"""
                        """<?xml-stylesheet type="text/xsl" href="/static/samples/xslt/atom2html.xslt"?>\n"""
                        + ElementTree.tostring(feed, "utf-8").decode("utf-8"),
                        content_type="application/xml; charset=utf-8")
Esempio n. 39
0
 def label_from_instance(self, user):
     return get_really_full_name(user)
Esempio n. 40
0
def edit(request, task_id):
    """Edit or create a task.

    :param request: the current HTTP Request object
    :param task_id: number of the task to be edited.  If this is
        ``None``, create a new one.

    :type request: HttpRequest
    :type task_id: unicode

    :return:
      the HTTP response object

    :rtype: HttpResponse
    """
    task = get_object_or_404(Task, id=utils.convert_id_to_int(task_id)) if task_id else None
    user = request.user
    if task and user != task.customer:
        permissions.assert_can_add_physical_process(request.user, task.process_class.model_class())
    preset_sample = utils.extract_preset_sample(request) if not task_id else None
    if request.method == "POST":
        task_form = TaskForm(user, request.POST, instance=task)
        samples_form = SamplesForm(user, preset_sample, task, request.POST)
        if task_id:
            old_task = copy.copy(task)
            old_samples = set(task.samples.all())
        if task_form.is_valid() and (not samples_form.is_bound or samples_form.is_valid()):
            task = save_to_database(task_form, samples_form, old_task=old_task if task_id else None)
            if task_id:
                edit_description = {"important": True, "description": ""}
                if old_task.status != task.status:
                    edit_description["description"] += \
                        _("* Status is now “{new_status}”.\n").format(new_status=task.get_status_display())
                if old_task.priority != task.priority:
                    edit_description["description"] += \
                        _("* Priority is now “{new_priority}̣”.\n").format(new_priority=task.get_priority_display())
                if old_task.finished_process != task.finished_process:
                    edit_description["description"] += _("* Connected process.\n")
                if old_task.operator != task.operator:
                    if task.operator:
                        edit_description["description"] += _("* Operator is now {operator}.\n").format(
                            operator=common_utils.get_really_full_name(task.operator))
                    else:
                        edit_description["description"] += _("* No operator is set anymore.\n")
                if old_samples != set(task.samples.all()):
                    edit_description["description"] += "* {0}.\n".format(common_utils.capitalize_first_letter(_("samples")))
                if old_task.comments != task.comments:
                    edit_description["description"] += "* {0}.\n".format(common_utils.capitalize_first_letter(_("comments")))
            else:
                edit_description = None
            utils.Reporter(request.user).report_task(task, edit_description)
            message = _("Task was {verb} successfully.").format(verb=_("edited") if task_id else _("added"))
            return utils.successful_response(request, message, "samples.views.task_lists.show")
    else:
        samples_form = SamplesForm(user, preset_sample, task)
        initial = {}
        if "process_class" in request.GET:
            initial["process_class"] = request.GET["process_class"]
        task_form = TaskForm(request.user, instance=task, initial=initial)
    title = capfirst(_("edit task")) if task else capfirst(_("add task"))
    return render(request, "samples/edit_task.html", {"title": title, "task": task_form, "samples": samples_form})
Esempio n. 41
0
def edit_preferences(request, login_name):
    """View for editing preferences of a user.  Note that by giving the
    ``login_name`` explicitly, it is possible to edit the preferences of
    another user.  However, this is only allowed to staff.  The main reason for
    this explicitness is to be more “RESTful”.

    You can't switch the prefered language here because there are the flags
    anyway.

    Moreover, for good reason, you can't change your real name here.  This is
    taken automatically from the domain database through LDAP.  I want to give
    as few options as possible in order to avoid misbehaviour.

    :param request: the current HTTP Request object
    :param login_name: the login name of the user who's preferences should be
        edited.

    :type request: HttpRequest
    :type login_name: unicode

    :return:
      the HTTP response object

    :rtype: HttpResponse
    """
    def __change_folded_processes(default_folded_process_classes, user):
        """Creates the new exceptional processes dictionary and saves it into the user details.
        """
        old_default_classes = set(cls.id for cls in ContentType.objects.filter(dont_show_to_user=user.samples_user_details))
        new_default_classes = set(map(int, default_folded_process_classes))
        differences = old_default_classes ^ new_default_classes
        exceptional_processes_dict = json.loads(user.samples_user_details.folded_processes)
        for process_id_list in exceptional_processes_dict.values():
            for process_id in copy.copy(process_id_list):
                try:
                    if models.Process.objects.get(pk=process_id).content_type.id in differences:
                        process_id_list.remove(process_id)
                except models.Process.DoesNotExist:
                    # FixMe: the missing process should be removed from the exceptional_processes_dict
                    pass
        user.samples_user_details.folded_processes = json.dumps(exceptional_processes_dict)
        user.samples_user_details.save()

    user = get_object_or_404(django.contrib.auth.models.User, username=login_name)
    if not request.user.is_superuser and request.user != user:
        raise permissions.PermissionError(request.user, _("You can't access the preferences of another user."))
    initials_mandatory = request.GET.get("initials_mandatory") == "True"
    user_details = user.samples_user_details
    if request.method == "POST":
        user_details_form = UserDetailsForm(user, request.POST, instance=user_details)
        initials_form = utils.InitialsForm(user, initials_mandatory, request.POST)
        if user_details_form.is_valid() and initials_form.is_valid():
            __change_folded_processes(user_details_form.cleaned_data["default_folded_process_classes"], user)
            user_details = user_details_form.save(commit=False)
            user_details.show_users_from_departments = Department.objects.filter(id__in=
                                                        user_details_form.cleaned_data["show_users_from_departments"])
            user_details.default_folded_process_classes = [ContentType.objects.get_for_id(int(id_))
                 for id_ in user_details_form.cleaned_data["default_folded_process_classes"]]
            user_details.save()
            initials_form.save()
            return utils.successful_response(request, _("The preferences were successfully updated."))
    else:
        user_details_form = UserDetailsForm(user, instance=user_details)
        initials_form = utils.InitialsForm(user, initials_mandatory)
    return render(request, "samples/edit_preferences.html",
                  {"title": _("Change preferences for {user_name}").format(user_name=get_really_full_name(request.user)),
                   "user_details": user_details_form, "initials": initials_form,
                   "has_topics": user.topics.exists()})
Esempio n. 42
0
def show(request, username, user_hash):
    """View which doesn't generate an HTML page but an Atom 1.0 feed with
    current news for the user.

    The problem we have to deal with here is that the feed-reading program
    cannot login.  Therefore, it must be possible to fetch the feed without
    being logged-in.  The username is no problem, it is part of the path.
    Additionally, a secret hash (see `permissions.get_user_hash`) is appended
    to the URL in the query string.  This should be enough security for this
    purpose.

    :param request: the current HTTP Request object
    :param username: the login name of the user for whic the news should be
        delivered
    :param user_hash: the secret user hash, which works as an ersatz password
        because the feed clients can't login.

    :type request: HttpRequest
    :type username: str
    :type user_hash: str

    :return:
      the HTTP response object

    :rtype: HttpResponse
    """
    user = get_object_or_404(django.contrib.auth.models.User, username=username)
    permissions.assert_can_view_feed(user_hash, user)
    feed_absolute_url = request.build_absolute_uri(django.core.urlresolvers.reverse(
        show, kwargs={"username": username, "user_hash": user_hash}))
    feed = ElementTree.Element("feed", xmlns="http://www.w3.org/2005/Atom")
    feed.attrib["xml:base"] = request.build_absolute_uri("/")
    ElementTree.SubElement(feed, "id").text = feed_absolute_url
    ElementTree.SubElement(feed, "title").text = \
        _("JuliaBase news for {user_name}").format(user_name=get_really_full_name(user))
    entries = [entry.actual_instance for entry in user.feed_entries.all()]
    if entries:
        ElementTree.SubElement(feed, "updated").text = format_timestamp(entries[0].timestamp)
    else:
        ElementTree.SubElement(feed, "updated").text = format_timestamp(datetime.datetime.now())
    author = ElementTree.SubElement(feed, "author")
    if settings.ADMINS:
        ElementTree.SubElement(author, "name").text, ElementTree.SubElement(author, "email").text = settings.ADMINS[0]
    ElementTree.SubElement(feed, "link", rel="self", href=feed_absolute_url)
    ElementTree.SubElement(feed, "generator", version=__version__).text = "JuliaBase"
    ElementTree.SubElement(feed, "icon").text = request.build_absolute_uri("/static/juliabase/juliabase_logo.png")
    only_important = user.samples_user_details.only_important_news
    for entry in entries:
        if only_important and not entry.important:
            continue
        if isinstance(entry, (models.FeedNewSamples, models.FeedMovedSamples, models.FeedCopiedMySamples,
                              models.FeedEditedSamples)):
            # Remove orphaned entries (i.e. whose samples have been deleted)
            # because they are a) phony and b) cause tracebacks.
            if entry.samples.count() == 0:
                entry.delete()
                continue
        entry_element = ElementTree.SubElement(feed, "entry")
        ElementTree.SubElement(entry_element, "id").text = \
            "tag:{0},{1}:{2}".format(request.build_absolute_uri("/").partition("//")[2][:-1],
                                     entry.timestamp.strftime("%Y-%m-%d"), entry.sha1_hash)
        metadata = entry.get_metadata()
        ElementTree.SubElement(entry_element, "title").text = metadata["title"]
        ElementTree.SubElement(entry_element, "updated").text = format_timestamp(entry.timestamp)
        author = ElementTree.SubElement(entry_element, "author")
        ElementTree.SubElement(author, "name").text = get_really_full_name(entry.originator)
        if entry.originator.email:
            ElementTree.SubElement(author, "email").text = entry.originator.email
        category = ElementTree.SubElement(
            entry_element, "category", term=metadata["category term"], label=metadata["category label"])
        if "link" in metadata:
            ElementTree.SubElement(entry_element, "link", rel="alternate", href=request.build_absolute_uri(metadata["link"]))
        template = loader.get_template("samples/" + camel_case_to_underscores(entry.__class__.__name__) + ".html")
        content = ElementTree.SubElement(entry_element, "content")
        context_dict = {"entry": entry}
        context_dict.update(entry.get_additional_template_context(user))
        content.text = template.render(Context(context_dict))
        content.attrib["type"] = "html"
#    indent(feed)
    return HttpResponse("""<?xml version="1.0"?>\n"""
                        """<?xml-stylesheet type="text/xsl" href="/static/samples/xslt/atom2html.xslt"?>\n"""
                        + ElementTree.tostring(feed, "utf-8").decode("utf-8"),
                        content_type="application/xml; charset=utf-8")
Esempio n. 43
0
def edit(request, username):
    """View for editing user permissions.  You can change two kinds of user
    permissions here: The “add”, “view all”, and “edit permissions”
    permissions, as well as whether the user is a so-called “topic manager”.
    See `list_` for further information.

    :param request: the current HTTP Request object
    :param username: the username of the user whose permissions should be
        changed

    :type request: HttpRequest
    :type username: unicode

    :return:
      the HTTP response object

    :rtype: HttpResponse
    """
    edited_user = get_object_or_404(User, username=username)
    user = request.user
    has_global_edit_permission = user.has_perm(
        "samples.edit_permissions_for_all_physical_processes")
    addable_models = get_addable_models(user)
    permissions_list = []
    for model in addable_models:
        if model.add_permission or model.view_all_permission or model.edit_all_permission or \
                model.edit_permissions_permission:
            if user in model.permission_editors or has_global_edit_permission:
                if request.method == "POST":
                    permissions_list.append(
                        (model,
                         PermissionsForm(edited_user,
                                         model,
                                         request.POST,
                                         prefix=model.codename)))
                else:
                    permissions_list.append(
                        (model,
                         PermissionsForm(edited_user,
                                         model,
                                         prefix=model.codename)))
    if request.method == "POST":
        if all(permission[1].is_valid() for permission in permissions_list):
            for model, permissions_form in permissions_list:
                cleaned_data = permissions_form.cleaned_data

                def model_permission(form_key, attribute_name, permission):
                    if permission:
                        if cleaned_data[form_key]:
                            if edited_user not in getattr(
                                    model, attribute_name):
                                edited_user.user_permissions.add(permission)
                        else:
                            if edited_user in getattr(model, attribute_name):
                                edited_user.user_permissions.remove(permission)

                model_permission("can_add", "adders", model.add_permission)
                model_permission("can_view_all", "full_viewers",
                                 model.view_all_permission)
                model_permission("can_edit_all", "full_editors",
                                 model.edit_all_permission)
                model_permission("can_edit_permissions", "permission_editors",
                                 model.edit_permissions_permission)
            return utils.successful_response(request, _("The permissions of {name} were successfully changed."). \
                                                 format(name=get_really_full_name(edited_user)), "samples:list_permissions")
    return render(
        request, "samples/edit_permissions.html", {
            "title":
            _("Change permissions of {name}").format(
                name=get_really_full_name(edited_user)),
            "permissions_list":
            permissions_list
        })
Esempio n. 44
0
def add(request, username):
    """View for adding a new claim.  The ``username`` parameter is actually
    superfluous because it must be the currently logged-in user anyway.  But
    this way, we don't get into trouble if a user happens to be called
    ``"add"``.  Additionally, the URLs become RESTful.

    :param request: the current HTTP Request object
    :param username: the name of the user whose claim this will be; it must be
        the currently logged-in user

    :type request: HttpRequest
    :type username: unicode

    :return:
      the HTTP response object

    :rtype: HttpResponse
    """
    _ = ugettext
    user = get_object_or_404(django.contrib.auth.models.User,
                             username=username)
    if user != request.user:
        raise permissions.PermissionError(
            request.user,
            _("You are not allowed to add a claim in another user's name."))
    if request.method == "POST":
        samples_form = SamplesForm(user, request.POST)
        reviewer_form = ReviewerForm(request.POST)
        if samples_form.is_valid() and reviewer_form.is_valid():
            reviewer = reviewer_form.cleaned_data["reviewer"]
            claim = models.SampleClaim(requester=user, reviewer=reviewer)
            claim.save()
            _ = lambda x: x
            send_email(
                _("Sample request from {requester}"),
                _("""Hello {reviewer},

{requester} wants to become the new “currently responsible person”
of one or more samples.  Please visit

    {url}

for reviewing this request.  If you don't want or cannot approve
the request, please contact {requester} directly and ask him or her
to withdraw the request.

JuliaBase.
"""), reviewer, {
                    "reviewer":
                    get_really_full_name(reviewer),
                    "requester":
                    get_really_full_name(user),
                    "url":
                    request.build_absolute_uri(
                        django.core.urlresolvers.reverse(
                            show, kwargs={"claim_id": claim.pk}))
                })
            _ = ugettext
            claim.samples = samples_form.cleaned_data["samples"]
            return utils.successful_response(
                request,
                _("Sample claim {id_} was successfully submitted.").format(
                    id_=claim.pk),
                show,
                kwargs={"claim_id": claim.pk})
    else:
        samples_form = SamplesForm(user)
        reviewer_form = ReviewerForm()
    return render(
        request, "samples/add_claim.html", {
            "title": _("Assert claim"),
            "samples": samples_form,
            "reviewer": reviewer_form
        })
Esempio n. 45
0
def edit(request, task_id):
    """Edit or create a task.

    :param request: the current HTTP Request object
    :param task_id: number of the task to be edited.  If this is
        ``None``, create a new one.

    :type request: HttpRequest
    :type task_id: unicode

    :return:
      the HTTP response object

    :rtype: HttpResponse
    """
    task = get_object_or_404(
        Task, id=utils.convert_id_to_int(task_id)) if task_id else None
    user = request.user
    if task and user != task.customer:
        permissions.assert_can_add_physical_process(
            request.user, task.process_class.model_class())
    preset_sample = utils.extract_preset_sample(
        request) if not task_id else None
    if request.method == "POST":
        task_form = TaskForm(user, request.POST, instance=task)
        samples_form = SamplesForm(user, preset_sample, task, request.POST)
        if task_id:
            old_task = copy.copy(task)
            old_samples = set(task.samples.all())
        if task_form.is_valid() and (not samples_form.is_bound
                                     or samples_form.is_valid()):
            task = save_to_database(task_form,
                                    samples_form,
                                    old_task=old_task if task_id else None)
            if task_id:
                edit_description = {"important": True, "description": ""}
                if old_task.status != task.status:
                    edit_description["description"] += \
                        _("* Status is now “{new_status}”.\n").format(new_status=task.get_status_display())
                if old_task.priority != task.priority:
                    edit_description["description"] += \
                        _("* Priority is now “{new_priority}̣”.\n").format(new_priority=task.get_priority_display())
                if old_task.finished_process != task.finished_process:
                    edit_description["description"] += _(
                        "* Connected process.\n")
                if old_task.operator != task.operator:
                    if task.operator:
                        edit_description["description"] += _(
                            "* Operator is now {operator}.\n").format(
                                operator=common_utils.get_really_full_name(
                                    task.operator))
                    else:
                        edit_description["description"] += _(
                            "* No operator is set anymore.\n")
                if old_samples != set(task.samples.all()):
                    edit_description["description"] += "* {0}.\n".format(
                        common_utils.capitalize_first_letter(_("samples")))
                if old_task.comments != task.comments:
                    edit_description["description"] += "* {0}.\n".format(
                        common_utils.capitalize_first_letter(_("comments")))
            else:
                edit_description = None
            utils.Reporter(request.user).report_task(task, edit_description)
            message = _("Task was {verb} successfully.").format(
                verb=_("edited") if task_id else _("added"))
            return utils.successful_response(request, message,
                                             "samples:show_task_lists")
    else:
        samples_form = SamplesForm(user, preset_sample, task)
        initial = {}
        if "process_class" in request.GET:
            initial["process_class"] = request.GET["process_class"]
        task_form = TaskForm(request.user, instance=task, initial=initial)
    title = capfirst(_("edit task")) if task else capfirst(_("add task"))
    return render(request, "samples/edit_task.html", {
        "title": title,
        "task": task_form,
        "samples": samples_form
    })
Esempio n. 46
0
 def __init__(self, user, data=None, **kwargs):
     self.task = kwargs.get("instance")
     self.user = user
     self.fixed_fields = set()
     if self.task:
         eligible_operators = set(
             permissions.get_all_adders(
                 self.task.process_class.model_class()))
         if self.task.operator:
             eligible_operators.add(self.task.operator)
         self.fixed_fields.add("process_class")
         if self.task.status == "1 new":
             self.fixed_fields.add("finished_process")
             if self.user not in eligible_operators:
                 self.fixed_fields.update(["operator", "status"])
         elif self.task.status in ["2 accepted", "3 in progress"]:
             if self.user != self.task.operator:
                 self.fixed_fields.update(
                     ["status", "priority", "finished_process", "operator"])
                 if self.user != self.task.customer:
                     self.fixed_fields.add("comments")
         else:
             self.fixed_fields.update(
                 ["priority", "finished_process", "operator"])
             if self.user != self.task.operator:
                 self.fixed_fields.add("status")
                 if self.user != self.task.customer:
                     self.fixed_fields.add("comments")
     else:
         self.fixed_fields.update(
             ["status", "finished_process", "operator"])
     if data is not None:
         data = data.copy()
         if self.task:
             data.update(forms.model_to_dict(self.task, self.fixed_fields))
         else:
             initial = kwargs.get("initial", {})
             initial.update({"status": "1 new"})
             data.update(initial)
     super(TaskForm, self).__init__(data, **kwargs)
     self.fields["customer"].required = False
     self.fields["operator"].choices = [("", "---------")]
     if self.task:
         self.fields["operator"].choices.extend(
             (user.pk, common_utils.get_really_full_name(user))
             for user in common_utils.sorted_users_by_first_name(
                 eligible_operators))
     self.fields["process_class"].choices = utils.choices_of_content_types(
         permissions.get_all_addable_physical_process_models())
     self.fields["finished_process"].choices = [("", "---------")]
     if self.task:
         old_finished_process_id = self.task.finished_process.id if self.task.finished_process else None
         if self.user == self.task.operator:
             self.fields["finished_process"].choices.extend([(
                 process.id, process.actual_instance
             ) for process in Process.objects.filter(
                 Q(operator=self.user, content_type=self.task.process_class)
                 | Q(id=old_finished_process_id)).filter(
                     finished=True).order_by("-timestamp")[:10]])
         elif old_finished_process_id:
             self.fields["finished_process"].choices.append(
                 (old_finished_process_id, self.task.finished_process))
     self.fields["comments"].widget.attrs["cols"] = 30
     self.fields["comments"].widget.attrs["rows"] = 5
     for field_name in self.fixed_fields:
         self.fields[field_name].disabled = True
         self.fields[field_name].required = False
Esempio n. 47
0
def add_oldstyle(request, username):
    """View for adding a new claim to old-style sample names.  This is a nice
    example of a view of the app “samples” which is *extended* in the institute
    app.  The template – in this case,
    :file:`institute/templates/samples/list_claims.html` – overrides and extends the
    default one, and adds a link to a URL listed in institute's URLconf and pointing
    to this view function.

    The important step is the template.  This is the hook for your extensions.
    You override the template from “samples” by creating a file called the same
    in :file:`institute/templates/samples/`.  Because ``DIRS`` and ``loaders``
    are defined as recommended in :doc:`/programming/settings`, it shadows its
    counterpart.  By giving the full path, you can still access the original.
    Thus, you may start your template with

    ::

        {% extends "samples/templates/samples/list_claims.html" %}

    in order to extend it.

    The `username` parameter of this view function is actually superfluous
    because it must be the currently logged-in user anyway.  But this way, we
    don't get into trouble if a user happens to be called ``"add"``.
    Additionally, the URLs become RESTful.

    :param request: the current HTTP Request object
    :param username: the name of the user whose claim this will be; it must be
        the currently logged-in user

    :type request: HttpRequest
    :type username: unicode

    :return:
      the HTTP response object

    :rtype: HttpResponse
    """
    _ = ugettext
    user = get_object_or_404(django.contrib.auth.models.User, username=username)
    if user != request.user:
        raise permissions.PermissionError(request.user, _("You are not allowed to add a claim in another user's name."))
    if request.method == "POST":
        samples_form = SamplesForm(request.POST)
        substrate_form = SubstrateForm(request.POST)
        reviewer_form = ReviewerForm(request.POST)
        if samples_form.is_valid() and substrate_form.is_valid() and reviewer_form.is_valid():
            reviewer = reviewer_form.cleaned_data["reviewer"]
            claim = SampleClaim(requester=user, reviewer=reviewer)
            claim.save()
            _ = lambda x: x
            send_email(_("Sample request from {requester}"),
                       _("""Hello {reviewer},

{requester} wants to become the new “currently responsible person”
of one or more samples.  Please visit

    {url}

for reviewing this request.  If you don't want or cannot approve
the request, please contact {requester} directly and ask him or her
to withdraw the request.

JuliaBase.
"""), reviewer, {"reviewer": get_really_full_name(reviewer), "requester": get_really_full_name(user),
                 "url": request.build_absolute_uri(django.core.urlresolvers.reverse("samples.views.claim.show",
                                                                                    kwargs={"claim_id": claim.pk}))})
            _ = ugettext
            samples = []
            nobody = django.contrib.auth.models.User.objects.get(username="******")
            legacy = Topic.objects.get(name="Legacy")
            now = datetime.datetime.now()
            material, substrate_comments = substrate_form.cleaned_data["material"], substrate_form.cleaned_data["comments"]
            for name in samples_form.cleaned_data["samples"]:
                substrate = models.Substrate(operator=nobody, timestamp=now, material=material, comments=substrate_comments)
                substrate.save()
                sample = Sample(name=name, current_location="unknown", currently_responsible_person=nobody, topic=legacy)
                sample.save()
                sample.processes.add(substrate)
                samples.append(sample)
            claim.samples = samples
            return utils.successful_response(request,
                                             _("Sample claim {id_} was successfully submitted.").format(id_=claim.pk),
                                             "samples.views.claim.show", kwargs={"claim_id": claim.pk})
    else:
        samples_form = SamplesForm()
        substrate_form = SubstrateForm()
        reviewer_form = ReviewerForm()
    return render(request, "samples/add_claim_oldstyle.html", {"title": _("Assert claim"), "samples": samples_form,
                                                               "substrate": substrate_form, "reviewer": reviewer_form})
Esempio n. 48
0
 def label_from_instance(self, user):
     return get_really_full_name(user)