From 76fb0aa94f6b1a10417d808715dde1b13c39e0a1 Mon Sep 17 00:00:00 2001 From: Gabriel De Los Rios Date: Sat, 23 Nov 2024 19:53:27 -0300 Subject: [PATCH] feat(users): adds login functionality --- app/services/user_service.py | 21 +++++++++++++-- app/static/css/login.css | 9 +++++++ app/templates/users/login.html | 49 +++++++++++++++++++++++++++++++--- app/users/routes.py | 10 +++++-- 4 files changed, 82 insertions(+), 7 deletions(-) create mode 100644 app/static/css/login.css diff --git a/app/services/user_service.py b/app/services/user_service.py index 6015c5a..9b5a7f7 100644 --- a/app/services/user_service.py +++ b/app/services/user_service.py @@ -1,5 +1,5 @@ from werkzeug.datastructures import ImmutableMultiDict -from werkzeug.security import generate_password_hash +from werkzeug.security import generate_password_hash, check_password_hash from flask import flash, session from app.models.user import User @@ -47,4 +47,21 @@ class UserService: raise UserRegisterErrors("Something went wrong") except UserRegisterErrors as e: flash(FlashMessage(e.message, AlertType.DANGER.value )) - db.session.rollback() \ No newline at end of file + db.session.rollback() + + @staticmethod + def login(form: ImmutableMultiDict): + try: + email = UserValidators.is_valid_email(form.get("email")) + password = UserValidators.is_valid_password(form.get("password")) + user_row = db.session.execute(db.select(User).filter_by(email=email)).one_or_none() + if user_row is not None: + if check_password_hash(user_row[0].password, password): + session["id"] = user_row[0].id + return True + flash(FlashMessage("Invalid email or password", AlertType.DANGER.value )) + return False + except UserRegisterErrors as e: + flash(FlashMessage(e.message, AlertType.DANGER.value )) + + \ No newline at end of file diff --git a/app/static/css/login.css b/app/static/css/login.css new file mode 100644 index 0000000..2a21e10 --- /dev/null +++ b/app/static/css/login.css @@ -0,0 +1,9 @@ +.login { + max-width: 480px; +} +.register__form-button { + width: 100%; + @media(min-width: 576px) { + width: 200px; + } +} \ No newline at end of file diff --git a/app/templates/users/login.html b/app/templates/users/login.html index 25ba7ee..0c4d900 100644 --- a/app/templates/users/login.html +++ b/app/templates/users/login.html @@ -1,8 +1,51 @@ -{% extends "layout/layout.html" %} +{% extends "layout/layout.html" %} +{% from "layout/inner_header.html" import inner_header%} +{% from "forms/validation-block.html" import form_field_validation %} +{% from "forms/submit-btn.html" import form_submit_button %} {% block title %} Login {% endblock %} {% block head %} {{ super() }} + {% endblock %} {% block content %} -

Login!

-{% endblock %} \ No newline at end of file +
+
+
+ {{ inner_header("Login") }} +
+
+
+ + + {{ form_field_validation(FORM_ERRORS['REQUIRED'] + " " + FORM_ERRORS['VALID_EMAIL']) }} +
+
+ + + {{ form_field_validation(FORM_ERRORS['REQUIRED'] + " " + FORM_ERRORS['PASSWORD_LENGTH']) }} +
+
+ {{ form_submit_button("Login") }} +
+
+
+
+ +{% endblock %} diff --git a/app/users/routes.py b/app/users/routes.py index 70ca25a..434ae30 100644 --- a/app/users/routes.py +++ b/app/users/routes.py @@ -2,13 +2,19 @@ from flask import redirect, request, render_template, session from app.services.user_service import UserService from app.users import bp from app.utils.form_errors_dict import FORM_ERRORS +from app.utils.helpers import login_required + @bp.route('/') +@login_required def index(): return render_template("users/index.html") -@bp.route('/login') +@bp.route('/login', methods=["GET", "POST"]) def login(): - return render_template("users/login.html") + if request.method == 'POST': + if UserService.login(request.form): + return redirect("/") + return render_template("users/login.html", FORM_ERRORS=FORM_ERRORS) @bp.route('/logout') def logout():