def load_user(user_id):
    user_data = db.child("users").child(user_id).get()
    if user_data.val() is None:
        return None
    user = User()
    user.id = user_data.val()["id"]
    user.email = user_data.val()["email"]
    return user
def profile_edit_add():
    status = User().update_user(request.form)
    if status == "Success":
        return redirect('/profile')
    else:
        id = request.form.get('id', None)
        user, _ = User().get_user(db, id)
        context = {"parameters": User().get_parameters(), "user": user}
        return render_template('profile_edit.html', **context)
def login():
    login_form = LoginForm(request.form)
    if request.method == 'POST' and login_form.validate():
        user = User()
        user.email = login_form.email.data
        user.password = login_form.password.data
        login_result = login_form.login(user)
        if login_result >= 0:
            user.id = login_result
            login_user(user)
            return redirect(url_for('router.search'))
        if login_result == -1:
            flash("Incorrect email or password")
        if login_result == -3:
            return redirect(url_for('router.reset_password'))
    return render_template('index.html',
                           login_form=LoginForm(),
                           signup_form=SignUpForm())
def search():
    search = searchBar()
    if search.validate_on_submit():
        user = User()
        name, score = closest_match(search.ta_name.data)[0]
        num_views = user.number_views()

        if num_views is not None:
            if num_views <= 0 and not user.ta_viewable(name):
                return redirect('/purchase_credits')
            # if match score less than 90, don't redirect and waste a view
            if score < 90:
                return render_template('search.html', form=search)
            else:
                user.handle_viewlist(name)
                return redirect('/TA/' + name)

    return render_template('search.html', form=search)
def reset_with_token(token):
    try:
        password_reset_serializer = URLSafeTimedSerializer(
            current_app.config['SECRET_KEY'])
        email = password_reset_serializer.loads(token,
                                                salt='password-reset-salt',
                                                max_age=3600)
    except:
        flash('The password reset link is invalid or has expired.', 'error')
        return redirect(url_for('router.home'))

    form = PasswordForm()

    if form.validate_on_submit():
        found = False
        users = db.child("users").get()
        for u in users.each():
            data = u.val()
            if data['email'] == email:
                curr_user = User()
                found = True
                id = data['id']
                curr_pass = data['password']
                if curr_user.decrypt(curr_pass, form.password.data):
                    flash('new password cannot be a previous password')
                    return render_template('reset_password_with_token.html',
                                           form=form,
                                           token=token)

                payload = {}
                payload['password'] = curr_user.encrypt(form.password.data)
                db.child("users").child(id).update(payload)
                curr_user.update_password_reset(id)
                break
        flash('Your password has been updated!', 'success')
        return redirect(url_for('router.home'))
    return render_template('reset_password_with_token.html',
                           form=form,
                           token=token)
    def create_unauthenticated_user(self, db, signup_form):
        # SEND AN EMAIL CONFIRMATION
        self.send_confirmation_email(signup_form.email_addr.data)
        # CREATES A USER AND PUSHES IT INTO DB
        new_user = User()
        new_user.id = len(db.child("users").get().val())
        new_user.email = signup_form.email_addr.data
        new_user.first_name = signup_form.first_name.data
        new_user.last_name = signup_form.last_name.data
        new_user.password = new_user.encrypt(
            signup_form.password.data)  # encrypt the password
        new_user.authenticated = False
        reset_date = datetime.datetime.now() + datetime.timedelta(6 * 365 / 12)
        new_user.password_reset = reset_date.isoformat()
        new_user.credits = 0
        new_user.num_lockouts = 0
        last_lockout = datetime.datetime.now()
        new_user.last_lockout = last_lockout.isoformat()
        new_user.viewable_ta = ""
        new_user.remaining_views = 3

        db.child("users").child(new_user.id).set(json.loads(new_user.toJSON()))
        db.child("users").child(new_user.id).child('viewable_ta').push({
            'name':
            "placeholder",
            'rated':
            False
        })
def profile_edit():
    id = request.args.get('id', None)
    parameters = User().get_parameters()
    user, _ = User().get_user(db, id)
    context = {"parameters": parameters, "user": user}
    return render_template('profile_edit.html', **context)
def profile():
    current_session_user = db.child("users").child(current_user.id).get().val()
    id = int(current_session_user['id'])
    user, ta_list = User().get_user(db, id)
    context = {"user": user, "ta_list": ta_list}
    return render_template('profile.html', **context)
    def login(self, user):
        decrypter = User()  # we need the decrypt function from the user
        users = db.child("users").get()

        for u in users.each():
            data = u.val()
            if data['email'] == user.email and decrypter.decrypt(
                    data["password"],
                    user.password):  #data["password"] == user.password:
                last_lockout = data['last_lockout']
                last_lockout = datetime.datetime.strptime(
                    last_lockout, '%Y-%m-%dT%H:%M:%S.%f')
                if last_lockout > datetime.datetime.now():
                    flash(
                        "Too many login attempts. Please try again in 5 minutes"
                    )
                    return -4
                if data['authenticated'] is False:
                    flash("Account not authenticated. Please reauthenticate.")
                    return -2
                reset_date = data['password_reset']
                reset_date_obj = datetime.datetime.strptime(
                    reset_date, '%Y-%m-%dT%H:%M:%S.%f')
                if reset_date_obj < datetime.datetime.now():
                    flash("Password has expired. Please reset your password")
                    return -3
                id = data['id']
                db.child('users').child(id).update({"num_lockouts": 0})
                return int(data['id'])
            #incorrect password
            elif data['email'] == user.email:
                id = data['id']
                num_lockouts = data['num_lockouts']
                last_lockout = data['last_lockout']
                last_lockout = datetime.datetime.strptime(
                    last_lockout, '%Y-%m-%dT%H:%M:%S.%f')
                num_lockouts += 1
                if last_lockout < datetime.datetime.now():
                    if num_lockouts % 5 == 0:
                        last_lockout = datetime.datetime.now() + timedelta(
                            minutes=5)
                        last_lockout = last_lockout.isoformat()
                        flash(
                            "Too many login attempts. Please try again in 5 minutes"
                        )
                        db.child('users').child(id).update({
                            "num_lockouts":
                            num_lockouts,
                            "last_lockout":
                            last_lockout
                        })
                        return -4
                    else:
                        db.child('users').child(id).update(
                            {"num_lockouts": num_lockouts})
                        return -1
                else:
                    flash(
                        "Too many login attempts. Please try again in 5 minutes"
                    )
                    return -2
        return -1