diff --git a/app/__init__.py b/app/__init__.py index cf5442ec..aef0c2b6 100644 --- a/app/__init__.py +++ b/app/__init__.py @@ -10,7 +10,7 @@ import logging db = SQLAlchemy() logger = logging.getLogger(__name__) login_manager = LoginManager() -login_manager.login_view = 'main.index' +login_manager.login_view = 'auth.login' mail = Mail() socketio = SocketIO() diff --git a/app/auth/forms.py b/app/auth/forms.py index bd7f20b1..df1e46b6 100644 --- a/app/auth/forms.py +++ b/app/auth/forms.py @@ -12,25 +12,6 @@ class LoginForm(FlaskForm): submit = SubmitField('Log In') -class PasswordResetForm(FlaskForm): - password = PasswordField( - 'New Password', - validators=[DataRequired(), - EqualTo('password2', message='Passwords must match')] - ) - password2 = PasswordField( - 'Confirm password', - validators=[DataRequired(), - EqualTo('password', message='Passwords must match.')] - ) - submit = SubmitField('Reset Password') - - -class PasswordResetRequestForm(FlaskForm): - email = StringField('Email', validators=[DataRequired(), Email()]) - submit = SubmitField('Reset Password') - - class RegistrationForm(FlaskForm): email = StringField('Email', validators=[DataRequired(), Email()]) username = StringField( @@ -55,3 +36,22 @@ class RegistrationForm(FlaskForm): def validate_username(self, field): if User.query.filter_by(username=field.data).first(): raise ValidationError('Username already in use.') + + +class ResetPasswordForm(FlaskForm): + password = PasswordField( + 'New Password', + validators=[DataRequired(), + EqualTo('password2', message='Passwords must match')] + ) + password2 = PasswordField( + 'Confirm password', + validators=[DataRequired(), + EqualTo('password', message='Passwords must match.')] + ) + submit = SubmitField('Reset Password') + + +class ResetPasswordRequestForm(FlaskForm): + email = StringField('Email', validators=[DataRequired(), Email()]) + submit = SubmitField('Reset Password') diff --git a/app/auth/views.py b/app/auth/views.py index 5ed21377..ee6b75d4 100644 --- a/app/auth/views.py +++ b/app/auth/views.py @@ -1,62 +1,14 @@ -from app import db +from app import db, logger from app.email import send_email from app.models import User from flask import (current_app, flash, redirect, render_template, request, url_for) -from flask_login import current_user, login_required, logout_user +from flask_login import current_user, login_user, login_required, logout_user from . import auth -from .forms import (PasswordResetForm, PasswordResetRequestForm, +from .forms import (LoginForm, ResetPasswordForm, ResetPasswordRequestForm, RegistrationForm) import os - - -@auth.route('/logout') -@login_required -def logout(): - logout_user() - flash('You have been logged out.') - return redirect(url_for('main.index')) - - -@auth.route('/register', methods=['GET', 'POST']) -def register(): - if not current_user.is_anonymous: - return redirect(url_for('main.dashboard')) - registration_form = RegistrationForm(prefix='registration-form') - if registration_form.validate_on_submit(): - user = User(email=registration_form.email.data.lower(), - password=registration_form.password.data, - username=registration_form.username.data) - db.session.add(user) - db.session.commit() - dir = os.path.join(current_app.config['NOPAQUE_STORAGE'], str(user.id)) - try: - os.makedirs(dir) - except OSError: - flash('[ERROR]!') - user.delete() - else: - token = user.generate_confirmation_token() - send_email(user.email, 'Confirm Your Account', - 'auth/email/confirm', token=token, user=user) - flash('A confirmation email has been sent to you by email.') - return redirect(url_for('main.index')) - return render_template('auth/register.html.j2', - registration_form=registration_form, - title='Register') - - -@auth.route('/confirm/') -@login_required -def confirm(token): - if current_user.confirmed: - return redirect(url_for('main.index')) - if current_user.confirm(token): - db.session.commit() - flash('You have confirmed your account. Thanks!') - else: - flash('The confirmation link is invalid or has expired.') - return redirect(url_for('main.dashboard')) +import shutil @auth.before_app_request @@ -72,10 +24,76 @@ def before_request(): return redirect(url_for('auth.unconfirmed')) +@auth.route('/login') +def login(): + login_form = LoginForm(prefix='login-form') + if login_form.validate_on_submit(): + user = User.query.filter_by(username=login_form.user.data).first() + if user is not None and user.verify_password(login_form.password.data): + login_user(user, login_form.remember_me.data) + next = request.args.get('next') + if next is None or not next.startswith('/'): + next = url_for('main.dashboard') + return redirect(next) + flash('Invalid username or password.') + return render_template('auth/login.html.j2', login_form=login_form, + title='nopaque') + + +@auth.route('/logout') +@login_required +def logout(): + logout_user() + flash('You have been logged out.') + return redirect(url_for('main.index')) + + +@auth.route('/register', methods=['GET', 'POST']) +def register(): + if current_user.is_authenticated: + return redirect(url_for('main.dashboard')) + registration_form = RegistrationForm(prefix='registration-form') + if registration_form.validate_on_submit(): + user = User(email=registration_form.email.data.lower(), + password=registration_form.password.data, + username=registration_form.username.data) + db.session.add(user) + db.session.commit() + user_dir = os.path.join(current_app.config['NOPAQUE_STORAGE'], + str(user.id)) + if os.path.exists(user_dir): + shutil.rmtree(user_dir) + os.mkdir(user_dir) + token = user.generate_confirmation_token() + send_email(user.email, 'Confirm Your Account', + 'auth/email/confirm', token=token, user=user) + flash('A confirmation email has been sent to you by email.') + return redirect(url_for('auth.login')) + return render_template('auth/register.html.j2', + registration_form=registration_form, + title='Register') + + +@auth.route('/confirm/') +@login_required +def confirm(token): + if current_user.confirmed: + return redirect(url_for('main.dashboard')) + if current_user.confirm(token): + db.session.commit() + flash('You have confirmed your account. Thanks!') + return redirect(url_for('main.dashboard')) + else: + flash('The confirmation link is invalid or has expired.') + return redirect(url_for('auth.unconfirmed')) + + @auth.route('/unconfirmed') def unconfirmed(): - if current_user.is_anonymous or current_user.confirmed: + if current_user.is_anonymous: return redirect(url_for('main.index')) + elif current_user.confirmed: + return redirect(url_for('main.dashboard')) return render_template('auth/unconfirmed.html.j2', title='Unconfirmed') @@ -83,49 +101,46 @@ def unconfirmed(): @login_required def resend_confirmation(): token = current_user.generate_confirmation_token() - send_email(current_user.email, - 'Confirm Your Account', - 'auth/email/confirm', - token=token, - user=current_user) + send_email(current_user.email, 'Confirm Your Account', + 'auth/email/confirm', token=token, user=current_user) flash('A new confirmation email has benn sent to you by email.') - return redirect(url_for('main.dashboard')) + return redirect(url_for('auth.unconfirmed')) @auth.route('/reset', methods=['GET', 'POST']) -def password_reset_request(): - if not current_user.is_anonymous: +def reset_password_request(): + if current_user.is_authenticated: return redirect(url_for('main.dashboard')) - form = PasswordResetRequestForm() - if form.validate_on_submit(): - user = User.query.filter_by(email=form.email.data.lower()).first() + reset_password_request_form = ResetPasswordRequestForm() + if reset_password_request_form.validate_on_submit(): + submitted_email = reset_password_request_form.email.data + user = User.query.filter_by(email=submitted_email.lower()).first() if user: token = user.generate_reset_token() - send_email(user.email, - 'Reset Your Password', - 'auth/email/reset_password', - token=token, - user=user) + send_email(user.email, 'Reset Your Password', + 'auth/email/reset_password', token=token, user=user) flash('An email with instructions to reset your password has been ' 'sent to you.') - return redirect(url_for('main.index')) - return render_template('auth/reset_password_request.html.j2', - form=form, - title='Password Reset') + return redirect(url_for('auth.login')) + return render_template( + 'auth/reset_password_request.html.j2', + reset_password_request_form=reset_password_request_form, + title='Password Reset' + ) @auth.route('/reset/', methods=['GET', 'POST']) -def password_reset(token): - if not current_user.is_anonymous: +def reset_password(token): + if current_user.is_authenticated: return redirect(url_for('main.dashboard')) - form = PasswordResetForm() - if form.validate_on_submit(): - if User.reset_password(token, form.password.data): + reset_password_form = ResetPasswordForm() + if reset_password_form.validate_on_submit(): + if User.reset_password(token, reset_password_form.password.data): db.session.commit() flash('Your password has been updated.') - return redirect(url_for('main.index')) + return redirect(url_for('auth.login')) else: return redirect(url_for('main.index')) return render_template('auth/reset_password.html.j2', - form=form, + reset_password_form=reset_password_form, title='Password Reset') diff --git a/app/templates/auth/email/reset_password.html.j2 b/app/templates/auth/email/reset_password.html.j2 index 8b4b20e0..49b30f65 100644 --- a/app/templates/auth/email/reset_password.html.j2 +++ b/app/templates/auth/email/reset_password.html.j2 @@ -1,7 +1,7 @@

Dear {{ user.username }},

-

To reset your password click here.

+

To reset your password click here.

Alternatively, you can paste the following link in your browser's address bar:

-

{{ url_for('auth.password_reset', token=token, _external=True) }}

+

{{ url_for('auth.reset_password', token=token, _external=True) }}

If you have not requested a password reset simply ignore this message.

Sincerely,

The nopaque Team

diff --git a/app/templates/auth/email/reset_password.txt.j2 b/app/templates/auth/email/reset_password.txt.j2 index deb04b14..5d86e46f 100644 --- a/app/templates/auth/email/reset_password.txt.j2 +++ b/app/templates/auth/email/reset_password.txt.j2 @@ -2,7 +2,7 @@ Dear {{ user.username }}, To reset your password click on the following link: -{{ url_for('auth.password_reset', token=token, _external=True) }} +{{ url_for('auth.reset_password', token=token, _external=True) }} If you have not requested a password reset simply ignore this message. diff --git a/app/templates/auth/login.html.j2 b/app/templates/auth/login.html.j2 new file mode 100644 index 00000000..6d90327a --- /dev/null +++ b/app/templates/auth/login.html.j2 @@ -0,0 +1,52 @@ +{% extends "nopaque.html.j2" %} + +{% block page_content %} +
+

Cyber cyber

+

Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.

+
+ +
+
+
+
+ Log in + {{ login_form.hidden_tag() }} +
+ person + {{ login_form.user(class='validate') }} + {{ login_form.user.label }} + {% for error in login_form.user.errors %} + {{ error }} + {% endfor %} +
+
+ vpn_key + {{ login_form.password(class='validate') }} + {{ login_form.password.label }} + {% for error in login_form.password.errors %} + {{ error }} + {% endfor %} +
+
+ +
+
+ +
+
+
+
+
+ {{ login_form.submit(class='btn') }} +
+
+
+
+{% endblock %} diff --git a/app/templates/auth/reset_password.html.j2 b/app/templates/auth/reset_password.html.j2 index 1ef3adfa..4bcb4a7d 100644 --- a/app/templates/auth/reset_password.html.j2 +++ b/app/templates/auth/reset_password.html.j2 @@ -7,27 +7,27 @@
-
+
- {{ form.hidden_tag() }} + {{ reset_password_form.hidden_tag() }}
- {{ form.password(class='validate', type='password') }} - {{ form.password.label }} - {% for error in form.password.errors %} + {{ reset_password_form.password(type='password') }} + {{ reset_password_form.password.label }} + {% for error in reset_password_form.password.errors %} {{ error }} {% endfor %}
- {{ form.password2(class='validate', type='password') }} - {{ form.password2.label }} - {% for error in form.password2.errors %} + {{ reset_password_form.password2(type='password') }} + {{ reset_password_form.password2.label }} + {% for error in reset_password_form.password2.errors %} {{ error }} {% endfor %}
-
- {{ form.submit(class='btn right') }} +
+ {{ form.submit(class='btn') }}
diff --git a/app/templates/auth/reset_password_request.html.j2 b/app/templates/auth/reset_password_request.html.j2 index 86c513df..5abb50b6 100644 --- a/app/templates/auth/reset_password_request.html.j2 +++ b/app/templates/auth/reset_password_request.html.j2 @@ -7,20 +7,20 @@
-
+
- {{ form.hidden_tag() }} + {{ reset_password_request_form.hidden_tag() }}
- {{ form.email(class='validate', type='email') }} - {{ form.email.label }} - {% for error in form.email.errors %} + {{ reset_password_request_form.email(class='validate', type='email') }} + {{ reset_password_request_form.email.label }} + {% for error in reset_password_request_form.email.errors %} {{ error }} {% endfor %}
-
- {{ form.submit(class='btn right') }} +
+ {{ reset_password_request_form.submit(class='btn') }}
diff --git a/app/templates/main/index.html.j2 b/app/templates/main/index.html.j2 index 04d84855..6b97e6e9 100644 --- a/app/templates/main/index.html.j2 +++ b/app/templates/main/index.html.j2 @@ -116,7 +116,7 @@
diff --git a/app/templates/nopaque.html.j2 b/app/templates/nopaque.html.j2 index dc7ad1a1..5fe764e1 100644 --- a/app/templates/nopaque.html.j2 +++ b/app/templates/nopaque.html.j2 @@ -51,7 +51,7 @@
  • settingsSettings
  • power_settings_newLog out
  • {% else %} -
  • personLog in
  • +
  • personLog in
  • person_addRegister
  • {% endif %} @@ -77,7 +77,7 @@
  • settingsSettings
  • power_settings_newLog out
  • {% else %} -
  • personLog in
  • +
  • personLog in
  • person_addRegister
  • {% endif %} {% if current_user.is_administrator() %}