summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAssaf Gordon <assafgordon@gmail.com>2017-05-17 04:07:28 (GMT)
committerAssaf Gordon <assafgordon@gmail.com>2017-05-17 04:07:28 (GMT)
commit3f7b7e010ff562208c00f7b2dbe87fd9132561c7 (patch)
tree3a2577346f99fcf293f815cd9a31648a5c14e02a
parente2ad8c1820462e4415b4cb281760d70fc5d96eb7 (diff)
downloadvaranusex-3f7b7e010ff562208c00f7b2dbe87fd9132561c7.zip
varanusex-3f7b7e010ff562208c00f7b2dbe87fd9132561c7.tar.gz
varanusex-3f7b7e010ff562208c00f7b2dbe87fd9132561c7.tar.bz2
account/passwordless-email-login: implement
-rw-r--r--varanusex/templates/account/passwordless-email-login-sent.html52
-rw-r--r--varanusex/templates/account/passwordless-email-login.html60
-rw-r--r--varanusex/templates/login.html6
-rw-r--r--varanusex/views/account.py45
4 files changed, 163 insertions, 0 deletions
diff --git a/varanusex/templates/account/passwordless-email-login-sent.html b/varanusex/templates/account/passwordless-email-login-sent.html
new file mode 100644
index 0000000..bc2b6d7
--- /dev/null
+++ b/varanusex/templates/account/passwordless-email-login-sent.html
@@ -0,0 +1,52 @@
+{#
+VaranusEx - Savannah Monitor
+
+Copyright (C) 2017 Assaf Gordon (assafgordon@gmail.com)
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU Affero General Public License as
+published by the Free Software Foundation, either version 3 of the
+License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU Affero General Public License for more details.
+
+You should have received a copy of the GNU Affero General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+#}
+{% extends 'master-layout.html' %}
+
+{% block head %}
+<style>
+ div.formerror { color : red }
+</style>
+{% endblock %}
+
+{% block content %}
+
+<div class="header">
+ <h1>Savannah Account Configuration</h1>
+</div>
+
+<div class="content">
+
+ <h2 class="content-subhead">Passwordless Login Email Sent</h2>
+ <p>
+ Passwordless login token was sent to
+ <b>{{email}}</b>.
+
+ <br/>
+ <br/>
+
+ The email is sent from address <b>no-reply@gnu.org</b>.
+ <br/>
+ <br/>
+ If you do not receive the email within few minutes,
+ please be sure to check your spam folder.
+ </p>
+</div>
+
+
+{% endblock %}
diff --git a/varanusex/templates/account/passwordless-email-login.html b/varanusex/templates/account/passwordless-email-login.html
new file mode 100644
index 0000000..804a981
--- /dev/null
+++ b/varanusex/templates/account/passwordless-email-login.html
@@ -0,0 +1,60 @@
+{#
+VaranusEx - Savannah Monitor
+
+Copyright (C) 2017 Assaf Gordon (assafgordon@gmail.com)
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU Affero General Public License as
+published by the Free Software Foundation, either version 3 of the
+License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU Affero General Public License for more details.
+
+You should have received a copy of the GNU Affero General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+#}
+{% extends 'master-layout.html' %}
+
+{% block head %}
+<style>
+ div.formerror { color : red }
+</style>
+{% endblock %}
+
+{% block content %}
+
+<div class="header">
+ <h1>Savannah Account Configuration</h1>
+</div>
+
+<div class="content">
+
+ <h2 class="content-subhead">Password-less Email Login</h2>
+ <p>
+ The your email associated with your Savannah user in the form
+ below, and a login URL will be sent to you.
+ <br/>
+ Click on the URL within 5 minutes to login automatically
+ to savannah without entering your password.
+ </p>
+
+ <form class="pure-form pure-form-aligned" method="post">
+ {{ form.hidden_tag() }}
+ {{ form.email.label }}
+ {{ form.email(size=40) }}
+ {% for message in form.email.errors %}
+ <div class="formerror">{{ message }}</div>
+ {% endfor %}
+ <br/>
+ <br/>
+ <input type="submit" value="Send Login Token">
+
+ </form>
+
+</div>
+
+
+{% endblock %}
diff --git a/varanusex/templates/login.html b/varanusex/templates/login.html
index bb9b42e..9aad148 100644
--- a/varanusex/templates/login.html
+++ b/varanusex/templates/login.html
@@ -69,6 +69,12 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
<br/>
<input type="submit" value="Login">
+
+ <br/>
+ <br/>
+ or try <a href="{{url_for('account_passwordless_email_login')}}">
+ Password-less email login</a>.
+
</form>
</p>
diff --git a/varanusex/views/account.py b/varanusex/views/account.py
index 3e50de9..d11a850 100644
--- a/varanusex/views/account.py
+++ b/varanusex/views/account.py
@@ -121,6 +121,51 @@ def account_lost_password_token(token):
return render_template('account/lost-password-token.html',form=f)
+@app.route('/account/passwordlesslogin',methods=['GET','POST'])
+def account_passwordless_email_login():
+ f = LostPasswordForm() # (same form, we're just asking for an email address)
+ if f.validate_on_submit():
+ email = f.email.data.strip()
+ user = User.query.filter_by(email=email).first()
+ if user:
+ token = app.email_token.generate_token(user.user_name,salt='emllogin')
+ url = url_for('account_passwordless_email_login_token',token=token,_external=True)
+ print("sending login to email '%s' (user '%s'), url= %s" \
+ % (email, user.user_name, url))
+ else:
+ print("email-login attempt to unknown email '%s'" % (email))
+
+ # Show the 'sent' confirmation regardless of whether the email/user was
+ # found or not.
+ return render_template('account/passwordless-email-login-sent.html',email=email)
+
+ return render_template('account/passwordless-email-login.html',form=f)
+
+@app.route('/account/passwordlesslogin/<token>',methods=['GET'])
+def account_passwordless_email_login_token(token):
+ try:
+ timeout = 60*5 # TODO: get from config file
+ user_name = app.email_token.decode_token(token,
+ salt='emllogin',
+ max_age=timeout)
+ except itsdangerous.BadTimeSignature as e:
+ abort(400) #TODO: add descriptive error + logs
+ except itsdangerous.SignatureExpired as e:
+ abort(400) #TODO: add descriptive error + logs
+
+ user = User.query.filter_by(user_name=user_name).first()
+ if not user:
+ # Something terribly wrong: a valid signature for username
+ # which isn't found?
+ abort(400)
+
+ # Valid token - just login the user
+ logout_user()
+ login_user(user)
+ return redirect(url_for('index'))
+
+
+
@login_required
@app.route("/my/account")
def account_config():