aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--budget/forms.py10
-rw-r--r--budget/static/main.css6
-rw-r--r--budget/templates/authenticate.html4
-rw-r--r--budget/templates/forms.html12
-rw-r--r--budget/templates/home.html1
-rw-r--r--budget/templates/password_reminder8
-rw-r--r--budget/templates/password_reminder.html8
-rw-r--r--budget/tests.py18
-rw-r--r--budget/web.py20
9 files changed, 80 insertions, 7 deletions
diff --git a/budget/forms.py b/budget/forms.py
index 499f382..cf5068b 100644
--- a/budget/forms.py
+++ b/budget/forms.py
@@ -87,6 +87,16 @@ class AuthenticationForm(Form):
submit = SubmitField("Get in")
+class PasswordReminder(Form):
+ id = TextField("Project identifier", validators=[Required()])
+ submit = SubmitField("Send me the code by email")
+
+ def validate_id(form, field):
+ if not Project.query.get(field.data):
+ raise ValidationError("This project does not exists")
+
+
+
class BillForm(Form):
date = DateField("Date", validators=[Required()], default=datetime.now)
what = TextField("What?", validators=[Required()])
diff --git a/budget/static/main.css b/budget/static/main.css
index de3d675..fc8d284 100644
--- a/budget/static/main.css
+++ b/budget/static/main.css
@@ -98,3 +98,9 @@ div.topbar ul.secondary-nav { padding-right: 75px; }
text-align: right;
margin-top: -15px;
}
+
+.password-reminder{
+ float: right;
+ margin-right: 20px;
+ margin-top: 5px;
+}
diff --git a/budget/templates/authenticate.html b/budget/templates/authenticate.html
index 9852d6a..83839e1 100644
--- a/budget/templates/authenticate.html
+++ b/budget/templates/authenticate.html
@@ -2,10 +2,6 @@
{% block content %}
<h2>Authentication</h2>
-{% for errors in form.errors.values() %}
-<p class=error>{{ ", ".join(errors) }}</p>
-{% endfor %}
-
{% if create_project %}
<p class="info">The project you are trying to access do not exist, do you want
to <a href="{{ url_for(".create_project", project_id=create_project) }}">create it</a>?
diff --git a/budget/templates/forms.html b/budget/templates/forms.html
index 80a0d17..beb714b 100644
--- a/budget/templates/forms.html
+++ b/budget/templates/forms.html
@@ -21,7 +21,7 @@
<div class="actions">
<button type="submit" class="btn primary">{{ field.name }}</button>
{% if home %}
- <a href="{{ url_for(".home") }}">Go back Home</a>
+ <a href="{{ url_for(".remind_password") }}">Can't remember the password?</a>
{% endif %}
{% if cancel %}
<button id="cancel-form" type="reset" class="btn">Cancel</button>
@@ -32,6 +32,7 @@
{% macro authenticate(form, home=False) %}
{% include "display_errors.html" %}
+
{{ form.hidden_tag() }}
{{ input(form.id) }}
{{ input(form.password) }}
@@ -111,3 +112,12 @@
<button class="btn">Create the archive</button>
</div>
{% endmacro %}
+
+{% macro remind_password(form) %}
+
+ {% include "display_errors.html" %}
+ {{ form.hidden_tag() }}
+ {{ input(form.id) }}
+ {{ submit(form.submit) }}
+
+{% endmacro %}
diff --git a/budget/templates/home.html b/budget/templates/home.html
index ceb3b57..bf74767 100644
--- a/budget/templates/home.html
+++ b/budget/templates/home.html
@@ -26,6 +26,7 @@
<h3>Log to an existing project...</h3>
{{ forms.authenticate(auth_form, home=True) }}
<button class="btn">log in</button>
+ <a class="password-reminder" href="{{ url_for(".remind_password") }}">can't remember your password?</a>
</form>
</div>
<div class="span8 columns">
diff --git a/budget/templates/password_reminder b/budget/templates/password_reminder
new file mode 100644
index 0000000..fc24a6f
--- /dev/null
+++ b/budget/templates/password_reminder
@@ -0,0 +1,8 @@
+Hi,
+
+You requested to be reminded about your password for "{{ project.name }}".
+
+You can access it here: {{ config['SITE_URL'] }}{{ url_for(".list_bills", project_id=project.id) }}, the private code is "{{ project.password }}".
+
+Hope this helps,
+Some weird guys (with beards)
diff --git a/budget/templates/password_reminder.html b/budget/templates/password_reminder.html
new file mode 100644
index 0000000..0110cb8
--- /dev/null
+++ b/budget/templates/password_reminder.html
@@ -0,0 +1,8 @@
+{% extends "layout.html" %}
+
+{% block content %}
+<h2>Password reminder</h2>
+<form method="post">
+{{ forms.remind_password(form) }}
+</form>
+{% endblock %}
diff --git a/budget/tests.py b/budget/tests.py
index 2b573f4..a3fbd89 100644
--- a/budget/tests.py
+++ b/budget/tests.py
@@ -96,6 +96,24 @@ class BudgetTestCase(TestCase):
self.assertEqual(len(outbox), 0)
+ def test_password_reminder(self):
+ # test that it is possible to have an email cotaining the password of a
+ # project in case people forget it (and it happens!)
+
+ self.create_project("raclette")
+
+ with run.mail.record_messages() as outbox:
+ # a nonexisting project should not send an email
+ self.app.post("/password-reminder", data={"id": "unexisting"})
+ self.assertEqual(len(outbox), 0)
+
+ # a mail should be sent when a project exists
+ self.app.post("/password-reminder", data={"id": "raclette"})
+ self.assertEqual(len(outbox), 1)
+ self.assertIn("raclette", outbox[0].body)
+ self.assertIn("raclette@notmyidea.org", outbox[0].recipients)
+
+
def test_project_creation(self):
with run.app.test_client() as c:
diff --git a/budget/web.py b/budget/web.py
index 28740fc..8b251a1 100644
--- a/budget/web.py
+++ b/budget/web.py
@@ -6,8 +6,7 @@ import werkzeug
# local modules
from models import db, Project, Person, Bill
-from forms import (get_billform_for, ProjectForm, AuthenticationForm, BillForm,
- MemberForm, InviteForm, CreateArchiveForm, EditProjectForm)
+from forms import *
from utils import Redirect303
"""
@@ -149,6 +148,23 @@ def create_project():
return render_template("create_project.html", form=form)
+@main.route("/password-reminder", methods=["GET", "POST"])
+def remind_password():
+ form = PasswordReminder()
+ if request.method == "POST":
+ if form.validate():
+ # get the project
+ project = Project.query.get(form.id.data)
+
+ # send the password reminder
+ mail.send(Message("password recovery",
+ body=render_template("password_reminder", project=project),
+ recipients=[project.contact_email]))
+ flash("a mail has been sent to you with the password")
+
+ return render_template("password_reminder.html", form=form)
+
+
@main.route("/<project_id>/edit", methods=["GET", "POST"])
def edit_project():
form = EditProjectForm()