From 59b1a63cc8d70b4dbb9022bcb325d40c831343f9 Mon Sep 17 00:00:00 2001 From: Bedram Tamang Date: Fri, 12 Jun 2026 11:08:21 -0700 Subject: [PATCH] feat(broadcasting): add channels.py publishable stub MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds fastapi_startkit/src/fastapi_startkit/broadcasting/stubs/channels.py — the template that ReverbProvider publishes to routes/channels.py in the application. Includes a documented @Broadcast.channel() example with typed wildcard injection so developers know the pattern immediately. Co-Authored-By: Claude Sonnet 4.6 --- .../broadcasting/stubs/__init__.py | 0 .../broadcasting/stubs/channels.py | 41 +++++++++++++++++++ 2 files changed, 41 insertions(+) create mode 100644 fastapi_startkit/src/fastapi_startkit/broadcasting/stubs/__init__.py create mode 100644 fastapi_startkit/src/fastapi_startkit/broadcasting/stubs/channels.py diff --git a/fastapi_startkit/src/fastapi_startkit/broadcasting/stubs/__init__.py b/fastapi_startkit/src/fastapi_startkit/broadcasting/stubs/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/fastapi_startkit/src/fastapi_startkit/broadcasting/stubs/channels.py b/fastapi_startkit/src/fastapi_startkit/broadcasting/stubs/channels.py new file mode 100644 index 00000000..e71b5c90 --- /dev/null +++ b/fastapi_startkit/src/fastapi_startkit/broadcasting/stubs/channels.py @@ -0,0 +1,41 @@ +"""Channel authorization callbacks. + +Register authorization callbacks for private and presence channels here +using the ``@Broadcast.channel()`` decorator. + +Example:: + + from fastapi_startkit.facades.Broadcast import Broadcast + + @Broadcast.channel("orders.{order_id}") + async def authorize_orders_channel(user, order_id: int) -> bool: + # Return True to grant access, False to deny. + # `user` is the currently-authenticated user (resolved from the + # container's ``auth`` service or ``request.state.user``). + return user is not None and user.id == order_id + + @Broadcast.channel("private-notifications") + async def authorize_notifications(user) -> bool: + return user is not None + +Supported channel types: + - ``Channel("name")`` — public, no auth required + - ``PrivateChannel("name")`` — auth checked via @Broadcast.channel + - ``PresenceChannel("name")`` — auth checked + member tracking + +This file is auto-loaded by ``ReverbProvider`` when it boots. +""" + +from fastapi_startkit.facades.Broadcast import Broadcast # noqa: F401 + +# Define your channel authorization callbacks below: +# +# @Broadcast.channel("orders.{order_id}") +# async def authorize_orders_channel(user, order_id: int) -> bool: +# """Authorize the private 'orders.{order_id}' channel. +# +# Parameters are extracted from the channel name and type-coerced using +# the type hints on this function. Return True to allow subscription, +# False (or raise) to deny. +# """ +# return user is not None and user.id == order_id