コード例 #1
0
ファイル: json_client.py プロジェクト: Midnighter/juliabase
def add_alias(request):
    """Adds a new sample alias name to the database.  This view can only be
    used by admin accounts.

    :param request: the current HTTP Request object; it must contain the
        sample's primary key and the alias name in the POST data.

    :type request: HttpRequest

    :return:
      ``True`` if it worked, ``False`` if something went wrong.  It returns a
      404 if the sample wasn't found.

    :rtype: HttpResponse
    """
    if not request.user.is_staff:
        return respond_in_json(False)
    try:
        sample_pk = request.POST["sample"]
        alias = request.POST["alias"]
    except KeyError:
        return respond_in_json(False)
    sample = get_object_or_404(models.Sample,
                               pk=utils.convert_id_to_int(sample_pk))
    try:
        models.models.SampleAlias.create(name=alias, sample=sample)
    except IntegrityError:
        # Alias already present
        return respond_in_json(False)
    return respond_in_json(True)
コード例 #2
0
ファイル: json_client.py プロジェクト: Midnighter/juliabase
def login_remote_client(request):
    """Login for the JuliaBase Remote Client.  It expects ``username`` and
    ``password``.  AJAX code shouldn't need it because it has the cookie
    already.  An HTTP GET request yields nothing – this can be used to get the
    CSRF cookie.

    :param request: the current HTTP Request object

    :type request: HttpRequest

    :return:
      the HTTP response object.  It is a JSON boolean object, whether the login
      was successful or not.

    :rtype: HttpResponse
    """
    if request.method == "POST":
        try:
            username = request.POST["username"]
            password = request.POST["password"]
        except KeyError:
            raise JSONRequestException(3,
                                       '"username" and/or "password" missing')
        user = django.contrib.auth.authenticate(username=username,
                                                password=password)
        if user is not None and user.is_active:
            django.contrib.auth.login(request, user)
            return respond_in_json(True)
        raise JSONRequestException(4, "user could not be authenticated")
    else:
        return respond_in_json(None)
コード例 #3
0
ファイル: json_client.py プロジェクト: msincan/juliabase
def add_alias(request):
    """Adds a new sample alias name to the database.  This view can only be
    used by admin accounts.

    :param request: the current HTTP Request object; it must contain the
        sample's primary key and the alias name in the POST data.

    :type request: HttpRequest

    :return:
      ``True`` if it worked, ``False`` if something went wrong.  It returns a
      404 if the sample wasn't found.

    :rtype: HttpResponse
    """
    if not request.user.is_superuser:
        return respond_in_json(False)
    try:
        sample_pk = request.POST["sample"]
        alias = request.POST["alias"]
    except KeyError:
        return respond_in_json(False)
    sample = get_object_or_404(models.Sample, pk=utils.convert_id_to_int(sample_pk))
    try:
        models.models.SampleAlias.create(name=alias, sample=sample)
    except IntegrityError:
        # Alias already present
        return respond_in_json(False)
    return respond_in_json(True)
コード例 #4
0
ファイル: json_client.py プロジェクト: msincan/juliabase
def login_remote_client(request):
    """Login for the JuliaBase Remote Client.  It expects ``username`` and
    ``password``.  AJAX code shouldn't need it because it has the cookie
    already.  An HTTP GET request yields nothing – this can be used to get the
    CSRF cookie.

    :param request: the current HTTP Request object

    :type request: HttpRequest

    :return:
      the HTTP response object.  It is a JSON boolean object, whether the login
      was successful or not.

    :rtype: HttpResponse
    """
    if request.method == "POST":
        try:
            username = request.POST["username"]
            password = request.POST["password"]
        except KeyError:
            raise JSONRequestException(3, '"username" and/or "password" missing')
        user = django.contrib.auth.authenticate(username=username, password=password)
        if user is not None and user.is_active:
            django.contrib.auth.login(request, user)
            return respond_in_json(True)
        raise JSONRequestException(4, "user could not be authenticated")
    else:
        return respond_in_json(None)
コード例 #5
0
ファイル: json_client.py プロジェクト: colima/juliabase
def get_matching_solarsimulator_measurement(request, sample_id, irradiation,
                                            cell_position, date):
    """Finds the solarsimulator measurement which is best suited for the given
    data file.  This view is to solve the problem that for non-standard-Jülich
    cell layouts, many single data files must be merged into one solarsimulator
    measurements.  When importing them one by one, one has to find the already
    existing measurement to which they must be added.  This is done by this
    view.

    It returns the ID of the measurement, or ``None`` if none was found.

    :param request: the HTTP request object
    :param sample_id: the ID of the sample which was measured
    :param irradiation: the irradiation (AM1.5, BG7 etc) which was used
    :param cell_position: the position of the cell on the layout; don't mix it
        up with the *index* of the cell, which is the number used in the
        Solarsimulator datafile in the first column
    :param date: the day (not the time) of the measurement in YYYY-MM-DD format

    :type request: HttpRequest
    :type sample_id: unicode
    :type irradiation: unicode
    :type cell_position: unicode
    :type date: unicode

    :return:
      the HTTP response object

    :rtype: HttpResponse
    """
    try:
        filepath = request.GET["filepath"]
    except KeyError:
        raise JSONRequestException(3, '"filepath" missing')
    try:
        return respond_in_json(
            _get_solarsimulator_measurement_by_filepath(
                filepath, request.user))
    except Http404:
        sample = get_object_or_404(models.Sample, id=sample_id)
        start_date = django.utils.timezone.make_aware(
            datetime.datetime.strptime(date, "%Y-%m-%d"))
        end_date = start_date + datetime.timedelta(days=1)
        matching_measurements = institute.models.SolarsimulatorMeasurement.objects.filter(
            samples__id=sample_id, irradiation=irradiation, timestamp__gte=start_date, timestamp__lt=end_date). \
            exclude(cells__position=cell_position).order_by("timestamp")
        if matching_measurements.exists():
            solarsimulator_measurement = matching_measurements[0]
            permissions.assert_can_fully_view_sample(request.user, sample)
            permissions.assert_can_view_physical_process(
                request.user, solarsimulator_measurement)
            return respond_in_json(solarsimulator_measurement.id)
        else:
            return respond_in_json(None)
コード例 #6
0
ファイル: json_client.py プロジェクト: msincan/juliabase
def get_matching_solarsimulator_measurement(request, sample_id, irradiation, cell_position, date):
    """Finds the solarsimulator measurement which is best suited for the given
    data file.  This view is to solve the problem that for non-standard-Jülich
    cell layouts, many single data files must be merged into one solarsimulator
    measurements.  When importing them one by one, one has to find the already
    existing measurement to which they must be added.  This is done by this
    view.

    It returns the ID of the measurement, or ``None`` if none was found.

    :param request: the HTTP request object
    :param sample_id: the ID of the sample which was measured
    :param irradiation: the irradiation (AM1.5, BG7 etc) which was used
    :param cell_position: the position of the cell on the layout; don't mix it
        up with the *index* of the cell, which is the number used in the
        Solarsimulator datafile in the first column
    :param date: the day (not the time) of the measurement in YYYY-MM-DD format

    :type request: HttpRequest
    :type sample_id: unicode
    :type irradiation: unicode
    :type cell_position: unicode
    :type date: unicode

    :return:
      the HTTP response object

    :rtype: HttpResponse
    """
    try:
        filepath = request.GET["filepath"]
    except KeyError:
        raise JSONRequestException(3, '"filepath" missing')
    try:
        return respond_in_json(_get_solarsimulator_measurement_by_filepath(filepath, request.user))
    except Http404:
        sample = get_object_or_404(models.Sample, id=sample_id)
        start_date = datetime.datetime.strptime(date, "%Y-%m-%d")
        end_date = start_date + datetime.timedelta(days=1)
        matching_measurements = institute.models.SolarsimulatorMeasurement.objects.filter(
            samples__id=sample_id, irradiation=irradiation, timestamp__gte=start_date, timestamp__lt=end_date). \
            exclude(cells__position=cell_position).order_by("timestamp")
        if matching_measurements.exists():
            solarsimulator_measurement = matching_measurements[0]
            permissions.assert_can_fully_view_sample(request.user, sample)
            permissions.assert_can_view_physical_process(request.user, solarsimulator_measurement)
            return respond_in_json(solarsimulator_measurement.id)
        else:
            return respond_in_json(None)
コード例 #7
0
ファイル: views.py プロジェクト: msincan/juliabase
def get_player(request):
    try:
        user_details = models.UserDetails.objects.get(shortkey=request.GET.get("shortkey", ""))
    except (models.UserDetails.MultipleObjectsReturned, models.UserDetails.DoesNotExist):
        raise Http404("User not found.")
    return respond_in_json(
        (user_details.user.username, user_details.nickname or user_details.user.first_name or user_details.user.username))
コード例 #8
0
ファイル: json_client.py プロジェクト: Midnighter/juliabase
def fold_process(request, sample_id):
    """Fold a single process in one sample data sheet. The new behavior is also saved.

    :param request: The current HTTP Request object.  It must contain the process
        ID of the process which behavior should be changed.
    :param sample_id: The sample ID represent the data sheet where the process has to be changed.

    :type request: HttpRequest
    :type sample_id: unicode

    :return:
      True when the process is now folded else False.

    :rtype: HttpResponse
    """
    process_id = int_or_zero(request.POST["process_id"])
    folded_process_classes = ContentType.objects.filter(
        dont_show_to_user=request.user.samples_user_details)
    folded_processes = json.loads(
        request.user.samples_user_details.folded_processes)
    exceptional_processes = folded_processes.setdefault(sample_id, [])
    is_folded = _is_folded(process_id,
                           folded_process_classes,
                           exceptional_processes,
                           switch=True)
    request.user.samples_user_details.folded_processes = json.dumps(
        folded_processes)
    request.user.samples_user_details.save()
    return respond_in_json(is_folded)
コード例 #9
0
ファイル: json_client.py プロジェクト: Midnighter/juliabase
def get_folded_processes(request, sample_id):
    """Get all the IDs from the processes, who have to be folded.

    :param request: The current HTTP Request object.  It must contain all the process
        IDs of the processes from the selected sample.
    :param sample_id: The sample ID represent the data sheet the user wants to see.

    :type request: HttpRequest
    :type sample_id: unicode

    :return:
     The process IDs of the processes, who have to be folded on the samples data sheet.

    :rtype: HttpResponse
    """
    try:
        process_ids = [
            utils.convert_id_to_int(id_)
            for id_ in request.GET["process_ids"].split(",")
        ]
    except KeyError:
        raise JSONRequestException(3, '"process_ids" missing')
    utils.convert_id_to_int(sample_id)
    folded_process_classes = ContentType.objects.filter(
        dont_show_to_user=request.user.samples_user_details)
    exceptional_processes_by_sample_id = json.loads(
        request.user.samples_user_details.folded_processes).get(sample_id, [])
    folded_process_ids = []
    for process_id in process_ids:
        if _is_folded(process_id,
                      folded_process_classes,
                      exceptional_processes_by_sample_id,
                      switch=False):
            folded_process_ids.append(process_id)
    return respond_in_json(folded_process_ids)
コード例 #10
0
ファイル: json_client.py プロジェクト: msincan/juliabase
def available_items(request, model_name):
    """Returns the unique ids of all items that are already in the database for
    this model.  The point is that it will return primary keys only as a
    fallback.  Instead, it returns the “official” id of the respective model,
    represented by the `JBMeta.identifying_field` attribute, if given.  This
    may be the number of a deposition, or the number of a measurement run, etc.

    :param request: the current HTTP Request object
    :param model_name: the name of the database model

    :type request: HttpRequest
    :type model_name: unicode

    :return:
      The HTTP response object.  It is a JSON list object with all the ids of
      the objects in the database for the model.

    :rtype: HttpResponse
    """
    if not request.user.is_superuser:
        raise permissions.PermissionError(request.user, _("Only the administrator can access this resource."))
    # FixMe: This must be revisited; it is ugly.
    for app_name in settings.INSTALLED_APPS:
        try:
            model = sys.modules[app_name + ".models"].__dict__[model_name]
        except KeyError:
            continue
        break
    else:
        raise Http404("Model name not found.")
    try:
        pk = model.JBMeta.identifying_field
    except AttributeError:
        pk = "pk"
    return respond_in_json(list(model.objects.values_list(pk, flat=True)))
コード例 #11
0
ファイル: json_client.py プロジェクト: msincan/juliabase
def get_folded_processes(request, sample_id):
    """Get all the IDs from the processes, who have to be folded.

    :param request: The current HTTP Request object.  It must contain all the process
        IDs of the processes from the selected sample.
    :param sample_id: The sample ID represent the data sheet the user wants to see.

    :type request: HttpRequest
    :type sample_id: unicode

    :return:
     The process IDs of the processes, who have to be folded on the samples data sheet.

    :rtype: HttpResponse
    """
    try:
        process_ids = [utils.convert_id_to_int(id_) for id_ in request.GET["process_ids"].split(",")]
    except KeyError:
        raise JSONRequestException(3, '"process_ids" missing')
    utils.convert_id_to_int(sample_id)
    folded_process_classes = ContentType.objects.filter(dont_show_to_user=request.user.samples_user_details)
    exceptional_processes_by_sample_id = json.loads(request.user.samples_user_details.folded_processes).get(sample_id, [])
    folded_process_ids = []
    for process_id in process_ids:
        if _is_folded(process_id, folded_process_classes, exceptional_processes_by_sample_id, switch=False):
            folded_process_ids.append(process_id)
    return respond_in_json(folded_process_ids)
コード例 #12
0
def set_start_kicker_number(request, username):
    if request.user.username != "kicker":
        raise JSONRequestException(
            3005, "You must be the user \"kicker\" to use this function.")
    try:
        start_kicker_number = int(request.POST["start_kicker_number"])
        timestamp = django.utils.timezone.make_aware(
            datetime.datetime.strptime(request.POST["timestamp"],
                                       "%Y-%m-%d %H:%M:%S"))
    except KeyError:
        raise JSONRequestException(3, error.args[0])
    except ValueError as error:
        raise JSONRequestException(5, error.args[0])
    player, created = django.contrib.auth.models.User.objects.get_or_create(
        username=username)
    if created:
        player.set_unusable_password()
        player.save()
    if models.KickerNumber.objects.filter(player=player).exists():
        raise JSONRequestException(
            3006, "There are already kicker numbers stored for this user.")
    models.KickerNumber.objects.create(player=player,
                                       number=start_kicker_number,
                                       timestamp=timestamp)
    return respond_in_json(True)
コード例 #13
0
def fold_main_menu_element(request):
    """Fold a single topic or sample series from the main menu.

    :param request: The current HTTP Request object.  It must contain the topic
        ID or sample series name.

    :type request: HttpRequest

    :return:
      True if the topic or sample series is now folded else False

    :rtype: HttpResponse
    """
    def fold_element(element_id, folded_elements):
        folded_elements = json.loads(folded_elements)
        if element_id in folded_elements:
            folded_elements.remove(element_id)
            is_folded = False
        else:
            folded_elements.append(element_id)
            is_folded = True
        folded_elements = json.dumps(folded_elements)
        return is_folded, folded_elements

    element_id = int_or_zero(request.POST["element_id"])

    if not element_id:
        element_id = request.POST["element_id"]
        element_is_folded, request.user.samples_user_details.folded_series = \
            fold_element(element_id, request.user.samples_user_details.folded_series)
    else:
        element_is_folded, request.user.samples_user_details.folded_topics = \
            fold_element(element_id, request.user.samples_user_details.folded_topics)
    request.user.samples_user_details.save()
    return respond_in_json(element_is_folded)
コード例 #14
0
ファイル: views.py プロジェクト: msincan/juliabase
def cancel_match(request, id_):
    match = get_object_or_404(models.Match, pk=int_or_zero(id_)) if id_ else None
    if match and match.reporter != request.user:
        raise JSONRequestException(3005, _("You must be the original reporter of this match."))
    if match.finished:
        raise JSONRequestException(3003, _("A finished match can't be canceled."))
    match.delete()
    return respond_in_json(True)
コード例 #15
0
ファイル: my_samples.py プロジェクト: colima/juliabase
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
        })
コード例 #16
0
ファイル: sample.py プロジェクト: muescha/juliabase
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})
コード例 #17
0
ファイル: json_client.py プロジェクト: msincan/juliabase
def add_sample(request):
    """Adds a new sample to the database.  It is added without processes.  This
    view can only be used by admin accounts.

    :param request: the current HTTP Request object; it must contain the sample
        data in the POST data.

    :return:
      The primary key of the created sample.  ``False`` if something went
      wrong.  It may return a 404 if the topic or the currently responsible
      person wasn't found.

    :rtype: HttpResponse
    """
    try:
        name = request.POST["name"]
        current_location = request.POST["current_location"]
        currently_responsible_person = request.POST["currently_responsible_person"]
        purpose = request.POST.get("purpose", "")
        tags = request.POST.get("tags", "")
        topic = request.POST.get("topic")
    except KeyError as error:
        raise JSONRequestException(3, "'{}' parameter missing.".format(error.args[0]))
    if len(name) > 30:
        raise JSONRequestException(5, "The sample name is too long.")
    name_format = utils.sample_name_format(name)
    if name_format is None or \
       not request.user.is_superuser and \
       name_format not in settings.SAMPLE_NAME_FORMATS["provisional"].get("possible_renames", set()):
        raise JSONRequestException(5, "The sample name is invalid.")
    eligible_users = django.contrib.auth.models.User.objects.filter(is_active=True, jb_user_details__department__isnull=False)
    try:
        currently_responsible_person = eligible_users.get(pk=utils.convert_id_to_int(currently_responsible_person))
    except django.contrib.auth.models.User.DoesNotExist:
        raise Http404("Currently reponsible user not found.")
    if topic:
        all_topics = Topic.objects.all() if request.user.is_superuser else \
                     Topic.objects.filter(Q(confidential=False) | Q(members=request.user))
        try:
            topic = all_topics.get(pk=utils.convert_id_to_int(topic))
        except Topic.DoesNotExist:
            raise Http404("Topic not found")
    try:
        sample = models.Sample.objects.create(name=name, current_location=current_location,
                                              currently_responsible_person=currently_responsible_person, purpose=purpose,
                                              tags=tags, topic=topic)
        # They will be shadowed anyway.  Nevertheless, this action is an
        # emergency measure.  Probably the samples the aliases point to should
        # be merged with the sample but this can't be decided automatically.
        models.SampleAlias.objects.filter(name=name).delete()
    except IntegrityError as error:
        error_message = "The sample with this data could not be added."
        if request.user.is_superuser:
            error_message += " {}".format(error)
        raise JSONRequestException(5, error_message)
    sample.watchers.add(request.user)
    return respond_in_json(sample.pk)
コード例 #18
0
def get_player(request):
    try:
        user_details = models.UserDetails.objects.get(
            shortkey=request.GET.get("shortkey", ""))
    except (models.UserDetails.MultipleObjectsReturned,
            models.UserDetails.DoesNotExist):
        raise Http404("User not found.")
    return respond_in_json(
        (user_details.user.username, user_details.nickname
         or user_details.user.first_name or user_details.user.username))
コード例 #19
0
def cancel_match(request, id_):
    match = get_object_or_404(models.Match,
                              pk=int_or_zero(id_)) if id_ else None
    if match and match.reporter != request.user:
        raise JSONRequestException(
            3005, "You must be the original reporter of this match.")
    if match.finished:
        raise JSONRequestException(3003, "A finished match can't be canceled.")
    match.delete()
    return respond_in_json(True)
コード例 #20
0
ファイル: json_client.py プロジェクト: Midnighter/juliabase
def change_my_samples(request):
    """Adds or remove samples from “My Samples”.

    :param request: The current HTTP Request object.  It must contain the sample
        IDs of the to-be-removed samples comma-separated list in ``"remove"``
        and the to-be-added sample IDs in ``"add"``.  Both can be empty.
        Moreover, it may contain the ID of the user whose “My Samples” should
        be changed in ``"user"``.  If not given, the logged-in user is used.
        If given, the currently logged-in user must be admin.

    :type request: HttpRequest

    :return:
      The IDs of the samples for which the change had to be actually made.  It
      returns a 404 if one sample wasn't found.

    :rtype: HttpResponse
    """
    try:
        sample_ids_to_remove = {
            int(id_)
            for id_ in request.POST.get("remove", "").split(",") if id_
        }
        sample_ids_to_add = {
            int(id_)
            for id_ in request.POST.get("add", "").split(",") if id_
        }
    except ValueError:
        raise Http404("One or more of the sample IDs were invalid.")
    user = request.user
    user_id = request.POST.get("user")
    if user_id:
        if not request.user.is_superuser:
            raise JSONRequestException(
                6, "Only admins can change other users' My Samples.")
        try:
            user = django.contrib.auth.models.User.objects.get(pk=user_id)
        except django.contrib.auth.models.User.DoesNotExist:
            raise Http404("User not found.")
    doubled_ids = sample_ids_to_remove & sample_ids_to_add
    sample_ids_to_remove -= doubled_ids
    sample_ids_to_add -= doubled_ids
    try:
        samples_to_remove = models.Sample.objects.in_bulk(
            list(sample_ids_to_remove))
        samples_to_add = utils.restricted_samples_query(request.user).in_bulk(
            list(sample_ids_to_add))
    except models.Sample.DoesNotExist:
        raise Http404("One or more of the sample IDs could not be found.")
    current_my_samples = set(user.my_samples.values_list("id", flat=True))
    changed_sample_ids = sample_ids_to_remove & current_my_samples | \
        sample_ids_to_add - (current_my_samples - sample_ids_to_remove)
    user.my_samples.remove(*samples_to_remove.values())
    user.my_samples.add(*samples_to_add.values())
    return respond_in_json(changed_sample_ids)
コード例 #21
0
ファイル: json_client.py プロジェクト: Midnighter/juliabase
def substrate_by_sample(request, sample_id):
    """Searches for the substrate of a sample.  It returns a dictionary with
    the substrate data.  If the sample isn't found, a 404 is returned.  If
    something else went wrong (in particular, no substrate was found),
    ``False`` is returned.

    :param request: the HTTP request object
    :param sample_id: the primary key of the sample

    :type request: HttpRequest
    :type sample_id: unicode

    :return:
      the HTTP response object

    :rtype: HttpResponse
    """
    if not request.user.is_staff:
        return respond_in_json(False)
    sample = get_object_or_404(models.Sample, pk=utils.convert_id_to_int(sample_id))
    substrate = get_substrate(sample)
    return respond_in_json(substrate.get_data())
コード例 #22
0
ファイル: json_client.py プロジェクト: msincan/juliabase
def substrate_by_sample(request, sample_id):
    """Searches for the substrate of a sample.  It returns a dictionary with
    the substrate data.  If the sample isn't found, a 404 is returned.  If
    something else went wrong (in particular, no substrate was found),
    ``False`` is returned.

    :param request: the HTTP request object
    :param sample_id: the primary key of the sample

    :type request: HttpRequest
    :type sample_id: unicode

    :return:
      the HTTP response object

    :rtype: HttpResponse
    """
    if not request.user.is_superuser:
        return respond_in_json(False)
    sample = get_object_or_404(models.Sample, pk=utils.convert_id_to_int(sample_id))
    substrate = get_substrate(sample)
    return respond_in_json(substrate.get_data())
コード例 #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:list_permissions")})
コード例 #24
0
ファイル: json_client.py プロジェクト: msincan/juliabase
def get_folded_main_menu_elements(request):
    """Get all IDs or names from the folded topics or sample series.

    :param request: The current HTTP Request object.

    :type request: HttpRequest

    :return:
     The topic IDs and sample series names, who have to be folded on the main menu.

    :rtype: HttpResponse
    """
    folded_elements = (json.loads(request.user.samples_user_details.folded_topics),
                       json.loads(request.user.samples_user_details.folded_series))
    return respond_in_json(folded_elements)
コード例 #25
0
ファイル: user_details.py プロジェクト: msincan/juliabase
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_")})
コード例 #26
0
ファイル: json_client.py プロジェクト: msincan/juliabase
def next_deposition_number(request, letter):
    """Send the next free deposition number to a JSON client.

    :param request: the current HTTP Request object
    :param letter: the letter of the deposition system, see
        `utils.get_next_deposition_number`.

    :type request: HttpRequest
    :type letter: str

    :return:
      the next free deposition number for the given apparatus.

    :rtype: HttpResponse
    """
    return respond_in_json(institute.utils.base.get_next_deposition_number(letter))
コード例 #27
0
ファイル: json_client.py プロジェクト: Midnighter/juliabase
def next_deposition_number(request, letter):
    """Send the next free deposition number to a JSON client.

    :param request: the current HTTP Request object
    :param letter: the letter of the deposition system, see
        `utils.get_next_deposition_number`.

    :type request: HttpRequest
    :type letter: str

    :return:
      the next free deposition number for the given apparatus.

    :rtype: HttpResponse
    """
    return respond_in_json(institute.utils.base.get_next_deposition_number(letter))
コード例 #28
0
ファイル: json_client.py プロジェクト: msincan/juliabase
def logout_remote_client(request):
    """By requesting this view, the JuliaBase Remote Client can log out.  This
    view can never fail.

    :param request: the current HTTP Request object

    :type request: HttpRequest

    :return:
      the HTTP response object.  It is a JSON boolean object and always
      ``True``.

    :rtype: HttpResponse
    """
    django.contrib.auth.logout(request)
    return respond_in_json(True)
コード例 #29
0
ファイル: json_client.py プロジェクト: Midnighter/juliabase
def logout_remote_client(request):
    """By requesting this view, the JuliaBase Remote Client can log out.  This
    view can never fail.

    :param request: the current HTTP Request object

    :type request: HttpRequest

    :return:
      the HTTP response object.  It is a JSON boolean object and always
      ``True``.

    :rtype: HttpResponse
    """
    django.contrib.auth.logout(request)
    return respond_in_json(True)
コード例 #30
0
ファイル: main.py プロジェクト: colima/juliabase
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)
コード例 #31
0
ファイル: json_client.py プロジェクト: msincan/juliabase
def change_my_samples(request):
    """Adds or remove samples from “My Samples”.

    :param request: The current HTTP Request object.  It must contain the sample
        IDs of the to-be-removed samples comma-separated list in ``"remove"``
        and the to-be-added sample IDs in ``"add"``.  Both can be empty.
        Moreover, it may contain the ID of the user whose “My Samples” should
        be changed in ``"user"``.  If not given, the logged-in user is used.
        If given, the currently logged-in user must be admin.

    :type request: HttpRequest

    :return:
      The IDs of the samples for which the change had to be actually made.  It
      returns a 404 if one sample wasn't found.

    :rtype: HttpResponse
    """
    try:
        sample_ids_to_remove = {int(id_) for id_ in request.POST.get("remove", "").split(",") if id_}
        sample_ids_to_add = {int(id_) for id_ in request.POST.get("add", "").split(",") if id_}
    except ValueError:
        raise Http404("One or more of the sample IDs were invalid.")
    user = request.user
    user_id = request.POST.get("user")
    if user_id:
        if not request.user.is_superuser:
            raise JSONRequestException(6, "Only admins can change other users' My Samples.")
        try:
            user = django.contrib.auth.models.User.objects.get(pk=user_id)
        except django.contrib.auth.models.User.DoesNotExist:
            raise Http404("User not found.")
    doubled_ids = sample_ids_to_remove & sample_ids_to_add
    sample_ids_to_remove -= doubled_ids
    sample_ids_to_add -= doubled_ids
    try:
        samples_to_remove = models.Sample.objects.in_bulk(list(sample_ids_to_remove))
        samples_to_add = utils.restricted_samples_query(request.user).in_bulk(list(sample_ids_to_add))
    except models.Sample.DoesNotExist:
        raise Http404("One or more of the sample IDs could not be found.")
    current_my_samples = set(user.my_samples.values_list("id", flat=True))
    changed_sample_ids = sample_ids_to_remove & current_my_samples | \
        sample_ids_to_add - (current_my_samples - sample_ids_to_remove)
    user.my_samples.remove(*samples_to_remove.values())
    user.my_samples.add(*samples_to_add.values())
    return respond_in_json(changed_sample_ids)
コード例 #32
0
ファイル: json_client.py プロジェクト: Midnighter/juliabase
def get_folded_main_menu_elements(request):
    """Get all IDs or names from the folded topics or sample series.

    :param request: The current HTTP Request object.

    :type request: HttpRequest

    :return:
     The topic IDs and sample series names, who have to be folded on the main menu.

    :rtype: HttpResponse
    """
    folded_elements = (json.loads(
        request.user.samples_user_details.folded_topics),
                       json.loads(
                           request.user.samples_user_details.folded_series))
    return respond_in_json(folded_elements)
コード例 #33
0
ファイル: views.py プロジェクト: msincan/juliabase
def set_start_kicker_number(request, username):
    if request.user.username != "kicker":
        raise JSONRequestException(3005, "You must be the user \"kicker\" to use this function.")
    try:
        start_kicker_number = int(request.POST["start_kicker_number"])
        timestamp = datetime.datetime.strptime(request.POST["timestamp"], "%Y-%m-%d %H:%M:%S")
    except KeyError:
        raise JSONRequestException(3, error.args[0])
    except ValueError as error:
        raise JSONRequestException(5, error.args[0])
    player, created = django.contrib.auth.models.User.objects.get_or_create(username=username)
    if created:
        player.set_unusable_password()
        player.save()
    if models.KickerNumber.objects.filter(player=player).exists():
        raise JSONRequestException(3006, "There are already kicker numbers stored for this user.")
    models.KickerNumber.objects.create(player=player, number=start_kicker_number, timestamp=timestamp)
    return respond_in_json(True)
コード例 #34
0
ファイル: json_client.py プロジェクト: Midnighter/juliabase
def get_solarsimulator_measurement_by_filepath(request):
    """Returns the measurement ID of the solarsimulator measurement which
    contains the given filepath.  See `_get_solarsimulator_measurement_by_filepath`.  The filepath
    is given in the query string parameter “``filepath``”.

    :param request: the HTTP request object

    :type request: HttpRequest

    :return:
      the HTTP response object

    :rtype: HttpResponse
    """
    try:
        filepath = request.GET["filepath"]
    except KeyError:
        raise JSONRequestException(3, '"filepath" missing')
    return respond_in_json(_get_solarsimulator_measurement_by_filepath(filepath, request.user))
コード例 #35
0
ファイル: my_samples.py プロジェクト: muescha/juliabase
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})
コード例 #36
0
ファイル: json_client.py プロジェクト: msincan/juliabase
def get_solarsimulator_measurement_by_filepath(request):
    """Returns the measurement ID of the solarsimulator measurement which
    contains the given filepath.  See `_get_solarsimulator_measurement_by_filepath`.  The filepath
    is given in the query string parameter “``filepath``”.

    :param request: the HTTP request object

    :type request: HttpRequest

    :return:
      the HTTP response object

    :rtype: HttpResponse
    """
    try:
        filepath = request.GET["filepath"]
    except KeyError:
        raise JSONRequestException(3, '"filepath" missing')
    return respond_in_json(_get_solarsimulator_measurement_by_filepath(filepath, request.user))
コード例 #37
0
ファイル: split_and_rename.py プロジェクト: msincan/juliabase
def latest_split(request, sample_name):
    """Get the database ID of the latest split of a sample, if it is also the
    very latest process for that sample.  In all other cases, return ``None``
    (or an error HTML page if the sample didn't exist).

    :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
    """
    sample = utils.lookup_sample(sample_name, request.user)
    split = sample.last_process_if_split()
    return respond_in_json(split.pk if split else None)
コード例 #38
0
ファイル: split_and_rename.py プロジェクト: colima/juliabase
def latest_split(request, sample_name):
    """Get the database ID of the latest split of a sample, if it is also the
    very latest process for that sample.  In all other cases, return ``None``
    (or an error HTML page if the sample didn't exist).

    :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
    """
    sample = utils.lookup_sample(sample_name, request.user)
    split = sample.last_process_if_split()
    return respond_in_json(split.pk if split else None)
コード例 #39
0
ファイル: json_client.py プロジェクト: colima/juliabase
def get_current_structuring(request, sample_id):
    """Find the structuring process which is active for the given sample at a
    given timestamp.  The “``timestamp``” is an optional parameter in the query
    string in the format ``YYYY-MM-YY HH:MM:SS``.  If given, find the latest
    structuring process before that timestamp.  Otherwise, find the lastest
    structuring of the sample.  Typically, the timestamp is the timestamp of
    the process which needs the structuring, e.g. a solarsimulator measurement.

    It returns the ID of the structuring process, or ``None`` if none was
    found.

    :param request: the HTTP request object
    :param sample_id: the ID of the sample

    :type request: HttpRequest
    :type sample_id: unicode

    :return:
      the HTTP response object

    :rtype: HttpResponse
    """
    sample = get_object_or_404(models.Sample, id=sample_id)
    try:
        timestamp = django.utils.timezone.make_aware(
            datetime.datetime.strptime(
                request.GET["timestamp"].partition(".")[0],
                "%Y-%m-%d %H:%M:%S"))
    except KeyError:
        timestamp = None
    except ValueError:
        raise JSONRequestException(5, '"timestamp" has invalid format')
    try:
        structuring = layouts.get_current_structuring(sample, timestamp)
    except layouts.NoStructuringFound:
        result = None
    else:
        permissions.assert_can_fully_view_sample(request.user, sample)
        permissions.assert_can_view_physical_process(request.user, structuring)
        result = structuring.id
    return respond_in_json(result)
コード例 #40
0
ファイル: json_client.py プロジェクト: msincan/juliabase
def get_current_structuring(request, sample_id):
    """Find the structuring process which is active for the given sample at a
    given timestamp.  The “``timestamp``” is an optional parameter in the query
    string in the format ``YYYY-MM-YY HH:MM:SS``.  If given, find the latest
    structuring process before that timestamp.  Otherwise, find the lastest
    structuring of the sample.  Typically, the timestamp is the timestamp of
    the process which needs the structuring, e.g. a solarsimulator measurement.

    It returns the ID of the structuring process, or ``None`` if none was
    found.

    :param request: the HTTP request object
    :param sample_id: the ID of the sample

    :type request: HttpRequest
    :type sample_id: unicode

    :return:
      the HTTP response object

    :rtype: HttpResponse
    """
    sample = get_object_or_404(models.Sample, id=sample_id)
    try:
        timestamp = datetime.datetime.strptime(request.GET["timestamp"].partition(".")[0], "%Y-%m-%d %H:%M:%S")
    except KeyError:
        timestamp = None
    except ValueError:
        raise JSONRequestException(5, '"timestamp" has invalid format')
    try:
        structuring = layouts.get_current_structuring(sample, timestamp)
    except layouts.NoStructuringFound:
        result = None
    else:
        permissions.assert_can_fully_view_sample(request.user, sample)
        permissions.assert_can_view_physical_process(request.user, structuring)
        result = structuring.id
    return respond_in_json(result)
コード例 #41
0
ファイル: json_client.py プロジェクト: msincan/juliabase
def fold_process(request, sample_id):
    """Fold a single process in one sample data sheet. The new behavior is also saved.

    :param request: The current HTTP Request object.  It must contain the process
        ID of the process which behavior should be changed.
    :param sample_id: The sample ID represent the data sheet where the process has to be changed.

    :type request: HttpRequest
    :type sample_id: unicode

    :return:
      True when the process is now folded else False.

    :rtype: HttpResponse
    """
    process_id = int_or_zero(request.POST["process_id"])
    folded_process_classes = ContentType.objects.filter(dont_show_to_user=request.user.samples_user_details)
    folded_processes = json.loads(request.user.samples_user_details.folded_processes)
    exceptional_processes = folded_processes.setdefault(sample_id, [])
    is_folded = _is_folded(process_id, folded_process_classes, exceptional_processes, switch=True)
    request.user.samples_user_details.folded_processes = json.dumps(folded_processes)
    request.user.samples_user_details.save()
    return respond_in_json(is_folded)
コード例 #42
0
ファイル: json_client.py プロジェクト: Midnighter/juliabase
def available_items(request, model_name):
    """Returns the unique ids of all items that are already in the database for
    this model.  The point is that it will return primary keys only as a
    fallback.  Instead, it returns the “official” id of the respective model,
    represented by the `JBMeta.identifying_field` attribute, if given.  This
    may be the number of a deposition, or the number of a measurement run, etc.

    :param request: the current HTTP Request object
    :param model_name: the name of the database model

    :type request: HttpRequest
    :type model_name: unicode

    :return:
      The HTTP response object.  It is a JSON list object with all the ids of
      the objects in the database for the model.

    :rtype: HttpResponse
    """
    if not request.user.is_staff:
        raise permissions.PermissionError(
            request.user,
            _("Only the administrator can access this resource."))
    # FixMe: This must be revisited; it is ugly.
    for app_name in settings.INSTALLED_APPS:
        try:
            model = sys.modules[app_name + ".models"].__dict__[model_name]
        except KeyError:
            continue
        break
    else:
        raise Http404("Model name not found.")
    try:
        pk = model.JBMeta.identifying_field
    except AttributeError:
        pk = "pk"
    return respond_in_json(list(model.objects.values_list(pk, flat=True)))
コード例 #43
0
ファイル: json_client.py プロジェクト: msincan/juliabase
def fold_main_menu_element(request):
    """Fold a single topic or sample series from the main menu.

    :param request: The current HTTP Request object.  It must contain the the topic ID or
        sample series name.
    :param element_id: The id from the topic or sample series

    :type request: HttpRequest

    :return:
     True when the topic or sample series is now folded else False

    :rtype: HttpResponse
    """
    def fold_element(element_id, folded_elements):
        folded_elements = json.loads(folded_elements)
        if element_id in folded_elements:
            folded_elements.remove(element_id)
            is_folded = False
        else:
            folded_elements.append(element_id)
            is_folded = True
        folded_elements = json.dumps(folded_elements)
        return is_folded, folded_elements

    element_id = int_or_zero(request.POST["element_id"])

    if not element_id:
        element_id = request.POST["element_id"]
        element_is_folded, request.user.samples_user_details.folded_series = \
            fold_element(element_id, request.user.samples_user_details.folded_series)
    else:
        element_is_folded, request.user.samples_user_details.folded_topics = \
            fold_element(element_id, request.user.samples_user_details.folded_topics)
    request.user.samples_user_details.save()
    return respond_in_json(element_is_folded)
コード例 #44
0
def edit_match(request, id_=None):
    match = get_object_or_404(models.Match,
                              pk=int_or_zero(id_)) if id_ else None
    if match and match.reporter != request.user:
        raise JSONRequestException(
            3005, _("You must be the original reporter of this match."))
    try:
        if not match:
            player_a_1 = get_object_or_404(django.contrib.auth.models.User,
                                           username=request.POST["player_a_1"])
            player_a_2 = get_object_or_404(django.contrib.auth.models.User,
                                           username=request.POST["player_a_2"])
            player_b_1 = get_object_or_404(django.contrib.auth.models.User,
                                           username=request.POST["player_b_1"])
            player_b_2 = get_object_or_404(django.contrib.auth.models.User,
                                           username=request.POST["player_b_2"])
        goals_a = int(request.POST["goals_a"])
        goals_b = int(request.POST["goals_b"])
        seconds = float(request.POST["seconds"])
        finished = request.POST.get("finished") == "on"
        timestamp = django.utils.timezone.make_aware(
            datetime.datetime.strptime(request.POST["timestamp"],
                                       "%Y-%m-%d %H:%M:%S"))
    except KeyError as error:
        raise JSONRequestException(3, error.args[0])
    except ValueError as error:
        raise JSONRequestException(5, error.args[0])
    if not match:
        if player_a_1 == player_a_2 and player_b_1 != player_b_2 or player_a_1 != player_a_2 and player_b_1 == player_b_2:
            raise JSONRequestException(
                3000, _("Matches with three players can't be processed."))
        if player_a_1 == player_a_2 == player_b_1 == player_b_2:
            raise JSONRequestException(3001,
                                       _("All players are the same person."))
        models.Match.objects.filter(finished=False,
                                    reporter=request.user).delete()
    else:
        if match.finished:
            raise JSONRequestException(
                3003, _("A finished match can't be edited anymore."))
        player_a_1 = match.player_a_1
        player_a_2 = match.player_a_2
        player_b_1 = match.player_b_1
        player_b_2 = match.player_b_2
    try:
        if finished and models.KickerNumber.objects.latest(
        ).timestamp > timestamp:
            raise JSONRequestException(
                3002,
                _("This match is older than the most recent kicker numbers."))
    except models.KickerNumber.DoesNotExist:
        pass
    if match:
        match.player_a_1 = player_a_1
        match.player_a_2 = player_a_2
        match.player_b_1 = player_b_1
        match.player_b_2 = player_b_2
        match.goals_a = goals_a
        match.goals_b = goals_b
        match.timestamp = timestamp
        match.finished = finished
        match.seconds = seconds
        match.save()
    else:
        match = models.Match.objects.create(player_a_1=player_a_1,
                                            player_a_2=player_a_2,
                                            player_b_1=player_b_1,
                                            player_b_2=player_b_2,
                                            goals_a=goals_a,
                                            goals_b=goals_b,
                                            timestamp=timestamp,
                                            finished=finished,
                                            seconds=seconds,
                                            reporter=request.user)
    if match.finished:
        if seconds <= 0:
            raise JSONRequestException(5, _("Seconds must be positive."))
        match_result = MatchResult(match)
        match_result.add_kicker_numbers()
        match_result.add_stock_values()
    else:
        match.seconds = max(1, match.seconds)
        match_result = MatchResult(match)
    return respond_in_json((match.pk, match_result.expected_goal_difference,
                            match_result.estimated_win_team_1))
コード例 #45
0
ファイル: json_client.py プロジェクト: Midnighter/juliabase
def primary_keys(request):
    """Return the mappings of names of database objects to primary keys.
    While this can be used by everyone by entering the URL directly, this view
    is intended to be used only by a JSON client program to get primary keys.
    The reason for this is simple: In forms, you have to give primary keys in
    POST data sent to the web server.  However, a priori, the JSON client
    doesn't know them.  Therefore, it can query this view to get them.

    The syntax of the query string to be appended to the URL is very simple.
    If you say::

        ...?samples=01B410,01B402

    you get the primary keys of those two samples::

        {"samples": {"01B410": 5, "01B402": 42}}

    The same works for ``"topics"``, ``"users"``, and ``"external_operators"``.
    You can also mix all tree in the query string.  If you pass ``"*"`` instead
    of a values list, you get *all* primary keys.  For samples, however, this
    is limited to “My Samples”.  If a sample name is mapped to a list, it is an
    alias (which may point to more than one sample).

    The result is the JSON representation of the resulting nested dictionary.

    :param request: the current HTTP Request object

    :type request: HttpRequest

    :return:
      the HTTP response object

    :rtype: HttpResponse
    """
    result_dict = {}
    if "topics" in request.GET:
        all_topics = Topic.objects.all() if request.user.is_staff else \
                     Topic.objects.filter(Q(confidential=False) | Q(members=request.user))
        if request.GET["topics"] == "*":
            topics = all_topics
        else:
            topicnames = request.GET["topics"].split(",")
            topics = {
                topic
                for topic in all_topics if topic.name in topicnames
            }
        result_dict["topics"] = {topic.name: topic.id for topic in topics}
    if "samples" in request.GET:
        if request.GET["samples"] == "*":
            result_dict["samples"] = dict(
                request.user.my_samples.values_list("name", "id"))
        else:
            restricted_samples = utils.restricted_samples_query(request.user)
            sample_names = request.GET["samples"].split(",")
            result_dict["samples"] = {}
            for alias, sample_id in models.SampleAlias.objects.filter(name__in=sample_names, sample__in=restricted_samples). \
               values_list("name", "sample"):
                result_dict["samples"].setdefault(alias, set()).add(sample_id)
            result_dict["samples"].update(
                restricted_samples.filter(name__in=sample_names).values_list(
                    "name", "id"))
    if "depositions" in request.GET:
        deposition_numbers = request.GET["depositions"].split(",")
        result_dict["depositions"] = dict(
            models.Deposition.objects.filter(
                number__in=deposition_numbers).values_list("number", "id"))
    if "users" in request.GET:
        eligible_users = django.contrib.auth.models.User.objects.all() if request.user.is_staff else \
                django.contrib.auth.models.User.objects.filter(is_active=True, jb_user_details__department__isnull=False)
        if request.GET["users"] == "*":
            result_dict["users"] = dict(
                eligible_users.values_list("username", "id"))
        else:
            user_names = request.GET["users"].split(",")
            result_dict["users"] = dict(
                eligible_users.filter(username__in=user_names).values_list(
                    "username", "id"))
    if "external_operators" in request.GET:
        if request.user.is_staff:
            all_external_operators = models.ExternalOperator.objects.all()
        else:
            all_external_operators = models.ExternalOperator.objects.filter(
                Q(confidential=False) | Q(contact_persons=request.user))
        if request.GET["external_operators"] == "*":
            external_operators = all_external_operators
        else:
            external_operator_names = request.GET["external_operators"].split(
                ",")
            external_operators = all_external_operators.filter(
                name__in=external_operator_names)
        result_dict["external_operators"] = {
            external_operator.name: external_operator.id
            for external_operator in external_operators
        }
    return respond_in_json(result_dict)
コード例 #46
0
def edit_match(request, id_=None):
    match = get_object_or_404(models.Match,
                              pk=int_or_zero(id_)) if id_ else None
    if match and match.reporter != request.user:
        raise JSONRequestException(
            3005, "You must be the original reporter of this match.")
    try:
        if not match:
            player_a_1 = get_object_or_404(django.contrib.auth.models.User,
                                           username=request.POST["player_a_1"])
            player_a_2 = get_object_or_404(django.contrib.auth.models.User,
                                           username=request.POST["player_a_2"])
            player_b_1 = get_object_or_404(django.contrib.auth.models.User,
                                           username=request.POST["player_b_1"])
            player_b_2 = get_object_or_404(django.contrib.auth.models.User,
                                           username=request.POST["player_b_2"])
        goals_a = int(request.POST["goals_a"])
        goals_b = int(request.POST["goals_b"])
        seconds = float(request.POST["seconds"])
        finished = request.POST.get("finished") == "on"
        timestamp = datetime.datetime.strptime(request.POST["timestamp"],
                                               "%Y-%m-%d %H:%M:%S")
    except KeyError as error:
        raise JSONRequestException(3, error.args[0])
    except ValueError as error:
        raise JSONRequestException(5, error.args[0])
    if not match:
        if player_a_1 == player_a_2 and player_b_1 != player_b_2 or player_a_1 != player_a_2 and player_b_1 == player_b_2:
            raise JSONRequestException(
                3000, "Games with three players can't be processed.")
        if player_a_1 == player_a_2 == player_b_1 == player_b_2:
            raise JSONRequestException(3001,
                                       "All players are the same person.")
        unfinished_matches = models.Match.objects.filter(finished=False)
        if unfinished_matches.exists():
            if unfinished_matches.exclude(reporter=request.user).exists():
                raise JSONRequestException(
                    3004,
                    "You can't add a match if another one of another reporter is not yet finished."
                )
            for match in unfinished_matches.all():
                match.delete()
    else:
        if match.finished:
            raise JSONRequestException(
                3003, "A finished match can't be edited anymore.")
        player_a_1 = match.player_a_1
        player_a_2 = match.player_a_2
        player_b_1 = match.player_b_1
        player_b_2 = match.player_b_2
    try:
        seconds_since_most_recent = (
            timestamp - models.Match.objects.latest("timestamp").timestamp
        ).total_seconds()
        if seconds_since_most_recent <= 0:
            if seconds_since_most_recent < -10:
                raise JSONRequestException(
                    3002, "This game is not the most recent one.")
            else:
                timestamp = models.Match.objects.latest(
                    "timestamp").timestamp + datetime.timedelta(seconds=1)
    except models.Match.DoesNotExist:
        pass
    if match:
        match.player_a_1 = player_a_1
        match.player_a_2 = player_a_2
        match.player_b_1 = player_b_1
        match.player_b_2 = player_b_2
        match.goals_a = goals_a
        match.goals_b = goals_b
        match.timestamp = timestamp
        match.finished = finished
        match.seconds = seconds
        match.save()
    else:
        match = models.Match.objects.create(player_a_1=player_a_1,
                                            player_a_2=player_a_2,
                                            player_b_1=player_b_1,
                                            player_b_2=player_b_2,
                                            goals_a=goals_a,
                                            goals_b=goals_b,
                                            timestamp=timestamp,
                                            finished=finished,
                                            seconds=seconds,
                                            reporter=request.user)
    if match.finished:
        if seconds <= 0:
            raise JSONRequestException(5, "Seconds must be positive.")
        match_result = MatchResult(match)
        match_result.add_kicker_numbers()
        match_result.add_stock_values()
    else:
        match.seconds = max(1, match.seconds)
        match_result = MatchResult(match)
    return respond_in_json((match.pk, match_result.expected_goal_difference,
                            match_result.estimated_win_team_1))
コード例 #47
0
ファイル: views.py プロジェクト: msincan/juliabase
def edit_match(request, id_=None):
    match = get_object_or_404(models.Match, pk=int_or_zero(id_)) if id_ else None
    if match and match.reporter != request.user:
        raise JSONRequestException(3005, _("You must be the original reporter of this match."))
    try:
        if not match:
            player_a_1 = get_object_or_404(django.contrib.auth.models.User, username=request.POST["player_a_1"])
            player_a_2 = get_object_or_404(django.contrib.auth.models.User, username=request.POST["player_a_2"])
            player_b_1 = get_object_or_404(django.contrib.auth.models.User, username=request.POST["player_b_1"])
            player_b_2 = get_object_or_404(django.contrib.auth.models.User, username=request.POST["player_b_2"])
        goals_a = int(request.POST["goals_a"])
        goals_b = int(request.POST["goals_b"])
        seconds = float(request.POST["seconds"])
        finished = request.POST.get("finished") == "on"
        timestamp = datetime.datetime.strptime(request.POST["timestamp"], "%Y-%m-%d %H:%M:%S")
    except KeyError as error:
        raise JSONRequestException(3, error.args[0])
    except ValueError as error:
        raise JSONRequestException(5, error.args[0])
    if not match:
        if player_a_1 == player_a_2 and player_b_1 != player_b_2 or player_a_1 != player_a_2 and player_b_1 == player_b_2:
            raise JSONRequestException(3000, _("Matches with three players can't be processed."))
        if player_a_1 == player_a_2 == player_b_1 == player_b_2:
            raise JSONRequestException(3001, _("All players are the same person."))
        models.Match.objects.filter(finished=False, reporter=request.user).delete()
    else:
        if match.finished:
            raise JSONRequestException(3003, _("A finished match can't be edited anymore."))
        player_a_1 = match.player_a_1
        player_a_2 = match.player_a_2
        player_b_1 = match.player_b_1
        player_b_2 = match.player_b_2
    try:
        if finished and models.KickerNumber.objects.latest().timestamp > timestamp:
            raise JSONRequestException(3002, _("This match is older than the most recent kicker numbers."))
    except models.KickerNumber.DoesNotExist:
        pass
    if match:
        match.player_a_1 = player_a_1
        match.player_a_2 = player_a_2
        match.player_b_1 = player_b_1
        match.player_b_2 = player_b_2
        match.goals_a = goals_a
        match.goals_b = goals_b
        match.timestamp = timestamp
        match.finished = finished
        match.seconds = seconds
        match.save()
    else:
        match = models.Match.objects.create(
            player_a_1=player_a_1, player_a_2=player_a_2, player_b_1=player_b_1, player_b_2=player_b_2,
            goals_a=goals_a, goals_b=goals_b, timestamp=timestamp, finished=finished, seconds=seconds,
            reporter=request.user)
    if match.finished:
        if seconds <= 0:
            raise JSONRequestException(5, _("Seconds must be positive."))
        match_result = MatchResult(match)
        match_result.add_kicker_numbers()
        match_result.add_stock_values()
    else:
        match.seconds = max(1, match.seconds)
        match_result = MatchResult(match)
    return respond_in_json((match.pk, match_result.expected_goal_difference, match_result.estimated_win_team_1))
コード例 #48
0
ファイル: json_client.py プロジェクト: msincan/juliabase
def primary_keys(request):
    """Return the mappings of names of database objects to primary keys.
    While this can be used by everyone by entering the URL directly, this view
    is intended to be used only by a JSON client program to get primary keys.
    The reason for this is simple: In forms, you have to give primary keys in
    POST data sent to the web server.  However, a priori, the JSON client
    doesn't know them.  Therefore, it can query this view to get them.

    The syntax of the query string to be appended to the URL is very simple.
    If you say::

        ...?samples=01B410,01B402

    you get the primary keys of those two samples::

        {"samples": {"01B410": 5, "01B402": 42}}

    The same works for ``"topics"``, ``"users"``, and ``"external_operators"``.
    You can also mix all tree in the query string.  If you pass ``"*"`` instead
    of a values list, you get *all* primary keys.  For samples, however, this
    is limited to “My Samples”.  If a sample name is mapped to a list, it is an
    alias (which may point to more than one sample).

    The result is the JSON representation of the resulting nested dictionary.

    :param request: the current HTTP Request object

    :type request: HttpRequest

    :return:
      the HTTP response object

    :rtype: HttpResponse
    """
    result_dict = {}
    if "topics" in request.GET:
        all_topics = Topic.objects.all() if request.user.is_superuser else \
                     Topic.objects.filter(Q(confidential=False) | Q(members=request.user))
        if request.GET["topics"] == "*":
            topics = all_topics
        else:
            topicnames = request.GET["topics"].split(",")
            topics = {topic for topic in all_topics if topic.name in topicnames}
        result_dict["topics"] = {topic.name: topic.id for topic in topics}
    if "samples" in request.GET:
        if request.GET["samples"] == "*":
            result_dict["samples"] = dict(request.user.my_samples.values_list("name", "id"))
        else:
            restricted_samples = utils.restricted_samples_query(request.user)
            sample_names = request.GET["samples"].split(",")
            result_dict["samples"] = {}
            for alias, sample_id in models.SampleAlias.objects.filter(name__in=sample_names, sample__in=restricted_samples). \
               values_list("name", "sample"):
                result_dict["samples"].setdefault(alias, set()).add(sample_id)
            result_dict["samples"].update(restricted_samples.filter(name__in=sample_names).values_list("name", "id"))
    if "depositions" in request.GET:
        deposition_numbers = request.GET["depositions"].split(",")
        result_dict["depositions"] = dict(models.Deposition.objects.
                                          filter(number__in=deposition_numbers).values_list("number", "id"))
    if "users" in request.GET:
        eligible_users = django.contrib.auth.models.User.objects.all() if request.user.is_superuser else \
                django.contrib.auth.models.User.objects.filter(jb_user_details__department__isnull=False)
        if request.GET["users"] == "*":
            result_dict["users"] = dict(eligible_users.values_list("username", "id"))
        else:
            user_names = request.GET["users"].split(",")
            result_dict["users"] = dict(eligible_users.filter(username__in=user_names).values_list("username", "id"))
    if "external_operators" in request.GET:
        if request.user.is_superuser:
            all_external_operators = models.ExternalOperator.objects.all()
        else:
            all_external_operators = models.ExternalOperator.objects.filter(Q(confidential=False) | Q(contact_persons=request.user))
        if request.GET["external_operators"] == "*":
            external_operators = all_external_operators
        else:
            external_operator_names = request.GET["external_operators"].split(",")
            external_operators = all_external_operators.filter(name__in=external_operator_names)
        result_dict["external_operators"] = {external_operator.name: external_operator.id for external_operator in external_operators}
    return respond_in_json(result_dict)
コード例 #49
0
ファイル: json_client.py プロジェクト: Midnighter/juliabase
def add_sample(request):
    """Adds a new sample to the database.  It is added without processes.  This
    view can only be used by admin accounts.

    :param request: the current HTTP Request object; it must contain the sample
        data in the POST data.

    :return:
      The primary key of the created sample.  ``False`` if something went
      wrong.  It may return a 404 if the topic or the currently responsible
      person wasn't found.

    :rtype: HttpResponse
    """
    try:
        name = request.POST["name"]
        current_location = request.POST["current_location"]
        currently_responsible_person = request.POST[
            "currently_responsible_person"]
        purpose = request.POST.get("purpose", "")
        tags = request.POST.get("tags", "")
        topic = request.POST.get("topic")
    except KeyError as error:
        raise JSONRequestException(
            3, "'{}' parameter missing.".format(error.args[0]))
    if len(name) > 30:
        raise JSONRequestException(5, "The sample name is too long.")
    name_format = utils.sample_name_format(name)
    if name_format is None or \
       not request.user.is_staff and name_format not in settings.SAMPLE_NAME_FORMATS["provisional"].get("possible_renames", set()):
        raise JSONRequestException(5, "The sample name is invalid.")
    eligible_users = django.contrib.auth.models.User.objects.filter(
        is_active=True, jb_user_details__department__isnull=False)
    try:
        currently_responsible_person = eligible_users.get(
            pk=utils.convert_id_to_int(currently_responsible_person))
    except django.contrib.auth.models.User.DoesNotExist:
        raise Http404("Currently reponsible user not found.")
    if topic:
        all_topics = Topic.objects.all() if request.user.is_staff else \
                     Topic.objects.filter(Q(confidential=False) | Q(members=request.user))
        try:
            topic = all_topics.get(pk=utils.convert_id_to_int(topic))
        except Topic.DoesNotExist:
            raise Http404("Topic not found")
    try:
        sample = models.Sample.objects.create(
            name=name,
            current_location=current_location,
            currently_responsible_person=currently_responsible_person,
            purpose=purpose,
            tags=tags,
            topic=topic)
        # They will be shadowed anyway.  Nevertheless, this action is an
        # emergency measure.  Probably the samples the aliases point to should
        # be merged with the sample but this can't be decided automatically.
        models.SampleAlias.objects.filter(name=name).delete()
    except IntegrityError as error:
        error_message = "The sample with this data could not be added."
        if request.user.is_staff:
            error_message += " {}".format(error)
        raise JSONRequestException(5, error_message)
    sample.watchers.add(request.user)
    return respond_in_json(sample.pk)