Exemple #1
0
def by_id(request, sample_id, path_suffix):
    """Pure re-direct view in case a sample is accessed by ID instead of by
    name.  It redirects to the URL with the name.  The query string, if given,
    is passed, too.

    :param request: the current HTTP Request object
    :param sample_id: the numeric ID of the sample
    :param path_suffix: the trailing path, e.g. ``"/split/"``; if you just view
        a sample, it is empty (or only the query string)

    :type request: HttpRequest
    :type sample_id: unicode
    :type path_suffix: unicode

    :return:
      the HTTP response object

    :rtype: HttpResponse
    """
    sample = get_object_or_404(models.Sample, pk=utils.convert_id_to_int(sample_id))
    if is_json_requested(request):
        # No redirect for the remote client.  This also makes a POST request
        # possible.
        if path_suffix == "/edit/":
            return edit(request, sample.name)
        else:  # FixMe: More path_suffixes should be tested
            return show(request, sample.name)
    # Necessary so that the sample's name isn't exposed through the URL
    permissions.get_sample_clearance(request.user, sample)
    query_string = request.META["QUERY_STRING"] or ""
    return HttpResponseSeeOther(
        django.core.urlresolvers.reverse("show_sample_by_name", kwargs={"sample_name": sample.name}) + path_suffix +
        ("?" + query_string if query_string else ""))
Exemple #2
0
 def process_response(self, request, response):
     """Return a HTTP 422 response if a JSON response was requested and an
     HTML page with form errors is returned.
     """
     if is_json_requested(request) and response._headers["content-type"][1].startswith("text/html") and \
             response.status_code == 200:
         user = request.user
         if not user.is_authenticated():
             # Login view was returned
             return HttpResponseUnauthorised()
         hash_ = hashlib.sha1()
         hash_.update(six.text_type(random.random()).encode("ascii"))
         # For some very obscure reason, a random number was not enough --
         # it led to collisions time after time.
         hash_.update(six.text_type(time.time()).encode("ascii"))
         hash_value = hash_.hexdigest()
         ErrorPage.objects.create(hash_value=hash_value,
                                  user=user,
                                  requested_url=request.get_full_path(),
                                  html=response.content)
         return HttpResponseUnprocessableEntity(
             json.dumps((1,
                         request.build_absolute_uri(
                             django.core.urlresolvers.reverse(
                                 "jb_common:show_error_page",
                                 kwargs={"hash_value": hash_value})))),
             content_type="application/json")
     return response
Exemple #3
0
 def process_request(self, request):
     if is_json_requested(request):
         # JSON responses are made for programs, so strings must be stable
         language = "en"
     else:
         language = self.get_language_for_user(request)
     translation.activate(language)
     request.LANGUAGE_CODE = translation.get_language()
Exemple #4
0
 def process_request(self, request):
     if is_json_requested(request):
         # JSON responses are made for programs, so strings must be stable
         language = "en"
     else:
         language = self.get_language_for_user(request)
     translation.activate(language)
     request.LANGUAGE_CODE = translation.get_language()
Exemple #5
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
        })
Exemple #6
0
def show(request, sample_name):
    """A view for showing existing samples.

    :param request: the current HTTP Request object
    :param sample_name: the name of the sample

    :type request: HttpRequest
    :type sample_name: unicode

    :return:
      the HTTP response object

    :rtype: HttpResponse
    """
    start = time.time()
    if request.method == "POST":
        samples_and_processes = SamplesAndProcesses.samples_and_processes(sample_name, request.user, request.POST)
        if samples_and_processes.is_valid():
            added, removed = samples_and_processes.save_to_database()
            if is_json_requested(request):
                return respond_in_json(True)
            if added:
                success_message = ungettext("Sample {samples} was added to My Samples.",
                                            "Samples {samples} were added to My Samples.",
                                            len(added)).format(samples=format_enumeration(added))
            else:
                success_message = ""
            if removed:
                if added:
                    success_message += "  "
                success_message += ungettext("Sample {samples} was removed from My Samples.",
                                             "Samples {samples} were removed from My Samples.",
                                             len(removed)).format(samples=format_enumeration(removed))
            elif not added:
                success_message = _("Nothing was changed.")
            messages.success(request, success_message)
    else:
        if is_json_requested(request):
            sample = utils.lookup_sample(sample_name, request.user)
            return respond_in_json(sample.get_data())
        samples_and_processes = SamplesAndProcesses.samples_and_processes(sample_name, request.user)
    messages.debug(request, "DB-Zugriffszeit: {0:.1f} ms".format((time.time() - start) * 1000))
    return render(request, "samples/show_sample.html",
                  {"title": _("Sample “{sample}”").format(sample=samples_and_processes.sample_context["sample"]),
                   "samples_and_processes": samples_and_processes})
Exemple #7
0
 def process_exception(self, request, exception):
     """Convert response to exceptions to JSONised version if the response
     is requested to be JSON.
     """
     if isinstance(exception, django.http.Http404):
         if is_json_requested(request):
             return django.http.HttpResponseNotFound(json.dumps((2, exception.args[0])), content_type="application/json")
     elif isinstance(exception, JSONRequestException):
         return HttpResponseUnprocessableEntity(json.dumps((exception.error_number, exception.error_message)),
                                                content_type="application/json")
Exemple #8
0
 def process_exception(self, request, exception):
     """Convert response to exceptions to JSONised version if the response
     is requested to be JSON.
     """
     if isinstance(exception, django.http.Http404):
         if is_json_requested(request):
             return django.http.HttpResponseNotFound(
                 json.dumps((2, exception.args[0])),
                 content_type="application/json")
     elif isinstance(exception, JSONRequestException):
         return HttpResponseUnprocessableEntity(
             json.dumps((exception.error_number, exception.error_message)),
             content_type="application/json")
Exemple #9
0
    def is_all_valid(self):
        """Tests the “inner” validity of all forms belonging to this view.  This
        function calls the ``is_valid()`` method of all forms, even if one of
        them returns ``False`` (and makes the return value clear prematurely).

        :return:
          whether all forms are valid.

        :rtype: bool
        """
        all_valid = not self._change_structure() if not is_json_requested(self.request) else True
        all_valid = super(DepositionView, self).is_all_valid() and all_valid
        return all_valid
Exemple #10
0
    def is_all_valid(self):
        """Tests the “inner” validity of all forms belonging to this view.  This
        function calls the ``is_valid()`` method of all forms, even if one of
        them returns ``False`` (and makes the return value clear prematurely).

        :return:
          whether all forms are valid.

        :rtype: bool
        """
        all_valid = not self._change_structure() if not is_json_requested(
            self.request) else True
        all_valid = super(DepositionView, self).is_all_valid() and all_valid
        return all_valid
Exemple #11
0
def split_and_rename_after_deposition(request, deposition_number):
    """View for renaming and/or splitting samples immediately after they have
    been deposited in the same run.

    Optionally, you can give query string parameters of the form
    ``new-name-21=super`` where 21 is the sample ID and “super” is the
    suggested new name of this sample.

    :param request: the current HTTP Request object
    :param deposition_number: the number of the deposition after which samples
        should be split and/or renamed

    :type request: HttpRequest
    :type deposition_number: unicode

    :return:
      the HTTP response object

    :rtype: HttpResponse
    """
    deposition = get_object_or_404(models.Deposition, number=deposition_number).actual_instance
    permissions.assert_can_edit_physical_process(request.user, deposition)
    if not deposition.finished:
        raise Http404("This deposition is not finished yet.")
    if deposition.split_done:
        raise Http404("You can use the split and rename function only once after a deposition.")
    remote_client = is_json_requested(request)
    if request.POST:
        original_data_forms, new_name_form_lists, global_new_data_form = \
            forms_from_post_data(request.user, request.POST, deposition, remote_client)
        all_valid = is_all_valid(original_data_forms, new_name_form_lists, global_new_data_form)
        structure_changed = change_structure(request.user, original_data_forms, new_name_form_lists)
        referentially_valid = is_referentially_valid(original_data_forms, new_name_form_lists, deposition)
        if all_valid and referentially_valid and not structure_changed:
            sample_splits = save_to_database(original_data_forms, new_name_form_lists, global_new_data_form, deposition)
            for sample_split in sample_splits:
                utils.Reporter(request.user).report_sample_split(sample_split, sample_completely_split=True)
            return utils.successful_response(request, _("Samples were successfully split and/or renamed."),
                                             json_response=True)
    else:
        new_names = dict((int_or_zero(key[len("new-name-"):]), new_name)
                         for key, new_name in request.GET.items() if key.startswith("new-name-"))
        new_names.pop(0, None)
        original_data_forms, new_name_form_lists, global_new_data_form = \
            forms_from_database(request.user, deposition, remote_client, new_names)
    return render(request, "samples/split_after_deposition.html",
                  {"title": _("Bulk sample rename for {deposition}").format(deposition=deposition),
                   "samples": list(zip(original_data_forms, new_name_form_lists)),
                   "new_sample_data": global_new_data_form})
Exemple #12
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_")})
Exemple #13
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")})
Exemple #14
0
def show_process(request, process_id, process_name="Process"):
    """Show an existing physical process.  This is some sort of fallback view in
    case a process doesn't provide its own show view (which is mostly the
    case).

    The ``process_id`` needn't be the ``"id"`` field: If `process_name` is not
    ``None``, its ``JBMeta.identifying_field``, it given, is used instead for
    the lookup.

    :param request: the current HTTP Request object
    :param process_id: the ID or the process's identifying field value
    :param process_name: the class name of the process; if ``None``, ``Process``
        is assumed

    :type request: HttpRequest
    :type process_id: unicode
    :type process_name: unicode

    :return:
      the HTTP response object

    :rtype: HttpResponse
    """
    process_class = get_all_models()[process_name]
    try:
        identifying_field = process_class.JBMeta.identifying_field
    except AttributeError:
        identifying_field = "id"
    try:
        process = get_object_or_404(process_class, **{
            identifying_field: process_id
        }).actual_instance
    except ValueError:
        raise Http404("Invalid value for {} passed: {}".format(
            identifying_field, repr(process_id)))
    if not isinstance(process, models.PhysicalProcess):
        raise Http404("No physical process with that ID was found.")
    permissions.assert_can_view_physical_process(request.user, process)
    if is_json_requested(request):
        return respond_in_json(process.get_data())
    template_context = {
        "title": six.text_type(process),
        "samples": process.samples.all(),
        "process": process
    }
    template_context.update(utils.digest_process(process, request.user))
    return render(request, "samples/show_process.html", template_context)
Exemple #15
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})
Exemple #16
0
 def process_response(self, request, response):
     """Return a HTTP 422 response if a JSON response was requested and an
     HTML page with form errors is returned.
     """
     if is_json_requested(request) and response._headers["content-type"][1].startswith("text/html") and \
             response.status_code == 200:
         user = request.user
         if not user.is_authenticated():
             # Login view was returned
             return HttpResponseUnauthorised()
         hash_ = hashlib.sha1()
         hash_.update(six.binary_type(random.random()))
         # For some very obscure reason, a random number was not enough --
         # it led to collisions time after time.
         hash_.update(six.binary_type(time.time()))
         hash_value = hash_.hexdigest()
         ErrorPage.objects.create(hash_value=hash_value, user=user, requested_url=request.get_full_path(),
                                  html=response.content)
         return HttpResponseUnprocessableEntity(
             json.dumps((1, request.build_absolute_uri(
                 django.core.urlresolvers.reverse("jb_common.views.show_error_page", kwargs={"hash_value": hash_value})))),
             content_type="application/json")
     return response