From eabc6e23be014ae921989ba31515ef28691af422 Mon Sep 17 00:00:00 2001 From: Ozzieisaacs Date: Sun, 15 Dec 2019 17:08:17 +0100 Subject: [PATCH] Test Email now send to user's email address (#834) Added forgot/reset password routine (#1098, #1063) --- cps/admin.py | 24 +++++++++--------------- cps/helper.py | 14 ++++++++++++++ cps/templates/login.html | 3 +++ cps/web.py | 37 ++++++++++++++++++++++++++----------- 4 files changed, 52 insertions(+), 26 deletions(-) diff --git a/cps/admin.py b/cps/admin.py index 3c64b01b..57796080 100644 --- a/cps/admin.py +++ b/cps/admin.py @@ -36,11 +36,10 @@ from flask_babel import gettext as _ from sqlalchemy import and_ from sqlalchemy.exc import IntegrityError from sqlalchemy.sql.expression import func -from werkzeug.security import generate_password_hash from . import constants, logger, helper, services from . import db, ub, web_server, get_locale, config, updater_thread, babel, gdriveutils -from .helper import speaking_language, check_valid_domain, send_test_mail, generate_random_password, send_registration_mail +from .helper import speaking_language, check_valid_domain, send_test_mail, reset_password, generate_password_hash from .gdriveutils import is_gdrive_ready, gdrive_support from .web import admin_required, render_title_template, before_request, unconfigured, login_required_if_no_ano @@ -524,15 +523,15 @@ def update_mailsettings(): config.save() if to_save.get("test"): - if current_user.kindle_mail: - result = send_test_mail(current_user.kindle_mail, current_user.nickname) + if current_user.email: + result = send_test_mail(current_user.email, current_user.nickname) if result is None: - flash(_(u"Test e-mail successfully send to %(kindlemail)s", kindlemail=current_user.kindle_mail), + flash(_(u"Test e-mail successfully send to %(kindlemail)s", kindlemail=current_user.email), category="success") else: flash(_(u"There was an error sending the Test e-mail: %(res)s", res=result), category="error") else: - flash(_(u"Please configure your kindle e-mail address first..."), category="error") + flash(_(u"Please configure your e-mail address first..."), category="error") else: flash(_(u"E-mail server settings updated"), category="success") @@ -644,15 +643,10 @@ def reset_password(user_id): if not config.config_public_reg: abort(404) if current_user is not None and current_user.is_authenticated: - existing_user = ub.session.query(ub.User).filter(ub.User.id == user_id).first() - password = generate_random_password() - existing_user.password = generate_password_hash(password) - try: - ub.session.commit() - send_registration_mail(existing_user.email, existing_user.nickname, password, True) - flash(_(u"Password for user %(user)s reset", user=existing_user.nickname), category="success") - except Exception: - ub.session.rollback() + ret, message = reset_password(user_id) + if ret == 1: + flash(_(u"Password for user %(user)s reset", user=message), category="success") + else: flash(_(u"An unknown error occurred. Please try again later."), category="error") return redirect(url_for('admin.admin')) diff --git a/cps/helper.py b/cps/helper.py index 9771d57a..025fc4d1 100644 --- a/cps/helper.py +++ b/cps/helper.py @@ -41,6 +41,7 @@ from flask_babel import gettext as _ from flask_login import current_user from sqlalchemy.sql.expression import true, false, and_, or_, text, func from werkzeug.datastructures import Headers +from werkzeug.security import generate_password_hash try: from urllib.parse import quote @@ -407,6 +408,19 @@ def delete_book_gdrive(book, book_format): return error +def reset_password(user_id): + existing_user = ub.session.query(ub.User).filter(ub.User.id == user_id).first() + password = generate_random_password() + existing_user.password = generate_password_hash(password) + try: + ub.session.commit() + send_registration_mail(existing_user.email, existing_user.nickname, password, True) + return (1, existing_user.nickname) + except Exception: + ub.session.rollback() + return (0, None) + + def generate_random_password(): s = "abcdefghijklmnopqrstuvwxyz01234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%&*()?" passlen = 8 diff --git a/cps/templates/login.html b/cps/templates/login.html index 4f01157b..4a259287 100644 --- a/cps/templates/login.html +++ b/cps/templates/login.html @@ -18,6 +18,9 @@ + {% if config.config_login_type == 0 and mail%} + + {% endif %} {% if config.config_remote_login %} {{_('Log in with magic link')}} {% endif %} diff --git a/cps/web.py b/cps/web.py index 7823be39..572ac969 100644 --- a/cps/web.py +++ b/cps/web.py @@ -38,8 +38,7 @@ from flask import render_template, request, redirect, send_from_directory, make_ from flask_babel import gettext as _ from flask_login import login_user, logout_user, login_required, current_user from sqlalchemy.exc import IntegrityError -from sqlalchemy.sql.expression import text, func, true, false, not_, and_, \ - exists +from sqlalchemy.sql.expression import text, func, true, false, not_, and_, exists from werkzeug.exceptions import default_exceptions from werkzeug.datastructures import Headers from werkzeug.security import generate_password_hash, check_password_hash @@ -50,7 +49,7 @@ from .gdriveutils import getFileFromEbooksFolder, do_gdrive_download from .helper import common_filters, get_search_results, fill_indexpage, speaking_language, check_valid_domain, \ order_authors, get_typeahead, render_task_status, json_serial, get_cc_columns, \ get_book_cover, get_download_link, send_mail, generate_random_password, send_registration_mail, \ - check_send_to_kindle, check_read_formats, lcase, tags_filters + check_send_to_kindle, check_read_formats, lcase, tags_filters, reset_password from .pagination import Pagination from .redirect import redirect_back @@ -1043,7 +1042,7 @@ def download_link(book_id, book_format): @download_required def send_to_kindle(book_id, book_format, convert): settings = config.get_mail_settings() - if settings.get("mail_server", "mail.example.com") == "mail.example.com": + if settings.get("mail_server", "mail.example.org") == "mail.example.org": flash(_(u"Please configure the SMTP mail settings first..."), category="error") elif current_user.kindle_mail: result = send_mail(book_id, book_format, convert, current_user.kindle_mail, config.config_calibre_dir, @@ -1140,17 +1139,33 @@ def login(): log.info('LDAP Login failed for user "%s" IP-adress: %s', form['username'], ipAdress) flash(_(u"Wrong Username or Password"), category="error") else: - if user and check_password_hash(str(user.password), form['password']) and user.nickname != "Guest": - login_user(user, remember=True) - flash(_(u"You are now logged in as: '%(nickname)s'", nickname=user.nickname), category="success") - return redirect_back(url_for("web.index")) ipAdress = request.headers.get('X-Forwarded-For', request.remote_addr) - log.info('Login failed for user "%s" IP-adress: %s', form['username'], ipAdress) - flash(_(u"Wrong Username or Password"), category="error") + if 'forgot' in form and form['forgot'] == 'forgot': + if user != None and user.nickname != "Guest": + ret, __ = reset_password(user.id) + if ret == 1: + flash(_(u"New Password was send to your email address"), category="info") + log.info('Password reset for user "%s" IP-adress: %s', form['username'], ipAdress) + else: + flash(_(u"An unknown error occurred. Please try again later."), category="error") + else: + flash(_(u"Please enter valid username to reset password"), category="error") + log.info('Username missing for password reset IP-adress: %s', ipAdress) + else: + if user and check_password_hash(str(user.password), form['password']) and user.nickname != "Guest": + login_user(user, remember=True) + flash(_(u"You are now logged in as: '%(nickname)s'", nickname=user.nickname), category="success") + return redirect_back(url_for("web.index")) + else: + log.info('Login failed for user "%s" IP-adress: %s', form['username'], ipAdress) + flash(_(u"Wrong Username or Password"), category="error") + settings = config.get_mail_settings() + mail_configured = bool(settings.get("mail_server", "mail.example.org") != "mail.example.org") next_url = url_for('web.index') - return render_title_template('login.html', title=_(u"login"), next_url=next_url, config=config, page="login") + return render_title_template('login.html', title=_(u"login"), next_url=next_url, config=config, + mail = mail_configured, page="login") @web.route('/logout')