linklogger/app/main.py
2024-08-07 16:08:21 -05:00

169 lines
3.9 KiB
Python

from flask_login import (
current_user,
login_user,
login_required,
logout_user,
LoginManager,
UserMixin,
)
from flask import Flask, redirect, render_template, request, url_for, Request
import bcrypt
import os
import string
import random
from models import User, Link
from database import *
from app.util.log import log
from var import BASE_URL
class FlaskUser(UserMixin):
pass
app = Flask(__name__)
app.config["SECRET_KEY"] = os.urandom(24)
login_manager = LoginManager()
login_manager.init_app(app)
@login_manager.user_loader
def user_loader(username):
user = FlaskUser()
user.id = username
return user
"""
Handle login requests from the web UI
"""
@app.route("/login", methods=["GET", "POST"])
def login():
if request.method == "POST":
username = request.form["username"]
password = request.form["password"]
# Get database session
db = SessionLocal()
user = db.query(User).filter(User.username == username).first()
db.close()
if not user:
return {"status": "Invalid username or password"}
if bcrypt.checkpw(password.encode("utf-8"), user.password.encode("utf-8")):
flask_user = FlaskUser()
flask_user.id = username
login_user(flask_user)
return {"status": "success"}
return {"status": "Invalid username or password"}
return render_template("login.html")
"""
Handle signup requests from the web UI
"""
@app.route("/signup", methods=["GET", "POST"])
def signup():
if request.method == "POST":
username = request.form["username"]
password = request.form["password"]
# Get database session
db = SessionLocal()
user = db.query(User).filter(User.username == username).first()
if user:
db.close()
return {"status": "User already exists"}
# Add information to the database
hashed_password = bcrypt.hashpw(
password.encode("utf-8"), bcrypt.gensalt()
).decode("utf-8")
api_key = "".join(random.choices(string.ascii_letters + string.digits, k=20))
new_user = User(username=username, password=hashed_password, api_key=api_key)
db.add(new_user)
db.commit()
db.close()
# Log in the newly created user
flask_user = FlaskUser()
flask_user.id = username
login_user(flask_user)
return {"status": "success"}
return render_template("signup.html")
"""
Load the 'dashboard' page for logged in users
"""
@app.route("/dashboard", methods=["GET"])
@login_required
def dashboard():
# Get database session
db = SessionLocal()
# Get the API key for the current user
user = db.query(User).filter(User.username == current_user.id).first()
db.close()
api_key = user.api_key
return render_template("dashboard.html", api_key=api_key)
"""
Log users out of their account
"""
@app.route("/logout", methods=["GET"])
@login_required
def logout():
logout_user()
return redirect(url_for("login"))
"""
Log all records for visits to shortened links
"""
@app.route("/<link>", methods=["GET"])
def log_redirect(link):
# If `link` is not exactly 5 characters, return redirect to base url
if len(link) != 5:
return redirect(BASE_URL)
# Make sure the link exists in the database
db = SessionLocal()
link_record = db.query(Link).filter(Link.link == link).first()
if not link_record:
db.close()
return redirect(BASE_URL)
else:
# Log the visit
ip = request.remote_addr
user_agent = request.headers.get("User-Agent")
log(link, ip, user_agent)
db.close()
return redirect(link_record.redirect_link)
@app.errorhandler(401)
def unauthorized(e):
return redirect(url_for("login"))
@app.errorhandler(404)
def not_found(e):
return redirect(url_for("login"))