mirror of
https://github.com/Dvorinka/swingmusic-extended.git
synced 2026-06-03 20:13:02 +00:00
add a pairing endpoint
+ append / to folder paths + filter recently played by logged in user id + fix typo in login response + update track logger migration to add foreign key
This commit is contained in:
@@ -1,16 +1,16 @@
|
||||
# TODO
|
||||
- Migrations:
|
||||
1. Move userdata to new hashing algorithm
|
||||
- Store (and read) from the correct user account:
|
||||
1. Playlists
|
||||
2. Favorites
|
||||
|
||||
- Package jsoni and publish on PyPi
|
||||
- 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
|
||||
|
||||
# DONE
|
||||
- Support auth headers
|
||||
- Add recently played playlist
|
||||
- Move user track logs to user zero
|
||||
- Move future logs to appropriate user id
|
||||
- Store (and read) from the correct user account:
|
||||
1. Playlists
|
||||
2. Favorites
|
||||
+34
-2
@@ -48,7 +48,7 @@ def create_new_token(user: dict):
|
||||
|
||||
return {
|
||||
"msg": f"Logged in as {user['username']}",
|
||||
"acccesstoken": access_token,
|
||||
"accesstoken": access_token,
|
||||
"refreshtoken": create_refresh_token(identity=user),
|
||||
"maxage": max_age,
|
||||
}
|
||||
@@ -76,7 +76,7 @@ def login(body: LoginBody):
|
||||
return {"msg": "Hehe! invalid password"}, 401
|
||||
|
||||
res = create_new_token(user.todict())
|
||||
token = res["acccesstoken"]
|
||||
token = res["accesstoken"]
|
||||
age = res["maxage"]
|
||||
res = jsonify(res)
|
||||
set_access_cookies(res, token, max_age=age)
|
||||
@@ -84,6 +84,38 @@ def login(body: LoginBody):
|
||||
return res
|
||||
|
||||
|
||||
pair_token = dict()
|
||||
|
||||
|
||||
class PairDeviceQuery(BaseModel):
|
||||
code: str = Field("", description="The code")
|
||||
|
||||
|
||||
@api.get("/pair")
|
||||
@jwt_required(optional=True)
|
||||
def pair_device(query: PairDeviceQuery):
|
||||
"""
|
||||
Pair the Swing Music mobile app with this server
|
||||
|
||||
Send a code to get an access token. Send an authenticated request without the code to generate a new token.
|
||||
"""
|
||||
if current_user:
|
||||
token = create_new_token(get_jwt_identity())
|
||||
key = token["accesstoken"][-6:]
|
||||
|
||||
global pair_token
|
||||
pair_token = {
|
||||
key: token,
|
||||
}
|
||||
|
||||
return {"code": key}
|
||||
|
||||
if query.code:
|
||||
return pair_token.get(query.code, {"msg": "Invalid code"})
|
||||
|
||||
return {"msg": "No code provided"}, 400
|
||||
|
||||
|
||||
@api.post("/refresh")
|
||||
@jwt_required(refresh=True)
|
||||
def refresh():
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
from flask_jwt_extended import current_user
|
||||
from flask_openapi3 import Tag
|
||||
from flask_openapi3 import APIBlueprint
|
||||
from pydantic import Field
|
||||
@@ -40,7 +39,6 @@ def log_track(body: LogTrackBody):
|
||||
timestamp=timestamp,
|
||||
duration=duration,
|
||||
source=source,
|
||||
userid=current_user["id"],
|
||||
)
|
||||
|
||||
return {"total entries": last_row}
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
from flask_jwt_extended import current_user
|
||||
from app.db.sqlite.utils import SQLiteManager
|
||||
from app.models.logger import TrackLog as TrackLog
|
||||
|
||||
|
||||
class SQLiteTrackLogger:
|
||||
@classmethod
|
||||
def insert_track(cls, trackhash: str, duration: int, source: str, timestamp: int, userid: int):
|
||||
def insert_track(cls, trackhash: str, duration: int, source: str, timestamp: int):
|
||||
"""
|
||||
Inserts a track play record into the database
|
||||
"""
|
||||
@@ -19,7 +20,9 @@ class SQLiteTrackLogger:
|
||||
) VALUES(?,?,?,?,?)
|
||||
"""
|
||||
|
||||
cur.execute(sql, (trackhash, duration, timestamp, source, userid))
|
||||
cur.execute(
|
||||
sql, (trackhash, duration, timestamp, source, current_user["id"])
|
||||
)
|
||||
lastrowid = cur.lastrowid
|
||||
|
||||
return lastrowid
|
||||
@@ -31,7 +34,7 @@ class SQLiteTrackLogger:
|
||||
"""
|
||||
|
||||
with SQLiteManager(userdata_db=True) as cur:
|
||||
sql = """SELECT * FROM track_logger ORDER BY timestamp DESC"""
|
||||
sql = f"""SELECT * FROM track_logger WHERE userid = {current_user['id']} ORDER BY timestamp DESC"""
|
||||
|
||||
cur.execute(sql)
|
||||
rows = cur.fetchall()
|
||||
@@ -45,7 +48,7 @@ class SQLiteTrackLogger:
|
||||
"""
|
||||
|
||||
with SQLiteManager(userdata_db=True) as cur:
|
||||
sql = """SELECT * FROM track_logger ORDER BY timestamp DESC LIMIT ?,?"""
|
||||
sql = f"""SELECT * FROM track_logger WHERE userid = {current_user['id']} ORDER BY timestamp DESC LIMIT ?,?"""
|
||||
|
||||
cur.execute(sql, (start, limit))
|
||||
rows = cur.fetchall()
|
||||
|
||||
@@ -55,7 +55,8 @@ CREATE TABLE IF NOT EXISTS track_logger (
|
||||
duration integer NOT NULL,
|
||||
timestamp integer NOT NULL,
|
||||
source text,
|
||||
userid integer NOT NULL DEFAULT 0
|
||||
userid integer NOT NULL DEFAULT 1,
|
||||
constraint fk_users foreign key (userid) references users(id) on delete cascade
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS users (
|
||||
|
||||
@@ -18,7 +18,7 @@ def create_folder(path: str, trackcount=0, foldercount=0) -> Folder:
|
||||
|
||||
return Folder(
|
||||
name=folder.name,
|
||||
path=win_replace_slash(str(folder)),
|
||||
path=win_replace_slash(str(folder)) + "/",
|
||||
is_sym=folder.is_symlink(),
|
||||
trackcount=trackcount,
|
||||
foldercount=foldercount,
|
||||
|
||||
@@ -69,9 +69,25 @@ class _3MoveScrobbleToUserId1(Migration):
|
||||
|
||||
@staticmethod
|
||||
def migrate():
|
||||
sql = """
|
||||
UPDATE track_logger SET userid = 1 WHERE userid = 0;
|
||||
ALTER TABLE track_logger RENAME TO _track_logger;
|
||||
CREATE TABLE IF NOT EXISTS track_logger (
|
||||
id integer PRIMARY KEY,
|
||||
trackhash text NOT NULL,
|
||||
duration integer NOT NULL,
|
||||
timestamp integer NOT NULL,
|
||||
source text,
|
||||
userid integer NOT NULL DEFAULT 1,
|
||||
constraint fk_users foreign key (userid) references users(id) on delete cascade
|
||||
);
|
||||
|
||||
INSERT INTO track_logger SELECT * FROM _track_logger;
|
||||
DROP TABLE _track_logger;
|
||||
"""
|
||||
# INFO: Move the scrobble table to the user id 1
|
||||
with SQLiteManager(userdata_db=True) as cur:
|
||||
cur.execute("UPDATE track_logger SET userid = 1 WHERE userid = 0")
|
||||
cur.executescript(sql)
|
||||
cur.close()
|
||||
|
||||
|
||||
|
||||
@@ -84,7 +84,14 @@ app = create_api()
|
||||
app.static_folder = get_home_res_path("client")
|
||||
|
||||
# INFO: Routes that don't need authentication
|
||||
whitelisted_routes = {"/auth/login", "/auth/users", "/auth/logout", "/auth/refresh", "/docs"}
|
||||
whitelisted_routes = {
|
||||
"/auth/login",
|
||||
"/auth/users",
|
||||
"/auth/pair",
|
||||
"/auth/logout",
|
||||
"/auth/refresh",
|
||||
"/docs",
|
||||
}
|
||||
blacklist_extensions = {".webp"}.union(getClientFilesExtensions())
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user