summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAssaf Gordon <assafgordon@gmail.com>2017-06-29 22:34:46 (GMT)
committerAssaf Gordon <assafgordon@gmail.com>2017-06-29 22:34:46 (GMT)
commit926be1df4448ede34f1bc28eb3be48efae841f51 (patch)
tree35d9c8cfd34ec728197c4cf9bfff99f876a1c9a3
parentda6910654d57985b84104d2cb905888df4ee936f (diff)
downloadvaranusex-926be1df4448ede34f1bc28eb3be48efae841f51.zip
varanusex-926be1df4448ede34f1bc28eb3be48efae841f51.tar.gz
varanusex-926be1df4448ede34f1bc28eb3be48efae841f51.tar.bz2
flask: add 'demo mode'user-config
If DEMO_MODE=True (in the config file), account database changes are disabled. This allows putting the demo website public, but ensuring no one will change passwords or emails.
-rw-r--r--varanusex.cfg.sample7
-rw-r--r--varanusex/__init__.py4
-rw-r--r--varanusex/static/css/varanusex.css38
-rw-r--r--varanusex/templates/master-layout.html12
-rw-r--r--varanusex/views/account.py93
-rw-r--r--varanusex/views/main.py2
6 files changed, 124 insertions, 32 deletions
diff --git a/varanusex.cfg.sample b/varanusex.cfg.sample
index 5117708..db3a084 100644
--- a/varanusex.cfg.sample
+++ b/varanusex.cfg.sample
@@ -53,3 +53,10 @@ SESSION_TYPE='filesystem'
#CAPTCHA_DIRECTORY="captcha_files"
#CAPTCHA_ACCESS_MODE=0o755
#CAPTCHA_PNG_HEIGHT=100
+
+
+
+# Demo mode:
+# Lock certain aspects of the website when running it
+# as a public demo (e.g. changing passwords in the database).
+# DEMO_MODE=True \ No newline at end of file
diff --git a/varanusex/__init__.py b/varanusex/__init__.py
index 6e89526..e0a79e2 100644
--- a/varanusex/__init__.py
+++ b/varanusex/__init__.py
@@ -53,6 +53,10 @@ from varanusex.EmailToken import EmailToken
email_token = EmailToken()
email_token.init_app(app)
+# Set 'demo mode' flag, to lock certain aspects while
+# making the demo website public (e.g. changing passwords in the DB)
+app.demo_mode = app.config.get('DEMO_MODE',False)
+
# Initialize the server-side sessions
# NOTE:
diff --git a/varanusex/static/css/varanusex.css b/varanusex/static/css/varanusex.css
index fbd0610..bb05719 100644
--- a/varanusex/static/css/varanusex.css
+++ b/varanusex/static/css/varanusex.css
@@ -45,3 +45,41 @@ ul.project_features_topbar li {
display: inline;
margin-right: 1ex;
}
+
+
+/* Flask-Flash messages,
+ see nice colors here: https://codepen.io/palimadra/pen/OVvbaY */
+ul.flashes {
+ list-style: none;
+}
+ul.flashes li {
+ border: 1px solid;
+ margin: 10px 10px;
+ padding: 15px 10px 15px 50px;
+ background-repeat: no-repeat;
+ background-position: 10px center;
+}
+ul.flashes li.info {
+ color: #00529B;
+ background-color: #BDE5F8;
+}
+ul.flashes li.success {
+ color: #4F8A10;
+ background-color: #DFF2BF;
+}
+ul.flashes li.warning {
+ color: #9F6000;
+ background-color: #FEEFB3;
+}
+ul.flashes li.demomode {
+ color: #cF6000;
+ background-color: #FEcFc3;
+}
+ul.flashes li.error {
+ color: #D8000C;
+ background-color: #FFBABA;
+}
+ul.flashes li.validation {
+ color: #D63301;
+ background-color: #FFCCBA;
+}
diff --git a/varanusex/templates/master-layout.html b/varanusex/templates/master-layout.html
index f29e125..aac9863 100644
--- a/varanusex/templates/master-layout.html
+++ b/varanusex/templates/master-layout.html
@@ -120,6 +120,18 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
<!-- Page Content -->
<div id="main">
+ {# Flask-Flash messages, see http://flask.pocoo.org/docs/0.12/patterns/flashing/ #}
+ {% with messages = get_flashed_messages(with_categories=true) %}
+ {% if messages %}
+ <ul class="flashes">
+ {% for category, message in messages %}
+ <li class="{{ category }}">{{ message }}</li>
+ {% endfor %}
+ </ul>
+ {% endif %}
+ {% endwith %}
+
+
{% block content %}
{% endblock %}
diff --git a/varanusex/views/account.py b/varanusex/views/account.py
index 568f394..9cf0d8f 100644
--- a/varanusex/views/account.py
+++ b/varanusex/views/account.py
@@ -19,7 +19,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
from pprint import pprint
import re, datetime
from flask import Flask, render_template, url_for, redirect, request, \
- make_response, abort, session, send_file
+ make_response, abort, session, send_file, flash
from flask_login import login_required, login_user, \
logout_user, current_user
import itsdangerous
@@ -91,11 +91,14 @@ def account_register():
nu = User()
nu.user_name = u
nu.email = e
- nu.set_new_password(p)
nu.realname = r
- db.session.add(nu)
- db.session.commit()
+ if app.demo_mode:
+ flash("DEMO MODE: adding users is disabled","demomode")
+ else:
+ nu.set_new_password(p)
+ db.session.add(nu)
+ db.session.commit()
# TODO: redirect to a GET location to prevent re-post on reload?
return render_template('account/register-new-user-pending.html',
@@ -180,11 +183,16 @@ def account_lost_password_token(token):
f = ResetPasswordForm()
if f.validate_on_submit():
if user.email == f.email.data.strip():
+
# set the new password and continue
- user.set_new_password(f.new_password1.data)
- db.session.add(user)
- db.session.commit()
- # TODO: Flask message?
+ if app.demo_mode:
+ flash("DEMO MODE: changing passwords is disabled","demomode")
+ else:
+ flash("password updated","info")
+ user.set_new_password(f.new_password1.data)
+ db.session.add(user)
+ db.session.commit()
+
return redirect(url_for('login'))
else:
f.email.errors.append("Incorrect email")
@@ -255,9 +263,14 @@ def account_change_real_name():
if f.validate_on_submit():
# TODO: Udpate 'history' table ?
- current_user.realname = f.realname.data.strip()
- db.session.add(current_user)
- db.session.commit()
+ if app.demo_mode:
+ flash("DEMO MODE: changing names is disabled","demomode")
+ else:
+ flash("Name changed","info")
+ current_user.realname = f.realname.data.strip()
+ db.session.add(current_user)
+ db.session.commit()
+
return redirect(url_for('account_config'))
return render_template('account/change-real-name.html',form=f)
@@ -272,9 +285,13 @@ def account_change_password():
if current_user.check_password(f.current_password.data):
# TODO: Notify by email about password change
# TODO: update 'history' table ?
- current_user.set_new_password(f.new_password1.data)
- db.session.add(current_user)
- db.session.commit()
+ if app.demo_mode:
+ flash("DEMO MODE: changing passwords is disabled","demomode")
+ else:
+ flash("password updated","info")
+ current_user.set_new_password(f.new_password1.data)
+ db.session.add(current_user)
+ db.session.commit()
return redirect(url_for('account_config'))
else:
f.current_password.errors.append("wrong password")
@@ -296,9 +313,13 @@ def account_change_email():
# Change the password before updating the email
if current_user.check_password(f.password.data):
# TODO: send notification + verification to both old/new emails?
- current_user.email = f.email.data
- db.session.add(current_user)
- db.session.commit()
+ if app.demo_mode:
+ flash("DEMO MODE: changing emails is disabled","demomode")
+ else:
+ flash("email changed","info")
+ current_user.email = f.email.data
+ db.session.add(current_user)
+ db.session.commit()
return redirect(url_for('account_config'))
else:
f.password.errors.append("wrong password")
@@ -323,9 +344,12 @@ def account_change_ssh_keys():
nk = re.sub(' *\r?\n','', nk)
pprint(nk)
if valid_ssh_pubkey(nk):
- current_user.add_ssh_public_key(nk)
- db.session.add(current_user)
- db.session.commit()
+ if app.demo_mode:
+ flash("DEMO MODE: changing SSH keys is disabled","demomode")
+ else:
+ current_user.add_ssh_public_key(nk)
+ db.session.add(current_user)
+ db.session.commit()
# Ugly Hack:
# Redirect to ourselves again (forcing GET request).
@@ -340,14 +364,18 @@ def account_change_ssh_keys():
md5 = request.form.get('entry_md5',None)
if md5 is None:
abort(400) # should not happen - foul play?
- if not current_user.delete_ssh_publickey_entry(md5):
- # This could happen if the user had a stale page listing
- # non-existing (old) SSH keys, and requested to delete
- # an entry which is not in the database any more.
- # TODO: present a proper error message.
- abort(400)
- db.session.add(current_user)
- db.session.commit()
+
+ if app.demo_mode:
+ flash("DEMO MODE: deleting SSH keys is disabled","demomode")
+ else:
+ if not current_user.delete_ssh_publickey_entry(md5):
+ # This could happen if the user had a stale page listing
+ # non-existing (old) SSH keys, and requested to delete
+ # an entry which is not in the database any more.
+ # TODO: present a proper error message.
+ abort(400)
+ db.session.add(current_user)
+ db.session.commit()
# Ugly Hack:
# Redirect to ourselves again (forcing GET request).
@@ -388,9 +416,12 @@ def account_change_gpg_keys():
if f.validate_on_submit():
k = f.new_key.data.strip()
if valid_gpg_pubkey(k):
- current_user.gpg_key = k
- db.session.add(current_user)
- db.session.commit()
+ if app.demo_mode:
+ flash("DEMO MODE: changing GPG keys is disabled","demomode")
+ else:
+ current_user.gpg_key = k
+ db.session.add(current_user)
+ db.session.commit()
return redirect(url_for('account_config'))
else:
f.new_key.errors = ["Invalid GPG public key"]
diff --git a/varanusex/views/main.py b/varanusex/views/main.py
index 523941d..ad6e7f0 100644
--- a/varanusex/views/main.py
+++ b/varanusex/views/main.py
@@ -16,7 +16,7 @@ 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/>.
"""
-from flask import Flask, render_template
+from flask import Flask, render_template, flash
from .. import app
from ..models.utilities import get_project_type_counts, \