diff --git a/ref-test/app/admin/views.py b/ref-test/app/admin/views.py index 929485a..dbaa0d9 100644 --- a/ref-test/app/admin/views.py +++ b/ref-test/app/admin/views.py @@ -1,4 +1,4 @@ -from ..forms.admin import Login, Register +from ..forms.admin import CreateUser, Login, Register, ResetPassword, UpdatePassword from ..models import User from ..tools.auth import disable_if_logged_in, require_account_creation @@ -6,6 +6,7 @@ from flask import Blueprint, flash, jsonify, render_template, redirect, request, from flask.helpers import url_for from flask_login import current_user, login_required +import secrets admin = Blueprint( name='admin', @@ -43,7 +44,8 @@ def _login(): return jsonify({'success': f'Successfully logged in.'}), 200 return jsonify({'error': f'The password you entered is incorrect.'}), 401 return jsonify({'error': f'The username you entered does not exist.'}), 401 - + errors = [*form.username.errors, *form.password.errors] + return jsonify({ 'error': errors}), 400 if 'remembered_username' in session: form.username.data = session.pop('remembered_username') next = request.args.get('next') return render_template('/admin/auth/login.html', form=form, next=next) @@ -52,7 +54,7 @@ def _login(): @login_required def _logout(): current_user.logout() - return redirect(url_for('views._login')) + return redirect(url_for('admin._login')) @admin.route('/register/', methods=['GET','POST']) @disable_if_logged_in @@ -66,24 +68,75 @@ def _register(): new_user.set_username = request.form.get('username').lower() new_user.set_email = request.form.get('email').lower() new_user.set_password = request.form.get('password').lower() - success, message = new_user.register() - if success: - flash(message=f'{message} Please log in to continue.', category='success') - session['remembered_username'] = request.form.get('username').lower() - return jsonify({'success': message}), 200 - flash(message=message, category='error') - return jsonify({'error': message}), 401 - + success, message = new_user.register() + if success: + flash(message=f'{message} Please log in to continue.', category='success') + session['remembered_username'] = request.form.get('username').lower() + return jsonify({'success': message}), 200 + flash(message=message, category='error') + return jsonify({'error': message}), 401 + errors = [*form.username.errors, *form.email.errors, *form.password.errors, *form.password_reenter.errors] + return jsonify({ 'error': errors}), 400 return render_template('admin/auth/register.html') @admin.route('/reset/') def _reset(): - return 'Reset Page' + form = ResetPassword() + if request.method == 'POST': + if form.validate_on_submit(): + user = None + users = User.query.all() + for _user in users: + if _user.get_username() == request.form.get('username'): + user = _user + break + if not user: return jsonify({'error': 'The user account does not exist.'}), 400 + if not user.get_email() == request.form.get('email'): return jsonify({'error': 'The email address does not match the user account.'}), 400 + return user.reset_password() + errors = [*form.username.errors, *form.email.errors] + return jsonify({ 'error': errors}), 400 + + token = request.args.get('token') + if token: + user = User.query.filter_by(reset_token=token).first() + if not user: return redirect(url_for('admin._reset')) + verification_token = user.verification_token + user.clear_reset_tokens() + if request.args.get('verification') == verification_token: + form = UpdatePassword() + return render_template('/auth/update_password.html', form=form, user=user.id) + flash('The verification of your password reset request failed and the token has been invalidated. Please make a new reset password request.', 'error') + + return render_template('/admin/auth/reset.html', form=form) @admin.route('/update_password/', methods=['POST']) def _update_password(): - return 'Password Update' + form = UpdatePassword() + if form.validate_on_submit(): + user = request.form.get('user') + user = User.query.filter_by(id=user).first() + user.update(password=request.form.get('password')) + session['remembered_username'] = user.get_username() + flash('Your password has been reset.', 'success') + return jsonify({'success':'Your password has been reset'}), 200 + errors = [*form.password.errors, *form.password_reenter.errors] + return jsonify({ 'error': errors}), 401 -@admin.route('/settings/users/') +@admin.route('/settings/users/', methods=['GET', 'POST']) +@login_required def _users(): - return 'Manage Users' \ No newline at end of file + form = CreateUser() + users = User.query.all() + if request.method == 'POST': + if form.validate_on_submit(): + password = request.form.get('password') + new_user = User() + new_user.set_username = request.form.get('username').lower() + new_user.set_password = secrets.token_hex(12) if not password else password + new_user.set_email = request.form.get('email') + success, message = new_user.register(notify=request.form.get('notify')) + if success: return jsonify({'success': message}), 200 + return jsonify({'error': message}), 401 + errors = [*form.username.errors, *form.email.errors, *form.password.errors] + return jsonify({ 'error': errors}), 401 + return render_template('/admin/settings/users.html', form = form, users = users) diff --git a/ref-test/app/forms/admin.py b/ref-test/app/forms/admin.py index d417945..8718189 100644 --- a/ref-test/app/forms/admin.py +++ b/ref-test/app/forms/admin.py @@ -30,6 +30,7 @@ class CreateUser(FlaskForm): username = StringField('Username', validators=[InputRequired(), Length(min=4, max=15)]) email = StringField('Email Address', validators=[InputRequired(), Email(message='You must enter a valid email address.'), Length(max=50)]) password = PasswordField('Password (Optional)', validators=[Optional(),Length(min=6, max=30, message='The password must be between 6 and 20 characters long.')]) + notify = BooleanField('Notify accout creation by email', render_kw={'checked': True}) class DeleteUser(FlaskForm): password = PasswordField('Confirm Your Password', validators=[InputRequired(), Length(min=6, max=30, message='The password must be between 6 and 20 characters long.')]) diff --git a/ref-test/app/models/user.py b/ref-test/app/models/user.py index 9d45103..f950da3 100644 --- a/ref-test/app/models/user.py +++ b/ref-test/app/models/user.py @@ -51,13 +51,11 @@ class User(UserMixin, db.Model): def get_email(self): return decrypt(self.email) - def register(self): + def register(self, notify:bool=False): users = User.query.all() for user in users: - if user.get_username() == self.get_username(): - return False, f'Username {self.get_username()} already in use.' - elif user.get_email() == self.get_email(): - return False, f'Email address {self.get_email()} already in use.' + if user.get_username() == self.get_username(): return False, f'Username {self.get_username()} already in use.' + if user.get_email() == self.get_email(): return False, f'Email address {self.get_email()} already in use.' db.session.add(self) db.session.commit() write('users.log', f'User \'{self.get_username()}\' was created with id \'{self.id}\'.')