mirror of
https://github.com/pyMC-dev/pyMC_Repeater.git
synced 2026-11-03 11:52:22 +01:00
fix(acl): reload a room given its first password; log a refused restore
Sixth review round (opencode: design still clean): - A room whose passwords were cleared, then set again in a settings-only update, was told no reload was needed, yet had no login handler or ACL until a restart. Turning a password on counts as a reload. - A restore refused because the new entry already holds the hash is logged. - The no-login-helper move path says why it keeps its own store guard.
This commit is contained in:
1 parent
99ff0f0963
commit
8274638ede
2 files changed
+32
-3
No files matched your search
@@ -6872,11 +6872,17 @@ class APIEndpoints:
|
||||
needs_reload = data.get("identity_key") or "new_name" in data
|
||||
# A room with no password is not registered for logins, so a live
|
||||
# reload would leave its login ACL under the old name; it waits
|
||||
# for a restart instead.
|
||||
# for a restart instead. Giving such a room a password is a
|
||||
# reload too: it has no login handler or ACL until it registers.
|
||||
room_settings = identity.get("settings") or {}
|
||||
can_log_in = bool(
|
||||
room_settings.get("admin_password") or room_settings.get("guest_password")
|
||||
)
|
||||
old_settings = snapshot.get("settings") or {}
|
||||
could_log_in = bool(
|
||||
old_settings.get("admin_password") or old_settings.get("guest_password")
|
||||
)
|
||||
needs_reload = needs_reload or (can_log_in and not could_log_in)
|
||||
|
||||
if needs_reload and can_log_in and self.daemon_instance:
|
||||
try:
|
||||
@@ -6931,9 +6937,15 @@ class APIEndpoints:
|
||||
)
|
||||
finally:
|
||||
if not registration_success and previous is not None:
|
||||
identity_manager.register_identity(
|
||||
# Refused only when the new entry already holds
|
||||
# the hash, i.e. it did register before failing.
|
||||
if not identity_manager.register_identity(
|
||||
old_name, previous[0], previous[1], previous[2]
|
||||
)
|
||||
):
|
||||
logger.warning(
|
||||
f"Hot reload: could not restore '{old_name}'; "
|
||||
f"it stays registered as '{final_name}'"
|
||||
)
|
||||
if registration_success:
|
||||
logger.info(
|
||||
f"Hot reload: Re-registered identity '{final_name}' with all systems"
|
||||
@@ -7302,6 +7314,9 @@ class APIEndpoints:
|
||||
if login_helper is not None:
|
||||
login_helper.move_room_acl(old_name, old_pubkey, new_pubkey, new_name, commit)
|
||||
return
|
||||
# No login helper (a daemon still starting, or a test double): move the
|
||||
# rows in the store directly. LoginHelper.move_room_acl holds the same
|
||||
# guard for the usual path, against the store its ACLs were built with.
|
||||
storage = getattr(getattr(self.daemon_instance, "repeater_handler", None), "storage", None)
|
||||
sqlite_handler = getattr(storage, "sqlite_handler", None)
|
||||
if sqlite_handler is None and old_pubkey != new_pubkey:
|
||||
|
||||
@@ -554,3 +554,17 @@ def test_delete_identity_frees_the_name_and_hash(db, request_ctx):
|
||||
identity = LocalIdentity(seed=bytes.fromhex("11" * 32))
|
||||
# Re-creating the room registers at once instead of conflicting until a restart.
|
||||
assert daemon.identity_manager.registration_error("room-a", identity, "room_server") is None
|
||||
|
||||
|
||||
def test_giving_a_passwordless_room_a_password_registers_it_live(db, request_ctx):
|
||||
daemon = _LiveDaemon(db, "room-a", "11" * 32)
|
||||
api = _api(daemon, daemon.config)
|
||||
request_ctx.method = "PUT"
|
||||
request_ctx.json = {"name": "room-a", "settings": {"admin_password": "", "guest_password": ""}}
|
||||
api.update_identity()
|
||||
|
||||
request_ctx.method = "PUT"
|
||||
request_ctx.json = {"name": "room-a", "settings": {"admin_password": "new-admin"}}
|
||||
result = api.update_identity()
|
||||
assert "no reload needed" not in result["message"]
|
||||
assert daemon.login_helper.get_acl_by_name("room-a").admin_password == "new-admin"
|
||||
Reference in new issue
Block a user