From: Michael Tremer Date: Thu, 31 Oct 2019 16:17:47 +0000 (+0000) Subject: people: Implement initiation of password reset X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=c7594d583748fdca9e30407ab452e0b23e1bf849;p=ipfire.org.git people: Implement initiation of password reset Signed-off-by: Michael Tremer --- diff --git a/Makefile.am b/Makefile.am index 7fbf75d0..6d4c8e5f 100644 --- a/Makefile.am +++ b/Makefile.am @@ -113,6 +113,8 @@ templates_auth_DATA = \ src/templates/auth/activate.html \ src/templates/auth/activated.html \ src/templates/auth/login.html \ + src/templates/auth/password-reset-initiation.html \ + src/templates/auth/password-reset-successful.html \ src/templates/auth/register.html \ src/templates/auth/register-spam.html \ src/templates/auth/register-success.html @@ -120,6 +122,7 @@ templates_auth_DATA = \ templates_authdir = $(templatesdir)/auth templates_auth_messages_DATA = \ + src/templates/auth/messages/password-reset.txt \ src/templates/auth/messages/register.txt templates_auth_messagesdir = $(templates_authdir)/messages diff --git a/src/backend/accounts.py b/src/backend/accounts.py index 7cd4d726..341709e2 100644 --- a/src/backend/accounts.py +++ b/src/backend/accounts.py @@ -603,6 +603,16 @@ class Account(Object): self.first_name, self.last_name, )) + def reset_password(self, address=None): + reset_code = util.random_string(64) + + self.db.execute("INSERT INTO account_password_resets(uid, reset_code, address) \ + VALUES(%s, %s, %s)", self.uid, reset_code, address) + + # Send a password reset email + self.backend.messages.send_template("auth/messages/password-reset", + recipients=[self.email], priority=100, account=self, reset_code=reset_code) + def is_admin(self): return self.is_member_of_group("sudo") diff --git a/src/templates/auth/login.html b/src/templates/auth/login.html index 23bdb025..897a1955 100644 --- a/src/templates/auth/login.html +++ b/src/templates/auth/login.html @@ -37,7 +37,7 @@

- + {{ _("Did you forget your password?") }}

diff --git a/src/templates/auth/messages/password-reset.txt b/src/templates/auth/messages/password-reset.txt new file mode 100644 index 00000000..26c91198 --- /dev/null +++ b/src/templates/auth/messages/password-reset.txt @@ -0,0 +1,11 @@ +From: IPFire Project +To: {{ account }} <{{ account.email }}> +Subject: {{ _("Please Reset Your Password") }} + +{{ _("Hello %s!") % account.first_name }} + +{{ _("You, or somebody else on your behalf, has requested to change your password.") }} {{ _("If this was not you, please notify a team member.") }} + +{{ _("To reset your password, please click on this link:") }} + + https://people.ipfire.org/password-reset/{{ account.uid }}/{{ reset_code }} diff --git a/src/templates/auth/password-reset-initiation.html b/src/templates/auth/password-reset-initiation.html new file mode 100644 index 00000000..c1306d7f --- /dev/null +++ b/src/templates/auth/password-reset-initiation.html @@ -0,0 +1,29 @@ +{% extends "../base.html" %} + +{% block title %}{{ _("Password Reset") }}{% end block %} + +{% block content %} +
+
+
+
+
{{ _("Password Reset") }}
+ +
+ {% raw xsrf_form_html() %} + +
+ +
+ + +
+
+
+
+
+{% end block %} diff --git a/src/templates/auth/password-reset-successful.html b/src/templates/auth/password-reset-successful.html new file mode 100644 index 00000000..ff45d61a --- /dev/null +++ b/src/templates/auth/password-reset-successful.html @@ -0,0 +1,19 @@ +{% extends "../base.html" %} + +{% block title %}{{ _("Password Reset") }}{% end block %} + +{% block content %} +
+
+
+
+ + +

+ {{ _("You will shortly receive an email with instructions on how to reset your password.") }} +

+
+
+
+
+{% end block %} diff --git a/src/web/__init__.py b/src/web/__init__.py index d1712816..4acb0dfc 100644 --- a/src/web/__init__.py +++ b/src/web/__init__.py @@ -287,6 +287,9 @@ class Application(tornado.web.Application): # Single-Sign-On for Discourse (r"/sso/discourse", people.SSODiscourse), + # Password Reset + (r"/password-reset", auth.PasswordResetInitiationHandler), + # API (r"/api/check/uid", auth.APICheckUID), ] + authentication_handlers) diff --git a/src/web/auth.py b/src/web/auth.py index cb980666..e3fb5f13 100644 --- a/src/web/auth.py +++ b/src/web/auth.py @@ -147,6 +147,25 @@ class ActivateHandler(AuthenticationMixin, base.BaseHandler): self.render("auth/activated.html", account=account) +class PasswordResetInitiationHandler(AuthenticationMixin, base.BaseHandler): + def get(self): + username = self.get_argument("username", None) + + self.render("auth/password-reset-initiation.html", username=username) + + @base.ratelimit(minutes=60, requests=5) + def post(self): + username = self.get_argument("username") + + # Fetch account and submit password reset + account = self.backend.accounts.get_by_uid(username) + if account: + with self.db.transaction(): + account.reset_password() + + self.render("auth/password-reset-successful.html") + + class APICheckUID(base.APIHandler): @base.ratelimit(minutes=10, requests=100) def get(self):