forked from coracle/caravel
Add identity endpoint
This commit is contained in:
@@ -61,6 +61,7 @@ See [spec](spec) for more details
|
||||
|
||||
All routes are NIP-98 protected.
|
||||
|
||||
- `GET /identity` — get auth identity (`pubkey`, `is_admin`, `is_tenant`)
|
||||
- `GET /tenants` — list tenants (admin)
|
||||
- `POST /tenants` — create current auth pubkey as tenant
|
||||
- `GET /tenants/:pubkey` — get tenant (admin or same tenant)
|
||||
|
||||
@@ -40,6 +40,14 @@ Notes:
|
||||
- Return `data` is a single plan struct matching `id`
|
||||
- If plan does not exist, return `404` with `code=not-found`
|
||||
|
||||
--- Identity routes
|
||||
|
||||
## `async fn get_identity(...) -> Response`
|
||||
|
||||
- Serves `GET /identity`
|
||||
- Authorizes anyone, but must be authorized
|
||||
- Return `data` is an `Identity` struct
|
||||
|
||||
--- Tenant routes
|
||||
|
||||
## `async fn list_tenants(...) -> Response`
|
||||
|
||||
@@ -3,6 +3,14 @@ This file describes the domain model. This description should be translated into
|
||||
- Fields marked as private should use `#[serde(skip_serializing)]` in their definition.
|
||||
- Fields marked as readonly should use `#[serde(skip_deserializing)]` in their definition.
|
||||
|
||||
# Identity
|
||||
|
||||
Identity is a description of a user.
|
||||
|
||||
- `pubkey` - the user's nostr pubkey
|
||||
- `is_admin` - whether the user is an admin
|
||||
- `is_tenant` - whether the user has an account
|
||||
|
||||
# Activity
|
||||
|
||||
Activity is an audit log of all actions performed by a user or a worker process. This allows us to trace history to create invoices, synchronize actions to external services, and debug system behavior.
|
||||
|
||||
@@ -100,6 +100,7 @@ impl Api {
|
||||
};
|
||||
|
||||
Router::new()
|
||||
.route("/identity", get(get_identity))
|
||||
.route("/plans", get(list_plans))
|
||||
.route("/plans/:id", get(get_plan))
|
||||
.route("/tenants", get(list_tenants).post(create_tenant))
|
||||
@@ -292,6 +293,13 @@ struct UpdateTenantBillingRequest {
|
||||
nwc_url: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
struct IdentityResponse {
|
||||
pubkey: String,
|
||||
is_admin: bool,
|
||||
is_tenant: bool,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct CreateRelayRequest {
|
||||
tenant: String,
|
||||
@@ -351,6 +359,35 @@ async fn list_plans(
|
||||
Ok(ok(StatusCode::OK, Repo::list_plans()))
|
||||
}
|
||||
|
||||
async fn get_identity(
|
||||
State(state): State<AppState>,
|
||||
headers: HeaderMap,
|
||||
) -> std::result::Result<Response, ApiError> {
|
||||
let pubkey = state.api.extract_auth_pubkey(&headers)?;
|
||||
let is_admin = state.api.admins.iter().any(|a| a == &pubkey);
|
||||
|
||||
let is_tenant = match state.api.repo.get_tenant(&pubkey).await {
|
||||
Ok(Some(_)) => true,
|
||||
Ok(None) => false,
|
||||
Err(e) => {
|
||||
return Ok(err(
|
||||
StatusCode::INTERNAL_SERVER_ERROR,
|
||||
"internal",
|
||||
&e.to_string(),
|
||||
));
|
||||
}
|
||||
};
|
||||
|
||||
Ok(ok(
|
||||
StatusCode::OK,
|
||||
IdentityResponse {
|
||||
pubkey,
|
||||
is_admin,
|
||||
is_tenant,
|
||||
},
|
||||
))
|
||||
}
|
||||
|
||||
async fn get_plan(
|
||||
State(state): State<AppState>,
|
||||
headers: HeaderMap,
|
||||
|
||||
Reference in New Issue
Block a user