mirror of
https://github.com/pyMC-dev/pyMC_Repeater.git
synced 2026-08-07 09:23:06 +02:00
Refactor security configuration handling: update LoginHelper to retrieve security settings from the correct config path and adjust max_clients default value; modify APIEndpoints to ensure distinct admin and guest passwords, and enhance identity key validation logic in API responses.
This commit is contained in:
@@ -55,10 +55,10 @@ class LoginHelper:
|
||||
"allow_read_only": settings.get("allow_read_only", True),
|
||||
}
|
||||
else:
|
||||
# Repeater uses security from its config
|
||||
security = config.get("security", {})
|
||||
# Repeater uses security from repeater.security in config
|
||||
security = config.get("repeater", {}).get("security", {})
|
||||
final_security = {
|
||||
"max_clients": security.get("max_clients", 50),
|
||||
"max_clients": security.get("max_clients", 10),
|
||||
"admin_password": security.get("admin_password", "admin123"),
|
||||
"guest_password": security.get("guest_password", "guest123"),
|
||||
"allow_read_only": security.get("allow_read_only", True),
|
||||
|
||||
+1
-2
@@ -168,12 +168,11 @@ class RepeaterDaemon:
|
||||
)
|
||||
|
||||
# Register default repeater identity
|
||||
repeater_config = self.config.get("repeater", {})
|
||||
self.login_helper.register_identity(
|
||||
name="repeater",
|
||||
identity=self.local_identity,
|
||||
identity_type="repeater",
|
||||
config=repeater_config # Pass repeater config (includes security settings)
|
||||
config=self.config # Pass full config so repeater can access top-level security section
|
||||
)
|
||||
|
||||
# Register room server identities with their configs
|
||||
|
||||
@@ -1141,6 +1141,12 @@ class APIEndpoints:
|
||||
if not name:
|
||||
return self._error("Missing required field: name")
|
||||
|
||||
# Validate passwords are different if both provided
|
||||
admin_pw = settings.get("admin_password")
|
||||
guest_pw = settings.get("guest_password")
|
||||
if admin_pw and guest_pw and admin_pw == guest_pw:
|
||||
return self._error("admin_password and guest_password must be different")
|
||||
|
||||
# Auto-generate identity key if not provided
|
||||
key_was_generated = False
|
||||
if not identity_key:
|
||||
@@ -1301,15 +1307,32 @@ class APIEndpoints:
|
||||
return self._error(f"Identity with name '{new_name}' already exists")
|
||||
identity["name"] = new_name
|
||||
|
||||
# Only update identity_key if a non-empty value is provided
|
||||
# Only update identity_key if a valid full key is provided
|
||||
# Silently reject truncated keys (containing "...") or invalid hex strings
|
||||
if "identity_key" in data and data["identity_key"]:
|
||||
identity["identity_key"] = data["identity_key"]
|
||||
new_key = data["identity_key"]
|
||||
# Check if it's a truncated key (contains "...") or not a valid 64-char hex string
|
||||
if "..." not in new_key and len(new_key) == 64:
|
||||
try:
|
||||
# Validate it's proper hex
|
||||
bytes.fromhex(new_key)
|
||||
identity["identity_key"] = new_key
|
||||
logger.info(f"Updated identity_key for '{name}'")
|
||||
except ValueError:
|
||||
# Invalid hex, silently ignore
|
||||
pass
|
||||
|
||||
if "settings" in data:
|
||||
# Merge settings
|
||||
if "settings" not in identity:
|
||||
identity["settings"] = {}
|
||||
identity["settings"].update(data["settings"])
|
||||
|
||||
# Validate passwords are different if both are now set
|
||||
admin_pw = identity["settings"].get("admin_password")
|
||||
guest_pw = identity["settings"].get("guest_password")
|
||||
if admin_pw and guest_pw and admin_pw == guest_pw:
|
||||
return self._error("admin_password and guest_password must be different")
|
||||
|
||||
# Save to config
|
||||
room_servers[identity_index] = identity
|
||||
|
||||
+73
-22
@@ -699,7 +699,7 @@ paths:
|
||||
get:
|
||||
tags: [ACL]
|
||||
summary: List ACL clients
|
||||
description: Get list of clients in access control list
|
||||
description: Get list of authenticated clients in access control list for an identity
|
||||
parameters:
|
||||
- name: identity_hash
|
||||
in: query
|
||||
@@ -730,7 +730,32 @@ paths:
|
||||
clients:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/ACLEntry'
|
||||
$ref: '#/components/schemas/ACLClient'
|
||||
count:
|
||||
type: integer
|
||||
description: Number of clients returned
|
||||
filter:
|
||||
type: string
|
||||
nullable: true
|
||||
description: Filter applied (if any)
|
||||
examples:
|
||||
success:
|
||||
value:
|
||||
success: true
|
||||
data:
|
||||
clients:
|
||||
- public_key: "03ccf3bb0bed9a51...21416fff"
|
||||
public_key_full: "03ccf3bb0bed9a5109868a1e33ed020519aab6dbb30e42df3b11a21d21416fff"
|
||||
address: "e1"
|
||||
permissions: "admin"
|
||||
last_activity: 1766065148
|
||||
last_login_success: 1766065146
|
||||
last_timestamp: 1766065146
|
||||
identity_name: "rrrrr"
|
||||
identity_type: "room_server"
|
||||
identity_hash: "0xC5"
|
||||
count: 1
|
||||
filter: null
|
||||
|
||||
/acl_remove_client:
|
||||
post:
|
||||
@@ -1441,32 +1466,58 @@ components:
|
||||
description: Maximum messages to keep (room_server only, hard limit 32)
|
||||
example: 32
|
||||
|
||||
ACLEntry:
|
||||
ACLClient:
|
||||
type: object
|
||||
required: [action, network_address, port]
|
||||
required: [public_key, public_key_full, address, permissions]
|
||||
properties:
|
||||
action:
|
||||
public_key:
|
||||
type: string
|
||||
enum: [allow, deny]
|
||||
description: Truncated public key for display (first 24 and last 8 chars)
|
||||
example: "03ccf3bb0bed9a51...21416fff"
|
||||
public_key_full:
|
||||
type: string
|
||||
pattern: '^[0-9a-fA-F]{64}$'
|
||||
description: Full client public key (64 hex chars)
|
||||
example: "03ccf3bb0bed9a5109868a1e33ed020519aab6dbb30e42df3b11a21d21416fff"
|
||||
address:
|
||||
type: string
|
||||
description: Client address identifier
|
||||
example: "e1"
|
||||
permissions:
|
||||
type: string
|
||||
enum: [admin, guest, read_only]
|
||||
description: |
|
||||
- allow: Permit packets from this address
|
||||
- deny: Block packets from this address
|
||||
example: allow
|
||||
network_address:
|
||||
type: string
|
||||
description: IP address or CIDR range (e.g., 192.168.1.0/24)
|
||||
example: "192.168.1.0/24"
|
||||
port:
|
||||
Client permission level:
|
||||
- admin: Full access
|
||||
- guest: Limited access
|
||||
- read_only: Read-only access
|
||||
example: "admin"
|
||||
last_activity:
|
||||
type: integer
|
||||
minimum: 0
|
||||
maximum: 65535
|
||||
description: Source port (0 = any port)
|
||||
example: 0
|
||||
comment:
|
||||
description: Unix timestamp of last activity
|
||||
example: 1766065148
|
||||
last_login_success:
|
||||
type: integer
|
||||
description: Unix timestamp of last successful login
|
||||
example: 1766065146
|
||||
last_timestamp:
|
||||
type: integer
|
||||
description: Unix timestamp from last client message
|
||||
example: 1766065146
|
||||
identity_name:
|
||||
type: string
|
||||
maxLength: 200
|
||||
description: Optional description
|
||||
example: "Allow local network"
|
||||
description: Name of the identity this client is authenticated to
|
||||
example: "rrrrr"
|
||||
identity_type:
|
||||
type: string
|
||||
enum: [repeater, room_server]
|
||||
description: Type of identity
|
||||
example: "room_server"
|
||||
identity_hash:
|
||||
type: string
|
||||
pattern: '^0x[0-9a-fA-F]{2}$'
|
||||
description: Hash of the identity
|
||||
example: "0xC5"
|
||||
|
||||
securitySchemes:
|
||||
# Future: API key authentication
|
||||
|
||||
Reference in New Issue
Block a user