| @ -0,0 +1,62 @@ | |||
| from flask import Blueprint, render_template, redirect, url_for, request, flash | |||
| from werkzeug.security import generate_password_hash, check_password_hash | |||
| from flask_login import login_user, logout_user, login_required | |||
| from .models import User | |||
| from . import db | |||
| bp = Blueprint('auth', __name__) | |||
| @bp.route('/login') | |||
| def login(): | |||
| return render_template('login.html') | |||
| @bp.route('/login', methods=['POST']) | |||
| def login_post(): | |||
| email = request.form.get('email') | |||
| password = request.form.get('password') | |||
| remember = True if request.form.get('remember') else False | |||
| user = User.query.filter_by(email=email).first() | |||
| # check if the user actually exists | |||
| # take the user-supplied password, hash it, and compare it to the hashed password in the database | |||
| if not user or not check_password_hash(user.password, password): | |||
| flash('Por favor, comprueba los datos de registro y vuelve a intentarlo.') | |||
| return redirect(url_for('auth.login')) # if the user doesn't exist or password is wrong, reload the page | |||
| # if the above check passes, then we know the user has the right credentials | |||
| login_user(user, remember=remember) | |||
| return redirect(url_for('reservas.misreservas')) | |||
| @bp.route('/signup') | |||
| def signup(): | |||
| return render_template('signup.html') | |||
| @bp.route('/signup', methods=['POST']) | |||
| def signup_post(): | |||
| email = request.form.get('email') | |||
| name = request.form.get('name') | |||
| password = request.form.get('password') | |||
| user = User.query.filter_by(email=email).first() # if this returns a user, then the email already exists in database | |||
| if user: # if a user is found, we want to redirect back to signup page so user can try again | |||
| flash('La dirección de correo ya existe') | |||
| return redirect(url_for('auth.signup')) | |||
| # create a new user with the form data. Hash the password so the plaintext version isn't saved. | |||
| new_user = User(email=email, name=name, password=generate_password_hash(password, method='pbkdf2:sha256')) | |||
| # add the new user to the database | |||
| db.session.add(new_user) | |||
| db.session.commit() | |||
| return redirect(url_for('auth.login')) | |||
| @bp.route('/logout') | |||
| @login_required | |||
| def logout(): | |||
| logout_user() | |||
| return redirect(url_for('auth.index')) | |||
| @ -0,0 +1,75 @@ | |||
| <nav class="navbar is-dark" role="navigation" aria-label="main navigation"> | |||
| <div class="navbar-brand"> | |||
| <img src="./static/bruce.jpeg" class="image is-48x48"/> | |||
| <a class="navbar-item" href="/">Letras de canciones</a> | |||
| <div class="navbar-burger" role="button" data-target="navMenu"> | |||
| <span></span> | |||
| {% if current_user.is_authenticated %} | |||
| <span></span> | |||
| <span></span> | |||
| {% else %} | |||
| <span></span> | |||
| <span></span> | |||
| {% endif %} | |||
| </div> | |||
| </div> | |||
| <div class="navbar-menu" id="navMenu"> | |||
| <div class="navbar-end"> | |||
| <a class="navbar-item" href="{{ url_for('paginas.index') }}" > | |||
| Inicio | |||
| </a> | |||
| <div class="navbar-item"> | |||
| <!-- <div class="buttons">--> | |||
| {% if current_user.is_authenticated %} | |||
| <div class="navbar-item has-dropdown is-hoverable"> | |||
| <a class="navbar-link"> | |||
| {{ current_user.name }} | |||
| </a> | |||
| <div class="navbar-dropdown"> | |||
| <a href="{{ url_for('reservas.misreservas') }}" class="navbar-item">Mis reservas</a> | |||
| <a href="{{ url_for('auth.logout') }}" class="navbar-item">Salir</a> | |||
| </div> | |||
| </div> | |||
| {% else %} | |||
| <a href="{{ url_for('auth.login') }}" class="button is-primary">Entrar</a> | |||
| <a href="{{ url_for('auth.signup') }}" class="button is-light">Registrarse</a> | |||
| {% endif %} | |||
| <!--</div>--> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| <script> | |||
| document.addEventListener('DOMContentLoaded', function () { | |||
| // Get all "navbar-burger" elements | |||
| var $navbarBurgers = Array.prototype.slice.call(document.querySelectorAll('.navbar-burger'), 0); | |||
| // Check if there are any navbar burgers | |||
| if ($navbarBurgers.length > 0) { | |||
| // Add a click event on each of them | |||
| $navbarBurgers.forEach(function ($el) { | |||
| $el.addEventListener('click', function () { | |||
| // Get the target from the "data-target" attribute | |||
| var target = $el.dataset.target; | |||
| var $target = document.getElementById(target); | |||
| // Toggle the class on both the "navbar-burger" and the "navbar-menu" | |||
| $el.classList.toggle('is-active'); | |||
| $target.classList.toggle('is-active'); | |||
| }); | |||
| }); | |||
| } | |||
| }); | |||
| </script> | |||
| </nav> | |||
| @ -0,0 +1,36 @@ | |||
| {% extends "base.html" %} | |||
| {% block content %} | |||
| <div class="column is-4 is-offset-4"> | |||
| <h3 class="title">Login</h3> | |||
| <div class="box"> | |||
| {% with messages = get_flashed_messages() %} | |||
| {% if messages %} | |||
| <div class="notification is-danger"> | |||
| {{ messages[0] }} | |||
| </div> | |||
| {% endif %} | |||
| {% endwith %} | |||
| <form method="POST" action="/login"> | |||
| <div class="field"> | |||
| <div class="control"> | |||
| <input class="input is-large" type="email" name="email" placeholder="Tu correo" autofocus=""> | |||
| </div> | |||
| </div> | |||
| <div class="field"> | |||
| <div class="control"> | |||
| <input class="input is-large" type="password" name="password" placeholder="Tu contraseña"> | |||
| </div> | |||
| </div> | |||
| <div class="field"> | |||
| <label class="checkbox"> | |||
| <input type="checkbox"> | |||
| Recuerdame | |||
| </label> | |||
| </div> | |||
| <button class="button is-block is-info is-large is-fullwidth">Entrar</button> | |||
| </form> | |||
| </div> | |||
| </div> | |||
| {% endblock %} | |||
| @ -0,0 +1,56 @@ | |||
| {% extends "base.html" %} | |||
| {% block content %} | |||
| <div class="column is-4 is-offset-4"> | |||
| <h3 class="title">Nuevo usuario</h3> | |||
| <div class="box"> | |||
| {% with messages = get_flashed_messages() %} | |||
| {% if messages %} | |||
| <div class="notification is-danger"> | |||
| {{ messages[0] }}. Go to <a href="{{ url_for('auth.login') }}">login page</a>. | |||
| </div> | |||
| {% endif %} | |||
| {% endwith %} | |||
| <form method="POST" action="/signup"> | |||
| <div class="field"> | |||
| <div class="control"> | |||
| <input class="input is-large" type="email" name="email" placeholder="Email" autofocus=""> | |||
| </div> | |||
| </div> | |||
| <div class="field"> | |||
| <div class="control"> | |||
| <input class="input is-large" type="text" name="name" placeholder="Nombre" autofocus=""> | |||
| </div> | |||
| </div> | |||
| <div class="field"> | |||
| <div class="control"> | |||
| <input class="input is-large" type="password" name="password" placeholder="Password"> | |||
| </div> | |||
| </div> | |||
| <button class="button is-block is-info is-large is-fullwidth">Registrarse</button> | |||
| </form> | |||
| </div> | |||
| <div class="box"> | |||
| <article class="media"> | |||
| <div class="media-content"> | |||
| <div class="content"> | |||
| <h3> | |||
| Información importante. | |||
| </h3> | |||
| <p> | |||
| El correo se usará exclusivamente para informarte de que has hecho una reserva. | |||
| </p> | |||
| <p> | |||
| El nombre aparecerá en el listado de reservas. | |||
| </p> | |||
| </div> | |||
| </div> | |||
| </article> | |||
| </div> | |||
| </div> | |||
| {% endblock %} | |||
| @ -1,11 +1,14 @@ | |||
| blinker==1.8.2 | |||
| click==8.1.7 | |||
| Flask==3.0.3 | |||
| Flask-Login==0.6.3 | |||
| Flask-SQLAlchemy==3.1.1 | |||
| greenlet==3.0.3 | |||
| gunicorn==22.0.0 | |||
| itsdangerous==2.2.0 | |||
| Jinja2==3.1.4 | |||
| MarkupSafe==2.1.5 | |||
| packaging==24.1 | |||
| SQLAlchemy==2.0.31 | |||
| typing_extensions==4.12.2 | |||
| Werkzeug==3.0.3 | |||
| gunicorn==22.0.0 | |||