summaryrefslogtreecommitdiffstats
path: root/packages/meshbay-hub/src/meshbay_hub/api/signaling.py
diff options
context:
space:
mode:
Diffstat (limited to 'packages/meshbay-hub/src/meshbay_hub/api/signaling.py')
-rw-r--r--packages/meshbay-hub/src/meshbay_hub/api/signaling.py33
1 files changed, 22 insertions, 11 deletions
diff --git a/packages/meshbay-hub/src/meshbay_hub/api/signaling.py b/packages/meshbay-hub/src/meshbay_hub/api/signaling.py
index 84c1167..a8feae8 100644
--- a/packages/meshbay-hub/src/meshbay_hub/api/signaling.py
+++ b/packages/meshbay-hub/src/meshbay_hub/api/signaling.py
@@ -22,6 +22,7 @@ from pydantic import BaseModel
from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession
+from meshbay_hub import hub_settings
from meshbay_hub.api.deps import get_current_user
from meshbay_hub.api.middleware import limiter
from meshbay_hub.db.engine import get_db
@@ -93,6 +94,11 @@ async def webrtc_offer(
# The caller must share at least one active group with the target node,
# OR the node must host at least one open-join group (public groups admit
# anyone — the node's MNP handshake handles authorization).
+ #
+ # That second path is exactly what "public groups" means, so it is gated by
+ # the instance switch: with public groups off, a non-member is not brokered a
+ # connection to a node just because it happens to host an open group. Members
+ # of that group are unaffected — they match `shared` below.
node_group_ids = set(_node_groups.get(node_id, []))
if node_group_ids:
result = await db.execute(
@@ -102,19 +108,24 @@ async def webrtc_offer(
))
shared = [gid for (gid,) in result.all()]
if not shared:
- has_open = await db.execute(
- select(Group.id).where(
- Group.id.in_(node_group_ids),
- Group.join_policy == "open",
- Group.status == "active",
- ))
- if not has_open.first():
+ has_open = None
+ if await hub_settings.public_groups_allowed(db):
+ has_open = (await db.execute(
+ select(Group.id).where(
+ Group.id.in_(node_group_ids),
+ Group.join_policy == "open",
+ Group.status == "active",
+ ))).first()
+ if not has_open:
raise HTTPException(status_code=403, detail="Not a member of any group on this node")
else:
- active = await db.execute(
- select(Group.id).where(Group.id.in_(shared), Group.status == "active"))
- if not active.first():
- raise HTTPException(status_code=403, detail="Group is not active")
+ statuses = set((await db.execute(
+ select(Group.status).where(Group.id.in_(shared)))).scalars().all())
+ if "active" not in statuses:
+ # Report the strongest state present — "revoked" is the signed,
+ # node-enforced one; "suspended" is the reversible hub flag.
+ state = "revoked" if "revoked" in statuses else next(iter(statuses), "suspended")
+ raise HTTPException(status_code=403, detail=f"Group is {state}")
if _pending_per_user.get(current_user.id, 0) >= MAX_PENDING_PER_USER:
raise HTTPException(status_code=429, detail="Too many pending connections")