diff --git a/TODO.md b/TODO.md index cfeee899..7237b471 100644 --- a/TODO.md +++ b/TODO.md @@ -8,9 +8,9 @@ - Rewrite stores to use dictionaries instead of list pools - last updated date on tracks added via watchdog is broken - hide "remove from playlist" option on system playlists -- Support auth headers # DONE +- Support auth headers - Add recently played playlist - Move user track logs to user zero - Move future logs to appropriate user id \ No newline at end of file diff --git a/app/db/sqlite/auth.py b/app/db/sqlite/auth.py index 3d9da234..e79dfe78 100644 --- a/app/db/sqlite/auth.py +++ b/app/db/sqlite/auth.py @@ -139,8 +139,8 @@ class SQLiteAuthMethods: """ Delete a user by username. """ - sql = "DELETE FROM users WHERE username = ?" - + sql = "DELETE FROM users WHERE id = ?" + print("deleting user: ", username) with SQLiteManager(userdata_db=True) as cur: - cur.execute(sql, (username,)) + cur.execute(sql, (3,)) cur.close() diff --git a/app/db/sqlite/playlists.py b/app/db/sqlite/playlists.py index ccf99dc5..bfed7185 100644 --- a/app/db/sqlite/playlists.py +++ b/app/db/sqlite/playlists.py @@ -1,6 +1,8 @@ import json from collections import OrderedDict +from flask_jwt_extended import current_user + from app.db.sqlite.utils import SQLiteManager, tuple_to_playlist, tuples_to_playlists from app.utils.dates import create_new_date @@ -27,10 +29,12 @@ class SQLitePlaylistMethods: last_updated, name, settings, - trackhashes - ) VALUES(:image, :last_updated, :name, :settings, :trackhashes) + trackhashes, + userid + ) VALUES(:image, :last_updated, :name, :settings, :trackhashes, :userid) """ + playlist["userid"] = current_user["id"] playlist = OrderedDict(sorted(playlist.items())) with SQLiteManager(userdata_db=True) as cur: @@ -41,24 +45,9 @@ class SQLitePlaylistMethods: p_tuple = (pid, *playlist.values()) return tuple_to_playlist(p_tuple) - @staticmethod - def get_playlist_by_name(name: str): - sql = "SELECT * FROM playlists WHERE name = ?" - - with SQLiteManager(userdata_db=True) as cur: - cur.execute(sql, (name,)) - - data = cur.fetchone() - cur.close() - - if data is not None: - return tuple_to_playlist(data) - - return None - @staticmethod def count_playlist_by_name(name: str): - sql = "SELECT COUNT(*) FROM playlists WHERE name = ?" + sql = f"SELECT COUNT(*) FROM playlists WHERE name = ? and userid = {current_user['id']}" with SQLiteManager(userdata_db=True) as cur: cur.execute(sql, (name,)) @@ -71,7 +60,7 @@ class SQLitePlaylistMethods: @staticmethod def get_all_playlists(): with SQLiteManager(userdata_db=True) as cur: - cur.execute("SELECT * FROM playlists") + cur.execute(f"SELECT * FROM playlists WHERE userid = {current_user['id']}") playlists = cur.fetchall() cur.close() @@ -82,7 +71,7 @@ class SQLitePlaylistMethods: @staticmethod def get_playlist_by_id(playlist_id: int): - sql = "SELECT * FROM playlists WHERE id = ?" + sql = f"SELECT * FROM playlists WHERE id = ? and userid = {current_user['id']}" with SQLiteManager(userdata_db=True) as cur: cur.execute(sql, (playlist_id,)) @@ -103,7 +92,7 @@ class SQLitePlaylistMethods: Adds a string item to a json dumped list using a playlist id and field name. Takes the playlist ID, a field name, an item to add to the field. """ - sql = f"SELECT {field} FROM playlists WHERE id = ?" + sql = f"SELECT {field} FROM playlists WHERE id = ? and userid = {current_user['id']}" with SQLiteManager(userdata_db=True) as cur: cur.execute(sql, (playlist_id,)) @@ -134,12 +123,12 @@ class SQLitePlaylistMethods: @classmethod def update_playlist(cls, playlist_id: int, playlist: dict): - sql = """UPDATE playlists SET + sql = f"""UPDATE playlists SET image = ?, last_updated = ?, name = ?, settings = ? - WHERE id = ? + WHERE id = ? and userid = {current_user['id']} """ del playlist["id"] @@ -156,7 +145,7 @@ class SQLitePlaylistMethods: @classmethod def update_settings(cls, playlist_id: int, settings: dict): - sql = """UPDATE playlists SET settings = ? WHERE id = ?""" + sql = f"""UPDATE playlists SET settings = ? WHERE id = ? and userid = {current_user['id']}""" with SQLiteManager(userdata_db=True) as cur: cur.execute(sql, (json.dumps(settings), playlist_id)) @@ -165,14 +154,14 @@ class SQLitePlaylistMethods: @staticmethod def delete_playlist(pid: str): - sql = "DELETE FROM playlists WHERE id = ?" + sql = f"DELETE FROM playlists WHERE id = ? and userid = {current_user['id']}" with SQLiteManager(userdata_db=True) as cur: cur.execute(sql, (pid,)) @staticmethod def remove_banner(playlistid: int): - sql = """UPDATE playlists SET image = NULL WHERE id = ?""" + sql = f"""UPDATE playlists SET image = NULL WHERE id = ? and userid = {current_user['id']}""" with SQLiteManager(userdata_db=True) as cur: cur.execute(sql, (playlistid,)) @@ -186,7 +175,10 @@ class SQLitePlaylistMethods: sql = """UPDATE playlists SET trackhashes = ? WHERE id = ?""" with SQLiteManager(userdata_db=True) as cur: - cur.execute("SELECT trackhashes FROM playlists WHERE id = ?", (playlistid,)) + cur.execute( + f"SELECT trackhashes FROM playlists WHERE id = ? and userid = {current_user['id']}", + (playlistid,), + ) data = cur.fetchone() if data is None: diff --git a/app/db/sqlite/queries.py b/app/db/sqlite/queries.py index 3bd40b8f..6ab9056f 100644 --- a/app/db/sqlite/queries.py +++ b/app/db/sqlite/queries.py @@ -9,16 +9,16 @@ CREATE TABLE IF NOT EXISTS playlists ( last_updated text not null, name text not null, settings text, - trackhashes text + trackhashes text, + userid integer not null, + constraint fk_users foreign key (userid) references users(id) on delete cascade ); CREATE TABLE IF NOT EXISTS favorites ( id integer PRIMARY KEY, hash text not null, type text not null, - timestamp integer not null default 0, - userid integer not null, - foreign key (userid) references users(id) on delete cascade + timestamp integer not null default 0 ); CREATE TABLE IF NOT EXISTS settings ( diff --git a/app/db/sqlite/utils.py b/app/db/sqlite/utils.py index c4c83e39..27535d25 100644 --- a/app/db/sqlite/utils.py +++ b/app/db/sqlite/utils.py @@ -83,7 +83,9 @@ class SQLiteManager: def __enter__(self) -> Cursor: if self.conn is not None: - return self.conn.cursor() + cur = self.conn.cursor() + cur.execute("PRAGMA foreign_keys = ON") + return cur if self.test_db_path: db_path = self.test_db_path @@ -97,7 +99,10 @@ class SQLiteManager: db_path, timeout=15, ) - return self.conn.cursor() + + cur = self.conn.cursor() + cur.execute("PRAGMA foreign_keys = ON") + return cur def __exit__(self, exc_type, exc_value, exc_traceback): trial_count = 0 diff --git a/app/migrations/v1_4_9/__init__.py b/app/migrations/v1_4_9/__init__.py index 17720054..a6ecf357 100644 --- a/app/migrations/v1_4_9/__init__.py +++ b/app/migrations/v1_4_9/__init__.py @@ -83,15 +83,79 @@ class _4AddUserIdToFavoritesTable(Migration): @staticmethod def migrate(): # check if userid column exists - exists_sql = "select count(*) from pragma_table_info('favorites') where name = 'userid'" - sql = "ALTER TABLE favorites ADD userid INTEGER NOT NULL DEFAULT 1 REFERENCES users(id) ON DELETE CASCADE" + exists_sql = ( + "select count(*) from pragma_table_info('favorites') where name = 'userid'" + ) + sql = """ + ALTER TABLE favorites ADD userid INTEGER NOT NULL DEFAULT 1; + ALTER TABLE favorites RENAME TO _favorites; + + CREATE TABLE IF NOT EXISTS favorites ( + id integer PRIMARY KEY, + hash text not null, + type text not null, + timestamp integer not null default 0, + userid integer not null, + constraint fk_users foreign key (userid) references users(id) on delete cascade + ); + + INSERT INTO favorites SELECT * FROM _favorites; + DROP TABLE _favorites; + """ with SQLiteManager(userdata_db=True) as cur: data = cur.execute(exists_sql) data = data.fetchone() if data[0] == 1: - return# INFO: column already exists + return # INFO: column already exists cur.executescript(sql) - \ No newline at end of file + + +class _5AddUserIdToPlaylistsTable(Migration): + """ + Adds a userid column to the playlists table. + """ + + @staticmethod + def migrate(): + # check if userid column exists + exists_sql = ( + "select count(*) from pragma_table_info('playlists') where name = 'userid'" + ) + + # Add the userid column to the playlists table + # Rename the old table to _playlists + # Create a new playlists table with the userid column + # Then, copy the data from the old table to the new table + # Finally, drop the old table + sql = """ + ALTER TABLE playlists ADD userid INTEGER NOT NULL DEFAULT 1; + ALTER TABLE playlists RENAME TO _playlists; + CREATE TABLE IF NOT EXISTS playlists ( + id integer PRIMARY KEY, + image text, + last_updated text not null, + name text not null, + settings text, + trackhashes text, + userid integer not null, + constraint fk_users foreign key (userid) references users(id) on delete cascade + ); + + INSERT INTO playlists SELECT * FROM _playlists; + DROP TABLE _playlists; + """ + + with SQLiteManager(userdata_db=True) as cur: + # INFO: Check if the column already exists + data = cur.execute(exists_sql) + data = data.fetchone() + + # INFO: If the column already exists, return + if data[0] == 1: + return # INFO: column already exists + + # INFO: Execute the sql + cur.executescript(sql)