Discord perms: partial guild payload is unknown, not a deny (#225 S1 review)
A guild without its @everyone role (or that role's permissions) was read as base 0, a definite deny that would block a start. It now raises ValueError, which S3 treats as unknown and lets the start go ahead. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
09746c467b
commit
9e850fedf0
@@ -178,9 +178,14 @@ def effective_permissions(
|
|||||||
if member_id and member_id == _sid(guild.get("owner_id")):
|
if member_id and member_id == _sid(guild.get("owner_id")):
|
||||||
return ALL_PERMISSIONS, {}
|
return ALL_PERMISSIONS, {}
|
||||||
|
|
||||||
# 2. Base from @everyone + the member's roles.
|
# 2. Base from @everyone + the member's roles. Every guild has an
|
||||||
|
# @everyone role (id == guild id) with a permissions value; without one
|
||||||
|
# the payload is partial, and reading it as "no permissions" would turn
|
||||||
|
# it into a definite deny instead of "unknown" (the plan is fail-open).
|
||||||
everyone_role = roles.get(guild_id)
|
everyone_role = roles.get(guild_id)
|
||||||
base = parse_permissions(everyone_role.get("permissions")) if everyone_role else 0
|
if not guild_id or everyone_role is None or everyone_role.get("permissions") in (None, ""):
|
||||||
|
raise ValueError(f"guild payload has no @everyone role permissions (guild {guild_id or '?'})")
|
||||||
|
base = parse_permissions(everyone_role.get("permissions"))
|
||||||
for rid in member_role_ids:
|
for rid in member_role_ids:
|
||||||
role = roles.get(rid)
|
role = roles.get(rid)
|
||||||
if role is not None and rid != guild_id:
|
if role is not None and rid != guild_id:
|
||||||
|
|||||||
@@ -245,9 +245,21 @@ def test_unknown_member_role_ids_are_ignored():
|
|||||||
assert bits == VOICE
|
assert bits == VOICE
|
||||||
|
|
||||||
|
|
||||||
def test_missing_everyone_role_means_empty_base():
|
@pytest.mark.parametrize("g", [
|
||||||
g = {"id": GUILD, "owner_id": OWNER, "roles": []}
|
{"id": GUILD, "owner_id": OWNER, "roles": []},
|
||||||
bits, trace = eff(g, member(), channel())
|
{"id": GUILD, "owner_id": OWNER},
|
||||||
|
{"id": GUILD, "owner_id": OWNER, "roles": [{"id": GUILD, "name": "@everyone"}]},
|
||||||
|
{"owner_id": OWNER, "roles": [{"id": GUILD, "name": "@everyone", "permissions": "0"}]},
|
||||||
|
])
|
||||||
|
def test_partial_guild_payload_raises_not_silently_denies(g):
|
||||||
|
# A guild without its @everyone role (or its permissions) is a partial
|
||||||
|
# payload: "unknown" (ValueError, start goes ahead), never a definite deny.
|
||||||
|
with pytest.raises(ValueError):
|
||||||
|
eff(g, member(), channel())
|
||||||
|
|
||||||
|
|
||||||
|
def test_everyone_role_granting_nothing_is_a_real_deny():
|
||||||
|
bits, trace = eff(guild(everyone=0), member(), channel())
|
||||||
assert bits == 0 and "not granted" in trace["View Channel"]
|
assert bits == 0 and "not granted" in trace["View Channel"]
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user