From 8dd90b728cd59f330f971c251664be634b2e879e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Phillip=20K=C3=BChne?= Date: Sat, 8 Oct 2022 19:47:29 +0200 Subject: [PATCH] MySQL Working, bug fixes. --- .vscode/launch.json | 10 ++++---- .vscode/tasks.json | 7 ++++++ Dockerfile | 2 +- backend/app.py | 13 +++++----- backend/database.py | 40 ++++++++++++++++-------------- backend/helpers.py | 41 ++++++++++++++++++++----------- backend/templates/base.html | 2 +- backend/templates/main_admin.html | 10 +++++--- docker-compose.prod.yml | 12 +++++++++ 9 files changed, 86 insertions(+), 51 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index d9b4ed5..27002f1 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -5,7 +5,7 @@ "version": "0.2.0", "configurations": [ { - "preLaunchTask": "versiondump", + "preLaunchTask": "mariadb", "name": "Python: Flask", "type": "python", "cwd": "${workspaceFolder}/backend", @@ -15,7 +15,7 @@ "FLASK_APP": "backend/app.py", "FLASK_ENV": "development", "FLASK_DEBUG": "1", - "DBSTRING": "mysql://ek0ur6p6ky9gdmif:kpmi2bav4mvh4jbx@eporqep6b4b8ql12.chr7pe7iynqr.eu-west-1.rds.amazonaws.com:3306/xdfmpudc3remzgj0" + "DBSTRING": "mysql://devuser:devpw@127.0.0.1:3306/karaoqueue" }, "args": [ "run", @@ -25,7 +25,7 @@ "jinja": true }, { - "preLaunchTask": "versiondump", + "preLaunchTask": "mariadb", "name": "Python: Flask (with reload)", "type": "python", "cwd": "${workspaceFolder}/backend", @@ -43,7 +43,7 @@ "jinja": true }, { - "preLaunchTask": "versiondump", + "preLaunchTask": "mariadb", "name": "Python: Flask (with reload, externally reachable)", "type": "python", "cwd": "${workspaceFolder}/backend", @@ -62,7 +62,7 @@ "jinja": true }, { - "preLaunchTask": "versiondump", + "preLaunchTask": "mariadb", "name": "Python: Flask (externally reachable)", "type": "python", "cwd": "${workspaceFolder}/backend", diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 563a855..bdaee63 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -8,6 +8,13 @@ "type": "shell", "command": "echo \"$(git rev-parse --abbrev-ref HEAD)-$(git describe)\"> ${workspaceFolder}/backend/.version", "problemMatcher": [] + }, + { + "label": "mariadb", + "type": "shell", + "command": "docker run --rm --name some-mariadb --env MARIADB_USER=devuser --env MARIADB_PASSWORD=devpw --env MARIADB_ROOT_PASSWORD=devrootpw --env MARIADB_DATABASE=karaoqueue -p 3306:3306 mariadb:latest", + "isBackground": true, + "activeOnStart": false } ] } \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 0e36a09..7389e11 100644 --- a/Dockerfile +++ b/Dockerfile @@ -8,4 +8,4 @@ RUN pip install Flask-BasicAuth RUN pip install bs4 -COPY ./app /app \ No newline at end of file +COPY ./backend /app \ No newline at end of file diff --git a/backend/app.py b/backend/app.py index 0a86157..370c2b6 100644 --- a/backend/app.py +++ b/backend/app.py @@ -1,4 +1,5 @@ -from flask import Flask, render_template, Response, abort, request, redirect, send_from_directory, jsonify +from flask import Flask, render_template, abort, request, redirect, send_from_directory, jsonify +from flask.wrappers import Request, Response import helpers import database import data_adapters @@ -9,7 +10,7 @@ from helpers import nocache app = Flask(__name__, static_url_path='/static') basic_auth = BasicAuth(app) -accept_entries = False +accept_entries = True @app.route("/") def home(): @@ -81,12 +82,12 @@ def settings(): def settings_post(): entryquota = request.form.get("entryquota") maxqueue = request.form.get("maxqueue") - if entryquota.isnumeric() and int(entryquota) > 0: - app.config['ENTRY_QUOTA'] = int(entryquota) + if entryquota.isnumeric() and int(entryquota) > 0: # type: ignore + app.config['ENTRY_QUOTA'] = int(entryquota) # type: ignore else: abort(400) - if maxqueue.isnumeric and int(maxqueue) > 0: - app.config['MAX_QUEUE'] = int(maxqueue) + if maxqueue.isnumeric and int(maxqueue) > 0: # type: ignore + app.config['MAX_QUEUE'] = int(maxqueue) # type: ignore else: abort(400) diff --git a/backend/database.py b/backend/database.py index 579f141..fe9805d 100644 --- a/backend/database.py +++ b/backend/database.py @@ -19,7 +19,7 @@ def open_db() -> engine.base.Connection: global connection if (not connection): print(current_app.config.get("DBCONNSTRING")) - engine = create_engine(current_app.config.get("DBCONNSTRING")) + engine = create_engine(current_app.config.get("DBCONNSTRING")) # type: ignore connection = engine.connect() # cur.execute('PRAGMA encoding = "UTF-8";') return connection @@ -32,7 +32,7 @@ def import_songs(song_csv): df.to_sql(song_table, conn, if_exists='replace', index=False) cur = conn.execute("SELECT Count(Id) FROM songs") - num_songs = cur.fetchone()[0] + num_songs = cur.fetchone()[0] # type: ignore # conn.close() print("Imported songs ({} in Database)".format(num_songs)) return("Imported songs ({} in Database)".format(num_songs)) @@ -41,7 +41,7 @@ def import_songs(song_csv): def create_entry_table(): conn = open_db() conn.execute('CREATE TABLE IF NOT EXISTS '+entry_table + - ' (ID INTEGER PRIMARY KEY NOT NULL, Song_Id INTEGER NOT NULL, Name VARCHAR(255), Client_Id VARCHAR(36), Transferred INTEGER DEFAULT 0)') + ' (ID INTEGER PRIMARY KEY NOT NULL AUTO_INCREMENT, Song_Id INTEGER NOT NULL, Name VARCHAR(255), Client_Id VARCHAR(36), Transferred INTEGER DEFAULT 0)') # conn.close() @@ -73,14 +73,14 @@ def create_list_view(): conn.execute("""CREATE OR REPLACE VIEW `Liste` AS SELECT Name, Title, Artist, entries.Id AS entry_ID, songs.Id AS song_ID, entries.Transferred FROM entries, songs - WHERE entries.Song_Id=Song_ID""") + WHERE entries.Song_Id=songs.Id""") # conn.close() def create_done_song_view(): conn = open_db() conn.execute("""CREATE OR REPLACE VIEW `Abspielliste` AS - SELECT Artist || \" - \" || Title AS Song, Plays AS Wiedergaben + SELECT CONCAT(Artist," - ", Title) AS Song, Plays AS Wiedergaben FROM songs, done_songs WHERE done_songs.Song_Id=songs.Id""") # conn.close() @@ -127,14 +127,16 @@ def add_entry(name, song_id, client_id): def add_sung_song(entry_id): conn = open_db() cur = conn.execute( - """SELECT Song_Id FROM entries WHERE Id=?""", (entry_id,)) - song_id = cur.fetchone()[0] - conn.execute("""INSERT OR REPLACE INTO done_songs (Song_Id, Plays) - VALUES("""+str(song_id)+""", - COALESCE( - (SELECT Plays FROM done_songs - WHERE Song_Id="""+str(song_id)+"), 0) + 1)" - ) + """SELECT Song_Id FROM entries WHERE Id=%s""", (entry_id,)) + song_id = cur.fetchone()[0] # type: ignore + conn.execute("""INSERT INTO done_songs (Song_Id, Plays) VALUES("""+str(song_id)+""",1) ON DUPLICATE KEY UPDATE Plays=Plays + 1;""") +# SQLite bullshittery +# conn.execute("""REPLACE INTO done_songs (Song_Id, Plays) +# VALUES("""+str(song_id)+""", +# COALESCE( +# (SELECT Plays FROM done_songs +# WHERE Song_Id="""+str(song_id)+"), 0) + 1)" +# ) delete_entry(entry_id) # conn.close() return True @@ -143,14 +145,14 @@ def add_sung_song(entry_id): def toggle_transferred(entry_id): conn = open_db() cur = conn.execute( - "SELECT Transferred FROM entries WHERE ID =?", (entry_id,)) + "SELECT Transferred FROM entries WHERE ID =%s", (entry_id,)) marked = cur.fetchall()[0][0] if(marked == 0): conn.execute( - "UPDATE entries SET Transferred = 1 WHERE ID =?", (entry_id,)) + "UPDATE entries SET Transferred = 1 WHERE ID =%s", (entry_id,)) else: conn.execute( - "UPDATE entries SET Transferred = 0 WHERE ID =?", (entry_id,)) + "UPDATE entries SET Transferred = 0 WHERE ID =%s", (entry_id,)) # conn.close() return True @@ -158,7 +160,7 @@ def toggle_transferred(entry_id): def check_entry_quota(client_id): conn = open_db() cur = conn.execute( - "SELECT Count(*) FROM entries WHERE entries.Client_Id = ?", (client_id,)) + "SELECT Count(*) FROM entries WHERE entries.Client_Id = %s", (client_id,)) return cur.fetchall()[0][0] @@ -177,7 +179,7 @@ def clear_played_songs(): def delete_entry(id): conn = open_db() - conn.execute("DELETE FROM entries WHERE id=?", (id,)) + conn.execute("DELETE FROM entries WHERE id=%s", (id,)) # conn.close() return True @@ -188,7 +190,7 @@ def delete_entries(ids): idlist.append((x,)) try: conn = open_db() - cur = conn.execute("DELETE FROM entries WHERE id=?", idlist) + cur = conn.execute("DELETE FROM entries WHERE id=%s", idlist) # conn.close() return cur.rowcount except Exception as error: diff --git a/backend/helpers.py b/backend/helpers.py index 53ee6a1..656a6bf 100644 --- a/backend/helpers.py +++ b/backend/helpers.py @@ -37,7 +37,7 @@ def check_config_exists(): def load_version(app): if os.environ.get("SOURCE_VERSION"): - app.config['VERSION'] = os.environ.get("SOURCE_VERSION")[0:7] + app.config['VERSION'] = os.environ.get("SOURCE_VERSION")[0:7] # type: ignore elif os.path.isfile(".version"): with open('.version', 'r') as file: data = file.read().replace('\n', '') @@ -57,6 +57,11 @@ def load_dbconfig(app): app.config['DBCONNSTRING'] = os.environ.get("JAWSDB_MARIA_URL") else: app.config['DBCONNSTRING'] = "" + if os.environ.get("DEPLOYMENT_PLATFORM") == "Docker": + if os.environ.get("DBSTRING"): + app.config['DBCONNSTRING'] = os.environ.get("DBSTRING") + else: + app.config['DBCONNSTRING'] = "" elif os.path.isfile(".dbconn"): with open('.dbconn', 'r') as file: data = file.read().replace('\n', '') @@ -68,20 +73,26 @@ def load_dbconfig(app): app.config['DBCONNSTRING'] = "" def setup_config(app): - if check_config_exists(): - config = json.load(open(config_file)) - with open(config_file, 'r') as handle: - config = json.load(handle) - print("Loaded existing config") + if os.environ.get("DEPLOYMENT_PLATFORM") == "Docker": + app.config['BASIC_AUTH_USERNAME'] = os.environ.get('BASIC_AUTH_USERNAME') + app.config['BASIC_AUTH_PASSWORD'] = os.environ.get('BASIC_AUTH_PASSWORD') + app.config['ENTRY_QUOTA'] = os.environ.get('ENTRY_QUOTA') + app.config['MAX_QUEUE'] = os.environ.get('MAX_QUEUE') else: - config = {'username': 'admin', 'password': 'changeme', 'entryquota': 3, 'maxqueue': 20} - with open(config_file, 'w') as handle: - json.dump(config, handle, indent=4, sort_keys=True) - print("Wrote new config") - app.config['BASIC_AUTH_USERNAME'] = config['username'] - app.config['BASIC_AUTH_PASSWORD'] = config['password'] - app.config['ENTRY_QUOTA'] = config['entryquota'] - app.config['MAX_QUEUE'] = config['maxqueue'] + if check_config_exists(): + config = json.load(open(config_file)) + with open(config_file, 'r') as handle: + config = json.load(handle) + print("Loaded existing config") + else: + config = {'username': 'admin', 'password': 'changeme', 'entryquota': 3, 'maxqueue': 20} + with open(config_file, 'w') as handle: + json.dump(config, handle, indent=4, sort_keys=True) + print("Wrote new config") + app.config['BASIC_AUTH_USERNAME'] = config['username'] + app.config['BASIC_AUTH_PASSWORD'] = config['password'] + app.config['ENTRY_QUOTA'] = config['entryquota'] + app.config['MAX_QUEUE'] = config['maxqueue'] @@ -89,7 +100,7 @@ def nocache(view): @wraps(view) def no_cache(*args, **kwargs): response = make_response(view(*args, **kwargs)) - response.headers['Last-Modified'] = datetime.now() + response.headers['Last-Modified'] = datetime.now() # type: ignore response.headers['Cache-Control'] = 'no-store, no-cache, must-revalidate, post-check=0, pre-check=0, max-age=0' response.headers['Pragma'] = 'no-cache' response.headers['Expires'] = '-1' diff --git a/backend/templates/base.html b/backend/templates/base.html index f243850..8b598ea 100644 --- a/backend/templates/base.html +++ b/backend/templates/base.html @@ -75,7 +75,7 @@ {% endif %} - KaraoQueue {{karaoqueue_version}} - © 2019-21 - Phillip + KaraoQueue {{karaoqueue_version}} - 2019-22 - Phillip Kühne diff --git a/backend/templates/main_admin.html b/backend/templates/main_admin.html index 5234a88..5379dc2 100644 --- a/backend/templates/main_admin.html +++ b/backend/templates/main_admin.html @@ -52,10 +52,10 @@ table td:nth-child(2) { {% block extrajs %} diff --git a/docker-compose.prod.yml b/docker-compose.prod.yml index 7ef04ae..2ee48c0 100644 --- a/docker-compose.prod.yml +++ b/docker-compose.prod.yml @@ -1,5 +1,17 @@ version: "3.9" services: + karaoqueue: + image: "phillipkhne/karaoqueue:latest" + restart: always + ports: + - "127.0.0.1:8081:80" + environment: + DEPLOYMENT_PLATFORM: Docker + DBSTRING: mysql://user:pass@host:3306/database + BASIC_AUTH_USERNAME: admin + BASIC_AUTH_PASSWORD: changeme + ENTRY_QUOTA: 3 + MAX_QUEUE: 20 db: image: mariadb restart: always