actingweb.handlers package

Submodules

actingweb.handlers.base_handler module

class actingweb.handlers.base_handler.AuthResult(actor, auth_obj, response)[source]

Bases: object

Result of actor authentication with helper methods for authorization.

property authenticated: bool

True if authentication succeeded (regardless of authorization).

authorize(method: str, path: str = '', subpath: str = '') bool[source]

Check authorization for the given method and path.

Parameters:
  • method – HTTP method (“GET”, “POST”, etc.)

  • path – Path for authorization (defaults to path used in authentication)

  • subpath – Subpath for authorization

Returns:

True if authorized, False otherwise. Sets 403 response if unauthorized.

property success: bool

True if actor exists and authentication succeeded.

class actingweb.handlers.base_handler.BaseHandler(webobj: ~actingweb.aw_web_request.AWWebObj = <actingweb.aw_web_request.AWWebObj object>, config: ~actingweb.config.Config = <actingweb.config.Config object>, hooks: HookRegistry | None = None)[source]

Bases: object

authenticate_actor(actor_id: str, path: str = '', subpath: str = '', add_response: bool = True) AuthResult[source]

Authenticate actor and return detailed auth result.

This provides more control than require_authenticated_actor() by returning an AuthResult object that can be used for custom authorization logic.

Parameters:
  • actor_id – Actor ID to authenticate

  • path – ActingWeb path for auth type selection

  • subpath – Optional subpath

  • add_response – Whether to automatically set HTTP response

Returns:

AuthResult object with actor, auth status, and authorization helper methods

get_actor_allow_unauthenticated(actor_id: str, path: str = '', subpath: str = '') Any | None[source]

Get actor allowing unauthenticated access (for public endpoints like meta).

This method loads an actor but doesn’t require authentication. It’s used for endpoints that should be publicly accessible but still need actor data.

Parameters:
  • actor_id – Actor ID to load

  • path – Path for authorization context

  • subpath – Subpath for authorization context

Returns:

Actor object if it exists, None otherwise. Sets 404 if actor doesn’t exist.

require_authenticated_actor(actor_id: str, path: str, method: str = 'GET', subpath: str = '') Any | None[source]

Simplified actor authentication and authorization in one call.

This method combines actor loading, authentication, and authorization into a single call that handles all the common error cases and sets appropriate HTTP responses.

Parameters:
  • actor_id – Actor ID to authenticate

  • path – ActingWeb path for authorization (e.g., “properties”, “trust”)

  • method – HTTP method for authorization check (“GET”, “POST”, etc.)

  • subpath – Optional subpath for authorization

Returns:

Actor object if authentication and authorization successful, None otherwise. When None is returned, the HTTP response has already been set appropriately.

actingweb.handlers.bot module

class actingweb.handlers.bot.BotHandler(webobj: ~actingweb.aw_web_request.AWWebObj = <actingweb.aw_web_request.AWWebObj object>, config: ~actingweb.config.Config = <actingweb.config.Config object>, hooks: HookRegistry | None = None)[source]

Bases: BaseHandler

post(path)[source]

Handles POST callbacks for bots.

actingweb.handlers.callback_oauth module

class actingweb.handlers.callback_oauth.CallbackOauthHandler(webobj: ~actingweb.aw_web_request.AWWebObj = <actingweb.aw_web_request.AWWebObj object>, config: ~actingweb.config.Config = <actingweb.config.Config object>, hooks: HookRegistry | None = None)[source]

Bases: BaseHandler

get()[source]

actingweb.handlers.callbacks module

class actingweb.handlers.callbacks.CallbacksHandler(webobj: ~actingweb.aw_web_request.AWWebObj = <actingweb.aw_web_request.AWWebObj object>, config: ~actingweb.config.Config = <actingweb.config.Config object>, hooks: HookRegistry | None = None)[source]

Bases: BaseHandler

delete(actor_id, name)[source]

Handles deletion of callbacks, like subscriptions

get(actor_id, name)[source]

Handles GETs to callbacks

post(actor_id, name)[source]

Handles POST callbacks

put(actor_id, name)[source]

PUT requests are handled as POST for callbacks

actingweb.handlers.factory module

class actingweb.handlers.factory.RootFactoryHandler(webobj: ~actingweb.aw_web_request.AWWebObj = <actingweb.aw_web_request.AWWebObj object>, config: ~actingweb.config.Config = <actingweb.config.Config object>, hooks: HookRegistry | None = None)[source]

Bases: BaseHandler

get()[source]
post()[source]

actingweb.handlers.meta module

class actingweb.handlers.meta.MetaHandler(webobj: ~actingweb.aw_web_request.AWWebObj = <actingweb.aw_web_request.AWWebObj object>, config: ~actingweb.config.Config = <actingweb.config.Config object>, hooks: HookRegistry | None = None)[source]

Bases: BaseHandler

get(actor_id, path)[source]

actingweb.handlers.oauth2_callback module

OAuth2 callback handler for ActingWeb.

This handler processes OAuth2 callbacks from various providers after user authentication, exchanges the authorization code for an access token, and sets up the user session. Uses the consolidated oauth2 module for provider-agnostic OAuth2 handling.

Supports SPA (Single Page Application) mode when spa_mode=true is included in the OAuth state parameter. In SPA mode, returns JSON with tokens instead of redirecting.

class actingweb.handlers.oauth2_callback.OAuth2CallbackHandler(webobj: aw_web_request.AWWebObj | None = None, config: Config | None = None, hooks: HookRegistry | None = None)[source]

Bases: BaseHandler

Handles OAuth2 callbacks at /oauth/callback for Google/GitHub OAuth flows.

This handler processes TWO types of OAuth2 flows:

  1. Web UI Login (no trust_type in state):

    • User clicks “Login with Google/GitHub” on factory page

    • After OAuth, creates/looks up actor and redirects to UI page (/www if config.ui is enabled, /app for SPAs when config.ui is disabled)

    • If email is missing, redirects to /oauth/email for manual input

  2. MCP Authorization (trust_type in state, e.g., ‘mcp_client’):

    • OAuth flow initiated with trust_type parameter

    • After OAuth, creates/looks up actor AND trust relationship

    • If email is missing, returns error (MCP clients can’t use web forms)

Note: MCP OAuth2 flow where ActingWeb is the auth server uses encrypted state and is routed to OAuth2EndpointsHandler, not this handler.

Expected query parameters:

  • code: Authorization code to exchange for access token

  • state: CSRF protection and optional redirect URL, actor_id, trust_type

  • error: Error code if authentication failed

error_response(status_code: int, message: str) dict[str, Any][source]

Create error response with template rendering for user-friendly errors.

get() dict[str, Any][source]

Handle GET request to /oauth/callback from OAuth2 provider.

Expected parameters: - code: Authorization code from OAuth2 provider - state: State parameter for CSRF protection - error: Error code if authentication failed

Returns:

Response dict with success/error status

actingweb.handlers.oauth2_endpoints module

OAuth2 endpoints handler for ActingWeb (MCP OAuth2 Server Role).

IMPORTANT: ActingWeb has TWO OAuth2 roles:

  1. OAuth2 SERVER (this handler) - MCP clients authenticate TO ActingWeb - /oauth/register - Dynamic client registration (RFC 7591) for MCP clients - /oauth/authorize - Authorization endpoint (MCP client → user consent → ActingWeb) - /oauth/token - Token endpoint (issues ActingWeb tokens to MCP clients) - /oauth/logout - Logout endpoint

  2. OAuth2 CLIENT (see oauth2_spa.py) - Users authenticate VIA Google/GitHub - /oauth/spa/authorize - Initiate login with external provider - /oauth/spa/token - Refresh external provider tokens - /oauth/callback - Receive callback from Google/GitHub

This handler implements role #1: ActingWeb as OAuth2 authorization server for MCP clients (ChatGPT, Claude, Cursor). User authentication is proxied to Google/GitHub, but the final tokens issued are ActingWeb tokens.

class actingweb.handlers.oauth2_endpoints.OAuth2EndpointsHandler(webobj: aw_web_request.AWWebObj | None = None, config: config_class.Config | None = None, hooks: HookRegistry | None = None)[source]

Bases: BaseHandler

Handler for OAuth2 authorization server endpoints.

This handler implements ActingWeb as a full OAuth2 authorization server: 1. Dynamic client registration (RFC 7591) for MCP clients 2. OAuth2 authorization flow with Google user authentication proxy 3. ActingWeb token issuance and management 4. OAuth2 callback handling from Google

error_response(status_code: int, message: str) dict[str, Any][source]

Create OAuth2 error response.

get(path: str = '') dict[str, Any][source]

Handle GET requests to OAuth2 endpoints.

Routes: - /oauth/authorize - Authorization endpoint (shows email form) - /oauth/callback - OAuth2 callback from Google (completes MCP flow) - /.well-known/oauth-authorization-server - Authorization server discovery (RFC 8414)

Parameters:

path – The sub-path after /oauth/ (or the full well-known path)

Returns:

Response dict or redirect

options(_path: str = '') dict[str, Any][source]

Handle OPTIONS requests (CORS preflight).

Parameters:

path – The sub-path after /oauth/

Returns:

CORS headers response

post(path: str = '') dict[str, Any][source]

Handle POST requests to OAuth2 endpoints.

Routes: - /oauth/register - Dynamic client registration for MCP clients - /oauth/token - Token exchange (authorization_code or refresh_token) - /oauth/authorize - Authorization request processing (email form submission)

Parameters:

path – The sub-path after /oauth/

Returns:

Response dict

actingweb.handlers.properties module

class actingweb.handlers.properties.PropertiesHandler(webobj: ~actingweb.aw_web_request.AWWebObj = <actingweb.aw_web_request.AWWebObj object>, config: ~actingweb.config.Config = <actingweb.config.Config object>, hooks: HookRegistry | None = None)[source]

Bases: BaseHandler

delete(actor_id, name)[source]
get(actor_id, name)[source]
listall(myself, check)[source]
post(actor_id, name)[source]
put(actor_id, name)[source]
class actingweb.handlers.properties.PropertyListItemsHandler(webobj: ~actingweb.aw_web_request.AWWebObj = <actingweb.aw_web_request.AWWebObj object>, config: ~actingweb.config.Config = <actingweb.config.Config object>, hooks: HookRegistry | None = None)[source]

Bases: BaseHandler

Handler for list property items operations.

Handles GET/POST /{actor_id}/properties/{name}/items for reading all items and adding/updating/deleting items in list properties.

get(actor_id: str, name: str)[source]

Get all items from a list property.

post(actor_id: str, name: str)[source]

Add, update, or delete items in a list property.

Expects JSON body with: - action: “add”, “update”, or “delete” - item_value: The value to add or update to (for add/update) - item_index: The index to update or delete (for update/delete)

class actingweb.handlers.properties.PropertyMetadataHandler(webobj: ~actingweb.aw_web_request.AWWebObj = <actingweb.aw_web_request.AWWebObj object>, config: ~actingweb.config.Config = <actingweb.config.Config object>, hooks: HookRegistry | None = None)[source]

Bases: BaseHandler

Handler for list property metadata operations.

Handles PUT /{actor_id}/properties/{name}/metadata for updating list property description and explanation fields.

get(actor_id: str, name: str)[source]

Get list property metadata (description, explanation).

put(actor_id: str, name: str)[source]

Update list property metadata (description, explanation).

actingweb.handlers.properties.delete_dict(d1, path)[source]

Deletes path (an array of strings) in d1 dict.

d1 is modified to no longer contain the attr/value pair or dict that is specified by path.

actingweb.handlers.properties.merge_dict(d1, d2)[source]

Modifies d1 in-place to contain values from d2.

If any value in d1 is a dictionary (or dict-like), and the corresponding value in d2 is also a dictionary, then merge them in-place. Thanks to Edward Loper on stackoverflow.com

actingweb.handlers.resources module

class actingweb.handlers.resources.ResourcesHandler(webobj: ~actingweb.aw_web_request.AWWebObj = <actingweb.aw_web_request.AWWebObj object>, config: ~actingweb.config.Config = <actingweb.config.Config object>, hooks: HookRegistry | None = None)[source]

Bases: BaseHandler

delete(actor_id, name)[source]
get(actor_id, name)[source]
post(actor_id, name)[source]
put(actor_id, name)[source]

actingweb.handlers.root module

class actingweb.handlers.root.RootHandler(webobj: ~actingweb.aw_web_request.AWWebObj = <actingweb.aw_web_request.AWWebObj object>, config: ~actingweb.config.Config = <actingweb.config.Config object>, hooks: HookRegistry | None = None)[source]

Bases: BaseHandler

delete(actor_id)[source]
get(actor_id)[source]

actingweb.handlers.subscription module

class actingweb.handlers.subscription.SubscriptionDiffHandler(webobj: ~actingweb.aw_web_request.AWWebObj = <actingweb.aw_web_request.AWWebObj object>, config: ~actingweb.config.Config = <actingweb.config.Config object>, hooks: HookRegistry | None = None)[source]

Bases: BaseHandler

Handling requests to specific diffs for one subscription and clears it, e.g. /subscriptions/<peerid>/<subid>/112

get(actor_id, peerid, subid, seqnr)[source]
class actingweb.handlers.subscription.SubscriptionHandler(webobj: ~actingweb.aw_web_request.AWWebObj = <actingweb.aw_web_request.AWWebObj object>, config: ~actingweb.config.Config = <actingweb.config.Config object>, hooks: HookRegistry | None = None)[source]

Bases: BaseHandler

Handling requests to specific subscriptions, e.g. /subscriptions/<peerid>/12f2ae53bd

delete(actor_id, peerid, subid)[source]
get(actor_id, peerid, subid)[source]
put(actor_id, peerid, subid)[source]
class actingweb.handlers.subscription.SubscriptionRelationshipHandler(webobj: ~actingweb.aw_web_request.AWWebObj = <actingweb.aw_web_request.AWWebObj object>, config: ~actingweb.config.Config = <actingweb.config.Config object>, hooks: HookRegistry | None = None)[source]

Bases: BaseHandler

get(actor_id, peerid)[source]
post(actor_id, peerid)[source]
class actingweb.handlers.subscription.SubscriptionRootHandler(webobj: ~actingweb.aw_web_request.AWWebObj = <actingweb.aw_web_request.AWWebObj object>, config: ~actingweb.config.Config = <actingweb.config.Config object>, hooks: HookRegistry | None = None)[source]

Bases: BaseHandler

Handles requests to /subscription

get(actor_id)[source]
post(actor_id)[source]

actingweb.handlers.trust module

class actingweb.handlers.trust.TrustHandler(webobj: ~actingweb.aw_web_request.AWWebObj = <actingweb.aw_web_request.AWWebObj object>, config: ~actingweb.config.Config = <actingweb.config.Config object>, hooks: HookRegistry | None = None)[source]

Bases: BaseHandler

get(actor_id)[source]
post(actor_id)[source]
class actingweb.handlers.trust.TrustPeerHandler(webobj: ~actingweb.aw_web_request.AWWebObj = <actingweb.aw_web_request.AWWebObj object>, config: ~actingweb.config.Config = <actingweb.config.Config object>, hooks: HookRegistry | None = None)[source]

Bases: BaseHandler

delete(actor_id, relationship, peerid)[source]
get(actor_id, relationship, peerid)[source]
post(actor_id, relationship, peerid)[source]
put(actor_id, relationship, peerid)[source]
class actingweb.handlers.trust.TrustPermissionHandler(webobj: ~actingweb.aw_web_request.AWWebObj = <actingweb.aw_web_request.AWWebObj object>, config: ~actingweb.config.Config = <actingweb.config.Config object>, hooks: HookRegistry | None = None)[source]

Bases: BaseHandler

delete(actor_id: str, relationship: str, peerid: str)[source]

Delete permission overrides for a trust relationship.

get(actor_id: str, relationship: str, peerid: str)[source]

Get effective permissions for a specific trust relationship (custom or default from trust type).

put(actor_id: str, relationship: str, peerid: str)[source]

Create or update permission overrides for a trust relationship.

class actingweb.handlers.trust.TrustRelationshipHandler(webobj: ~actingweb.aw_web_request.AWWebObj = <actingweb.aw_web_request.AWWebObj object>, config: ~actingweb.config.Config = <actingweb.config.Config object>, hooks: HookRegistry | None = None)[source]

Bases: BaseHandler

delete(actor_id, relationship)[source]
get(actor_id, relationship)[source]
post(actor_id, relationship)[source]
put(actor_id, relationship)[source]
class actingweb.handlers.trust.TrustSharedPropertiesHandler(webobj: ~actingweb.aw_web_request.AWWebObj = <actingweb.aw_web_request.AWWebObj object>, config: ~actingweb.config.Config = <actingweb.config.Config object>, hooks: HookRegistry | None = None)[source]

Bases: BaseHandler

Handler for /{actor_id}/trust/{relationship}/{peerid}/shared_properties

Returns properties the authenticated peer is permitted to subscribe to. Requires an active trust relationship with the requesting peer.

get(actor_id: str, relationship: str, peerid: str)[source]

Get properties available for subscription by this peer.

actingweb.handlers.www module

class actingweb.handlers.www.WwwHandler(webobj: ~actingweb.aw_web_request.AWWebObj = <actingweb.aw_web_request.AWWebObj object>, config: ~actingweb.config.Config = <actingweb.config.Config object>, hooks: HookRegistry | None = None)[source]

Bases: BaseHandler

get(actor_id: str, path: str) None[source]
post(actor_id: str, path: str) None[source]

Handle POST requests for web UI property operations.