forked from coracle/caravel
5.6 KiB
5.6 KiB
pub struct Api
Api manages the HTTP interface for the application
Members:
host: String- the hostname of the service for checking NIP 98 auth, fromHOSTport: u16- a port to run the server on fromPORTadmins: Vec<String>- a list of admin pubkeys fromADMINSorigins: Vec<String>- to be used in CORS headers, fromALLOW_ORIGINSrepo: Repo
Notes:
- Authentication is done using NIP 98 comparing
utoself.host, not the incoming request - Each route is responsible for authorization using
self.is_admin(pubkey)orself.is_tenant(authorized_pubkey, tenant_pubkey) - Successful API responses should be of the form
{data, code: "ok"}with an appropriate http status code. - Unsuccessful API responses should be of the form
{error, code}with an appropriate http status code.codeis a short error code (e.g.duplicate-subdomain) anderroris a human-readable error message.
pub fn new() -> Self
- Reads environment and populates members
pub fn serve(&self) -> Result<()>
- Initializes an
axum::Router - Adds CORS middleware based on
origins - Calls
axum::servewith a listener
--- Plan routes
async fn list_plans(...) -> Response
- Serves
GET /plans - Return
datais a list of plan structs fromRepo::list_plans
async fn get_plan(...) -> Response
- Serves
GET /plans/:id - Return
datais a single plan struct matchingid - If plan does not exist, return
404withcode=not-found
--- Identity routes
async fn get_identity(...) -> Response
- Serves
GET /identity - Authorizes anyone, but must be authorized
- Return
datais anIdentitystruct
--- Tenant routes
async fn list_tenants(...) -> Response
- Serves
GET /tenants - Authorizes admin only
- Return
datais a list of tenant structs fromrepo.list_tenants
async fn get_tenant(...) -> Response
- Serves
GET /tenants/:pubkey - Authorizes admin or matching tenant
- Return
datais a single tenant struct fromrepo.get_tenant
async fn create_tenant(...) -> Response
- Serves
POST /tenants - Authorizes anyone, but must be authorized
- Creates a new tenant using
repo.create_tenantbased on the authorized pubkey - If tenant is a duplicate, return a
422withcode=pubkey-exists - Return
datais a single tenant struct. Use HTTP201.
async fn list_tenant_relays(...) -> Response
- Serves
GET /tenants/:pubkey/relays - Authorizes admin or matching tenant
- Return
datais a list of relay structs fromrepo.list_relays_for_tenant
async fn list_tenant_invoices(...) -> Response
- Serves
GET /tenants/:pubkey/invoices - Authorizes admin or matching tenant
- Return
datais a list of invoice structs fromrepo.list_invoices_for_tenant
async fn update_tenant_billing(...) -> Response
- Serves
PUT /tenants/:pubkey/billing - Authorizes admin or matching tenant
- Updates tenant billing NWC URL using
repo.update_tenant_nwc_url - Return
datais the submitted billing payload
--- Relay routes
async fn list_relays(...) -> Response
- Serves
GET /relays - Authorizes admin only
- Return
datais a list of relay structs fromrepo.list_relays
async fn get_relay(...) -> Response
- Serves
GET /relays/:id - Authorizes admin or relay owner
- Return
datais a single relay struct fromrepo.get_relay
async fn create_relay(...) -> Response
- Serves
POST /relays - Authorizes admin or matching tenant pubkey in request body
- Validates/prepares the relay data to be saved using
prepare_relay - Creates a new relay using
repo.create_relay - If relay is a duplicate by subdomain, return a
422withcode=subdomain-exists - Return
datais a single relay struct. Use HTTP201.
async fn update_relay(...) -> Response
- Serves
PUT /relays/:id - Authorizes admin or relay owner
- Validates/prepares the relay data to be saved using
prepare_relay - Updates the given relay using
repo.update_relay - If relay is a duplicate by subdomain, return a
422withcode=subdomain-exists - Return
datais a single relay struct.
async fn deactivate_relay(...) -> Response
- Serves
POST /relays/:id/deactivate - Authorizes admin or relay owner
- Deactivates relay using
repo.deactivate_relay - Return
datais empty
--- Invoice routes
async fn list_invoices(...) -> Response
- Serves
GET /invoices - Authorizes admin only
- Return
datais a list of invoice structs fromrepo.list_invoices
async fn get_invoice(...) -> Response
- Serves
GET /invoices/:id - Authorizes admin or invoice owner
- Return
datais a single invoice struct fromrepo.get_invoice
--- Utilities
extract_auth_pubkey(&self, headers: &HeaderMap) -> Result<String>
- Parses
Authorizationheader - Validates event kind and signature using
nostr_sdk - Validates event
uagainstHOST(not the request path. Non-standard, but correct) - Does not validate
methodtag - Returns pubkey if header all checks pass
Refer to https://github.com/nostr-protocol/nips/blob/master/98.md for details. Use nostr_sdk functionality where possible.
require_admin(&self, authorized_pubkey: &str)
- Checks whether
authorized_pubkeyis inself.admins. If not, returns an forbidden error
require_admin_or_tenant(&self, authorized_pubkey: &str, tenant_pubkey: &str)
- Checks whether
authorized_pubkeyis an admin or matchestenant_pubkey
prepare_relay(&self, relay: Relay) -> anyhow::Result<Relay>
- Validate
subdomain - If
planis free andblossomis enabled, returnpremium-feature - If
planis free andlivekitis enabled, returnpremium-feature - Populate
schemaif not already set - Populate missing fields using reasonable defaults