Skip to content

Commit

Permalink
Rework project deletion to add CSRF validation
Browse files Browse the repository at this point in the history
It requires reworking the user interface, but it's probably for the best.
  • Loading branch information
Baptiste Jonglez authored and zorun committed Jul 17, 2021
1 parent 109d7fc commit 2bb6f2b
Show file tree
Hide file tree
Showing 5 changed files with 61 additions and 13 deletions.
20 changes: 20 additions & 0 deletions ihatemoney/forms.py
Expand Up @@ -221,6 +221,26 @@ def validate_id(form, field):
raise ValidationError(Markup(message))


class DeleteProjectForm(FlaskForm):
password = PasswordField(
_("Private code"),
description=_("Enter private code to confirm deletion"),
validators=[DataRequired()],
)

def __init__(self, *args, **kwargs):
# Same trick as EditProjectForm: we need to know the project ID
self.id = SimpleNamespace(data=kwargs.pop("id", ""))
super().__init__(*args, **kwargs)

def validate_password(form, field):
project = Project.query.get(form.id.data)
if project is None:
raise ValidationError(_("Unknown error"))
if not check_password_hash(project.password, form.password.data):
raise ValidationError(_("Invalid private code."))


class AuthenticationForm(FlaskForm):
id = StringField(_("Project identifier"), validators=[DataRequired()])
password = PasswordField(_("Private code"), validators=[DataRequired()])
Expand Down
5 changes: 0 additions & 5 deletions ihatemoney/static/css/main.css
Expand Up @@ -303,11 +303,6 @@ footer .footer-left {
color: #fff;
}

.confirm,
.confirm:hover {
color: red;
}

.bill-actions {
padding-top: 10px;
text-align: center;
Expand Down
18 changes: 15 additions & 3 deletions ihatemoney/templates/edit_project.html
@@ -1,9 +1,17 @@
{% extends "layout.html" %}

{% block js %}
$('#delete-project').click(function ()
{
$(this).html("<a style='color:red; ' href='{{ url_for('.delete_project') }}' >{{_("you sure?")}}</a>");

$('#delete-project').click(function(){
var link = $(this).find('button');
link.click(function(){
if ($(this).hasClass("confirm")){
return true;
}
$(this).html("{{_("Are you sure?")}}");
$(this).addClass("confirm");
return false;
});
});

$('.custom-file-input').on('change', function(event) {
Expand All @@ -21,6 +29,10 @@ <h2>{{ _("Edit project") }}</h2>
{{ forms.edit_project(edit_form) }}
</form>

<h2>{{ _("Delete project") }}</h2>
<form id="delete-project" class="form-horizontal" action="{{ url_for(".delete_project") }}" method="post" >
{{ forms.delete_project(delete_form) }}
</form>

<h2>{{ _("Import JSON") }}</h2>
<form class="form-horizontal" method="post" enctype="multipart/form-data">
Expand Down
13 changes: 12 additions & 1 deletion ihatemoney/templates/forms.html
Expand Up @@ -100,7 +100,18 @@
{{ input(form.default_currency) }}
<div class="actions">
<button class="btn btn-primary">{{ _("Edit the project") }}</button>
<a id="delete-project" style="color:red; margin-left:10px; cursor:pointer; ">{{ _("delete") }}</a>
</div>

{% endmacro %}

{% macro delete_project(form) %}

{% include "display_errors.html" %}
<p><strong>{{ _("This will remove all bills and participants in this project!") }}</strong></p>
{{ form.hidden_tag() }}
{{ input(form.password) }}
<div class="actions">
<button class="btn btn-danger">{{ _("Delete project") }}</button>
</div>

{% endmacro %}
Expand Down
18 changes: 14 additions & 4 deletions ihatemoney/web.py
Expand Up @@ -39,6 +39,7 @@
from ihatemoney.forms import (
AdminAuthenticationForm,
AuthenticationForm,
DeleteProjectForm,
EditProjectForm,
EmptyForm,
InviteForm,
Expand Down Expand Up @@ -401,6 +402,7 @@ def reset_password():
@main.route("/<project_id>/edit", methods=["GET", "POST"])
def edit_project():
edit_form = EditProjectForm(id=g.project.id)
delete_form = DeleteProjectForm(id=g.project.id)
import_form = UploadForm()
# Import form
if import_form.validate_on_submit():
Expand Down Expand Up @@ -434,6 +436,7 @@ def edit_project():
return render_template(
"edit_project.html",
edit_form=edit_form,
delete_form=delete_form,
import_form=import_form,
current_view="edit_project",
)
Expand Down Expand Up @@ -512,11 +515,18 @@ def import_project(file, project):
db.session.commit()


@main.route("/<project_id>/delete")
@main.route("/<project_id>/delete", methods=["POST"])
def delete_project():
g.project.remove_project()
flash(_("Project successfully deleted"))

form = DeleteProjectForm(id=g.project.id)
if form.validate():
g.project.remove_project()
flash(_("Project successfully deleted"))
return redirect(url_for(".home"))
else:
flash(
_("Error deleting project: wrong private code or wrong CSRF token"),
category="danger",
)
return redirect(request.headers.get("Referer") or url_for(".home"))


Expand Down

0 comments on commit 2bb6f2b

Please sign in to comment.