def recipe_edit(request, uid): "Edit meta-data associated with a recipe." recipe = Analysis.objects.get_all(uid=uid).first() project = recipe.project action_url = reverse('recipe_edit', request=request, kwargs=dict(uid=recipe.uid)) form = forms.RecipeForm(instance=recipe, user=request.user) if request.method == "POST": form = forms.RecipeForm(data=request.POST, files=request.FILES, instance=recipe, user=request.user) if form.is_valid(): recipe = form.save() return redirect( reverse("recipe_view", request=request, kwargs=dict(uid=recipe.uid))) context = dict(analysis=recipe, project=project, form=form, action_url=action_url, name=recipe.name) return render(request, 'recipe_edit.html', context)
def post_create(request, project=None, template="post_create.html", url="post_view", extra_context={}, filter_func=lambda x: x): "Make a new post" # Filter function ( filter_func ) is used to filter choices from the form # between sites. form = forms.PostLongForm(project=project, filter_func=filter_func) if request.method == "POST": form = forms.PostLongForm(data=request.POST, project=project, filter_func=filter_func) if form.is_valid(): # Create a new post by user post = form.save(author=request.user) if tasks.HAS_UWSGI: tasks.created_post(pid=post.id) return redirect( reverse(url, request=request, kwargs=dict(uid=post.uid))) context = dict(form=form, extra_tab="active", extra_tab_name="New Post", action_url=reverse("post_create")) context.update(extra_context) return render(request, template, context=context)
def edit_post(request, uid): "Edit an existing post" post = Post.objects.filter(uid=uid).first() if post.is_toplevel: template, edit_form = "post_create.html", forms.PostLongForm else: template, edit_form = "shortpost_edit.html", forms.PostShortForm user = request.user form = edit_form(post=post, user=user) if request.method == "POST": form = edit_form(post=post, data=request.POST, user=user) if form.is_valid(): form.save(edit=True) messages.success(request, f"Edited :{post.title}") return redirect(reverse("post_view", kwargs=dict(uid=uid))) context = dict(form=form, post=post, action_url=reverse("post_edit", kwargs=dict(uid=uid)), extra_tab="active", extra_tab_name="Edit Post") return render(request, template, context)
def _wrapped_view(request, *args, **kwargs): # Each wrapped view must take an alphanumeric uid as parameter. uid = kwargs.get('uid') user = request.user # Fetches the object that will be checked for permissions. instance = self.type.objects.get_all(uid=uid).first() if not instance: messages.error(request, f"Object id {uid} does not exist.") return redirect(reverse("project_list")) # Build redirect url if self.fallback_view: target = reverse(self.fallback_view, kwargs=dict(uid=uid)) else: target = request.GET.get("next") or instance.url() # The project that corresponds to the instance. project = instance.project # Check write to an object. access = auth.has_write_access(user=user, project=project) # Project owners may write their project. if access: return function(request, *args, **kwargs) msg = auth.access_denied_message( user=user, needed_access=models.Access.WRITE_ACCESS) messages.error(request, msg) return redirect(target)
def post_body(context, post, user, tree, form, include_userbox=True, next_url=None, project_uid=None, sub_url=None): "Renders the post body" request = context['request'] sub_url = sub_url or reverse( "subs_action", request=request, kwargs=dict(uid=post.uid)) next_url = next_url or reverse( "post_view", request=request, kwargs=dict(uid=post.uid)) return dict(post=post, user=user, tree=tree, request=request, form=form, include_userbox=include_userbox, sub_url=sub_url, next_url=next_url, redir_field_name=const.REDIRECT_FIELD_NAME, project_uid=project_uid)
def traverse_comments(request, post, tree, comment_template, next_url, project_uid=None): "Traverses the tree and generates the page" body = template.loader.get_template(comment_template) comment_url = reverse("post_comment") def traverse(node): vote_url = reverse("vote") data = ['<div class="ui comment segments">'] cont = {"post": node, 'user': request.user, 'request': request, "comment_url":comment_url, "vote_url": vote_url, "next_url":next_url, "redir_field_name":const.REDIRECT_FIELD_NAME, "project_uid": project_uid} html = body.render(cont) data.append(html) for child in tree.get(node.id, []): data.append(f'<div class="ui segment comment basic">') data.append(traverse(child)) data.append("</div>") data.append("</div>") return '\n'.join(data) # this collects the comments for the post coll = [] for node in tree[post.id]: coll.append(traverse(node)) return '\n'.join(coll)
def project_create(request): """ View used create an empty project belonging to request.user. Input is validated with a form and actual creation is routed through auth.create_project. """ initial = dict(name="Project Name", text="project description", summary="project summary") form = forms.ProjectForm(initial=initial, request=request, create=True) if request.method == "POST": # create new projects here ( just populates metadata ). form = forms.ProjectForm(request=request, data=request.POST, create=True, files=request.FILES) if form.is_valid(): project = form.custom_save(owner=request.user) return redirect( reverse("project_view", request=request, kwargs=dict(uid=project.uid))) context = dict(form=form) return render(request, "project_create.html", context=context)
def recipe_delete(request, uid): recipe = Analysis.objects.get_all(uid=uid).first() auth.delete_object(obj=recipe, request=request) return redirect(reverse("recipe_list", kwargs=dict(uid=recipe.project.uid)))
def user_login(request): form = forms.LoginForm() if request.method == "POST": form = forms.LoginForm(data=request.POST) if form.is_valid(): email = form.cleaned_data['email'] password = form.cleaned_data['password'] user = User.objects.filter( email__iexact=email).order_by('-id').first() message, valid_user = check_user(email=email, password=password) if valid_user: login(request, user, backend="django.contrib.auth.backends.ModelBackend") Profile.objects.filter(user=user).update(last_login=now()) messages.success(request, "Login successful!") return redirect(reverse("project_list_private")) else: messages.error(request, mark_safe(message)) messages.error(request, mark_safe(form.errors)) context = dict(form=form, social_login=SocialApp.objects.all()) return render(request, "accounts/login.html", context=context)
def post_view(request, uid): "Return a detailed view for specific post" # Form used for answers form = forms.PostShortForm() # Get the parents info obj = Post.objects.filter(uid=uid).first() # Return root view if not at top level. obj = obj if obj.is_toplevel else obj.root auth.update_post_views(post=obj, request=request) if request.method == "POST": form = forms.PostShortForm(data=request.POST) if form.is_valid(): post = form.save(author=request.user) location = reverse("post_view", request=request, kwargs=dict(uid=obj.root.uid)) + "#" + post.uid if tasks.HAS_UWSGI: tasks.created_post(pid=post.id) return redirect(location) # Populate the object to build a tree that contains all posts in the thread. # Answers are added here as well. comment_tree, answers, thread = auth.build_obj_tree(request=request, obj=obj) context = dict(post=obj, tree=comment_tree, form=form, answers=answers) return render(request, "post_view.html", context=context)
def data_paste(request, uid): """Used to paste objects in results and data clipboards as a Data object.""" project = Project.objects.get_all(uid=uid).first() owner = request.user board = request.GET.get("board") clipboard = request.session.get(settings.CLIPBOARD_NAME, {}) data_clipboard = clipboard.get(board, []) for datauid in data_clipboard: if board == const.DATA_CLIPBOARD: obj = Data.objects.get_all(uid=datauid).first() dtype = obj.type else: obj = Job.objects.get_all(uid=datauid).first() dtype = "DATA" if obj: auth.create_data(project=project, path=obj.get_data_dir(), user=owner, name=obj.name, type=dtype, text=obj.text) clipboard[board] = [] request.session.update({settings.CLIPBOARD_NAME: clipboard}) messages.success(request, "Pasted data in clipboard") return redirect(reverse("data_list", kwargs=dict(uid=project.uid)))
def recipe_run(request, uid): """ View used to execute recipes and start a 'Queued' job. """ analysis = Analysis.objects.get_all(uid=uid).first() project = analysis.project # Form submission. if request.method == "POST": form = forms.RecipeInterface(request=request, analysis=analysis, json_data=analysis.json_data, data=request.POST) # The form validation will authorize the job. if form.is_valid(): # The desired name of for the results. name = form.cleaned_data.get("name") # Generates the JSON data from the bound form field. json_data = form.fill_json_data() # Create the job from the recipe and incoming json data. job = auth.create_job(analysis=analysis, user=request.user, json_data=json_data, name=name) # Spool the job right away if UWSGI exists. if tasks.HAS_UWSGI: # Update the job state. Job.objects.get_all(id=job.id).update(state=Job.SPOOLED) # Spool via UWSGI. tasks.execute_job.spool(job_id=job.id) return redirect( reverse("job_list", request=request, kwargs=dict(uid=project.uid))) else: initial = dict(name=f"Results for: {analysis.name}") form = forms.RecipeInterface(request=request, analysis=analysis, json_data=analysis.json_data, initial=initial) context = dict(project=project, analysis=analysis, form=form, activate='Run Recipe') context.update(get_counts(project)) return render(request, 'recipe_run.html', context)
def job_copy(request, uid): job = Job.objects.get_all(uid=uid).first() next_url = request.GET.get( "next", reverse("job_list", kwargs=dict(uid=job.project.uid))) auth.copy_uid(request=request, instance=job, board=const.RESULTS_CLIPBOARD) return redirect(next_url)
def data_copy(request, uid): data = Data.objects.get_all(uid=uid).first() next_url = request.GET.get( "next", reverse("data_list", kwargs=dict(uid=data.project.uid))) auth.copy_uid(request=request, instance=data, board=const.DATA_CLIPBOARD) return redirect(next_url)
def data_file_copy(request, uid, path): # Get the root data where the file exists data = Data.objects.get_all(uid=uid).first() fullpath = os.path.join(data.get_data_dir(), path) auth.copy_file(request=request, fullpath=fullpath) return redirect(reverse("data_view", kwargs=dict(uid=uid)))
def recipe_copy(request, uid): recipe = Analysis.objects.get_all(uid=uid).first() next_url = request.GET.get( "next", reverse("recipe_list", kwargs=dict(uid=recipe.project.uid))) auth.copy_uid(request=request, instance=recipe, board=const.RECIPE_CLIPBOARD) return redirect(next_url)
def recipe_api_list(request): recipes = Analysis.objects.get_all() api_key = request.GET.get("k", "") # Only show public recipes when api key is not correct or provided. if settings.API_KEY != api_key: recipes = recipes.filter(project__privacy=Project.PUBLIC) payload = dict() for recipe in recipes: payload.setdefault(recipe.uid, dict()).update( name=recipe.name, json=reverse("recipe_api_json", kwargs=dict(uid=recipe.uid)), template=reverse("recipe_api_template", kwargs=dict(uid=recipe.uid)), privacy=dict(Project.PRIVACY_CHOICES)[recipe.project.privacy], ) return Response(data=payload, status=status.HTTP_200_OK)
def comment(request): location = reverse("post_list") if request.method == "POST": form = forms.PostShortForm(data=request.POST) if form.is_valid(): post = form.save(author=request.user, post_type=Post.COMMENT) messages.success(request, "Added comment") location = reverse("post_view", kwargs=dict(uid=post.uid)) + "#" + post.uid if tasks.HAS_UWSGI: tasks.created_post(pid=post.id) else: messages.error(request, f"Error adding comment:{form.errors}") parent = Post.objects.filter( uid=request.POST.get("parent_uid")).first() location = location if parent is None else reverse( "post_view", kwargs=dict(uid=parent.root.uid)) return redirect(location)
def post_body(context, post, user, tree, form): "Renders the post body" request = context['request'] next_url = reverse("post_view", request=request, kwargs=dict(uid=post.uid)) return dict(post=post, user=user, tree=tree, request=request, form=form, next_url=next_url, redir_field_name=const.REDIRECT_FIELD_NAME)
def upload(uid, view, source_name): # Build full api url given the view full_url = urljoin(base_url, reverse(view, kwargs=dict(uid=uid))) # Get the intended file to upload. upload_file = dict(file=open(os.path.join(recipe, source_name), "r")) # Prepare the payload with the api_key payload = dict(k=api_key) # Send a PUT request. response = requests.put(url=full_url, files=upload_file, data=payload) return response
def send_email_verify(request): "Send one-time valid link to validate email" # Sends verification email with a token user = request.user send_verification_email(user=user) messages.success(request, "Verification sent, check your email.") return redirect(reverse("user_profile", kwargs=dict(uid=user.profile.uid)))
def toggle_moderate(request): user = request.user if settings.ALLOW_SELF_MODERATE: role = Profile.NORMAL if user.profile.is_moderator else Profile.MODERATOR Profile.objects.filter(user=user).update(role=role) mapper = {Profile.MODERATOR: " a moderator"} messages.success(request, f"You are now {mapper.get(role, 'not a moderator')}") return redirect(reverse("user_profile", kwargs=dict(uid=user.profile.uid)))
def comment(request): location = reverse("post_list") get_view = lambda p: "discussion_view" if (p.project is not None ) else "post_view" if request.method == "POST": form = forms.PostShortForm(data=request.POST) if form.is_valid(): post = form.save(author=request.user, post_type=Post.COMMENT) messages.success(request, "Added comment") location = reverse(get_view(post), kwargs=dict(uid=post.uid)) + "#" + post.uid else: messages.error(request, f"Error adding comment:{form.errors}") parent = Post.objects.get_all( uid=request.POST.get("parent_uid")).first() location = location if parent is None else reverse( get_view(parent), kwargs=dict(uid=parent.root.uid)) return redirect(location)
def job_delete(request, uid): job = Job.objects.get_all(uid=uid).first() running_job = job.state == Job.RUNNING and not job.deleted if running_job: messages.error( request, "Can not delete a running job. Wait until it finishes.") return redirect(job.url()) auth.delete_object(obj=job, request=request) return redirect(reverse("job_list", kwargs=dict(uid=job.project.uid)))
def project_delete(request, uid): project = Project.objects.get_all(uid=uid).first() project.deleted = not project.deleted project.save() msg = f"Project:{project.name} successfully " msg += "deleted!" if project.deleted else "restored!" messages.success(request, msg) return redirect(reverse("project_list_private"))
def discussion_view(request, uid): template = "discussion_view.html" # Get the parents info obj = Post.objects.get_discussions(uid=uid).first() project = obj.root.project sub_url = reverse("discussion_subs", kwargs=dict(uid=obj.uid)) next_url = reverse("discussion_view", kwargs=dict(uid=obj.uid)) context = dict(project=project, activate="Discussion", sub_url=sub_url, next_url=next_url) counts = get_counts(project) context.update(counts) return forum_views.post_view(request=request, template=template, extra_context=context, url="discussion_view", uid=uid)
def clear_clipboard(request, uid): "Clear copied objects held in clipboard." next_url = request.GET.get("next", reverse("project_view", kwargs=dict(uid=uid))) board = request.GET.get("board") clipboard = request.session.get(settings.CLIPBOARD_NAME, {}) if clipboard.get(board): clipboard[board] = [] request.session.update({settings.CLIPBOARD_NAME: clipboard}) return redirect(next_url)
def badge_view(request, uid): badge = Badge.objects.filter(uid=uid).annotate( count=Count("award")).first() if not badge: messages.error(request, f"Badge with id={uid} does not exist.") return redirect(reverse("badge_list")) awards = badge.award_set.order_by("-pk")[:100] awards = awards.prefetch_related("user", "user__profile", "post", "post__root") context = dict(awards=awards, badge=badge) return render(request, "badge_view.html", context=context)
def toggle_notify(request): if request.user.is_anonymous: messages.error(request, "Must be logged in to edit profile") return redirect("/") user = request.user user.profile.notify = not user.profile.notify user.profile.save() msg = "Emails notifications disabled." if user.profile.notify: msg = "Emails notifications enabled." messages.success(request, msg) return redirect(reverse('user_profile', kwargs=dict(uid=user.profile.uid)))
def file_paste(request, uid): project = Project.objects.get_all(uid=uid).first() clipboard = request.session.get(settings.CLIPBOARD_NAME, {}) file_clipboard = clipboard.get(const.FILES_CLIPBOARD, []) for single_file in file_clipboard: if os.path.exists(single_file): auth.create_data(project=project, path=single_file, user=request.user) clipboard[const.FILES_CLIPBOARD] = [] request.session.update({settings.CLIPBOARD_NAME: clipboard}) return redirect(reverse("data_list", kwargs=dict(uid=project.uid)))