mirror of
https://github.com/Such-Software/smirk-backend-core.git
synced 2026-10-17 07:21:32 +02:00
feat(tips): serve /tips/social/received + /claimable as empty (public-only)
Public-only instances have no targeted-recipient inbox (public tips are claimed
via share URL, never delivered to a user), so the client's inbox poll of
/received + /claimable 404'd. Serve them 200-empty instead so the poll succeeds
quietly. Matches the client contract ({tips:[]}).
This commit is contained in:
@@ -751,6 +751,70 @@
|
||||
]
|
||||
}
|
||||
},
|
||||
"/tips/social/claimable": {
|
||||
"get": {
|
||||
"tags": [
|
||||
"tips"
|
||||
],
|
||||
"summary": "Tips CLAIMABLE by the caller. As with `received`, a public-only instance has\nno targeted-claimable inbox, so this is always empty (served 200, not 404).",
|
||||
"operationId": "get_claimable_social_tips",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Claimable tips (empty on a public-only instance)",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/SocialTipsResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Tips off"
|
||||
},
|
||||
"401": {
|
||||
"description": "Missing or invalid token"
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"bearer_auth": []
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"/tips/social/received": {
|
||||
"get": {
|
||||
"tags": [
|
||||
"tips"
|
||||
],
|
||||
"summary": "Tips RECEIVED by the caller. Public-only instances have no targeted-recipient\ninbox (public tips are claimed via share URL, never delivered to a user), so\nthis is always empty — served (200) rather than 404 so the client's inbox\npoll doesn't error on a targeted-only endpoint this instance doesn't serve.",
|
||||
"operationId": "get_received_social_tips",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Received tips (empty on a public-only instance)",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/SocialTipsResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Tips off"
|
||||
},
|
||||
"401": {
|
||||
"description": "Missing or invalid token"
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"bearer_auth": []
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"/tips/social/sent": {
|
||||
"get": {
|
||||
"tags": [
|
||||
|
||||
@@ -70,6 +70,8 @@ use utoipa::OpenApi;
|
||||
crate::api::premium::status,
|
||||
crate::api::tips::create_social_tip,
|
||||
crate::api::tips::get_sent_social_tips,
|
||||
crate::api::tips::get_received_social_tips,
|
||||
crate::api::tips::get_claimable_social_tips,
|
||||
crate::api::tips::get_public_social_tip,
|
||||
crate::api::tips::cancel_social_tip,
|
||||
crate::api::tips::attach_funding,
|
||||
|
||||
@@ -419,6 +419,54 @@ pub async fn get_sent_social_tips(
|
||||
}))
|
||||
}
|
||||
|
||||
/// Tips RECEIVED by the caller. Public-only instances have no targeted-recipient
|
||||
/// inbox (public tips are claimed via share URL, never delivered to a user), so
|
||||
/// this is always empty — served (200) rather than 404 so the client's inbox
|
||||
/// poll doesn't error on a targeted-only endpoint this instance doesn't serve.
|
||||
#[utoipa::path(
|
||||
security(("bearer_auth" = [])),
|
||||
get,
|
||||
path = "/tips/social/received",
|
||||
responses(
|
||||
(status = 200, description = "Received tips (empty on a public-only instance)", body = SocialTipsResponse),
|
||||
(status = 400, description = "Tips off"),
|
||||
(status = 401, description = "Missing or invalid token")
|
||||
),
|
||||
tag = "tips"
|
||||
)]
|
||||
#[instrument(skip(state, headers))]
|
||||
pub async fn get_received_social_tips(
|
||||
State(state): State<Arc<AppState>>,
|
||||
headers: HeaderMap,
|
||||
) -> Result<Json<SocialTipsResponse>, AppError> {
|
||||
extract_user_id_from_token(&state, &headers).await?;
|
||||
ensure_tips_enabled(&state)?;
|
||||
Ok(Json(SocialTipsResponse { tips: Vec::new() }))
|
||||
}
|
||||
|
||||
/// Tips CLAIMABLE by the caller. As with `received`, a public-only instance has
|
||||
/// no targeted-claimable inbox, so this is always empty (served 200, not 404).
|
||||
#[utoipa::path(
|
||||
security(("bearer_auth" = [])),
|
||||
get,
|
||||
path = "/tips/social/claimable",
|
||||
responses(
|
||||
(status = 200, description = "Claimable tips (empty on a public-only instance)", body = SocialTipsResponse),
|
||||
(status = 400, description = "Tips off"),
|
||||
(status = 401, description = "Missing or invalid token")
|
||||
),
|
||||
tag = "tips"
|
||||
)]
|
||||
#[instrument(skip(state, headers))]
|
||||
pub async fn get_claimable_social_tips(
|
||||
State(state): State<Arc<AppState>>,
|
||||
headers: HeaderMap,
|
||||
) -> Result<Json<SocialTipsResponse>, AppError> {
|
||||
extract_user_id_from_token(&state, &headers).await?;
|
||||
ensure_tips_enabled(&state)?;
|
||||
Ok(Json(SocialTipsResponse { tips: Vec::new() }))
|
||||
}
|
||||
|
||||
/// Public tip metadata for a share-URL holder. UNAUTHENTICATED: the tip id (a
|
||||
/// UUID) is the bearer token. 404s for an unknown or non-public tip.
|
||||
#[utoipa::path(
|
||||
@@ -664,6 +712,8 @@ pub fn routes() -> Router<Arc<AppState>> {
|
||||
Router::new()
|
||||
.route("/tips/social", post(create_social_tip))
|
||||
.route("/tips/social/sent", get(get_sent_social_tips))
|
||||
.route("/tips/social/received", get(get_received_social_tips))
|
||||
.route("/tips/social/claimable", get(get_claimable_social_tips))
|
||||
.route("/tips/social/:tip_id/public", get(get_public_social_tip))
|
||||
.route("/tips/social/:tip_id/cancel", post(cancel_social_tip))
|
||||
.route(
|
||||
|
||||
Reference in New Issue
Block a user