import threading from datetime import datetime from sqlalchemy import DateTime, cast, func from validate_email import validate_email from flask_mail import Message from flask import current_app, render_template, url_for from app import db, mail from app.models import User from .lock import Lock from .reservation import ReservationController from .record import RecordController from ..exceptions import ActiveReservationExistsError, \ ActiveRecordExistsError, NoActiveRecordError, ReservationExpiredError, \ NoFreeWorkplaceError, UserRegistrationInvalidDataError class UserController(): @staticmethod def check_user_data(name, email, telegram_id=None, password=None, password2=None): errors = [] if name is None or len(name) < 3: errors.append('name') if not validate_email(email_address=email, \ check_regex=True, \ check_mx=False, \ use_blacklist=True, \ debug=False) or \ User.query.filter(User.email == email).count(): errors.append('email') if telegram_id is not None and User.query.filter(User.telegram_id == telegram_id).count() > 0: errors.append('telegram_id') if telegram_id is None and (password is None or len(password) == 0): errors.append('password') if password != password2: errors.append('password2') if len(errors) > 0: raise UserRegistrationInvalidDataError(errors) @classmethod def create(cls, name, email, telegram_id=None, telegram_chat_id=None, password=None): cls.check_user_data( \ name=name, \ email=email, \ telegram_id=telegram_id, \ password=password, \ password2=password) user = User() user.name = name user.email = email user.telegram_id = telegram_id user.telegram_chat_id = telegram_chat_id user.generate_new_token() if password is not None: user.set_password(password) db.session.add(user) db.session.commit() cls.send_confirm_email(user) @staticmethod def update(user, name=None, email=None, telegram_chat_id=None): if name: user.name = name if email: user.email = email user.is_confirmed = False if telegram_chat_id: user.telegram_chat_id = telegram_chat_id db.session.commit() @staticmethod def get(user_id): return User.query.get(user_id) @staticmethod def get_by_email(email): return User.query.filter(User.email == email).first() @staticmethod def get_by_telegram_user_id(telegram_user_id): return User.query.filter(User.telegram_id == telegram_user_id).first() @classmethod def verify_confirm_email(cls, email, token): user = cls.get_by_email(email) return user is not None and user.is_token_valid(token) @classmethod def confirm_email(cls, email, token): user = cls.get_by_email(email) if user is None or not user.is_token_valid(token): return False user.is_confirmed = True user.generate_new_token() db.session.commit() return True @classmethod def reset_password(cls, email, token, password): user = cls.get_by_email(email) if user is None or not user.is_token_valid(token): return False user.set_password(password) user.generate_new_token() db.session.commit() return True @staticmethod def reserve(user): if ReservationController.has_active_reservation(user): raise ActiveReservationExistsError if RecordController.has_active_record(user): raise ActiveRecordExistsError return ReservationController.create(user) @staticmethod def start_record(user): if RecordController.has_active_record(user): raise ActiveRecordExistsError reservation = ReservationController.get_active_reservation(user) if reservation is not None: RecordController.create_from_reservation(reservation) else: RecordController.create(user) @staticmethod def terminate_record(user): record = RecordController.get_active_record(user) if record is None: raise NoActiveRecordError RecordController.terminate(record) @classmethod def unlink_telegram_user_id(cls, telegram_user_id): user = cls.get_by_telegram_user_id(telegram_user_id) if user: user.telegram_id = None user.telegram_chat_id = None db.session.commit() @staticmethod def get_password_reset_link(user): user.generate_new_token() db.session.commit() return url_for('login.password_reset', token=user.token, email=user.email, _external=True) @classmethod def send_password_reset_email(cls, user): password_reset_link = cls.get_password_reset_link(user) msg = Message(subject='[Bastli Bouncer] Reset Password', body=render_template('email/password_reset.txt', user=user, password_reset_link=password_reset_link), recipients=[user.email]) print(password_reset_link) mail.send(msg) @staticmethod def send_confirm_email(user): msg = Message( subject='[Bastli Bouncer] Confirm Email Address', body=render_template('email/confirm.txt', user=user), recipients=[user.email]) print(url_for('login.confirm_email', token=user.token, email=user.email, _external=True)) mail.send(msg)