From 9d76144a8333d6af81ddefddf59af38bd96a72ae Mon Sep 17 00:00:00 2001 From: Alexis Metaireau Date: Fri, 10 Aug 2018 23:04:31 +0200 Subject: [PATCH 01/14] Fix failing tests (#365) * Remove unwanted space in utils.py * Fix email validation when sending invites --- CHANGELOG.rst | 1 + ihatemoney/forms.py | 7 +++++-- requirements.txt | 1 + 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 382e8897..7947b1a4 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -14,6 +14,7 @@ Fixed - Fix the generation of the supervisord template (#309) - Fix the validation of the hashed password (#310) - Fix infinite loop that happened when accessing / (#358) +- Fix email validation when sending invites Added ===== diff --git a/ihatemoney/forms.py b/ihatemoney/forms.py index 3966891c..de9004d5 100644 --- a/ihatemoney/forms.py +++ b/ihatemoney/forms.py @@ -10,6 +10,8 @@ from werkzeug.security import generate_password_hash from datetime import datetime from jinja2 import Markup +import email_validator + from ihatemoney.models import Project, Person from ihatemoney.utils import slugify @@ -184,9 +186,10 @@ class InviteForm(FlaskForm): submit = SubmitField(_("Send invites")) def validate_emails(form, field): - validator = Email() for email in [email.strip() for email in form.emails.data.split(",")]: - if not validator.regex.match(email): + try: + email_validator.validate_email(email) + except email_validator.EmailNotValidError as e: raise ValidationError(_("The email %(email)s is not valid", email=email)) diff --git a/requirements.txt b/requirements.txt index c2fe5348..964d7fc5 100644 --- a/requirements.txt +++ b/requirements.txt @@ -11,3 +11,4 @@ raven blinker six>=1.10 itsdangerous>=0.24 +email_validator>=1.0 From db70a9a6d25b8387c0d5375a21f8724c93cdc43b Mon Sep 17 00:00:00 2001 From: 0livd Date: Fri, 10 Aug 2018 23:24:16 +0200 Subject: [PATCH 02/14] Fix docker ADMIN_PASSWORD configuration (#384) Use single quotes instead of double to not interpret inner $ as nested variables. Fixes #334 --- conf/confandrun.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conf/confandrun.sh b/conf/confandrun.sh index e37a5739..0e105b2c 100755 --- a/conf/confandrun.sh +++ b/conf/confandrun.sh @@ -13,7 +13,7 @@ MAIL_USERNAME = "$MAIL_USERNAME" MAIL_PASSWORD = "$MAIL_PASSWORD" MAIL_DEFAULT_SENDER = "$MAIL_DEFAULT_SENDER" ACTIVATE_DEMO_PROJECT = $ACTIVATE_DEMO_PROJECT -ADMIN_PASSWORD = "$ADMIN_PASSWORD" +ADMIN_PASSWORD = '$ADMIN_PASSWORD' ALLOW_PUBLIC_PROJECT_CREATION = $ALLOW_PUBLIC_PROJECT_CREATION ACTIVATE_ADMIN_DASHBOARD = $ACTIVATE_ADMIN_DASHBOARD EOF From 665dfd5c44425e6d30e841b4b0ed35e3cbef8b58 Mon Sep 17 00:00:00 2001 From: Alexis Metaireau Date: Sat, 11 Aug 2018 00:11:00 +0200 Subject: [PATCH 03/14] Remove Sentry, as it's not used anymore on prod. (#380) Fixes #312. --- ihatemoney/run.py | 4 ---- requirements.txt | 1 - 2 files changed, 5 deletions(-) diff --git a/ihatemoney/run.py b/ihatemoney/run.py index 6dac2330..1a5ac17e 100644 --- a/ihatemoney/run.py +++ b/ihatemoney/run.py @@ -6,7 +6,6 @@ from flask import Flask, g, request, session from flask_babel import Babel from flask_mail import Mail from flask_migrate import Migrate, upgrade, stamp -from raven.contrib.flask import Sentry from werkzeug.contrib.fixers import ProxyFix from ihatemoney.api import api @@ -130,9 +129,6 @@ def create_app(configuration=None, instance_path='/etc/ihatemoney', mail.init_app(app) app.mail = mail - # Error reporting - Sentry(app) - # Jinja filters app.jinja_env.filters['minimal_round'] = minimal_round diff --git a/requirements.txt b/requirements.txt index 964d7fc5..f61c9b93 100644 --- a/requirements.txt +++ b/requirements.txt @@ -7,7 +7,6 @@ Flask-script flask-babel flask-restful>=0.3.6 jinja2>=2.6 -raven blinker six>=1.10 itsdangerous>=0.24 From 2eafb7260ceb25dbf2f1ff3b381450d6a572ac25 Mon Sep 17 00:00:00 2001 From: Alexis Metaireau Date: Sat, 11 Aug 2018 00:13:53 +0200 Subject: [PATCH 04/14] Add a favicon.ico route and logo. (#381) Might fix #255 --- ihatemoney/static/favicon.ico | Bin 0 -> 1742 bytes ihatemoney/web.py | 9 ++++++++- 2 files changed, 8 insertions(+), 1 deletion(-) create mode 100644 ihatemoney/static/favicon.ico diff --git a/ihatemoney/static/favicon.ico b/ihatemoney/static/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..9db04f25d60d2ab20a6d3a83b8bf3a666b7fa5ee GIT binary patch literal 1742 zcmds1%W4!s6upCwph6PjXjfN{8bw5i=z!o8#f7K{x)4-ci65W@#ART15o1^NjJg%LDf-5O8F zyL@HO`8w@NoxTl1d*EMq`TQU>d*pq?=`S7LgLo%+XQeV1N)-lR@X&0APZQK~YyYOl zGH>SVCUAc6+UdS3T`x?Ih)%ktN?yb{4sgCM;=FIDWK2fs)uL>y^L-fjBjoI6QO0{; zn`dP{at+GjM2>F2hsXFnOKqoykUvTcr)o&!br_lEC5(WY{b_)&}N zRq{aFCOBss%5A99$>WIU^hC?yMXMe%G8e)5UbcU2uhc@$xVGHSl{z_r-|inoJ>O-0 ztn3-SuUuPxBLZ!Xa;{gD7v^@Z#`h1kZSh;hJRz;0AvN_0Emu(hC{%|nQZwI{#r2qf` literal 0 HcmV?d00001 diff --git a/ihatemoney/web.py b/ihatemoney/web.py index 6e876c03..b462fe4c 100644 --- a/ihatemoney/web.py +++ b/ihatemoney/web.py @@ -9,9 +9,10 @@ some shortcuts to make your life better when coding (see `pull_project` and `add_project_id` for a quick overview) """ +import os from flask import ( Blueprint, current_app, flash, g, redirect, render_template, request, - session, url_for, send_file + session, url_for, send_file, send_from_directory ) from flask_mail import Message from flask_babel import get_locale, gettext as _ @@ -582,3 +583,9 @@ def dashboard(): projects=Project.query.all(), is_admin_dashboard_activated=is_admin_dashboard_activated ) + + +@main.route('/favicon.ico') +def favicon(): + return send_from_directory(os.path.join(main.root_path, 'static'), + 'favicon.ico', mimetype='image/vnd.microsoft.icon') From 65bed7b45b433a58cb3834714f53dabaeda2e334 Mon Sep 17 00:00:00 2001 From: Benjamin Bouvier Date: Thu, 30 Aug 2018 21:42:09 +0200 Subject: [PATCH 05/14] Add a contributing section to the readme file; --- README.rst | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/README.rst b/README.rst index 6ecdf9c8..31104d9d 100644 --- a/README.rst +++ b/README.rst @@ -21,3 +21,10 @@ Requirements * **Python**: 2.7, 3.4, 3.5, 3.6. * **Backends**: MySQL, PostgreSQL, SQLite, Memory. + +Contributing +============ + +Do you wish to contribute to IHateMoney? Fantastic! There's a lot of very +useful help on the official `contributing +`_ page. From bfdcf31438a8fd8df440fec0d288e7183469747a Mon Sep 17 00:00:00 2001 From: Marien Fressinaud Date: Mon, 3 Sep 2018 20:28:46 +0200 Subject: [PATCH 06/14] doc: Improve Makefile (#387) * Add help target to the Makefile It is often expected to have a `help` target in a Makefile. This one is automatically generated from comments in the Makefile so it is easier to maintain. This commit only documents targets that seem the most important. * Add the server address and port on `make serve` Developers should not have to read the documentation to find where to point their browsers to access ihatemoney application. * Add .PHONY instructions to the Makefile `.PHONY` instructs Make to not look, for instance, for an `install` file before executing the corresponding target. If such a file would exist, the command would not be performed at all. This is because Make is initially intended to create files (i.e. targets) and consider there is nothing to do if the file already exists. More information on https://stackoverflow.com/a/2145605. --- Makefile | 43 +++++++++++++++++++++++++++++++------------ 1 file changed, 31 insertions(+), 12 deletions(-) diff --git a/Makefile b/Makefile index e273b80b..8c48ed4c 100644 --- a/Makefile +++ b/Makefile @@ -7,52 +7,71 @@ DOC_STAMP = $(VENV)/.doc_env_installed.stamp INSTALL_STAMP = $(VENV)/.install.stamp TEMPDIR := $(shell mktemp -d) -all: install -install: virtualenv $(INSTALL_STAMP) +.PHONY: all +all: install ## Alias for install +.PHONY: install +install: virtualenv $(INSTALL_STAMP) ## Install dependencies $(INSTALL_STAMP): $(VENV)/bin/pip install -U pip $(VENV)/bin/pip install -r requirements.txt touch $(INSTALL_STAMP) +.PHONY: virtualenv virtualenv: $(PYTHON) $(PYTHON): $(VIRTUALENV) $(VENV) -install-dev: $(INSTALL_STAMP) $(DEV_STAMP) +.PHONY: install-dev +install-dev: $(INSTALL_STAMP) $(DEV_STAMP) ## Install development dependencies $(DEV_STAMP): $(PYTHON) dev-requirements.txt $(VENV)/bin/pip install -Ur dev-requirements.txt touch $(DEV_STAMP) +.PHONY: remove-install-stamp remove-install-stamp: rm $(INSTALL_STAMP) -update: remove-install-stamp install +.PHONY: update +update: remove-install-stamp install ## Update the dependencies -serve: install +.PHONY: serve +serve: install ## Run the ihatemoney server + @echo 'Running ihatemoney on http://localhost:5000' $(PYTHON) -m ihatemoney.manage runserver -test: $(DEV_STAMP) +.PHONY: test +test: $(DEV_STAMP) ## Run the tests $(VENV)/bin/tox -release: $(DEV_STAMP) +.PHONY: release +release: $(DEV_STAMP) ## Release a new version (see https://ihatemoney.readthedocs.io/en/latest/contributing.html#how-to-release) $(VENV)/bin/fullrelease -build-translations: +.PHONY: build-translations +build-translations: ## Build the translations $(VENV)/bin/pybabel compile -d ihatemoney/translations -update-translations: +.PHONY: update-translations +update-translations: ## Extract new translations from source code $(VENV)/bin/pybabel extract --strip-comments --omit-header --no-location --mapping-file ihatemoney/babel.cfg -o ihatemoney/messages.pot ihatemoney $(VENV)/bin/pybabel update -i ihatemoney/messages.pot -d ihatemoney/translations/ -create-database-revision: +.PHONY: create-database-revision +create-database-revision: ## Create a new database revision @read -p "Please enter a message describing this revision: " rev_message; \ $(PYTHON) -m ihatemoney.manage db migrate -d ihatemoney/migrations -m "$${rev_message}" -build-requirements: +.PHONY: build-requirements +build-requirements: ## Save currently installed packages to requirements.txt $(VIRTUALENV) $(TEMPDIR) $(TEMPDIR)/bin/pip install -U pip $(TEMPDIR)/bin/pip install -Ue "." $(TEMPDIR)/bin/pip freeze | grep -v -- '-e' > requirements.txt -clean: +.PHONY: clean +clean: ## Destroy the virtual environment rm -rf .venv + +.PHONY: help +help: ## Show the help indications + @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' From bb77fdbe3e4f3605b201de5cdb96483d73b3dda4 Mon Sep 17 00:00:00 2001 From: Alexis Metaireau Date: Mon, 3 Sep 2018 20:49:30 +0200 Subject: [PATCH 07/14] Simplify a JS function. (#371) --- ihatemoney/static/js/ihatemoney.js | 25 +++++++------------------ ihatemoney/templates/forms.html | 2 +- 2 files changed, 8 insertions(+), 19 deletions(-) diff --git a/ihatemoney/static/js/ihatemoney.js b/ihatemoney/static/js/ihatemoney.js index 24e82b78..c240dc1a 100644 --- a/ihatemoney/static/js/ihatemoney.js +++ b/ihatemoney/static/js/ihatemoney.js @@ -1,18 +1,7 @@ - // Add scripts to select all or non of the checkboxes in the add_bill form -function selectall() - { - var els = document.getElementsByName('payed_for'); - for(var i =0;i{{ _("For whom?") }}
    -

    {{ _("Select all") }} | {{_("Select none")}}

    +

    {{ _("Select all") }} | {{_("Select none")}}

    {% for key, value, checked in form.payed_for.iter_choices() %}

    {% endfor %} From 22f8d552c3f2273f1ea1cfa81cb10fe8f3cad21d Mon Sep 17 00:00:00 2001 From: Benjamin Bouvier Date: Mon, 3 Sep 2018 20:52:48 +0200 Subject: [PATCH 08/14] Fix error escaping; (#388) --- ihatemoney/templates/display_errors.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ihatemoney/templates/display_errors.html b/ihatemoney/templates/display_errors.html index 9e196058..265fa251 100644 --- a/ihatemoney/templates/display_errors.html +++ b/ihatemoney/templates/display_errors.html @@ -1,5 +1,5 @@ {% for field_name, field_errors in form.errors.items() if field_errors %} {% for error in field_errors %} -

    {{ form[field_name].label.text }}: {{ error }}

    +

    {{ form[field_name].label.text }}: {{ error|escape }}

    {% endfor %} {% endfor %} From 24e0d8348fb5855d0255b41ec1ca9beaf233d9a6 Mon Sep 17 00:00:00 2001 From: Alexis Metaireau Date: Mon, 3 Sep 2018 20:53:37 +0200 Subject: [PATCH 09/14] Fix double-click when deleting a bill (#349) (#372) When double-clicking on the delete button, the first click actually deletes the bill, and the second click does the same action again. But as the bill is already deleted, it displays a 404 page which can be misleading. This fix makes the app trigger a redirect when the bill seem to doesn't exist, fixing this strange behaviour. --- ihatemoney/web.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ihatemoney/web.py b/ihatemoney/web.py index b462fe4c..f6f04af5 100644 --- a/ihatemoney/web.py +++ b/ihatemoney/web.py @@ -514,7 +514,7 @@ def delete_bill(bill_id): # fixme: everyone is able to delete a bill bill = Bill.query.get(g.project, bill_id) if not bill: - raise NotFound() + return redirect(url_for('.list_bills')) db.session.delete(bill) db.session.commit() From 6ab92ddbac84f87dc598016de45845a26818dd52 Mon Sep 17 00:00:00 2001 From: Alexis Metaireau Date: Mon, 3 Sep 2018 20:54:07 +0200 Subject: [PATCH 10/14] Add a handler when pages aren't found. (#379) Fixes #356 --- ihatemoney/messages.pot | 6 +++++ ihatemoney/run.py | 9 +++++-- ihatemoney/templates/404.html | 13 +++++++++++ ihatemoney/templates/layout.html | 22 +++++++++--------- .../translations/fr/LC_MESSAGES/messages.mo | Bin 9909 -> 10180 bytes .../translations/fr/LC_MESSAGES/messages.po | 11 ++++++--- 6 files changed, 45 insertions(+), 16 deletions(-) create mode 100644 ihatemoney/templates/404.html diff --git a/ihatemoney/messages.pot b/ihatemoney/messages.pot index bc8a8f39..bd4dcc49 100644 --- a/ihatemoney/messages.pot +++ b/ihatemoney/messages.pot @@ -182,6 +182,12 @@ msgstr "" msgid "The bill has been modified" msgstr "" +msgid "Sorry, we were unable to find the page you've asked for." +msgstr "" + +msgid "The best thing to do is probably to get back to the main page." +msgstr "" + msgid "Back to the list" msgstr "" diff --git a/ihatemoney/run.py b/ihatemoney/run.py index 1a5ac17e..e9b3ce16 100644 --- a/ihatemoney/run.py +++ b/ihatemoney/run.py @@ -2,7 +2,7 @@ import os import os.path import warnings -from flask import Flask, g, request, session +from flask import Flask, g, request, session, render_template from flask_babel import Babel from flask_mail import Mail from flask_migrate import Migrate, upgrade, stamp @@ -102,6 +102,10 @@ def validate_configuration(app): ) +def page_not_found(e): + return render_template('404.html', root="main"), 404 + + def create_app(configuration=None, instance_path='/etc/ihatemoney', instance_relative_config=True): app = Flask( @@ -121,8 +125,9 @@ def create_app(configuration=None, instance_path='/etc/ihatemoney', validate_configuration(app) app.register_blueprint(web_interface) app.register_blueprint(api) + app.register_error_handler(404, page_not_found) - # Configure the application + # Configure the a, root="main"pplication setup_database(app) mail = Mail() diff --git a/ihatemoney/templates/404.html b/ihatemoney/templates/404.html new file mode 100644 index 00000000..7e282c2e --- /dev/null +++ b/ihatemoney/templates/404.html @@ -0,0 +1,13 @@ +{% extends "layout.html" %} + +{% block body %} + +
    + +{% endblock %} diff --git a/ihatemoney/templates/layout.html b/ihatemoney/templates/layout.html index cb36a6fe..3523ef7b 100644 --- a/ihatemoney/templates/layout.html +++ b/ihatemoney/templates/layout.html @@ -32,13 +32,13 @@
diff --git a/ihatemoney/translations/fr/LC_MESSAGES/messages.mo b/ihatemoney/translations/fr/LC_MESSAGES/messages.mo index 3fa8d8f4c52f34ffbdb3e90d8579f61864b1ce5a..ab8a831618f68d3f7c23b560196812096c4c9bb8 100644 GIT binary patch delta 2505 zcmYM!e@sg$HTLH_gj-=3kjO7Iq@VIENzU=e0xEpo{;qiWcS zBCic0M**}z3bzs`_G{&{Tfy2 zWn73qqT<~0%pxmwpa@mq1E@|kq02qy2?lC;09APqb>2nY_%bTMFsgN@QA=_bmFPuO zLO-CMyMfv>K5o_$Ek$*%5(}{gYq2$x^&esIDkqd#HDxMrJu2`P)Prq!7uu-S4d8kl z!9{olHR0c=R_Bnlg%voBTd)ypXiFUX@ge*HDwp$W?YFeRK>?otsTR)IDzWO z4OF6jzL?W2#vraj?Tw>o;VAMkU-G5STt^l37v|$Fmw_tJr%!SPYSWc^R-x8-J>G{K zu>qe(y>_Qj1^kYhcpe*o?wfK{2kTLBn{XLEf{MS}yY9vqC?gj&(TkpkP@Cw8cYOr4 zM-oWR<|Jx@k5B>6qbmFgwfm>N^Rsh}+3#Z?pb~t8Y*ok@(qY&9%0NF9nJjP$Y2!+ltd2~=w@p%P3Xx+=*=b#Mc!kS5gT+JTDu4C?toRA)a#C3*o} zJ@6d^weBC(8m6*S7@929gcV59<}obCZd3(tqAEX*N@xrf=M1Vd=TM!yikk2@REPa! zrv!8J=|9DqYL3*RM^Tk;NA2ov{b5?F~^ign)kjmQ$;W11N#KnH4qFlz1kP@C-~@AyEUlWc* z`pc}R96k}piihm>pku|tR%cfzV8wPh)*gGOWA%sQCB2SiN4uSX)ftXdBx^HseYH+B z#ywr3oq8e=wz{I$o=CWz82vi4(}`K_c1O3y3e{tGg>J`7Zkm5IZFX&WWwo_tZC%ys zh{NmC2jA;q-N0c+?7!P9z-f4TlJBN3EbelhWR}WA*9=yVn`8 z0#1(|3QQ&{lHK`pe6^2oY9`HXw0#cu9u(F=VqB@;4_$l zH5kMdn1e4lH{u*K-`=4ymK&d7E`EWU;5??`Wt@OlPyyb;bo>YNF@@R3V{D#`>65hPnZ>BHm0(^#b|KP;;2AskU8xYoQWGyrG4Ms??OF)7M1BYs7x>5 zMEnUg&n@Q=ssbrQrvyDzC8Fqa&lb{9$*WPB*P{B@qaJKTO|T19x=z%VoJIwD9u?4! zsBza(XXZ9)i-u8|=Q6kmL--k1=CJ>YsGkl^cn3A%U#I~A(k{eIRLP1kgv(J2)T2tf z13m1(K|F_5_%YEp<86EnU#2V?--S`^&7=Mi8vS%A!!e|q4xA7R^sQl81JH9v+2}R z8N7yCxEZOgwWBI`9JN3XPQ@=#^IvuM`%wW6qSo<$ca0?K&^&Yx1UX4M6M4wmHVL&r zDQdz+s0^2)PWx)tzXjU@W;;;<{#P)XNSLTq;kBs03tO>9?|%yos%IBb3to5jqZS@O zZNWpFf>|7hB^W_H-+-)TO{mQGptf)y&clOPhTo%}Pa+>1<|~)=EuWL5J&oYV9}ZMW z<5-N#P?dQbwNM+9lzrs-&!QH-h{~`J^)?KkD)s>peh?BDkV^fdVVFU5*u;k{cohf z$F}pO1v`*n?Q1N>Yp4tYoG4|Ui3%u;ny3s_nT4pztwJrh4z+bnr~uzXai?ib>Kn*Rur zll6xE(HmFk7^EYK%khTCJC2be4j7(7MV?K0bf`)&ifd6NZAI<%QG5ZrQJE)Ehd7mg z1gcmeZpIRvg`GYP?fGR?WPc)Wpyd+24pjs_oQ>LoT2zK>P^DgnT4)pM`4+6gR$PkT zVKt^jMiW?pC0sY4D(HVeLlJhOUYj1&Av=dUOoONghurleR3I6ouRwB80TiINpxE^< zKyB$_)c6-s^VgxabQ5y6#@aU5aWb0d%)F46IFyqgNZcFuVR|rDS|0P}m&X@WB>aL2 nft1+XibQ+pt&BufI2Z`l)_bqlZ+N$POT(d0LlYC-o|o}I;g8pC diff --git a/ihatemoney/translations/fr/LC_MESSAGES/messages.po b/ihatemoney/translations/fr/LC_MESSAGES/messages.po index ccab28b1..b3e2fdbe 100644 --- a/ihatemoney/translations/fr/LC_MESSAGES/messages.po +++ b/ihatemoney/translations/fr/LC_MESSAGES/messages.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: PROJECT VERSION\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2018-07-16 23:26+0200\n" +"POT-Creation-Date: 2018-08-05 23:41+0200\n" "PO-Revision-Date: 2018-05-15 22:00+0200\n" "Last-Translator: Adrien CLERC <>\n" "Language: fr\n" @@ -16,7 +16,7 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" -"Generated-By: Babel 2.5.3\n" +"Generated-By: Babel 2.6.0\n" msgid "Project name" msgstr "Nom de projet" @@ -210,6 +210,12 @@ msgstr "La facture a été supprimée" msgid "The bill has been modified" msgstr "La facture a été modifiée" +msgid "Sorry, we were unable to find the page you've asked for." +msgstr "Navré, nous ne trouvons pas la page que vous avez demandé." + +msgid "The best thing to do is probably to get back to the main page." +msgstr "Votre meilleure piste est probablement la page d'accueil." + msgid "Back to the list" msgstr "Retourner à la liste" @@ -488,4 +494,3 @@ msgstr "Solde" #~ msgid "Invite" #~ msgstr "Invitez" - From 07aabeb07f138c51af61c50f1cd6c1e5bcf133e4 Mon Sep 17 00:00:00 2001 From: Alexis Metaireau Date: Mon, 3 Sep 2018 20:54:41 +0200 Subject: [PATCH 11/14] Replace the settings table with multiple sections. (#376) It's easier to read, and easier to maintain. Fixes #251. --- docs/installation.rst | 114 ++++++++++++++++++++++++++---------------- 1 file changed, 72 insertions(+), 42 deletions(-) diff --git a/docs/installation.rst b/docs/installation.rst index 4829c5de..2da0d945 100644 --- a/docs/installation.rst +++ b/docs/installation.rst @@ -189,49 +189,79 @@ deployed instance, simply look at your *ihatemoney.cfg*. Production values are recommended values for use in production. +`SQLALCHEMY_DATABASE_URI` +------------------------- -+-------------------------------+---------------------------------+----------------------------------------------------------------------------------------+ -| Setting name | Default | What does it do? | -+===============================+=================================+========================================================================================+ -| SQLALCHEMY_DATABASE_URI | ``sqlite:///tmp/ihatemoney.db`` | Specifies the type of backend to use and its location. More information on the | -| | | format used can be found on `the SQLAlchemy documentation`_. | -| | | | -| | | **Production value:** Set it to some path on your disk. Typically | -| | | ``sqlite:///home/ihatemoney/ihatemoney.db``. Do *not* store it under ``/tmp`` as this | -| | | folder is cleared at each boot. | -+-------------------------------+---------------------------------+----------------------------------------------------------------------------------------+ -| SECRET_KEY | ``tralala`` | The secret key used to encrypt the cookies. | -| | | | -| | | **Production value:** `ihatemoney conf-example ihatemoney.cfg` sets it to something | -| | | random, which is good. | -+-------------------------------+---------------------------------+----------------------------------------------------------------------------------------+ -| MAIL_DEFAULT_SENDER | ``("Budget manager", | A python tuple describing the name and email address to use when sending | -| | "budget@notmyidea.org")`` | emails. | -| | | | -| | | **Production value:** Any tuple you want. | -+-------------------------------+---------------------------------+----------------------------------------------------------------------------------------+ -| ACTIVATE_DEMO_PROJECT | ``True`` | If set to `True`, a demo project will be available on the frontpage. | -| | | | -| | | **Production value:** Usually, you will want to set it to ``False`` for a private | -| | | instance. | -+-------------------------------+---------------------------------+----------------------------------------------------------------------------------------+ -| | | Hashed password to access protected endpoints. If left empty, all administrative | -| ADMIN_PASSWORD | ``""`` | tasks are disabled. | -| | | | -| | | **Production value:** To generate the proper password HASH, use | -| | | ``ihatemoney generate_password_hash`` and copy the output into the value of | -| | | *ADMIN_PASSWORD*. | -+-------------------------------+---------------------------------+----------------------------------------------------------------------------------------+ -| ALLOW_PUBLIC_PROJECT_CREATION | ``True`` | If set to ``True``, everyone can create a project without entering the admin password | -| | | If set to ``False``, the password needs to be entered (and as such, defined in the | -| | | settings). | -+-------------------------------+---------------------------------+----------------------------------------------------------------------------------------+ -| ACTIVATE_ADMIN_DASHBOARD | ``False`` | If set to `True`, the dashboard will become accessible entering the admin password | -| | | If set to `True`, a non empty ADMIN_PASSWORD needs to be set | -+-------------------------------+---------------------------------+----------------------------------------------------------------------------------------+ -| APPLICATION_ROOT | ``""`` | If empty, ihatemoney will be served at domain root (e.g: *http://domain.tld*), if set | -| | | to ``"foo"``, it will be served from a "folder" (e.g: *http://domain.tld/foo*) | -+-------------------------------+---------------------------------+----------------------------------------------------------------------------------------+ +Specifies the type of backend to use and its location. More information on the +format used can be found on `the SQLAlchemy documentation`_. + +- **default value:** ``sqlite:///tmp/ihatemoney.db`` +- **Production value:** Set it to some path on your disk. Typically + ``sqlite:///home/ihatemoney/ihatemoney.db``. Do *not* store it under + ``/tmp`` as this folder is cleared at each boot. + +`SECRET_KEY` +------------ + +The secret key used to encrypt the cookies. + +- **Production value:** `ihatemoney conf-example ihatemoney.cfg` sets it to + something random, which is good. + +`MAIL_DEFAULT_SENDER` +--------------------- + +A python tuple describing the name and email address to use when sending emails. + +- **Default value:** ``("Budget manager", "budget@notmyidea.org")`` +- **Production value:** Any tuple you want. + +`ACTIVATE_DEMO_PROJECT` +----------------------- + +If set to `True`, a demo project will be available on the frontpage. + +- **Default value:** ``True`` +- **Production value:** Usually, you will want to set it to ``False`` for a + private instance. + +`ADMIN_PASSWORD` +---------------- + +Hashed password to access protected endpoints. If left empty, all administrative +tasks are disabled. + +- **Default value:** ``""`` (empty string) +- **Production value:** To generate the proper password HASH, use + ``ihatemoney generate_password_hash`` and copy the output into the value of + *ADMIN_PASSWORD*. + +`ALLOW_PUBLIC_PROJECT_CREATION` +------------------------------- + +If set to ``True``, everyone can create a project without entering the admin +password. If set to ``False``, the password needs to be entered (and as such, +defined in the settings). + +- **Default value:** : ``True``. + + +`ACTIVATE_ADMIN_DASHBOARD` +-------------------------- + +If set to `True`, the dashboard will become accessible entering the admin +password, if set to `True`, a non empty ADMIN_PASSWORD needs to be set. + +- **Default value**: ``False`` + +`APPLICATION_ROOT` +------------------ + +If empty, ihatemoney will be served at domain root (e.g: *http://domain.tld*), +if set to ``"somestring"``, it will be served from a "folder" +(e.g: *http://domain.tld/somestring*). + +- **Default value:** ``""`` (empty string) .. _the SQLAlchemy documentation: http://docs.sqlalchemy.org/en/latest/core/engines.html#database-urls From 5fcf667914e8cb19a883317c346165610c5d1754 Mon Sep 17 00:00:00 2001 From: Alexis Metaireau Date: Mon, 3 Sep 2018 20:55:10 +0200 Subject: [PATCH 12/14] Almet/docs/mail server configuration (#378) * Replace the settings table with multiple sections. It's easier to read, and easier to maintain. Fixes #251. * Document external mail server configuration. Fixes #278 --- docs/installation.rst | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/docs/installation.rst b/docs/installation.rst index 2da0d945..f4744ae7 100644 --- a/docs/installation.rst +++ b/docs/installation.rst @@ -265,6 +265,22 @@ if set to ``"somestring"``, it will be served from a "folder" .. _the SQLAlchemy documentation: http://docs.sqlalchemy.org/en/latest/core/engines.html#database-urls +Configuring emails sending +-------------------------- + +By default, Ihatemoney sends emails using a local SMTP server, but it's +possible to configure it to act differently, thanks to the great +`Flask-Mail project `_ + +* **MAIL_SERVER** : default **'localhost'** +* **MAIL_PORT** : default **25** +* **MAIL_USE_TLS** : default **False** +* **MAIL_USE_SSL** : default **False** +* **MAIL_DEBUG** : default **app.debug** +* **MAIL_USERNAME** : default **None** +* **MAIL_PASSWORD** : default **None** +* **DEFAULT_MAIL_SENDER** : default **None** + Using an alternate settings path -------------------------------- From 171dd81ed777411d216c9bb38c4bb4d6b2aa1e91 Mon Sep 17 00:00:00 2001 From: Alexis Metaireau Date: Mon, 3 Sep 2018 20:55:25 +0200 Subject: [PATCH 13/14] Underline actions links on hover. (#377) Fix #260 --- ihatemoney/static/css/main.css | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ihatemoney/static/css/main.css b/ihatemoney/static/css/main.css index 94ca4bd8..6c8b57f9 100644 --- a/ihatemoney/static/css/main.css +++ b/ihatemoney/static/css/main.css @@ -224,6 +224,10 @@ tr.payer_line .balance-name{ padding: 0 0 0 20px; } +.action button:hover { + text-decoration: underline; +} + .delete button, .delete button:hover { background: url('../images/deleter.png') left no-repeat; color: red; From c34583d07971e6436f5b9e559a97c8f734b46679 Mon Sep 17 00:00:00 2001 From: Alexis Metaireau Date: Mon, 3 Sep 2018 20:55:44 +0200 Subject: [PATCH 14/14] Add a ihatemoney delete-project command. (#375) --- ihatemoney/manage.py | 10 +++++++++- ihatemoney/tests/tests.py | 12 +++++++++++- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/ihatemoney/manage.py b/ihatemoney/manage.py index 3207b558..a9eca0f3 100755 --- a/ihatemoney/manage.py +++ b/ihatemoney/manage.py @@ -10,7 +10,7 @@ from flask_migrate import Migrate, MigrateCommand from werkzeug.security import generate_password_hash from ihatemoney.run import create_app -from ihatemoney.models import db +from ihatemoney.models import db, Project from ihatemoney.utils import create_jinja_env @@ -57,6 +57,13 @@ class GenerateConfig(Command): )) +class DeleteProject(Command): + def run(self, project_name): + demo_project = Project.query.get(project_name) + db.session.delete(demo_project) + db.session.commit() + + def main(): QUIET_COMMANDS = ('generate_password_hash', 'generate-config') @@ -76,6 +83,7 @@ def main(): manager.add_command('db', MigrateCommand) manager.add_command('generate_password_hash', GeneratePasswordHash) manager.add_command('generate-config', GenerateConfig) + manager.add_command('delete-project', DeleteProject) manager.run() diff --git a/ihatemoney/tests/tests.py b/ihatemoney/tests/tests.py index fd72a8da..63a73942 100644 --- a/ihatemoney/tests/tests.py +++ b/ihatemoney/tests/tests.py @@ -20,7 +20,8 @@ from flask import session from flask_testing import TestCase from ihatemoney.run import create_app, db, load_configuration -from ihatemoney.manage import GenerateConfig, GeneratePasswordHash +from ihatemoney.manage import ( + GenerateConfig, GeneratePasswordHash, DeleteProject) from ihatemoney import models from ihatemoney import utils @@ -1472,6 +1473,15 @@ class CommandTestCase(BaseTestCase): print(stdout.getvalue()) self.assertEqual(len(stdout.getvalue().strip()), 187) + def test_demo_project_deletion(self): + self.create_project('demo') + self.assertEquals(models.Project.query.get('demo').name, 'demo') + + cmd = DeleteProject() + cmd.run('demo') + + self.assertEqual(len(models.Project.query.all()), 0) + if __name__ == "__main__": unittest.main()