A very rudimentary implementation of a private mode with key base autorization
This commit is contained in:
parent
1ac2f6bf32
commit
f4389516f0
2 changed files with 49 additions and 11 deletions
|
@ -14,6 +14,7 @@ Excerp from the help::
|
||||||
--room ROOM, -r ROOM
|
--room ROOM, -r ROOM
|
||||||
--secret SECRET, -s SECRET
|
--secret SECRET, -s SECRET
|
||||||
--config-file CONFIG_FILE, -C CONFIG_FILE
|
--config-file CONFIG_FILE, -C CONFIG_FILE
|
||||||
|
--key KEY, -k KEY
|
||||||
|
|
||||||
The config file should be a json file in the following style::
|
The config file should be a json file in the following style::
|
||||||
|
|
||||||
|
@ -82,6 +83,8 @@ class State:
|
||||||
a room, this must be identical. Also, if a webclient wants to have
|
a room, this must be identical. Also, if a webclient wants to have
|
||||||
admin privileges, this must be included.
|
admin privileges, this must be included.
|
||||||
:type secret: str
|
:type secret: str
|
||||||
|
:param key: An optional key, if registration on the server is limited.
|
||||||
|
:type key: Optional[str]
|
||||||
:param preview_duration: Amount of seconds the preview before a song be
|
:param preview_duration: Amount of seconds the preview before a song be
|
||||||
displayed.
|
displayed.
|
||||||
:type preview_duration: int
|
:type preview_duration: int
|
||||||
|
@ -98,6 +101,7 @@ class State:
|
||||||
room: str = ""
|
room: str = ""
|
||||||
server: str = ""
|
server: str = ""
|
||||||
secret: str = ""
|
secret: str = ""
|
||||||
|
key: Optional[str] = None
|
||||||
preview_duration: int = 3
|
preview_duration: int = 3
|
||||||
last_song: Optional[datetime.datetime] = None
|
last_song: Optional[datetime.datetime] = None
|
||||||
|
|
||||||
|
@ -187,16 +191,16 @@ async def handle_connect() -> None:
|
||||||
:rtype: None
|
:rtype: None
|
||||||
"""
|
"""
|
||||||
logging.info("Connected to server")
|
logging.info("Connected to server")
|
||||||
await sio.emit(
|
data = {
|
||||||
"register-client",
|
|
||||||
{
|
|
||||||
"queue": state.queue,
|
"queue": state.queue,
|
||||||
"recent": state.recent,
|
"recent": state.recent,
|
||||||
"room": state.room,
|
"room": state.room,
|
||||||
"secret": state.secret,
|
"secret": state.secret,
|
||||||
"config": state.get_config(),
|
"config": state.get_config(),
|
||||||
},
|
}
|
||||||
)
|
if state.key:
|
||||||
|
data["registration-key"] = state.key
|
||||||
|
await sio.emit("register-client", data)
|
||||||
|
|
||||||
|
|
||||||
@sio.on("get-meta-info")
|
@sio.on("get-meta-info")
|
||||||
|
@ -390,6 +394,7 @@ async def aiomain() -> None:
|
||||||
parser.add_argument("--room", "-r")
|
parser.add_argument("--room", "-r")
|
||||||
parser.add_argument("--secret", "-s")
|
parser.add_argument("--secret", "-s")
|
||||||
parser.add_argument("--config-file", "-C", default="syng-client.json")
|
parser.add_argument("--config-file", "-C", default="syng-client.json")
|
||||||
|
parser.add_argument("--key", "-k", default=None)
|
||||||
parser.add_argument("server")
|
parser.add_argument("server")
|
||||||
|
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
@ -406,6 +411,8 @@ async def aiomain() -> None:
|
||||||
if "preview_duration" in config["config"]:
|
if "preview_duration" in config["config"]:
|
||||||
state.preview_duration = config["config"]["preview_duration"]
|
state.preview_duration = config["config"]["preview_duration"]
|
||||||
|
|
||||||
|
state.key = args.key if args.key else None
|
||||||
|
|
||||||
if args.room:
|
if args.room:
|
||||||
state.room = args.room
|
state.room = args.room
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,7 @@ from __future__ import annotations
|
||||||
|
|
||||||
import asyncio
|
import asyncio
|
||||||
import datetime
|
import datetime
|
||||||
|
import hashlib
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import random
|
import random
|
||||||
|
@ -350,6 +351,8 @@ async def handle_register_client(sid: str, data: dict[str, Any]) -> None:
|
||||||
Handle the "register-client" message.
|
Handle the "register-client" message.
|
||||||
|
|
||||||
The data dictionary should have the following keys:
|
The data dictionary should have the following keys:
|
||||||
|
- `registration_key` (Optional), a key corresponding to those stored
|
||||||
|
in `app["registration-keyfile"]`
|
||||||
- `room` (Optional), the requested room
|
- `room` (Optional), the requested room
|
||||||
- `config`, an dictionary of initial configurations
|
- `config`, an dictionary of initial configurations
|
||||||
- `queue`, a list of initial entries for the queue. The entries are
|
- `queue`, a list of initial entries for the queue. The entries are
|
||||||
|
@ -363,6 +366,9 @@ async def handle_register_client(sid: str, data: dict[str, Any]) -> None:
|
||||||
playback client will be replaced if and only if, the new playback
|
playback client will be replaced if and only if, the new playback
|
||||||
client has the same secret.
|
client has the same secret.
|
||||||
|
|
||||||
|
If registration is restricted, abort, if the given key is not in the
|
||||||
|
registration keyfile.
|
||||||
|
|
||||||
If no room is provided, a fresh room id is generated.
|
If no room is provided, a fresh room id is generated.
|
||||||
|
|
||||||
If the client provides a new room, or a new room id was generated, the
|
If the client provides a new room, or a new room id was generated, the
|
||||||
|
@ -394,6 +400,25 @@ async def handle_register_client(sid: str, data: dict[str, Any]) -> None:
|
||||||
client_id = gen_id(length + 1)
|
client_id = gen_id(length + 1)
|
||||||
return client_id
|
return client_id
|
||||||
|
|
||||||
|
if not app["public"]:
|
||||||
|
with open(app["registration-keyfile"]) as f:
|
||||||
|
raw_keys = f.readlines()
|
||||||
|
keys = [key[:64] for key in raw_keys]
|
||||||
|
|
||||||
|
if (
|
||||||
|
"registration-key" not in data
|
||||||
|
or hashlib.sha256(
|
||||||
|
data["registration-key"].encode()
|
||||||
|
).hexdigest()
|
||||||
|
not in keys
|
||||||
|
):
|
||||||
|
await sio.emit(
|
||||||
|
"client-registered",
|
||||||
|
{"success": False, "room": None},
|
||||||
|
room=sid,
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
room: str = data["room"] if "room" in data and data["room"] else gen_id()
|
room: str = data["room"] if "room" in data and data["room"] else gen_id()
|
||||||
async with sio.session(sid) as session:
|
async with sio.session(sid) as session:
|
||||||
session["room"] = room
|
session["room"] = room
|
||||||
|
@ -791,8 +816,14 @@ def main() -> None:
|
||||||
parser.add_argument("--host", "-H", default="localhost")
|
parser.add_argument("--host", "-H", default="localhost")
|
||||||
parser.add_argument("--port", "-p", default="8080")
|
parser.add_argument("--port", "-p", default="8080")
|
||||||
parser.add_argument("--root-folder", "-r", default="syng/static/")
|
parser.add_argument("--root-folder", "-r", default="syng/static/")
|
||||||
|
parser.add_argument("--registration-keyfile", "-k", default=None)
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
app["public"] = True
|
||||||
|
if args.registration_keyfile:
|
||||||
|
app["public"] = False
|
||||||
|
app["registration-keyfile"] = args.registration_keyfile
|
||||||
|
|
||||||
app["root_folder"] = args.root_folder
|
app["root_folder"] = args.root_folder
|
||||||
|
|
||||||
app.add_routes(
|
app.add_routes(
|
||||||
|
|
Loading…
Add table
Reference in a new issue