Beispiel #1
0
def toggle_delete(request):
    """
    Delete an object.
    """

    type_map = dict(job=Job, data=Data, recipe=Analysis)
    uid = request.POST.get('uid', "")
    obj_type = request.POST.get('type', '')

    obj_model = type_map.get(obj_type)

    if not obj_model:
        return ajax_error(f"Invalid data type:{obj_type}")

    obj = obj_model.objects.filter(uid=uid).first()

    if not obj:
        return ajax_error("Object does not exists.")

    access = auth.is_writable(user=request.user, project=obj.project)

    # Toggle the delete state if the user has write access
    if access:
        auth.delete_object(obj=obj, request=request)
        # Re-set project counts
        obj.project.set_counts(save=True)
        counts = obj_model.objects.filter(project=obj.project,
                                          deleted=False).count()
        return ajax_success(msg='Toggled delete', counts=counts)

    return ajax_error("Invalid action")
Beispiel #2
0
def ajax_move(request):

    pid = request.POST.get("id", 0)
    user = request.user
    project = Project.objects.filter(id=pid).first()

    # Get the board.
    board = auth.recent_clipboard(request=request)
    key, vals = board
    next_url = auth.resolve_paste_url(key=key, project=project)

    count = len(vals)

    if not project:
        return ajax_error(msg="Project does not exist.")

    if not auth.is_writable(user=user, project=project):
        return ajax_error(msg="You do not have access to move here.")

    # Move objects in clipboard to given project.
    auth.move(uids=vals, project=project, otype=key, user=user)

    # Clear the clipboard after moving.
    auth.clear(request=request)

    return ajax_success(msg=f"Moved {count} items into project.",
                        redirect=next_url)
Beispiel #3
0
def ajax_paste(request):
    """
    Paste the most recent
    """
    pid = request.POST.get("id", 0)
    user = request.user
    project = Project.objects.filter(id=pid).first()

    # Get the board.
    board = auth.recent_clipboard(request=request)
    key, vals = board
    count = len(vals)

    if not project:
        return ajax_error(msg="Project does not exist.")

    if not auth.is_writable(user=user, project=project):
        return ajax_error(msg="You do not have access to paste here.")

    if not count:
        return ajax_error(msg="Clipboard is empty")

    # The target of this action is to clone.
    clone = request.POST.get('target') == CLONED_RECIPES

    # Paste the clipboard item into the project
    auth.paste(board=board, user=user, project=project, clone=clone)

    # Resolve the redirect url.
    next_url = auth.resolve_paste_url(key=key, project=project)

    # Clear the clipboard after pasting.
    auth.clear(request=request)

    return ajax_success(msg=f"Pasted {count} items into project.", redirect=next_url)
Beispiel #4
0
def drop(request, klass=None):
    """
    Order objects in a list using drag and drop. 'rank' attribute is required .
    """
    user = request.user
    # Current object uid being moved/dropped
    source = int(request.POST.get("source_id", 0))
    source = klass.objects.filter(pk=source).first()

    # The object we intend to move it under
    top = int(request.POST.get("parent_id", 0))
    top = klass.objects.filter(pk=top).first()

    # Next object after the 'source'
    bottom = int(request.POST.get("next_id", 0))
    bottom = klass.objects.filter(pk=bottom).first()

    project = source.project
    # Check if the user has write access to source before moving.
    if not auth.is_writable(user=user, project=project):
        ajax_error(msg="You need write access to move objects.")

    # Compute and update the source with a new rank.
    maxrank = klass.objects.order_by('-rank').first().rank
    source.rank = auth.compute_rank(source=source,
                                    top=top,
                                    bottom=bottom,
                                    klass=klass,
                                    maxrank=maxrank)
    klass.objects.filter(pk=source.pk).update(rank=source.rank)

    return ajax_success(msg="Successfully moved")
Beispiel #5
0
def project_view(request, uid, template_name="project_info.html", active='info', show_summary=None,
                 extra_context={}):
    """
    This view handles the project info, data list, recipe list, result list views.
    """
    page = request.GET.get('page')

    # The user making the request
    user = request.user

    # The project that is viewed.
    project = Project.objects.filter(uid=uid).first()

    # Select all the data in the project.
    data_list = project.data_set.filter(deleted=False).order_by("-lastedit_date", "rank", "-date").all()
    data_paginator = Paginator(data_list, per_page=settings.PER_PAGE)
    data_list = data_paginator.get_page(page)

    recipe_list = project.analysis_set.filter(deleted=False).order_by("-rank", "-lastedit_date", "-date").all()

    # Annotate each recipe with the number of jobs it has.
    recipe_list = recipe_list.annotate(job_count=Count("job", filter=Q(job__deleted=False)))
    recipe_paginator = Paginator(recipe_list, per_page=settings.PER_PAGE)
    recipe_list = recipe_paginator.get_page(page)

    job_list = project.job_set.filter(deleted=False).order_by("-lastedit_date").all()

    # Filter job results by analysis
    filter_uid = request.GET.get('filter', '')
    recipe_filter = Analysis.objects.filter(uid=filter_uid).first()

    # The recipe filter exists
    if recipe_filter:
        job_list = job_list.filter(analysis=recipe_filter)

    # Add related content.
    job_list = job_list.select_related("analysis")
    job_paginator = Paginator(job_list, per_page=settings.PER_PAGE)
    job_list = job_paginator.get_page(page)

    # Who has write access
    write_access = auth.is_writable(user=user, project=project)

    # Build the context for the project.
    context = dict(project=project, data_list=data_list, recipe_list=recipe_list, job_list=job_list,
                   active=active, recipe_filter=recipe_filter, write_access=write_access, rerun_btn=True,
                   include_copy=False)

    # Compute counts for the project.
    counts = get_counts(project)

    # Update conext with the counts.
    context.update(counts)

    # Add any extra context that may come from parameters.
    context.update(extra_context)

    return render(request, template_name, context)
def recipe_view(request, uid):
    """
    Edit meta-data associated with a recipe.
    """

    # The user making the request.
    user = request.user

    # The recipe that needs to be edited.
    recipe = Analysis.objects.filter(uid=uid).annotate(
        job_count=Count("job", filter=Q(job__deleted=False))).first()

    # The project that recipe belongs to.
    project = recipe.project

    # Initial form loading via a GET request.
    form = forms.RecipeForm(instance=recipe,
                            user=request.user,
                            project=project)

    # Fills in project level counts (results, data and recipe counts).
    counts = get_counts(project)

    # Disable buttons if project not writeable.
    btn_state = '' if auth.is_writable(user=user,
                                       project=project) else 'disabled'

    # Get the list of jobs required to view recipe results
    jobs = recipe.job_set.filter(
        deleted=False).order_by("-lastedit_date").all()

    # Check to see if this recipe is runnable by the user.
    is_runnable = auth.authorize_run(user=user, recipe=recipe)

    # Check to see if recipe is editable
    editable = auth.writeable_recipe(user=user, source=recipe)

    # Generate the context.
    context = dict(recipe=recipe,
                   job_list=jobs,
                   project=project,
                   form=form,
                   btn_state=btn_state,
                   is_runnable=is_runnable,
                   activate='Recipe View',
                   rerun_btn=False,
                   include_copy=False,
                   editable=editable)

    # Update context with counts.
    context.update(counts)

    return render(request, 'recipe_view.html', context)
Beispiel #7
0
def manage_access(request):

    access_map = dict(none=Access.NO_ACCESS,
                      read=Access.READ_ACCESS,
                      write=Access.WRITE_ACCESS,
                      share=Access.SHARE_ACCESS)

    # Get the current user, project and access
    user_id = request.POST.get('user_id', '')
    project_uid = request.POST.get('project_uid', '')
    access_str = request.POST.get('access', '')

    user = User.objects.filter(id=user_id).first()
    new_access = access_map.get(access_str)
    project = Project.objects.filter(uid=project_uid).first()
    is_writable = auth.is_writable(user=request.user, project=project)

    # Validate submitted values.
    if not project:
        return ajax_error("Project does not exist.")
    if not user:
        return ajax_error("User does not exist.")
    if not new_access:
        return ajax_error(f"Invalid access option: {access_str}")
    if user == request.user:
        return ajax_error("Can not change your own access")
    if user == project.owner:
        return ajax_error("Can not change the project owner's access")
    if not is_writable:
        return ajax_error("You need write access to manage access.")

    # Check current user access.
    access = Access.objects.filter(user=user, project=project).first()

    # Update existing access
    if access:
        Access.objects.filter(id=access.id).update(access=new_access)
    # Create a new access object
    else:
        Access.objects.create(user=user, project=project, access=new_access)

    no_access = new_access == Access.NO_ACCESS

    return ajax_success("Changed access.", no_access=no_access)
Beispiel #8
0
def project_info(request, uid):
    user = request.user

    project = Project.objects.filter(uid=uid).first()

    # Show counts for the project.
    counts = get_counts(project)

    # Who has write access
    write_access = auth.is_writable(user=user, project=project)
    if user.is_authenticated:
        access = Access.objects.filter(user=user, project=project).first()
    else:
        access = Access(access=Access.NO_ACCESS)

    access = access or Access(access=Access.NO_ACCESS)

    context = dict(project=project, active="info", write_access=write_access, access=access)
    context.update(counts)

    return render(request, "project_info.html", context)
Beispiel #9
0
def ajax_paste(request):
    """
    Paste the most recent
    """
    pid = request.POST.get("id", 0)
    user = request.user
    project = Project.objects.filter(id=pid).first()

    # Get the board.
    board = auth.recent_clipboard(request=request)
    key, vals = board
    count = len(vals)

    if not project:
        return ajax_error(msg="Project does not exist.")

    if not auth.is_writable(user=user, project=project):
        return ajax_error(msg="You do not have access to paste here.")

    if not count:
        return ajax_error(msg="Clipboard is empty")

    # The target of this action is to clone.
    clone = request.POST.get('target')

    # Paste the clipboard item into the project
    auth.paste(board=board, user=user, project=project, clone=clone)

    data_url = reverse("data_list", kwargs=dict(uid=project.uid))
    recipes_url = reverse("recipe_list", kwargs=dict(uid=project.uid))

    # Resolve the redirect url.
    redir = recipes_url if key == COPIED_RECIPES else data_url

    # Clear the clipboard after pasting.
    auth.clear(request=request)

    return ajax_success(msg=f"Pasted {count} items into project.",
                        redirect=redir)
def writable(project, user):
    """
    Check if user has write access to the project.
    """
    return auth.is_writable(user=user, project=project)