Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .github/workflows/run-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,8 @@ jobs:

- name: Check coding style
run: uv run black --check .

- name: Run unit tests
run: uv run pytest --cov=netplay_index
env:
GEOIP_DATABASE_PATH: testdata/GeoLite2-Country.mmdb
32 changes: 16 additions & 16 deletions flake.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
description = "Dolphin's NetPlay Index / Lobby Server";

inputs.flake-utils.url = "github:numtide/flake-utils";
inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-25.05";
inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-25.11";

inputs.uv2nix.url = "github:pyproject-nix/uv2nix";
inputs.uv2nix.inputs.nixpkgs.follows = "nixpkgs";
Expand All @@ -24,7 +24,7 @@
overlay = workspace.mkPyprojectOverlay {
sourcePreference = "wheel";
};
python = pkgs.python310;
python = pkgs.python313;
pythonSet =
(pkgs.callPackage pyproject-nix.build.packages { inherit python; })
.overrideScope (pkgs.lib.composeManyExtensions [
Expand Down
44 changes: 24 additions & 20 deletions netplay_index/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
define("add_sysop", default=None, help="Add a new sysop via the command line")
define("reset_pw", default=None, help="Reset the password of a given user")


# pylint: disable=W0223
class MainHandler(RequestHandler):
"""Handler for root requests"""
Expand Down Expand Up @@ -56,26 +57,29 @@ def make_app():
def main():
parse_command_line()

APP = make_app()

if APP is None:
exit(1)

if options.add_sysop is not None:
RANDOM_PW = util.generate_secret()
database.add_login(options.add_sysop, RANDOM_PW, True)
print("Password for {}: {}".format(options.add_sysop, RANDOM_PW))
exit(0)

if options.reset_pw is not None:
RANDOM_PW = util.generate_secret()
database.update_login(options.reset_pw, RANDOM_PW)
print("New password for {}: {}".format(options.reset_pw, RANDOM_PW))
exit(0)

APP.listen(options.port, options.bind_address)
print("Listening on {}:{}...".format(options.bind_address, options.port))
tornado.ioloop.IOLoop.current().start()
try:
APP = make_app()

if APP is None:
exit(1)

if options.add_sysop is not None:
RANDOM_PW = util.generate_secret()
database.add_login(options.add_sysop, RANDOM_PW, True)
print("Password for {}: {}".format(options.add_sysop, RANDOM_PW))
exit(0)

if options.reset_pw is not None:
RANDOM_PW = util.generate_secret()
database.update_login(options.reset_pw, RANDOM_PW)
print("New password for {}: {}".format(options.reset_pw, RANDOM_PW))
exit(0)

APP.listen(options.port, options.bind_address)
print("Listening on {}:{}...".format(options.bind_address, options.port))
tornado.ioloop.IOLoop.current().start()
finally:
database.close()


if __name__ == "__main__":
Expand Down
1 change: 1 addition & 0 deletions netplay_index/admin/bans.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from netplay_index.admin.base import AdminHandler
import netplay_index.database as database


# pylint: disable=W0223
class Handler(AdminHandler):
"""Ban list"""
Expand Down
1 change: 1 addition & 0 deletions netplay_index/admin/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

import netplay_index.database as database


# pylint: disable=W0223
class AdminHandler(RequestHandler):
"""Base handler for admin URLs"""
Expand Down
1 change: 1 addition & 0 deletions netplay_index/admin/blacklist.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from netplay_index.admin.base import AdminHandler
import netplay_index.database as database


# pylint: disable=W0223
class Handler(AdminHandler):
"""Handle blacklist requests"""
Expand Down
1 change: 1 addition & 0 deletions netplay_index/admin/overview.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from netplay_index.admin.base import AdminHandler
import netplay_index.sessions as sessions


# pylint: disable=W0223
class Handler(AdminHandler):
"""Handle admin overview"""
Expand Down
1 change: 1 addition & 0 deletions netplay_index/admin/server_list.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from netplay_index.admin.base import AdminHandler
import netplay_index.sessions as sessions


# pylint: disable=W0223
class Handler(AdminHandler):
def template_args(self):
Expand Down
1 change: 1 addition & 0 deletions netplay_index/admin/user_management.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from netplay_index.admin.base import AdminHandler
import netplay_index.database as database


# pylint: disable=W0223
class Handler(AdminHandler):
"""User Management View"""
Expand Down
31 changes: 19 additions & 12 deletions netplay_index/database.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,19 @@ def _commit():
CONNECTION.commit()


def close():
"""Close the active database connection."""

# pylint: disable=W0603
global CONNECTION

connection = CONNECTION
CONNECTION = None

if connection is not None:
connection.close()


def _hash_password(password):
"""Hashes a password for storing in the database"""

Expand Down Expand Up @@ -45,30 +58,24 @@ def initialize():
cur.execute("pragma user_version=" + str(DB_REVISION))

# Initialize users
cur.execute(
"""
cur.execute("""
CREATE TABLE IF NOT EXISTS users
(username TEXT PRIMARY KEY, password TEXT, sysop BOOL, can_ban BOOL,
can_modify_blacklist BOOL)"""
)
can_modify_blacklist BOOL)""")

# Initialize blacklist
cur.execute(
"""
cur.execute("""
CREATE TABLE IF NOT EXISTS bans

(host TEXT PRIMARY KEY, date_added DATETIME DEFAULT CURRENT_TIMESTAMP,
added_by TEXT, reason TEXT)"""
)
added_by TEXT, reason TEXT)""")

# Initialize ban list
cur.execute(
"""
cur.execute("""
CREATE TABLE IF NOT EXISTS blacklist
(word TEXT PRIMARY KEY, date_added DATETIME DEFAULT CURRENT_TIMESTAMP,
added_by TEXT, reason TEXT)
"""
)
""")

print("Initialized database successfully.")

Expand Down
1 change: 1 addition & 0 deletions netplay_index/login/login.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import netplay_index.database as database
import netplay_index.settings as settings


# pylint: disable=W0223
class Logout(RequestHandler):
"""Logout handler"""
Expand Down
6 changes: 6 additions & 0 deletions netplay_index/tests/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,12 @@
class NetPlayIndexTest(AsyncHTTPTestCase):
"""Base class for tests"""

def tearDown(self):
try:
super().tearDown()
finally:
database.close()

def get_app(self):
# This greatly speeds up running tests
settings.LOGIN_ATTEMPT_DELAY = 0
Expand Down
12 changes: 10 additions & 2 deletions netplay_index/tests/test_database.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,15 @@
from unittest import TestCase


class BanTest(TestCase):
class DatabaseTest(TestCase):
def setUp(self):
database.initialize()

def tearDown(self):
database.close()


class BanTest(DatabaseTest):
def runTest(self):
can_ban = database.can_ban("test_user3")
self.assertEqual(can_ban, False)
Expand All @@ -22,7 +30,7 @@ def runTest(self):
database.delete_login("test_user")


class BlacklistTest(TestCase):
class BlacklistTest(DatabaseTest):
def runTest(self):
can_blacklist = database.can_modify_blacklist("test_user3")
self.assertEqual(can_blacklist, False)
Expand Down
24 changes: 12 additions & 12 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@ name = "netplay-index"
version = "0.1.0"
description = "Dolphin's NetPlay Index / Lobby Server"
authors = [{ name = "spycrab" }]
requires-python = ">=3.10,<3.11"
requires-python = ">=3.13,<3.14"
license = "GPL-3.0-or-later"
dependencies = [
"tornado>=6.0.2,<7",
"bcrypt>=3.1.6,<4",
"geoip2>=2.9.0,<3",
"prometheus-client>=0.22.1,<0.23",
"tornado>=6.5.8,<7",
"bcrypt>=5.0.0,<6",
"geoip2>=5.3.0,<6",
"prometheus-client>=0.26.0,<0.27",
]

[project.scripts]
Expand All @@ -18,14 +18,14 @@ netplay-index = "netplay_index.__main__:main"
[dependency-groups]
dev = [
"tornado-utils~=1.6",
"beautifulsoup4>=4.6.0,<5",
"coveralls>=3.3.1,<4",
"coverage>=6.4.4,<7",
"black>=22.6.0,<23",
"pytest>=7.1.2,<8",
"pytest-cov>=3.0.0,<4",
"beautifulsoup4>=4.15.0,<5",
"coveralls>=4.1.0,<5",
"coverage>=7.15.4,<8",
"black>=26.5.1,<27",
"pytest>=9.1.1,<10",
"pytest-cov>=7.1.0,<8",
]

[build-system]
requires = ["hatchling"]
requires = ["hatchling>=1.32.0,<2"]
build-backend = "hatchling.build"
Loading
Loading