From: Chris Fulljames Date: Sat, 4 Jan 2025 12:21:19 +0000 (-0500) Subject: Initial commit X-Git-Url: https://littlesong.place/gitweb/?a=commitdiff_plain;h=cf6b370887f3dedadf3261bb3fb3c14f4e5e3b8d;p=littlesongplace.git Initial commit --- cf6b370887f3dedadf3261bb3fb3c14f4e5e3b8d diff --git a/main.py b/main.py new file mode 100644 index 0000000..8a8ed81 --- /dev/null +++ b/main.py @@ -0,0 +1,147 @@ +import os +import sqlite3 +import uuid +from pathlib import Path, PosixPath + +import bcrypt +import click +from flask import Flask, render_template, request, redirect, g, session, abort +from werkzeug.utils import secure_filename + +app = Flask(__name__) +app.secret_key = "TODO" + +@app.route("/") +def index(): + username = session.get("username", None) + return render_template("index.html", username=username) + +@app.get("/signup") +def signup_get(): + return render_template("signup.html") + +@app.post("/signup") +def signup_post(): + print(request.form) + username = request.form["username"] + password = request.form["password"] + password_confirm = request.form["password_confirm"] + + error = None + if not username.isalnum(): + error = "Username cannot contain special characters" + elif len(username) < 3: + error ="Username must be at least 3 characters" + + elif password != password_confirm: + error = "Passwords do not match" + elif len(password) < 8: + error = "Password must be at least 8 characters" + + if query_db("select * from users where username = ?", [username], one=True): + error = f"Username '{username}' is already taken" + + if error: + return render_template("signup.html", error=error) + + password = bcrypt.hashpw(password.encode(), bcrypt.gensalt()) + query_db("insert into users (username, password) values (?, ?)", [username, password]) + get_db().commit() + + return render_template("login.html", note="User created. Sign in to continue") + +@app.get("/login") +def login_get(): + return render_template("login.html") + +@app.post("/login") +def login_post(): + username = request.form["username"] + password = request.form["password"] + + user_data = query_db("select * from users where username = ?", [username], one=True) + + if user_data and bcrypt.checkpw(password.encode(), user_data["password"]): + # Successful login + session["username"] = username + session.permanent = True + return redirect("/") + + return render_template("login.html", error="Invalid username/password") + +@app.get("/logout") +def logout(): + if "username" in session: + session.pop("username") + + return redirect("/") + +@app.get("/users") +def users(): + users = [row["username"] for row in query_db("select username from users")] + return render_template("users.html", users=users) + +@app.get("/users/") +def users_profile(name): + username = session.get("username", None) + songsdir = f"static/users/{username}/songs/" + songspath = Path(f"static/users/{username}/songs") + songs = [] + if songspath.exists(): + songs = [child.name for child in songspath.iterdir() if child.suffix.lower() == ".mp3"] + print(songs) + return render_template("profile.html", name=name, username=username, songs=songs) + +@app.post("/uploadsong") +def upload_song(): + if not "username" in session: + abort(401) + + username = session["username"] + userpath = Path(f"static/users/{username}/songs") + if not userpath.exists(): + os.makedirs(userpath) + + file = request.files["song"] + filename = secure_filename(file.filename) + filepath = userpath / filename + file.save(filepath) + + return redirect(f"/users/{username}") + + +################################################################################ +# Database +################################################################################ + +def get_db(): + db = getattr(g, '_database', None) + if db is None: + db = g._database = sqlite3.connect("database.db") + db.row_factory = sqlite3.Row + return db + +@app.teardown_appcontext +def close_db(exception): + db = getattr(g, '_database', None) + if db is not None: + db.close() + +def query_db(query, args=(), one=False): + cur = get_db().execute(query, args) + rv = cur.fetchall() + cur.close() + return (rv[0] if rv else None) if one else rv + +@click.command("init-db") +def init_db(): + """Clear the existing data and create new tables""" + with app.app_context(): + db = get_db() + with app.open_resource('schema.sql', mode='r') as f: + db.cursor().executescript(f.read()) + db.commit() + +app.teardown_appcontext(close_db) +app.cli.add_command(init_db) + diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..bb2793b --- /dev/null +++ b/requirements.txt @@ -0,0 +1,2 @@ +flask +bcrypt diff --git a/schema.sql b/schema.sql new file mode 100644 index 0000000..2be8601 --- /dev/null +++ b/schema.sql @@ -0,0 +1,7 @@ +DROP TABLE IF EXISTS users; + +CREATE TABLE users ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + username TEXT UNIQUE NOT NULL, + password TEXT NOT NULL +); diff --git a/templates/base.html b/templates/base.html new file mode 100644 index 0000000..1ab2582 --- /dev/null +++ b/templates/base.html @@ -0,0 +1,24 @@ + + + + {% block title %} Base {% endblock %} + + + + + {% block body %} + {% endblock %} + + + diff --git a/templates/index.html b/templates/index.html new file mode 100644 index 0000000..5cb6467 --- /dev/null +++ b/templates/index.html @@ -0,0 +1,2 @@ +{% extends "base.html" %} + diff --git a/templates/login.html b/templates/login.html new file mode 100644 index 0000000..6b490c1 --- /dev/null +++ b/templates/login.html @@ -0,0 +1,32 @@ +{% extends "base.html" %} + +{% block title %}Login{% endblock %} + +{% block body %} + +{% if note %} +
{{ note }}
+{% endif %} + +
+ + + + + +
+ +{% if error %} + +{% endif %} + +{% endblock %} + diff --git a/templates/profile.html b/templates/profile.html new file mode 100644 index 0000000..7112ab5 --- /dev/null +++ b/templates/profile.html @@ -0,0 +1,27 @@ +{% extends "base.html" %} + +{% block title %}{{ name }}'s Profile{% endblock %} + +{% block body %} + +

{{ name }}

+ +{% if name == username %} +
+
+ +
+
+ +
+
+{% endif %} + +{% for song in songs %} +
+ {{song}} + +
+{% endfor %} + +{% endblock %} diff --git a/templates/signup.html b/templates/signup.html new file mode 100644 index 0000000..5f7a07f --- /dev/null +++ b/templates/signup.html @@ -0,0 +1,41 @@ +{% extends "base.html" %} + +{% block title %}Create Account{% endblock %} + +{% block body %} +

Create a new account

+

Welcome to the site!

+

Rules:

+
    +
  1. Be nice
  2. +
  3. Be cool
  4. +
  5. Have fun
  6. +
+
+ + + + + + + +
+ +{% if error %} + +{% endif %} + +{% endblock %} + + diff --git a/templates/users.html b/templates/users.html new file mode 100644 index 0000000..0e9b644 --- /dev/null +++ b/templates/users.html @@ -0,0 +1,12 @@ +{% extends "base.html" %} + +{% block title %}All Users{% endblock %} + +{% block body %} + +

All Users

+{% for user in users %} +{{ user }}
+{% endfor %} + +{% endblock %} diff --git a/todo.txt b/todo.txt new file mode 100644 index 0000000..b419060 --- /dev/null +++ b/todo.txt @@ -0,0 +1,12 @@ +- file upload +- file download +- user file list +- user profile + +URL +secrethideout.net +sneaky.place +sneaky.website +hotnew.singles +hotlocal.singles +