Finished auth
This commit is contained in:
parent
47d549be85
commit
b3b8a3fd5f
77
app.py
77
app.py
@ -1,12 +1,30 @@
|
|||||||
import datetime
|
import datetime
|
||||||
|
import hashlib
|
||||||
|
|
||||||
from flask import Flask, render_template, redirect, url_for, request
|
from flask import Flask, render_template, redirect, url_for, request
|
||||||
from flask_login import login_required, LoginManager
|
from flask_login import login_required, LoginManager, login_user, logout_user, current_user
|
||||||
|
|
||||||
from models.User import User
|
from models.User import User
|
||||||
|
from utils import anonymous_required
|
||||||
|
|
||||||
# Create a new Flask instance
|
# Create a new Flask instance
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
|
app.secret_key = 'PSSSSSHHHT!'
|
||||||
|
|
||||||
|
# Initialize the Flask-Login extension
|
||||||
|
login_manager = LoginManager()
|
||||||
|
login_manager.login_view = 'login'
|
||||||
|
login_manager.init_app(app)
|
||||||
|
|
||||||
|
|
||||||
|
@login_manager.user_loader
|
||||||
|
def load_user(user_id):
|
||||||
|
return User.get(user_id)
|
||||||
|
|
||||||
|
|
||||||
|
@app.context_processor
|
||||||
|
def inject_user():
|
||||||
|
return dict(user=current_user)
|
||||||
|
|
||||||
|
|
||||||
# Create a new route
|
# Create a new route
|
||||||
@ -15,20 +33,25 @@ def index():
|
|||||||
# return 'Hello World'
|
# return 'Hello World'
|
||||||
return render_template('index.html', title='Home', utc_dt=datetime.datetime.now().strftime("%d.%m.%Y %H:%M:%S"))
|
return render_template('index.html', title='Home', utc_dt=datetime.datetime.now().strftime("%d.%m.%Y %H:%M:%S"))
|
||||||
|
|
||||||
|
|
||||||
@app.route('/test')
|
@app.route('/test')
|
||||||
@login_required
|
@login_required
|
||||||
def secret():
|
def secret():
|
||||||
return 'Pssst!'
|
return 'Pssst!'
|
||||||
|
|
||||||
|
|
||||||
@app.route('/login')
|
@app.route('/login')
|
||||||
|
@anonymous_required
|
||||||
def login():
|
def login():
|
||||||
return render_template('auth/login.html')
|
return render_template('auth/login.html', errors={})
|
||||||
|
|
||||||
|
|
||||||
@app.route('/signup')
|
@app.route('/signup')
|
||||||
|
@anonymous_required
|
||||||
def signup():
|
def signup():
|
||||||
return render_template('auth/signup.html', errors={})
|
return render_template('auth/signup.html', errors={})
|
||||||
|
|
||||||
|
|
||||||
@app.route('/signup', methods=['POST'])
|
@app.route('/signup', methods=['POST'])
|
||||||
def signup_post():
|
def signup_post():
|
||||||
email = request.form.get('email')
|
email = request.form.get('email')
|
||||||
@ -44,6 +67,7 @@ def signup_post():
|
|||||||
if not password:
|
if not password:
|
||||||
errors['password'] = 'Password is required.'
|
errors['password'] = 'Password is required.'
|
||||||
|
|
||||||
|
if errors:
|
||||||
return render_template(
|
return render_template(
|
||||||
'auth/signup.html',
|
'auth/signup.html',
|
||||||
email=email,
|
email=email,
|
||||||
@ -53,27 +77,56 @@ def signup_post():
|
|||||||
)
|
)
|
||||||
|
|
||||||
# Save user to database. Maybe log the user in directly.
|
# Save user to database. Maybe log the user in directly.
|
||||||
|
user = User.create(name, email, password)
|
||||||
|
login_user(user)
|
||||||
|
|
||||||
# Redirect to login page
|
# Redirect to login page
|
||||||
return redirect(url_for('login'))
|
return redirect(url_for('secret'))
|
||||||
|
|
||||||
|
|
||||||
|
@app.route('/login', methods=['POST'])
|
||||||
|
def login_post():
|
||||||
|
email = request.form.get('email')
|
||||||
|
password = request.form.get('password')
|
||||||
|
|
||||||
|
# Check for errors
|
||||||
|
errors = {}
|
||||||
|
if not email:
|
||||||
|
errors['email'] = 'Email is required.'
|
||||||
|
if not password:
|
||||||
|
errors['password'] = 'Password is required.'
|
||||||
|
|
||||||
|
# Check if user exists
|
||||||
|
user = User.get_by_email(email)
|
||||||
|
|
||||||
|
if not user:
|
||||||
|
errors['email'] = 'User does not exist.'
|
||||||
|
elif user.password is None or hashlib.sha256(password.encode()).hexdigest() != user.password:
|
||||||
|
errors['password'] = 'Password incorrect.'
|
||||||
|
|
||||||
|
if errors:
|
||||||
|
return render_template(
|
||||||
|
'auth/login.html',
|
||||||
|
email=email,
|
||||||
|
password=password,
|
||||||
|
errors=errors
|
||||||
|
)
|
||||||
|
|
||||||
|
login_user(user)
|
||||||
|
|
||||||
|
# Redirect to login page
|
||||||
|
return redirect(url_for('secret'))
|
||||||
|
|
||||||
|
|
||||||
@app.route('/logout')
|
@app.route('/logout')
|
||||||
@login_required
|
@login_required
|
||||||
def logout():
|
def logout():
|
||||||
# Log out functionality
|
# Log out functionality
|
||||||
|
logout_user()
|
||||||
|
|
||||||
return redirect(url_for('index'))
|
return redirect(url_for('index'))
|
||||||
|
|
||||||
|
|
||||||
# Run the application
|
# Run the application
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
login_manager = LoginManager()
|
|
||||||
login_manager.login_view = 'login'
|
|
||||||
login_manager.init_app(app)
|
|
||||||
app.secret_key = 'PSSSSSHHHT!'
|
|
||||||
|
|
||||||
@login_manager.user_loader
|
|
||||||
def load_user(user_id):
|
|
||||||
return User.get(user_id)
|
|
||||||
|
|
||||||
app.run(port=5000, debug=True)
|
app.run(port=5000, debug=True)
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
from datetime import datetime
|
||||||
import hashlib
|
import hashlib
|
||||||
import sqlite3
|
import sqlite3
|
||||||
|
|
||||||
@ -7,9 +8,11 @@ def con3():
|
|||||||
return conn
|
return conn
|
||||||
|
|
||||||
|
|
||||||
def create_user(name, email, password):
|
def create_user(name: str, email: str, password: str):
|
||||||
password = hashlib.md5(password.encode()).hexdigest()
|
password = hashlib.sha256(password.encode()).hexdigest()
|
||||||
query = f"INSERT INTO users (name, email, password) VALUES ({name}, {email}, {password})"
|
now = datetime.now().isoformat()
|
||||||
|
query = (f"INSERT INTO users (name, email, password, created_at, updated_at) VALUES ('{name}', '{email}', "
|
||||||
|
f"'{password}', '{now}', '{now}');")
|
||||||
conn = con3()
|
conn = con3()
|
||||||
cursor = conn.cursor()
|
cursor = conn.cursor()
|
||||||
cursor.execute(query)
|
cursor.execute(query)
|
||||||
@ -18,8 +21,18 @@ def create_user(name, email, password):
|
|||||||
return cursor.lastrowid
|
return cursor.lastrowid
|
||||||
|
|
||||||
|
|
||||||
def get_user(id):
|
def get_user(id: int):
|
||||||
query = f"SELECT * FROM users WHERE id = {id}"
|
query = f"SELECT * FROM users WHERE id = {id};"
|
||||||
|
conn = con3()
|
||||||
|
cursor = conn.cursor()
|
||||||
|
cursor.execute(query)
|
||||||
|
user = cursor.fetchone()
|
||||||
|
conn.close()
|
||||||
|
return user
|
||||||
|
|
||||||
|
|
||||||
|
def get_user_by_email(email: str):
|
||||||
|
query = f"SELECT * FROM users WHERE email = '{email}';"
|
||||||
conn = con3()
|
conn = con3()
|
||||||
cursor = conn.cursor()
|
cursor = conn.cursor()
|
||||||
cursor.execute(query)
|
cursor.execute(query)
|
||||||
|
|||||||
BIN
db/db.sqlite
BIN
db/db.sqlite
Binary file not shown.
@ -1,18 +1,26 @@
|
|||||||
from db.SQLiteClient import create_user, get_user
|
from flask_login import UserMixin
|
||||||
|
|
||||||
|
from db.SQLiteClient import create_user, get_user, get_user_by_email
|
||||||
|
|
||||||
|
|
||||||
class User:
|
class User(UserMixin):
|
||||||
def __init__(self, id, name, email):
|
def __init__(self, id, name, email, password=None):
|
||||||
self.id = id
|
self.id = id
|
||||||
self.name = name
|
self.name = name
|
||||||
self.email = email
|
self.email = email
|
||||||
|
self.password = password
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def create(name, email, password):
|
def create(name: str, email: str, password: str):
|
||||||
id = create_user(name, email, password)
|
id = create_user(name, email, password)
|
||||||
return User(id, name, email)
|
return User(id, name, email)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get(id):
|
def get(id: int):
|
||||||
user = get_user(id)
|
user = get_user(id)
|
||||||
return User(user[0], user[1], user[2]) if user else None
|
return User(user[0], user[1], user[2], user[3]) if user else None
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_by_email(email: str):
|
||||||
|
user = get_user_by_email(email)
|
||||||
|
return User(user[0], user[1], user[2], user[3]) if user else None
|
||||||
|
|||||||
@ -8,19 +8,25 @@
|
|||||||
<div class="mb-3 row">
|
<div class="mb-3 row">
|
||||||
<label for="email" class="col-sm-2 col-form-label">Email</label>
|
<label for="email" class="col-sm-2 col-form-label">Email</label>
|
||||||
<div class="col-sm-10">
|
<div class="col-sm-10">
|
||||||
<input type="email" class="form-control" id="email" placeholder="email@example.com">
|
<input type="email" value="{{ email }}" class="form-control {% if errors.get('email') %} is-invalid {% endif %}" id="email" placeholder="email@example.com" name="email">
|
||||||
|
<div class="invalid-feedback">
|
||||||
|
{{ errors.get('email', '') }}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="mb-3 row">
|
<div class="mb-3 row">
|
||||||
<label for="password" class="col-sm-2 col-form-label">Passwort</label>
|
<label for="password" class="col-sm-2 col-form-label">Passwort</label>
|
||||||
<div class="col-sm-10">
|
<div class="col-sm-10">
|
||||||
<input type="email" class="form-control" id="password">
|
<input type="password" value="{{ password }}" class="form-control {% if errors.get('password') %} is-invalid {% endif %}" id="password" name="password">
|
||||||
|
<div class="invalid-feedback">
|
||||||
|
{{ errors.get('password', '') }}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col-auto">
|
<div class="col-auto">
|
||||||
<button type="submit" class="btn btn-primary mb-3">Einloggen</button>
|
<button type="submit" class="btn btn-primary mb-3">Login</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -36,12 +36,18 @@
|
|||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<ul class="navbar-nav mb-2 mb-lg-0">
|
<ul class="navbar-nav mb-2 mb-lg-0">
|
||||||
|
{% if not current_user.is_authenticated %}
|
||||||
<li class="nav-item me-2">
|
<li class="nav-item me-2">
|
||||||
<a class="btn btn-primary" aria-current="page" href="{{ url_for('login') }}">Login</a>
|
<a class="btn btn-primary" aria-current="page" href="{{ url_for('login') }}">Login</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="btn btn-outline-secondary" aria-current="page" href="{{ url_for('signup') }}">Signup</a>
|
<a class="btn btn-outline-secondary" aria-current="page" href="{{ url_for('signup') }}">Signup</a>
|
||||||
</li>
|
</li>
|
||||||
|
{% else %}
|
||||||
|
<li class="nav-item me-2">
|
||||||
|
<a class="btn btn-primary" aria-current="page" href="{{ url_for('logout') }}">Logout</a>
|
||||||
|
</li>
|
||||||
|
{% endif %}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
14
utils.py
Normal file
14
utils.py
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
from functools import wraps
|
||||||
|
|
||||||
|
from flask import redirect, url_for
|
||||||
|
from flask_login import current_user
|
||||||
|
|
||||||
|
|
||||||
|
def anonymous_required(f):
|
||||||
|
@wraps(f)
|
||||||
|
def decorated_function(*args, **kwargs):
|
||||||
|
if current_user.is_authenticated:
|
||||||
|
return redirect(url_for('index'))
|
||||||
|
return f(*args, **kwargs)
|
||||||
|
|
||||||
|
return decorated_function
|
||||||
Loading…
x
Reference in New Issue
Block a user