This commit is contained in:
0livd 2017-05-08 20:19:01 +00:00 committed by GitHub
commit 658abc6523
8 changed files with 89 additions and 6 deletions

View file

@ -8,3 +8,7 @@ SQLALCHEMY_TRACK_MODIFICATIONS = False
SECRET_KEY = "tralala" SECRET_KEY = "tralala"
MAIL_DEFAULT_SENDER = ("Budget manager", "budget@notmyidea.org") MAIL_DEFAULT_SENDER = ("Budget manager", "budget@notmyidea.org")
ADMIN_PASS = ""
PUBLIC_PROJECT_CREATION = True

View file

@ -83,6 +83,11 @@ class AuthenticationForm(FlaskForm):
submit = SubmitField(_("Get in")) submit = SubmitField(_("Get in"))
class AdminAuthenticationForm(FlaskForm):
admin_pass = PasswordField(_("Admin password"), validators=[Required()])
submit = SubmitField(_("Get in"))
class PasswordReminder(FlaskForm): class PasswordReminder(FlaskForm):
id = StringField(_("Project identifier"), validators=[Required()]) id = StringField(_("Project identifier"), validators=[Required()])
submit = SubmitField(_("Send me the code by email")) submit = SubmitField(_("Send me the code by email"))

View file

@ -7,7 +7,13 @@
to") }} <a href="{{ url_for(".create_project", project_id=create_project) }}">{{ _("create it") }}</a>{{ _("?") }} to") }} <a href="{{ url_for(".create_project", project_id=create_project) }}">{{ _("create it") }}</a>{{ _("?") }}
</p> </p>
{% endif %} {% endif %}
{% if admin %}
<form class="form-horizontal" method="POST" accept-charset="utf-8">
{{ forms.authenticate_admin(form) }}
</form>
{% else %}
<form class="form-horizontal" method="POST" accept-charset="utf-8"> <form class="form-horizontal" method="POST" accept-charset="utf-8">
{{ forms.authenticate(form) }} {{ forms.authenticate(form) }}
</form> </form>
{% endif %}
{% endblock %} {% endblock %}

View file

@ -45,6 +45,16 @@
{% endmacro %} {% endmacro %}
{% macro authenticate_admin(form) %}
{% include "display_errors.html" %}
{{ form.hidden_tag() }}
{{ input(form.admin_pass) }}
{{ submit(form.submit) }}
{% endmacro %}
{% macro create_project(form, home=False) %} {% macro create_project(form, home=False) %}
{% include "display_errors.html" %} {% include "display_errors.html" %}

View file

@ -5,7 +5,9 @@
<header id="header" class="row"> <header id="header" class="row">
<div class="col-5 offset-md-2"> <div class="col-5 offset-md-2">
<h2>{{ _("Manage your shared <br>expenses, easily") }}</h2> <h2>{{ _("Manage your shared <br>expenses, easily") }}</h2>
{% if public_project_creation %}
<a href="{{ url_for(".demo") }}" class="tryout btn">{{ _("Try out the demo") }}</a> <a href="{{ url_for(".demo") }}" class="tryout btn">{{ _("Try out the demo") }}</a>
{% endif %}
</div> </div>
<div class="col-4"> <div class="col-4">
<p class="additional-content">{{ _("You're sharing a house?") }}<br /> {{ _("Going on holidays with friends?") }}<br /> {{ _("Simply sharing money with others?") }} <br /><strong>{{ _("We can help!") }}</strong></p> <p class="additional-content">{{ _("You're sharing a house?") }}<br /> {{ _("Going on holidays with friends?") }}<br /> {{ _("Simply sharing money with others?") }} <br /><strong>{{ _("We can help!") }}</strong></p>
@ -26,6 +28,7 @@
</form> </form>
</div> </div>
<div class="col-3 offset-md-1"> <div class="col-3 offset-md-1">
{% if public_project_creation %}
<form id="creation-form" class="form-horizontal" action="{{ url_for(".create_project") }}" method="post"> <form id="creation-form" class="form-horizontal" action="{{ url_for(".create_project") }}" method="post">
<fieldset class="form-group"> <fieldset class="form-group">
<legend>...{{ _("or create a new one") }}</legend> <legend>...{{ _("or create a new one") }}</legend>
@ -35,6 +38,9 @@
<button class="btn" type="submit">{{ _("let's get started") }}</button> <button class="btn" type="submit">{{ _("let's get started") }}</button>
</div> </div>
</form> </form>
{% else %}
<a href="{{ url_for(".create_project") }}">...{{ _("or create a new one") }}</a>
{% endif %}
</main> </main>
</div> </div>
{% endblock %} {% endblock %}

View file

@ -41,6 +41,10 @@ msgstr "Email"
msgid "Project identifier" msgid "Project identifier"
msgstr "Identifiant du projet" msgstr "Identifiant du projet"
#: forms.py:87
msgid "Admin password"
msgstr "Mot de passe administrateur"
#: forms.py:87 templates/send_invites.html:5 #: forms.py:87 templates/send_invites.html:5
msgid "Create the project" msgid "Create the project"
msgstr "Créer le projet" msgstr "Créer le projet"
@ -158,6 +162,10 @@ msgstr "remboursements"
msgid "Export file format" msgid "Export file format"
msgstr "Format du fichier d'export" msgstr "Format du fichier d'export"
#: web.py:95
msgid "This admin password is not the right one"
msgstr "Le mot de passe administrateur que vous avez entré n'est pas correct"
#: web.py:95 #: web.py:95
msgid "This private code is not the right one" msgid "This private code is not the right one"
msgstr "Le code que vous avez entré n'est pas correct" msgstr "Le code que vous avez entré n'est pas correct"

View file

@ -16,11 +16,12 @@ from flask_babel import get_locale, gettext as _
from smtplib import SMTPRecipientsRefused from smtplib import SMTPRecipientsRefused
import werkzeug import werkzeug
from sqlalchemy import orm from sqlalchemy import orm
from functools import wraps
# local modules # local modules
from models import db, Project, Person, Bill from models import db, Project, Person, Bill
from forms import AuthenticationForm, EditProjectForm, InviteForm, \ from forms import AdminAuthenticationForm, AuthenticationForm, EditProjectForm, \
MemberForm, PasswordReminder, ProjectForm, get_billform_for, \ InviteForm, MemberForm, PasswordReminder, ProjectForm, get_billform_for, \
ExportForm ExportForm
from utils import Redirect303, list_of_dicts2json, list_of_dicts2csv from utils import Redirect303, list_of_dicts2json, list_of_dicts2csv
@ -28,6 +29,19 @@ main = Blueprint("main", __name__)
mail = Mail() mail = Mail()
def require_admin(f):
"""Require admin permissions for @require_admin decorated endpoints.
Has no effect if ADMIN_PASS is empty (default value)
"""
@wraps(f)
def admin_auth(*args, **kws):
admin_pass = session.get('admin_pass', '')
if not admin_pass == current_app.config['ADMIN_PASS']:
raise Redirect303(url_for('.authenticate_admin', goto=request.path))
return f(*args, **kws)
return admin_auth
@main.url_defaults @main.url_defaults
def add_project_id(endpoint, values): def add_project_id(endpoint, values):
"""Add the project id to the url calls if it is expected. """Add the project id to the url calls if it is expected.
@ -66,6 +80,23 @@ def pull_project(endpoint, values):
url_for(".authenticate", project_id=project_id)) url_for(".authenticate", project_id=project_id))
@main.route("/authenticate_admin", methods=["GET", "POST"])
def authenticate_admin():
"""Admin authentication"""
form = AdminAuthenticationForm()
goto = request.args.get('goto', url_for('.home'))
if request.method == "POST":
if form.validate():
if form.admin_pass.data == current_app.config['ADMIN_PASS']:
session['admin_pass'] = form.admin_pass.data
session.update()
return redirect(goto)
else:
msg = _("This admin password is not the right one")
form.errors['admin_pass'] = [msg]
return render_template("authenticate.html", form=form, admin=True)
@main.route("/authenticate", methods=["GET", "POST"]) @main.route("/authenticate", methods=["GET", "POST"])
def authenticate(project_id=None): def authenticate(project_id=None):
"""Authentication form""" """Authentication form"""
@ -119,13 +150,20 @@ def authenticate(project_id=None):
@main.route("/") @main.route("/")
def home(): def home():
project_form = ProjectForm()
auth_form = AuthenticationForm() auth_form = AuthenticationForm()
public_project_creation = current_app.config['PUBLIC_PROJECT_CREATION']
if public_project_creation:
project_form = ProjectForm()
return render_template("home.html", project_form=project_form, return render_template("home.html", project_form=project_form,
public_project_creation=public_project_creation,
auth_form=auth_form, session=session)
# If public_project_creation is False we don't need to pass a project form to home
return render_template("home.html", public_project_creation=public_project_creation,
auth_form=auth_form, session=session) auth_form=auth_form, session=session)
@main.route("/create", methods=["GET", "POST"]) @main.route("/create", methods=["GET", "POST"])
@require_admin
def create_project(): def create_project():
form = ProjectForm() form = ProjectForm()
if request.method == "GET" and 'project_id' in request.values: if request.method == "GET" and 'project_id' in request.values:
@ -259,8 +297,14 @@ def demo():
Create a demo project if it doesnt exists yet (or has been deleted) Create a demo project if it doesnt exists yet (or has been deleted)
""" """
public_project_creation = current_app.config['PUBLIC_PROJECT_CREATION']
project = Project.query.get("demo") project = Project.query.get("demo")
if not project:
# Demo project is not automatically created if public project creation is disabled
if not project and not public_project_creation:
raise Redirect303(url_for(".create_project",
project_id='demo'))
if not project and public_project_creation:
project = Project(id="demo", name=u"demonstration", password="demo", project = Project(id="demo", name=u"demonstration", password="demo",
contact_email="demo@notmyidea.org") contact_email="demo@notmyidea.org")
db.session.add(project) db.session.add(project)