aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--fietsboek/__init__.py3
-rw-r--r--fietsboek/locale/de/LC_MESSAGES/messages.mobin11699 -> 11757 bytes
-rw-r--r--fietsboek/locale/de/LC_MESSAGES/messages.po180
-rw-r--r--fietsboek/locale/en/LC_MESSAGES/messages.mobin11018 -> 11069 bytes
-rw-r--r--fietsboek/locale/en/LC_MESSAGES/messages.po180
-rw-r--r--fietsboek/locale/fietslog.pot126
-rw-r--r--fietsboek/security.py30
-rw-r--r--fietsboek/templates/login.jinja210
-rw-r--r--fietsboek/views/default.py11
9 files changed, 298 insertions, 242 deletions
diff --git a/fietsboek/__init__.py b/fietsboek/__init__.py
index a248dc9..d45e9d5 100644
--- a/fietsboek/__init__.py
+++ b/fietsboek/__init__.py
@@ -73,6 +73,7 @@ def main(_global_config, **settings):
return page_manager
my_session_factory = SignedCookieSessionFactory(parsed_config.derive_secret("sessions"))
+ cookie_secret = parsed_config.derive_secret("auth-cookie")
with Configurator(settings=settings) as config:
config.include("pyramid_jinja2")
config.include(".routes")
@@ -82,7 +83,7 @@ def main(_global_config, **settings):
for pack in parsed_config.language_packs:
config.add_translation_dirs(f"{pack}:locale/")
config.set_session_factory(my_session_factory)
- config.set_security_policy(SecurityPolicy())
+ config.set_security_policy(SecurityPolicy(cookie_secret))
config.set_csrf_storage_policy(CookieCSRFStoragePolicy())
config.set_default_csrf_options(require_csrf=True)
config.set_locale_negotiator(locale_negotiator)
diff --git a/fietsboek/locale/de/LC_MESSAGES/messages.mo b/fietsboek/locale/de/LC_MESSAGES/messages.mo
index 7efce7f..7092994 100644
--- a/fietsboek/locale/de/LC_MESSAGES/messages.mo
+++ b/fietsboek/locale/de/LC_MESSAGES/messages.mo
Binary files differ
diff --git a/fietsboek/locale/de/LC_MESSAGES/messages.po b/fietsboek/locale/de/LC_MESSAGES/messages.po
index f4a7f03..dfa2bed 100644
--- a/fietsboek/locale/de/LC_MESSAGES/messages.po
+++ b/fietsboek/locale/de/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: 2022-08-10 13:36+0200\n"
+"POT-Creation-Date: 2022-12-10 17:37+0100\n"
"PO-Revision-Date: 2022-07-02 17:35+0200\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language: de\n"
@@ -16,41 +16,41 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"Generated-By: Babel 2.10.3\n"
+"Generated-By: Babel 2.11.0\n"
-#: fietsboek/util.py:282
+#: fietsboek/util.py:274
msgid "password_constraint.mismatch"
msgstr "Passwörter stimmen nicht überein"
-#: fietsboek/util.py:284
+#: fietsboek/util.py:276
msgid "password_constraint.length"
msgstr "Passwort zu kurz"
-#: fietsboek/models/track.py:526
+#: fietsboek/models/track.py:543
msgid "tooltip.table.length"
msgstr "Länge"
-#: fietsboek/models/track.py:527
+#: fietsboek/models/track.py:544
msgid "tooltip.table.uphill"
msgstr "Bergauf"
-#: fietsboek/models/track.py:528
+#: fietsboek/models/track.py:545
msgid "tooltip.table.downhill"
msgstr "Bergab"
-#: fietsboek/models/track.py:529
+#: fietsboek/models/track.py:546
msgid "tooltip.table.moving_time"
msgstr "Fahrzeit"
-#: fietsboek/models/track.py:530
+#: fietsboek/models/track.py:547
msgid "tooltip.table.stopped_time"
msgstr "Haltezeit"
-#: fietsboek/models/track.py:531
+#: fietsboek/models/track.py:549
msgid "tooltip.table.max_speed"
msgstr "Maximalgeschwindigkeit"
-#: fietsboek/models/track.py:533
+#: fietsboek/models/track.py:553
msgid "tooltip.table.avg_speed"
msgstr "Durchschnittsgeschwindigkeit"
@@ -154,43 +154,43 @@ msgstr "Dies ist eine Aufnahme einer Strecke"
msgid "page.browse.synthetic_tooltip"
msgstr "Dies ist eine geplante Strecke"
-#: fietsboek/templates/browse.jinja2:132 fietsboek/templates/details.jinja2:88
+#: fietsboek/templates/browse.jinja2:132 fietsboek/templates/details.jinja2:90
msgid "page.details.date"
msgstr "Datum"
-#: fietsboek/templates/browse.jinja2:134 fietsboek/templates/details.jinja2:102
+#: fietsboek/templates/browse.jinja2:134 fietsboek/templates/details.jinja2:104
msgid "page.details.length"
msgstr "Länge"
-#: fietsboek/templates/browse.jinja2:139 fietsboek/templates/details.jinja2:93
+#: fietsboek/templates/browse.jinja2:139 fietsboek/templates/details.jinja2:95
msgid "page.details.start_time"
msgstr "Startzeit"
-#: fietsboek/templates/browse.jinja2:141 fietsboek/templates/details.jinja2:97
+#: fietsboek/templates/browse.jinja2:141 fietsboek/templates/details.jinja2:99
msgid "page.details.end_time"
msgstr "Endzeit"
-#: fietsboek/templates/browse.jinja2:146 fietsboek/templates/details.jinja2:106
+#: fietsboek/templates/browse.jinja2:146 fietsboek/templates/details.jinja2:108
msgid "page.details.uphill"
msgstr "Bergauf"
-#: fietsboek/templates/browse.jinja2:148 fietsboek/templates/details.jinja2:110
+#: fietsboek/templates/browse.jinja2:148 fietsboek/templates/details.jinja2:112
msgid "page.details.downhill"
msgstr "Bergab"
-#: fietsboek/templates/browse.jinja2:153 fietsboek/templates/details.jinja2:115
+#: fietsboek/templates/browse.jinja2:153 fietsboek/templates/details.jinja2:117
msgid "page.details.moving_time"
msgstr "Fahrzeit"
-#: fietsboek/templates/browse.jinja2:155 fietsboek/templates/details.jinja2:119
+#: fietsboek/templates/browse.jinja2:155 fietsboek/templates/details.jinja2:121
msgid "page.details.stopped_time"
msgstr "Haltezeit"
-#: fietsboek/templates/browse.jinja2:159 fietsboek/templates/details.jinja2:123
+#: fietsboek/templates/browse.jinja2:159 fietsboek/templates/details.jinja2:125
msgid "page.details.max_speed"
msgstr "maximale Geschwindigkeit"
-#: fietsboek/templates/browse.jinja2:161 fietsboek/templates/details.jinja2:127
+#: fietsboek/templates/browse.jinja2:161 fietsboek/templates/details.jinja2:129
msgid "page.details.avg_speed"
msgstr "durchschnittliche Geschwindigkeit"
@@ -208,43 +208,43 @@ msgstr ""
"Es wurden keine Strecken gefunden, auf die Du Zugriff hast. Versuche, "
"Dich anzumelden."
-#: fietsboek/templates/create_account.jinja2:4
+#: fietsboek/templates/create_account.jinja2:5
msgid "page.create_account.title"
msgstr "Konto Erstellen"
-#: fietsboek/templates/create_account.jinja2:11
+#: fietsboek/templates/create_account.jinja2:13
msgid "page.create_account.email_invalid"
msgstr "E-Mail-Adresse ungültig"
-#: fietsboek/templates/create_account.jinja2:13
+#: fietsboek/templates/create_account.jinja2:15
msgid "page.create_account.email"
msgstr "E-Mail-Adresse"
-#: fietsboek/templates/create_account.jinja2:22
+#: fietsboek/templates/create_account.jinja2:24
msgid "page.create_account.name_invalid"
msgstr "Name ungültig"
-#: fietsboek/templates/create_account.jinja2:24
+#: fietsboek/templates/create_account.jinja2:26
msgid "page.create_account.name"
msgstr "Name"
-#: fietsboek/templates/create_account.jinja2:33
+#: fietsboek/templates/create_account.jinja2:35
msgid "page.create_account.password_invalid"
msgstr "Password zu kurz"
-#: fietsboek/templates/create_account.jinja2:35
+#: fietsboek/templates/create_account.jinja2:37
msgid "page.create_account.password"
msgstr "Passwort"
-#: fietsboek/templates/create_account.jinja2:44
+#: fietsboek/templates/create_account.jinja2:46
msgid "page.create_account.password_must_match"
msgstr "Passwörter stimmen nicht überein"
-#: fietsboek/templates/create_account.jinja2:46
+#: fietsboek/templates/create_account.jinja2:48
msgid "page.create_account.repeat_password"
msgstr "Passwort wiederholen"
-#: fietsboek/templates/create_account.jinja2:52
+#: fietsboek/templates/create_account.jinja2:54
msgid "page.create_account.create"
msgstr "Erstellen"
@@ -296,42 +296,42 @@ msgstr "Löschen"
msgid "page.details.delete.close"
msgstr "Abbrechen"
-#: fietsboek/templates/details.jinja2:69
+#: fietsboek/templates/details.jinja2:70
msgid "page.details.tags"
msgstr "Schlagwörter"
-#: fietsboek/templates/details.jinja2:78 fietsboek/templates/edit.jinja2:10
+#: fietsboek/templates/details.jinja2:80 fietsboek/templates/edit.jinja2:10
#: fietsboek/templates/finish_upload.jinja2:10
msgid "page.noscript"
msgstr ""
"JavaScript ist deaktiviert, zum Nutzen aller Funktionen bitte JavaScript "
"aktivieren"
-#: fietsboek/templates/details.jinja2:83
+#: fietsboek/templates/details.jinja2:85
msgid "page.details.download"
msgstr "Herunterladen"
-#: fietsboek/templates/details.jinja2:172
+#: fietsboek/templates/details.jinja2:174
msgid "page.details.comments"
msgstr "Kommentare"
-#: fietsboek/templates/details.jinja2:176
+#: fietsboek/templates/details.jinja2:178
msgid "page.details.comments.author"
msgstr "Kommentar von {}"
-#: fietsboek/templates/details.jinja2:193
+#: fietsboek/templates/details.jinja2:195
msgid "page.details.comments.new.title"
msgstr "Kommentar erstellen"
-#: fietsboek/templates/details.jinja2:196
+#: fietsboek/templates/details.jinja2:198
msgid "page.details.comments.new.input_title"
msgstr "Titel"
-#: fietsboek/templates/details.jinja2:197
+#: fietsboek/templates/details.jinja2:199
msgid "page.details.comments.new.input_comment"
msgstr "Kommentar"
-#: fietsboek/templates/details.jinja2:200
+#: fietsboek/templates/details.jinja2:202
msgid "page.details.comments.new.submit"
msgstr "Absenden"
@@ -401,40 +401,40 @@ msgstr "Vorlage (synthetisch)"
msgid "page.track.form.tags"
msgstr "Schlagwörter"
-#: fietsboek/templates/edit_form.jinja2:43
+#: fietsboek/templates/edit_form.jinja2:50
msgid "page.track.form.add_tag"
msgstr "Schlagwort hinzufügen"
-#: fietsboek/templates/edit_form.jinja2:48
+#: fietsboek/templates/edit_form.jinja2:55
msgid "page.track.form.tagged_people"
msgstr "Markierte Personen"
-#: fietsboek/templates/edit_form.jinja2:63
+#: fietsboek/templates/edit_form.jinja2:70
msgid "page.track.form.add_friend"
msgstr "Freund suchen"
-#: fietsboek/templates/edit_form.jinja2:83
+#: fietsboek/templates/edit_form.jinja2:90
msgid "page.track.form.badges"
msgstr "Wappen"
-#: fietsboek/templates/edit_form.jinja2:94
+#: fietsboek/templates/edit_form.jinja2:101
msgid "page.track.form.description"
msgstr "Beschreibung"
-#: fietsboek/templates/edit_form.jinja2:101
-#: fietsboek/templates/edit_form.jinja2:115
+#: fietsboek/templates/edit_form.jinja2:108
+#: fietsboek/templates/edit_form.jinja2:122
msgid "page.track.form.remove_image"
msgstr "Bild entfernen"
-#: fietsboek/templates/edit_form.jinja2:110
+#: fietsboek/templates/edit_form.jinja2:117
msgid "page.track.form.select_images"
msgstr "Bilder auswählen"
-#: fietsboek/templates/edit_form.jinja2:126
+#: fietsboek/templates/edit_form.jinja2:133
msgid "page.track.form.image_description_modal"
msgstr "Bildbeschreibung"
-#: fietsboek/templates/edit_form.jinja2:133
+#: fietsboek/templates/edit_form.jinja2:140
msgid "page.track.form.image_description_modal.save"
msgstr "Übernehmen"
@@ -460,7 +460,7 @@ msgstr "Startseite"
msgid "page.home.total"
msgstr "Gesamt"
-#: fietsboek/templates/layout.jinja2:40
+#: fietsboek/templates/layout.jinja2:35
msgid "page.navbar.toggle"
msgstr "Navigation umschalten"
@@ -476,31 +476,31 @@ msgstr "Stöbern"
msgid "page.navbar.upload"
msgstr "Hochladen"
-#: fietsboek/templates/layout.jinja2:57
+#: fietsboek/templates/layout.jinja2:62
msgid "page.navbar.user"
msgstr "Nutzer"
-#: fietsboek/templates/layout.jinja2:61
+#: fietsboek/templates/layout.jinja2:66
msgid "page.navbar.welcome_user"
msgstr "Willkommen, {}!"
-#: fietsboek/templates/layout.jinja2:64
+#: fietsboek/templates/layout.jinja2:69
msgid "page.navbar.logout"
msgstr "Abmelden"
-#: fietsboek/templates/layout.jinja2:67
+#: fietsboek/templates/layout.jinja2:72
msgid "page.navbar.profile"
msgstr "Profil"
-#: fietsboek/templates/layout.jinja2:71
+#: fietsboek/templates/layout.jinja2:76
msgid "page.navbar.admin"
msgstr "Admin"
-#: fietsboek/templates/layout.jinja2:77
+#: fietsboek/templates/layout.jinja2:82
msgid "page.navbar.login"
msgstr "Anmelden"
-#: fietsboek/templates/layout.jinja2:81
+#: fietsboek/templates/layout.jinja2:86
msgid "page.navbar.create_account"
msgstr "Konto Erstellen"
@@ -516,11 +516,15 @@ msgstr "E-Mail-Adresse"
msgid "page.login.password"
msgstr "Passwort"
-#: fietsboek/templates/login.jinja2:28
+#: fietsboek/templates/login.jinja2:30
+msgid "page.login.remember-me"
+msgstr "Eingeloggt bleiben"
+
+#: fietsboek/templates/login.jinja2:38
msgid "page.login.submit"
msgstr "Anmelden"
-#: fietsboek/templates/login.jinja2:33
+#: fietsboek/templates/login.jinja2:43
msgid "page.login.forgot_password"
msgstr "Passwort vergessen"
@@ -622,70 +626,70 @@ msgstr "Anfrage senden"
msgid "page.upload.form.gpx"
msgstr "GPX Datei"
-#: fietsboek/views/account.py:48
+#: fietsboek/views/account.py:54
msgid "flash.invalid_name"
msgstr "Ungültiger Name"
-#: fietsboek/views/account.py:53
+#: fietsboek/views/account.py:59
msgid "flash.invalid_email"
msgstr "Ungültige E-Mail-Adresse"
-#: fietsboek/views/account.py:66
+#: fietsboek/views/account.py:72
msgid "email.verify_mail.subject"
msgstr "Fietsboek Konto Bestätigung"
-#: fietsboek/views/account.py:68
+#: fietsboek/views/account.py:75
msgid "email.verify.text"
msgstr ""
"Um Dein Fietsboek-Konto zu bestätigen, nutze diesen Link: {}\n"
"\n"
"Falls Du kein Konto angelegt hast, ignoriere diese E-Mail."
-#: fietsboek/views/account.py:72
+#: fietsboek/views/account.py:86
msgid "flash.a_confirmation_link_has_been_sent"
msgstr "Ein Bestätigungslink wurde versandt"
-#: fietsboek/views/admin.py:45
+#: fietsboek/views/admin.py:49
msgid "flash.badge_added"
msgstr "Wappen hinzugefügt"
-#: fietsboek/views/admin.py:69
+#: fietsboek/views/admin.py:73
msgid "flash.badge_modified"
msgstr "Wappen bearbeitet"
-#: fietsboek/views/admin.py:89
+#: fietsboek/views/admin.py:93
msgid "flash.badge_deleted"
msgstr "Wappen gelöscht"
-#: fietsboek/views/default.py:75
+#: fietsboek/views/default.py:114
msgid "flash.invalid_credentials"
msgstr "Ungültige Nutzerdaten"
-#: fietsboek/views/default.py:79
+#: fietsboek/views/default.py:118
msgid "flash.account_not_verified"
msgstr "Konto noch nicht bestätigt"
-#: fietsboek/views/default.py:82
+#: fietsboek/views/default.py:121
msgid "flash.logged_in"
msgstr "Du bist nun angemeldet"
-#: fietsboek/views/default.py:96
+#: fietsboek/views/default.py:143
msgid "flash.logged_out"
msgstr "Du bist nun abgemeldet"
-#: fietsboek/views/default.py:127
+#: fietsboek/views/default.py:177
msgid "flash.reset_invalid_email"
msgstr "Ungültige E-Mail-Adresse angegeben"
-#: fietsboek/views/default.py:132
+#: fietsboek/views/default.py:182
msgid "flash.password_token_generated"
msgstr "Ein Link zum Zurücksetzen des Passworts wurde versandt"
-#: fietsboek/views/default.py:137
+#: fietsboek/views/default.py:187
msgid "page.password_reset.email.subject"
msgstr "Fietsboek Passwortzurücksetzung"
-#: fietsboek/views/default.py:141
+#: fietsboek/views/default.py:190
msgid "page.password_reset.email.body"
msgstr ""
"Du kannst Dein Fietsboek-Passwort hier zurücksetzen: {}\n"
@@ -693,51 +697,51 @@ msgstr ""
"Falls Du keine Passwortzurücksetzung beantragt hast, dann ignoriere diese"
" E-Mail."
-#: fietsboek/views/default.py:168
+#: fietsboek/views/default.py:223
msgid "flash.email_verified"
msgstr "E-Mail-Adresse bestätigt"
-#: fietsboek/views/default.py:182
+#: fietsboek/views/default.py:237
msgid "flash.password_updated"
msgstr "Passwort aktualisiert"
-#: fietsboek/views/detail.py:94
+#: fietsboek/views/detail.py:101
msgid "flash.track_deleted"
msgstr "Strecke gelöscht"
-#: fietsboek/views/profile.py:57
+#: fietsboek/views/profile.py:61
msgid "flash.personal_data_updated"
msgstr "Persönliche Daten wurden gespeichert"
-#: fietsboek/views/profile.py:77
+#: fietsboek/views/profile.py:79
msgid "flash.friend_not_found"
msgstr "Das angegebene Konto wurde nicht gefunden"
-#: fietsboek/views/profile.py:82
+#: fietsboek/views/profile.py:85
msgid "flash.friend_already_exists"
msgstr "Dieser Freund existiert bereits"
-#: fietsboek/views/profile.py:90
+#: fietsboek/views/profile.py:93
msgid "flash.friend_added"
msgstr "Freund hinzugefügt"
-#: fietsboek/views/profile.py:100
+#: fietsboek/views/profile.py:103
msgid "flash.friend_request_sent"
msgstr "Freundschaftsanfrage gesendet"
-#: fietsboek/views/upload.py:52
+#: fietsboek/views/upload.py:56
msgid "flash.no_file_selected"
msgstr "Keine Datei ausgewählt"
-#: fietsboek/views/upload.py:62
+#: fietsboek/views/upload.py:66
msgid "flash.invalid_file"
msgstr "Ungültige GPX-Datei gesendet"
-#: fietsboek/views/upload.py:179
+#: fietsboek/views/upload.py:189
msgid "flash.upload_success"
msgstr "Hochladen erfolgreich"
-#: fietsboek/views/upload.py:195
+#: fietsboek/views/upload.py:205
msgid "flash.upload_cancelled"
msgstr "Hochladen abgebrochen"
diff --git a/fietsboek/locale/en/LC_MESSAGES/messages.mo b/fietsboek/locale/en/LC_MESSAGES/messages.mo
index ee23eef..7827a62 100644
--- a/fietsboek/locale/en/LC_MESSAGES/messages.mo
+++ b/fietsboek/locale/en/LC_MESSAGES/messages.mo
Binary files differ
diff --git a/fietsboek/locale/en/LC_MESSAGES/messages.po b/fietsboek/locale/en/LC_MESSAGES/messages.po
index 71c8b17..f4b0239 100644
--- a/fietsboek/locale/en/LC_MESSAGES/messages.po
+++ b/fietsboek/locale/en/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: 2022-08-10 13:36+0200\n"
+"POT-Creation-Date: 2022-12-10 17:37+0100\n"
"PO-Revision-Date: 2022-06-28 13:11+0200\n"
"Last-Translator: \n"
"Language: en\n"
@@ -16,41 +16,41 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"Generated-By: Babel 2.10.3\n"
+"Generated-By: Babel 2.11.0\n"
-#: fietsboek/util.py:282
+#: fietsboek/util.py:274
msgid "password_constraint.mismatch"
msgstr "Passwords don't match"
-#: fietsboek/util.py:284
+#: fietsboek/util.py:276
msgid "password_constraint.length"
msgstr "Password not long enough"
-#: fietsboek/models/track.py:526
+#: fietsboek/models/track.py:543
msgid "tooltip.table.length"
msgstr "Length"
-#: fietsboek/models/track.py:527
+#: fietsboek/models/track.py:544
msgid "tooltip.table.uphill"
msgstr "Uphill"
-#: fietsboek/models/track.py:528
+#: fietsboek/models/track.py:545
msgid "tooltip.table.downhill"
msgstr "Downhill"
-#: fietsboek/models/track.py:529
+#: fietsboek/models/track.py:546
msgid "tooltip.table.moving_time"
msgstr "Moving Time"
-#: fietsboek/models/track.py:530
+#: fietsboek/models/track.py:547
msgid "tooltip.table.stopped_time"
msgstr "Stopped Time"
-#: fietsboek/models/track.py:531
+#: fietsboek/models/track.py:549
msgid "tooltip.table.max_speed"
msgstr "Max Speed"
-#: fietsboek/models/track.py:533
+#: fietsboek/models/track.py:553
msgid "tooltip.table.avg_speed"
msgstr "Average Speed"
@@ -154,43 +154,43 @@ msgstr "This is a recording of a track"
msgid "page.browse.synthetic_tooltip"
msgstr "This is a pre-planned track"
-#: fietsboek/templates/browse.jinja2:132 fietsboek/templates/details.jinja2:88
+#: fietsboek/templates/browse.jinja2:132 fietsboek/templates/details.jinja2:90
msgid "page.details.date"
msgstr "Date"
-#: fietsboek/templates/browse.jinja2:134 fietsboek/templates/details.jinja2:102
+#: fietsboek/templates/browse.jinja2:134 fietsboek/templates/details.jinja2:104
msgid "page.details.length"
msgstr "Length"
-#: fietsboek/templates/browse.jinja2:139 fietsboek/templates/details.jinja2:93
+#: fietsboek/templates/browse.jinja2:139 fietsboek/templates/details.jinja2:95
msgid "page.details.start_time"
msgstr "Record Start"
-#: fietsboek/templates/browse.jinja2:141 fietsboek/templates/details.jinja2:97
+#: fietsboek/templates/browse.jinja2:141 fietsboek/templates/details.jinja2:99
msgid "page.details.end_time"
msgstr "Record End"
-#: fietsboek/templates/browse.jinja2:146 fietsboek/templates/details.jinja2:106
+#: fietsboek/templates/browse.jinja2:146 fietsboek/templates/details.jinja2:108
msgid "page.details.uphill"
msgstr "Uphill"
-#: fietsboek/templates/browse.jinja2:148 fietsboek/templates/details.jinja2:110
+#: fietsboek/templates/browse.jinja2:148 fietsboek/templates/details.jinja2:112
msgid "page.details.downhill"
msgstr "Downhill"
-#: fietsboek/templates/browse.jinja2:153 fietsboek/templates/details.jinja2:115
+#: fietsboek/templates/browse.jinja2:153 fietsboek/templates/details.jinja2:117
msgid "page.details.moving_time"
msgstr "Moving Time"
-#: fietsboek/templates/browse.jinja2:155 fietsboek/templates/details.jinja2:119
+#: fietsboek/templates/browse.jinja2:155 fietsboek/templates/details.jinja2:121
msgid "page.details.stopped_time"
msgstr "Stopped Time"
-#: fietsboek/templates/browse.jinja2:159 fietsboek/templates/details.jinja2:123
+#: fietsboek/templates/browse.jinja2:159 fietsboek/templates/details.jinja2:125
msgid "page.details.max_speed"
msgstr "Max Speed"
-#: fietsboek/templates/browse.jinja2:161 fietsboek/templates/details.jinja2:127
+#: fietsboek/templates/browse.jinja2:161 fietsboek/templates/details.jinja2:129
msgid "page.details.avg_speed"
msgstr "Average Speed"
@@ -206,43 +206,43 @@ msgstr "No results matching the filters were found."
msgid "page.browse.no_tracks"
msgstr "You currently do not have access to any tracks. Try logging in."
-#: fietsboek/templates/create_account.jinja2:4
+#: fietsboek/templates/create_account.jinja2:5
msgid "page.create_account.title"
msgstr "Create Account"
-#: fietsboek/templates/create_account.jinja2:11
+#: fietsboek/templates/create_account.jinja2:13
msgid "page.create_account.email_invalid"
msgstr "Invalid email address"
-#: fietsboek/templates/create_account.jinja2:13
+#: fietsboek/templates/create_account.jinja2:15
msgid "page.create_account.email"
msgstr "E-Mail"
-#: fietsboek/templates/create_account.jinja2:22
+#: fietsboek/templates/create_account.jinja2:24
msgid "page.create_account.name_invalid"
msgstr "Name invalid"
-#: fietsboek/templates/create_account.jinja2:24
+#: fietsboek/templates/create_account.jinja2:26
msgid "page.create_account.name"
msgstr "Name"
-#: fietsboek/templates/create_account.jinja2:33
+#: fietsboek/templates/create_account.jinja2:35
msgid "page.create_account.password_invalid"
msgstr "Password not long enough"
-#: fietsboek/templates/create_account.jinja2:35
+#: fietsboek/templates/create_account.jinja2:37
msgid "page.create_account.password"
msgstr "Password"
-#: fietsboek/templates/create_account.jinja2:44
+#: fietsboek/templates/create_account.jinja2:46
msgid "page.create_account.password_must_match"
msgstr "Passwords must match"
-#: fietsboek/templates/create_account.jinja2:46
+#: fietsboek/templates/create_account.jinja2:48
msgid "page.create_account.repeat_password"
msgstr "Repeat password"
-#: fietsboek/templates/create_account.jinja2:52
+#: fietsboek/templates/create_account.jinja2:54
msgid "page.create_account.create"
msgstr "Create"
@@ -294,40 +294,40 @@ msgstr "Delete"
msgid "page.details.delete.close"
msgstr "Abort"
-#: fietsboek/templates/details.jinja2:69
+#: fietsboek/templates/details.jinja2:70
msgid "page.details.tags"
msgstr "Tagged as"
-#: fietsboek/templates/details.jinja2:78 fietsboek/templates/edit.jinja2:10
+#: fietsboek/templates/details.jinja2:80 fietsboek/templates/edit.jinja2:10
#: fietsboek/templates/finish_upload.jinja2:10
msgid "page.noscript"
msgstr "JavaScript is disabled, please enable JavaScript"
-#: fietsboek/templates/details.jinja2:83
+#: fietsboek/templates/details.jinja2:85
msgid "page.details.download"
msgstr "Download Tour"
-#: fietsboek/templates/details.jinja2:172
+#: fietsboek/templates/details.jinja2:174
msgid "page.details.comments"
msgstr "Comments"
-#: fietsboek/templates/details.jinja2:176
+#: fietsboek/templates/details.jinja2:178
msgid "page.details.comments.author"
msgstr "Comment by {}"
-#: fietsboek/templates/details.jinja2:193
+#: fietsboek/templates/details.jinja2:195
msgid "page.details.comments.new.title"
msgstr "Create a new comment"
-#: fietsboek/templates/details.jinja2:196
+#: fietsboek/templates/details.jinja2:198
msgid "page.details.comments.new.input_title"
msgstr "Title"
-#: fietsboek/templates/details.jinja2:197
+#: fietsboek/templates/details.jinja2:199
msgid "page.details.comments.new.input_comment"
msgstr "Comment"
-#: fietsboek/templates/details.jinja2:200
+#: fietsboek/templates/details.jinja2:202
msgid "page.details.comments.new.submit"
msgstr "Submit"
@@ -397,40 +397,40 @@ msgstr "Template (synthetic)"
msgid "page.track.form.tags"
msgstr "Tags"
-#: fietsboek/templates/edit_form.jinja2:43
+#: fietsboek/templates/edit_form.jinja2:50
msgid "page.track.form.add_tag"
msgstr "Add Tag"
-#: fietsboek/templates/edit_form.jinja2:48
+#: fietsboek/templates/edit_form.jinja2:55
msgid "page.track.form.tagged_people"
msgstr "Tagged People"
-#: fietsboek/templates/edit_form.jinja2:63
+#: fietsboek/templates/edit_form.jinja2:70
msgid "page.track.form.add_friend"
msgstr "Search friends"
-#: fietsboek/templates/edit_form.jinja2:83
+#: fietsboek/templates/edit_form.jinja2:90
msgid "page.track.form.badges"
msgstr "Badges"
-#: fietsboek/templates/edit_form.jinja2:94
+#: fietsboek/templates/edit_form.jinja2:101
msgid "page.track.form.description"
msgstr "Description"
-#: fietsboek/templates/edit_form.jinja2:101
-#: fietsboek/templates/edit_form.jinja2:115
+#: fietsboek/templates/edit_form.jinja2:108
+#: fietsboek/templates/edit_form.jinja2:122
msgid "page.track.form.remove_image"
msgstr "Remove image"
-#: fietsboek/templates/edit_form.jinja2:110
+#: fietsboek/templates/edit_form.jinja2:117
msgid "page.track.form.select_images"
msgstr "Select images"
-#: fietsboek/templates/edit_form.jinja2:126
+#: fietsboek/templates/edit_form.jinja2:133
msgid "page.track.form.image_description_modal"
msgstr "Image description"
-#: fietsboek/templates/edit_form.jinja2:133
+#: fietsboek/templates/edit_form.jinja2:140
msgid "page.track.form.image_description_modal.save"
msgstr "Apply"
@@ -456,7 +456,7 @@ msgstr "Home"
msgid "page.home.total"
msgstr "Total"
-#: fietsboek/templates/layout.jinja2:40
+#: fietsboek/templates/layout.jinja2:35
msgid "page.navbar.toggle"
msgstr "Toggle navigation"
@@ -472,31 +472,31 @@ msgstr "Browse"
msgid "page.navbar.upload"
msgstr "Upload"
-#: fietsboek/templates/layout.jinja2:57
+#: fietsboek/templates/layout.jinja2:62
msgid "page.navbar.user"
msgstr "User"
-#: fietsboek/templates/layout.jinja2:61
+#: fietsboek/templates/layout.jinja2:66
msgid "page.navbar.welcome_user"
msgstr "Welcome, {}!"
-#: fietsboek/templates/layout.jinja2:64
+#: fietsboek/templates/layout.jinja2:69
msgid "page.navbar.logout"
msgstr "Logout"
-#: fietsboek/templates/layout.jinja2:67
+#: fietsboek/templates/layout.jinja2:72
msgid "page.navbar.profile"
msgstr "Profile"
-#: fietsboek/templates/layout.jinja2:71
+#: fietsboek/templates/layout.jinja2:76
msgid "page.navbar.admin"
msgstr "Admin"
-#: fietsboek/templates/layout.jinja2:77
+#: fietsboek/templates/layout.jinja2:82
msgid "page.navbar.login"
msgstr "Login"
-#: fietsboek/templates/layout.jinja2:81
+#: fietsboek/templates/layout.jinja2:86
msgid "page.navbar.create_account"
msgstr "Create Account"
@@ -512,11 +512,15 @@ msgstr "E-Mail"
msgid "page.login.password"
msgstr "Password"
-#: fietsboek/templates/login.jinja2:28
+#: fietsboek/templates/login.jinja2:30
+msgid "page.login.remember-me"
+msgstr "Remember me"
+
+#: fietsboek/templates/login.jinja2:38
msgid "page.login.submit"
msgstr "Login"
-#: fietsboek/templates/login.jinja2:33
+#: fietsboek/templates/login.jinja2:43
msgid "page.login.forgot_password"
msgstr "Forgot password"
@@ -618,121 +622,121 @@ msgstr "Send request"
msgid "page.upload.form.gpx"
msgstr "GPX file"
-#: fietsboek/views/account.py:48
+#: fietsboek/views/account.py:54
msgid "flash.invalid_name"
msgstr "Invalid name"
-#: fietsboek/views/account.py:53
+#: fietsboek/views/account.py:59
msgid "flash.invalid_email"
msgstr "Invalid email"
-#: fietsboek/views/account.py:66
+#: fietsboek/views/account.py:72
msgid "email.verify_mail.subject"
msgstr "Fietsboek Account Verification"
-#: fietsboek/views/account.py:68
+#: fietsboek/views/account.py:75
msgid "email.verify.text"
msgstr ""
"To verify your Fietsboek account, please use this link: {}\n"
"\n"
"If you did not create an account, ignore this email."
-#: fietsboek/views/account.py:72
+#: fietsboek/views/account.py:86
msgid "flash.a_confirmation_link_has_been_sent"
msgstr "A confirmation link has been sent"
-#: fietsboek/views/admin.py:45
+#: fietsboek/views/admin.py:49
msgid "flash.badge_added"
msgstr "Badge has been added"
-#: fietsboek/views/admin.py:69
+#: fietsboek/views/admin.py:73
msgid "flash.badge_modified"
msgstr "Badge has been modified"
-#: fietsboek/views/admin.py:89
+#: fietsboek/views/admin.py:93
msgid "flash.badge_deleted"
msgstr "Badge has been deleted"
-#: fietsboek/views/default.py:75
+#: fietsboek/views/default.py:114
msgid "flash.invalid_credentials"
msgstr "Invalid login credentials"
-#: fietsboek/views/default.py:79
+#: fietsboek/views/default.py:118
msgid "flash.account_not_verified"
msgstr "Your account is not verified yet"
-#: fietsboek/views/default.py:82
+#: fietsboek/views/default.py:121
msgid "flash.logged_in"
msgstr "You are now logged in"
-#: fietsboek/views/default.py:96
+#: fietsboek/views/default.py:143
msgid "flash.logged_out"
msgstr "You have been logged out"
-#: fietsboek/views/default.py:127
+#: fietsboek/views/default.py:177
msgid "flash.reset_invalid_email"
msgstr "Invalid email address provided"
-#: fietsboek/views/default.py:132
+#: fietsboek/views/default.py:182
msgid "flash.password_token_generated"
msgstr "A password reset email has been sent"
-#: fietsboek/views/default.py:137
+#: fietsboek/views/default.py:187
msgid "page.password_reset.email.subject"
msgstr "Fietsboek Password Reset"
-#: fietsboek/views/default.py:141
+#: fietsboek/views/default.py:190
msgid "page.password_reset.email.body"
msgstr ""
"You can reset your Fietsboek password here: {}\n"
"\n"
"If you did not request a password reset, ignore this email."
-#: fietsboek/views/default.py:168
+#: fietsboek/views/default.py:223
msgid "flash.email_verified"
msgstr "Your email address has been verified"
-#: fietsboek/views/default.py:182
+#: fietsboek/views/default.py:237
msgid "flash.password_updated"
msgstr "Password has been updated"
-#: fietsboek/views/detail.py:94
+#: fietsboek/views/detail.py:101
msgid "flash.track_deleted"
msgstr "Track has been deleted"
-#: fietsboek/views/profile.py:57
+#: fietsboek/views/profile.py:61
msgid "flash.personal_data_updated"
msgstr "Personal data has been updated"
-#: fietsboek/views/profile.py:77
+#: fietsboek/views/profile.py:79
msgid "flash.friend_not_found"
msgstr "The friend was not found"
-#: fietsboek/views/profile.py:82
+#: fietsboek/views/profile.py:85
msgid "flash.friend_already_exists"
msgstr "Friend already exists"
-#: fietsboek/views/profile.py:90
+#: fietsboek/views/profile.py:93
msgid "flash.friend_added"
msgstr "Friend has been added"
-#: fietsboek/views/profile.py:100
+#: fietsboek/views/profile.py:103
msgid "flash.friend_request_sent"
msgstr "Friend request sent"
-#: fietsboek/views/upload.py:52
+#: fietsboek/views/upload.py:56
msgid "flash.no_file_selected"
msgstr "No file selected"
-#: fietsboek/views/upload.py:62
+#: fietsboek/views/upload.py:66
msgid "flash.invalid_file"
msgstr "Invalid GPX file selected"
-#: fietsboek/views/upload.py:179
+#: fietsboek/views/upload.py:189
msgid "flash.upload_success"
msgstr "Upload successful"
-#: fietsboek/views/upload.py:195
+#: fietsboek/views/upload.py:205
msgid "flash.upload_cancelled"
msgstr "Upload cancelled"
diff --git a/fietsboek/locale/fietslog.pot b/fietsboek/locale/fietslog.pot
index abb2bfc..a86c43b 100644
--- a/fietsboek/locale/fietslog.pot
+++ b/fietsboek/locale/fietslog.pot
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PROJECT VERSION\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
-"POT-Creation-Date: 2022-11-15 23:42+0100\n"
+"POT-Creation-Date: 2022-12-10 17:37+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -17,39 +17,39 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.11.0\n"
-#: fietsboek/util.py:282
+#: fietsboek/util.py:274
msgid "password_constraint.mismatch"
msgstr ""
-#: fietsboek/util.py:284
+#: fietsboek/util.py:276
msgid "password_constraint.length"
msgstr ""
-#: fietsboek/models/track.py:526
+#: fietsboek/models/track.py:543
msgid "tooltip.table.length"
msgstr ""
-#: fietsboek/models/track.py:527
+#: fietsboek/models/track.py:544
msgid "tooltip.table.uphill"
msgstr ""
-#: fietsboek/models/track.py:528
+#: fietsboek/models/track.py:545
msgid "tooltip.table.downhill"
msgstr ""
-#: fietsboek/models/track.py:529
+#: fietsboek/models/track.py:546
msgid "tooltip.table.moving_time"
msgstr ""
-#: fietsboek/models/track.py:530
+#: fietsboek/models/track.py:547
msgid "tooltip.table.stopped_time"
msgstr ""
-#: fietsboek/models/track.py:531
+#: fietsboek/models/track.py:549
msgid "tooltip.table.max_speed"
msgstr ""
-#: fietsboek/models/track.py:533
+#: fietsboek/models/track.py:553
msgid "tooltip.table.avg_speed"
msgstr ""
@@ -205,43 +205,43 @@ msgstr ""
msgid "page.browse.no_tracks"
msgstr ""
-#: fietsboek/templates/create_account.jinja2:4
+#: fietsboek/templates/create_account.jinja2:5
msgid "page.create_account.title"
msgstr ""
-#: fietsboek/templates/create_account.jinja2:11
+#: fietsboek/templates/create_account.jinja2:13
msgid "page.create_account.email_invalid"
msgstr ""
-#: fietsboek/templates/create_account.jinja2:13
+#: fietsboek/templates/create_account.jinja2:15
msgid "page.create_account.email"
msgstr ""
-#: fietsboek/templates/create_account.jinja2:22
+#: fietsboek/templates/create_account.jinja2:24
msgid "page.create_account.name_invalid"
msgstr ""
-#: fietsboek/templates/create_account.jinja2:24
+#: fietsboek/templates/create_account.jinja2:26
msgid "page.create_account.name"
msgstr ""
-#: fietsboek/templates/create_account.jinja2:33
+#: fietsboek/templates/create_account.jinja2:35
msgid "page.create_account.password_invalid"
msgstr ""
-#: fietsboek/templates/create_account.jinja2:35
+#: fietsboek/templates/create_account.jinja2:37
msgid "page.create_account.password"
msgstr ""
-#: fietsboek/templates/create_account.jinja2:44
+#: fietsboek/templates/create_account.jinja2:46
msgid "page.create_account.password_must_match"
msgstr ""
-#: fietsboek/templates/create_account.jinja2:46
+#: fietsboek/templates/create_account.jinja2:48
msgid "page.create_account.repeat_password"
msgstr ""
-#: fietsboek/templates/create_account.jinja2:52
+#: fietsboek/templates/create_account.jinja2:54
msgid "page.create_account.create"
msgstr ""
@@ -453,47 +453,47 @@ msgstr ""
msgid "page.home.total"
msgstr ""
-#: fietsboek/templates/layout.jinja2:40
+#: fietsboek/templates/layout.jinja2:35
msgid "page.navbar.toggle"
msgstr ""
-#: fietsboek/templates/layout.jinja2:51
+#: fietsboek/templates/layout.jinja2:46
msgid "page.navbar.home"
msgstr ""
-#: fietsboek/templates/layout.jinja2:54
+#: fietsboek/templates/layout.jinja2:49
msgid "page.navbar.browse"
msgstr ""
-#: fietsboek/templates/layout.jinja2:58
+#: fietsboek/templates/layout.jinja2:53
msgid "page.navbar.upload"
msgstr ""
-#: fietsboek/templates/layout.jinja2:67
+#: fietsboek/templates/layout.jinja2:62
msgid "page.navbar.user"
msgstr ""
-#: fietsboek/templates/layout.jinja2:71
+#: fietsboek/templates/layout.jinja2:66
msgid "page.navbar.welcome_user"
msgstr ""
-#: fietsboek/templates/layout.jinja2:74
+#: fietsboek/templates/layout.jinja2:69
msgid "page.navbar.logout"
msgstr ""
-#: fietsboek/templates/layout.jinja2:77
+#: fietsboek/templates/layout.jinja2:72
msgid "page.navbar.profile"
msgstr ""
-#: fietsboek/templates/layout.jinja2:81
+#: fietsboek/templates/layout.jinja2:76
msgid "page.navbar.admin"
msgstr ""
-#: fietsboek/templates/layout.jinja2:87
+#: fietsboek/templates/layout.jinja2:82
msgid "page.navbar.login"
msgstr ""
-#: fietsboek/templates/layout.jinja2:91
+#: fietsboek/templates/layout.jinja2:86
msgid "page.navbar.create_account"
msgstr ""
@@ -509,11 +509,15 @@ msgstr ""
msgid "page.login.password"
msgstr ""
-#: fietsboek/templates/login.jinja2:28
+#: fietsboek/templates/login.jinja2:30
+msgid "page.login.remember-me"
+msgstr ""
+
+#: fietsboek/templates/login.jinja2:38
msgid "page.login.submit"
msgstr ""
-#: fietsboek/templates/login.jinja2:33
+#: fietsboek/templates/login.jinja2:43
msgid "page.login.forgot_password"
msgstr ""
@@ -613,115 +617,115 @@ msgstr ""
msgid "page.upload.form.gpx"
msgstr ""
-#: fietsboek/views/account.py:48
+#: fietsboek/views/account.py:54
msgid "flash.invalid_name"
msgstr ""
-#: fietsboek/views/account.py:53
+#: fietsboek/views/account.py:59
msgid "flash.invalid_email"
msgstr ""
-#: fietsboek/views/account.py:66
+#: fietsboek/views/account.py:72
msgid "email.verify_mail.subject"
msgstr ""
-#: fietsboek/views/account.py:68
+#: fietsboek/views/account.py:75
msgid "email.verify.text"
msgstr ""
-#: fietsboek/views/account.py:72
+#: fietsboek/views/account.py:86
msgid "flash.a_confirmation_link_has_been_sent"
msgstr ""
-#: fietsboek/views/admin.py:45
+#: fietsboek/views/admin.py:49
msgid "flash.badge_added"
msgstr ""
-#: fietsboek/views/admin.py:69
+#: fietsboek/views/admin.py:73
msgid "flash.badge_modified"
msgstr ""
-#: fietsboek/views/admin.py:89
+#: fietsboek/views/admin.py:93
msgid "flash.badge_deleted"
msgstr ""
-#: fietsboek/views/default.py:96
+#: fietsboek/views/default.py:114
msgid "flash.invalid_credentials"
msgstr ""
-#: fietsboek/views/default.py:100
+#: fietsboek/views/default.py:118
msgid "flash.account_not_verified"
msgstr ""
-#: fietsboek/views/default.py:103
+#: fietsboek/views/default.py:121
msgid "flash.logged_in"
msgstr ""
-#: fietsboek/views/default.py:117
+#: fietsboek/views/default.py:143
msgid "flash.logged_out"
msgstr ""
-#: fietsboek/views/default.py:148
+#: fietsboek/views/default.py:177
msgid "flash.reset_invalid_email"
msgstr ""
-#: fietsboek/views/default.py:153
+#: fietsboek/views/default.py:182
msgid "flash.password_token_generated"
msgstr ""
-#: fietsboek/views/default.py:158
+#: fietsboek/views/default.py:187
msgid "page.password_reset.email.subject"
msgstr ""
-#: fietsboek/views/default.py:162
+#: fietsboek/views/default.py:190
msgid "page.password_reset.email.body"
msgstr ""
-#: fietsboek/views/default.py:189
+#: fietsboek/views/default.py:223
msgid "flash.email_verified"
msgstr ""
-#: fietsboek/views/default.py:203
+#: fietsboek/views/default.py:237
msgid "flash.password_updated"
msgstr ""
-#: fietsboek/views/detail.py:94
+#: fietsboek/views/detail.py:101
msgid "flash.track_deleted"
msgstr ""
-#: fietsboek/views/profile.py:57
+#: fietsboek/views/profile.py:61
msgid "flash.personal_data_updated"
msgstr ""
-#: fietsboek/views/profile.py:77
+#: fietsboek/views/profile.py:79
msgid "flash.friend_not_found"
msgstr ""
-#: fietsboek/views/profile.py:82
+#: fietsboek/views/profile.py:85
msgid "flash.friend_already_exists"
msgstr ""
-#: fietsboek/views/profile.py:90
+#: fietsboek/views/profile.py:93
msgid "flash.friend_added"
msgstr ""
-#: fietsboek/views/profile.py:100
+#: fietsboek/views/profile.py:103
msgid "flash.friend_request_sent"
msgstr ""
-#: fietsboek/views/upload.py:52
+#: fietsboek/views/upload.py:56
msgid "flash.no_file_selected"
msgstr ""
-#: fietsboek/views/upload.py:62
+#: fietsboek/views/upload.py:66
msgid "flash.invalid_file"
msgstr ""
-#: fietsboek/views/upload.py:179
+#: fietsboek/views/upload.py:189
msgid "flash.upload_success"
msgstr ""
-#: fietsboek/views/upload.py:195
+#: fietsboek/views/upload.py:205
msgid "flash.upload_cancelled"
msgstr ""
diff --git a/fietsboek/security.py b/fietsboek/security.py
index 84dd88a..6fbc5db 100644
--- a/fietsboek/security.py
+++ b/fietsboek/security.py
@@ -1,8 +1,10 @@
"""Module implementing the user authentication."""
from pyramid.security import Allowed, Denied
-from pyramid.authentication import SessionAuthenticationHelper
+from pyramid.authentication import SessionAuthenticationHelper, AuthTktCookieHelper
from pyramid.authorization import ACLHelper, Everyone, Authenticated
from pyramid.traversal import DefaultRootFactory
+from pyramid.interfaces import ISecurityPolicy
+from zope.interface import implementer
from sqlalchemy import select
@@ -12,16 +14,28 @@ from . import models
ADMIN_PERMISSIONS = {"admin"}
+@implementer(ISecurityPolicy)
class SecurityPolicy:
"""Implementation of the Pyramid security policy."""
- def __init__(self):
+ def __init__(self, cookie_secret):
self.helper = SessionAuthenticationHelper()
+ # The cookie_helper is used for the "Remember me" function, as the
+ # authentication set by the cookie is deliberately kept for a long long
+ # time. The session authentication on the other hand expires after the
+ # set time (by default, 15 minutes).
+ self.cookie_helper = AuthTktCookieHelper(cookie_secret, max_age=2**31 - 1)
def identity(self, request):
"""See :meth:`pyramid.interfaces.ISecurityPolicy.identity`"""
userid = self.helper.authenticated_userid(request)
if userid is None:
+ # Check if there is maybe a "Remember me" cookie
+ auth_info = self.cookie_helper.identify(request) or {}
+ userid = auth_info.get("userid")
+
+ # Still no identity found
+ if userid is None:
return None
query = select(models.User).filter_by(id=int(userid))
@@ -62,6 +76,16 @@ class SecurityPolicy:
"""See :meth:`pyramid.interfaces.ISecurityPolicy.remember`"""
return self.helper.remember(request, userid, **kw)
+ def remember_cookie(self, request, userid, **kw):
+ """Return the headers for remembering the user using the cookie method.
+
+ This is used for the "Remember me" functionality, as the cookie doesn't
+ expire (unlike the session).
+
+ The parameters are the same as for :meth:`remember`.
+ """
+ return self.cookie_helper.remember(request, userid, **kw)
+
def forget(self, request, **kw):
"""See :meth:`pyramid.interfaces.ISecurityPolicy.forget`"""
- return self.helper.forget(request, **kw)
+ return self.helper.forget(request, **kw) + self.cookie_helper.forget(request, **kw)
diff --git a/fietsboek/templates/login.jinja2 b/fietsboek/templates/login.jinja2
index 86e9adb..7a9bf07 100644
--- a/fietsboek/templates/login.jinja2
+++ b/fietsboek/templates/login.jinja2
@@ -22,6 +22,16 @@
</div>
</div>
</div>
+ <div class="row justify-content-center">
+ <div class="col-lg-5 mb-3">
+ <div class="form-check">
+ <input class="form-check-input" type="checkbox" name="remember-me" id="rememberMe" value="on">
+ <label class="form-check-label" for="rememberMe">
+ {{ _("page.login.remember-me") }}
+ </label>
+ </div>
+ </div>
+ </div>
{{ util.hidden_csrf_input() }}
<div class="row justify-content-center">
<div class="col-auto mb-3">
diff --git a/fietsboek/views/default.py b/fietsboek/views/default.py
index 883d8d7..fe9df08 100644
--- a/fietsboek/views/default.py
+++ b/fietsboek/views/default.py
@@ -3,6 +3,7 @@ from pyramid.view import view_config
from pyramid.httpexceptions import HTTPFound, HTTPNotFound
from pyramid.security import remember, forget
from pyramid.i18n import TranslationString as _
+from pyramid.interfaces import ISecurityPolicy
from pyramid.renderers import render_to_response
from sqlalchemy import select
@@ -119,7 +120,15 @@ def do_login(request):
request.session.flash(request.localizer.translate(_("flash.logged_in")))
headers = remember(request, str(user.id))
- return HTTPFound("/", headers=headers)
+
+ if request.params.get("remember-me") == "on":
+ # We don't want this logic to be the default in
+ # SecurityPolicy.remember, so we manually fake it here:
+ policy = request.registry.getUtility(ISecurityPolicy)
+ headers += policy.remember_cookie(request, str(user.id))
+
+ response = HTTPFound("/", headers=headers)
+ return response
@view_config(route_name="logout")