feat(users): adds login functionality

This commit is contained in:
2024-11-23 19:53:27 -03:00
parent 46a364dac7
commit 76fb0aa94f
4 changed files with 82 additions and 7 deletions

View File

@@ -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
@@ -48,3 +48,20 @@ class UserService:
except UserRegisterErrors as e:
flash(FlashMessage(e.message, AlertType.DANGER.value ))
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 ))

9
app/static/css/login.css Normal file
View File

@@ -0,0 +1,9 @@
.login {
max-width: 480px;
}
.register__form-button {
width: 100%;
@media(min-width: 576px) {
width: 200px;
}
}

View File

@@ -1,8 +1,51 @@
{% 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() }}
<link rel="stylesheet" href="{{ url_for('static', filename='css/login.css') }}">
{% endblock %}
{% block content %}
<h1>Login!</h1>
<div class="login container h-100">
<div class="row">
<div class="col-12 my-3">
{{ inner_header("Login") }}
</div>
<form class="col-12 needs-validation h-100" method="post" novalidate>
<div class="mb-3">
<label for="email" class="form-label">Email</label>
<input
class="form-control"
id="email"
name="email"
pattern="[A-Za-z0-9._%+\-]+@[A-Za-z0-9.\-]+\.[A-Za-z]{2,}$"
placeholder="Enter your email address"
required
type="text"
>
{{ form_field_validation(FORM_ERRORS['REQUIRED'] + " " + FORM_ERRORS['VALID_EMAIL']) }}
</div>
<div class="mb-3">
<label for="password" class="form-label">Password</label>
<input
class="form-control"
id="password"
maxlength="255"
minlength="6"
name="password"
placeholder="Enter password"
required
type="password"
>
{{ form_field_validation(FORM_ERRORS['REQUIRED'] + " " + FORM_ERRORS['PASSWORD_LENGTH']) }}
</div>
<div class="text-center mt-auto">
{{ form_submit_button("Login") }}
</div>
</form>
</div>
</div>
<script src="{{ url_for('static', filename='js/validate-form.js') }}"></script>
{% endblock %}

View File

@@ -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():