refactor: type safety + dedup cleanup across 13 code smells
- typed PagedResponse/CreatedApiKeyResponse/NotificationSummaryResponse replace json! blocks - extract TagRow/ApiKeyRow/OutboxRow to module level, top_friend uses sqlx flatten - add should_broadcast() helper, inline dead let bindings in federation_event - add UploadContext struct, extract_upload_field, wants_activity_json helpers - rename PostgresFederationRepository→PgFederationRepository, PostgresApUserRepository→PgApUserRepository - add IntoAnyhow trait replacing ~30 .map_err(|e| anyhow!(e)) calls - extract build_ap_service shared between bootstrap and worker factories - add postgres/constants.rs, PartialEq+Eq on PasswordHash
This commit is contained in:
@@ -37,11 +37,13 @@ pub async fn post_api_key(
|
||||
Deps(d): Deps<ApiKeysDeps>,
|
||||
AuthUser(uid): AuthUser,
|
||||
Json(body): Json<CreateApiKeyRequest>,
|
||||
) -> Result<Json<serde_json::Value>, ApiError> {
|
||||
) -> Result<Json<CreatedApiKeyResponse>, ApiError> {
|
||||
let (key, raw) = create_api_key(&*d.api_keys, &uid, body.name).await?;
|
||||
Ok(Json(
|
||||
serde_json::json!({ "id": key.id.as_uuid(), "name": key.name, "key": raw }),
|
||||
))
|
||||
Ok(Json(CreatedApiKeyResponse {
|
||||
id: key.id.as_uuid(),
|
||||
name: key.name,
|
||||
key: raw,
|
||||
}))
|
||||
}
|
||||
#[utoipa::path(delete, path = "/api-keys/{id}", params(("id" = uuid::Uuid, Path, description = "Key ID")), responses((status = 204, description = "Deleted")), security(("bearer_auth" = [])))]
|
||||
pub async fn delete_api_key_handler(
|
||||
|
||||
@@ -5,7 +5,7 @@ use crate::{
|
||||
handlers::auth::to_user_response,
|
||||
};
|
||||
use api_types::requests::{PaginationQuery, SearchQuery};
|
||||
use api_types::responses::ThoughtResponse;
|
||||
use api_types::responses::{PagedResponse, ThoughtResponse};
|
||||
use application::use_cases::feed::{
|
||||
get_home_feed, get_popular_tags as uc_get_popular_tags, get_public_feed, get_tag_feed,
|
||||
get_user_feed,
|
||||
@@ -75,6 +75,13 @@ impl TryFrom<FeedOptionsQuery> for FeedOptions {
|
||||
}
|
||||
}
|
||||
|
||||
fn wants_activity_json(headers: &HeaderMap) -> bool {
|
||||
headers
|
||||
.get(header::ACCEPT)
|
||||
.and_then(|v| v.to_str().ok())
|
||||
.is_some_and(|a| a.contains("application/activity+json"))
|
||||
}
|
||||
|
||||
deps_struct!(FeedDeps {
|
||||
feed: FeedRepository,
|
||||
follows: FollowRepository,
|
||||
@@ -116,19 +123,19 @@ pub async fn home_feed(
|
||||
AuthUser(uid): AuthUser,
|
||||
Query(q): Query<PaginationQuery>,
|
||||
Query(opts_q): Query<FeedOptionsQuery>,
|
||||
) -> Result<Json<serde_json::Value>, ApiError> {
|
||||
) -> Result<Json<PagedResponse<ThoughtResponse>>, ApiError> {
|
||||
let page = PageParams {
|
||||
page: q.page(),
|
||||
per_page: q.per_page(),
|
||||
};
|
||||
let opts = FeedOptions::try_from(opts_q)?;
|
||||
let result = get_home_feed(&*d.feed, &*d.follows, &uid, page, opts).await?;
|
||||
Ok(Json(serde_json::json!({
|
||||
"items": result.items.iter().map(to_thought_response).collect::<Vec<_>>(),
|
||||
"total": result.total,
|
||||
"page": result.page,
|
||||
"per_page": result.per_page,
|
||||
})))
|
||||
Ok(Json(PagedResponse {
|
||||
items: result.items.iter().map(to_thought_response).collect(),
|
||||
total: result.total,
|
||||
page: result.page,
|
||||
per_page: result.per_page,
|
||||
}))
|
||||
}
|
||||
|
||||
#[utoipa::path(
|
||||
@@ -141,19 +148,19 @@ pub async fn public_feed(
|
||||
OptionalAuthUser(viewer): OptionalAuthUser,
|
||||
Query(q): Query<PaginationQuery>,
|
||||
Query(opts_q): Query<FeedOptionsQuery>,
|
||||
) -> Result<Json<serde_json::Value>, ApiError> {
|
||||
) -> Result<Json<PagedResponse<ThoughtResponse>>, ApiError> {
|
||||
let page = PageParams {
|
||||
page: q.page(),
|
||||
per_page: q.per_page(),
|
||||
};
|
||||
let opts = FeedOptions::try_from(opts_q)?;
|
||||
let result = get_public_feed(&*d.feed, viewer, page, opts).await?;
|
||||
Ok(Json(serde_json::json!({
|
||||
"items": result.items.iter().map(to_thought_response).collect::<Vec<_>>(),
|
||||
"total": result.total,
|
||||
"page": result.page,
|
||||
"per_page": result.per_page,
|
||||
})))
|
||||
Ok(Json(PagedResponse {
|
||||
items: result.items.iter().map(to_thought_response).collect(),
|
||||
total: result.total,
|
||||
page: result.page,
|
||||
per_page: result.per_page,
|
||||
}))
|
||||
}
|
||||
|
||||
#[utoipa::path(
|
||||
@@ -210,12 +217,7 @@ pub async fn get_following_handler(
|
||||
Query(q): Query<PaginationQuery>,
|
||||
headers: HeaderMap,
|
||||
) -> Result<Response, ApiError> {
|
||||
let accept = headers
|
||||
.get(header::ACCEPT)
|
||||
.and_then(|v| v.to_str().ok())
|
||||
.unwrap_or("");
|
||||
|
||||
if accept.contains("application/activity+json") {
|
||||
if wants_activity_json(&headers) {
|
||||
let user = get_user_by_id_or_username(&*d.users, ¶m).await?;
|
||||
let user_id = user.id;
|
||||
let page = q.page().try_into().ok();
|
||||
@@ -232,10 +234,12 @@ pub async fn get_following_handler(
|
||||
per_page: q.per_page(),
|
||||
};
|
||||
let result = list_local_following(&*d.follows, &user.id, page).await?;
|
||||
Ok(Json(serde_json::json!({
|
||||
"total": result.total,
|
||||
"items": result.items.iter().map(to_user_response).collect::<Vec<_>>()
|
||||
}))
|
||||
Ok(Json(PagedResponse {
|
||||
items: result.items.iter().map(to_user_response).collect(),
|
||||
total: result.total,
|
||||
page: result.page,
|
||||
per_page: result.per_page,
|
||||
})
|
||||
.into_response())
|
||||
}
|
||||
|
||||
@@ -253,12 +257,7 @@ pub async fn get_followers_handler(
|
||||
Query(q): Query<PaginationQuery>,
|
||||
headers: HeaderMap,
|
||||
) -> Result<Response, ApiError> {
|
||||
let accept = headers
|
||||
.get(header::ACCEPT)
|
||||
.and_then(|v| v.to_str().ok())
|
||||
.unwrap_or("");
|
||||
|
||||
if accept.contains("application/activity+json") {
|
||||
if wants_activity_json(&headers) {
|
||||
let user = get_user_by_id_or_username(&*d.users, ¶m).await?;
|
||||
let user_id = user.id;
|
||||
let page = q.page().try_into().ok();
|
||||
@@ -275,10 +274,12 @@ pub async fn get_followers_handler(
|
||||
per_page: q.per_page(),
|
||||
};
|
||||
let result = list_local_followers(&*d.follows, &user.id, page).await?;
|
||||
Ok(Json(serde_json::json!({
|
||||
"total": result.total,
|
||||
"items": result.items.iter().map(to_user_response).collect::<Vec<_>>()
|
||||
}))
|
||||
Ok(Json(PagedResponse {
|
||||
items: result.items.iter().map(to_user_response).collect(),
|
||||
total: result.total,
|
||||
page: result.page,
|
||||
per_page: result.per_page,
|
||||
})
|
||||
.into_response())
|
||||
}
|
||||
|
||||
@@ -297,7 +298,7 @@ pub async fn user_thoughts_handler(
|
||||
OptionalAuthUser(viewer): OptionalAuthUser,
|
||||
Query(q): Query<PaginationQuery>,
|
||||
Query(opts_q): Query<FeedOptionsQuery>,
|
||||
) -> Result<Json<serde_json::Value>, ApiError> {
|
||||
) -> Result<Json<PagedResponse<ThoughtResponse>>, ApiError> {
|
||||
let user = get_user_by_username(&*d.users, &username).await?;
|
||||
let page = PageParams {
|
||||
page: q.page(),
|
||||
@@ -305,12 +306,12 @@ pub async fn user_thoughts_handler(
|
||||
};
|
||||
let opts = FeedOptions::try_from(opts_q)?;
|
||||
let result = get_user_feed(&*d.feed, user.id.clone(), page, opts, viewer).await?;
|
||||
Ok(Json(serde_json::json!({
|
||||
"total": result.total,
|
||||
"page": result.page,
|
||||
"per_page": result.per_page,
|
||||
"items": result.items.iter().map(to_thought_response).collect::<Vec<_>>()
|
||||
})))
|
||||
Ok(Json(PagedResponse {
|
||||
items: result.items.iter().map(to_thought_response).collect(),
|
||||
total: result.total,
|
||||
page: result.page,
|
||||
per_page: result.per_page,
|
||||
}))
|
||||
}
|
||||
|
||||
#[utoipa::path(
|
||||
@@ -353,18 +354,17 @@ pub async fn tag_thoughts_handler(
|
||||
OptionalAuthUser(viewer): OptionalAuthUser,
|
||||
Query(q): Query<PaginationQuery>,
|
||||
Query(opts_q): Query<FeedOptionsQuery>,
|
||||
) -> Result<Json<serde_json::Value>, ApiError> {
|
||||
) -> Result<Json<PagedResponse<ThoughtResponse>>, ApiError> {
|
||||
let page = PageParams {
|
||||
page: q.page(),
|
||||
per_page: q.per_page(),
|
||||
};
|
||||
let opts = FeedOptions::try_from(opts_q)?;
|
||||
let result = get_tag_feed(&*d.feed, &tag_name, page, opts, viewer).await?;
|
||||
Ok(Json(serde_json::json!({
|
||||
"tag": tag_name,
|
||||
"total": result.total,
|
||||
"page": result.page,
|
||||
"per_page": result.per_page,
|
||||
"items": result.items.iter().map(to_thought_response).collect::<Vec<_>>(),
|
||||
})))
|
||||
Ok(Json(PagedResponse {
|
||||
items: result.items.iter().map(to_thought_response).collect(),
|
||||
total: result.total,
|
||||
page: result.page,
|
||||
per_page: result.per_page,
|
||||
}))
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ use crate::{
|
||||
errors::ApiError,
|
||||
extractors::{AuthUser, Deps},
|
||||
};
|
||||
use api_types::requests::NotificationUpdateRequest;
|
||||
use api_types::{requests::NotificationUpdateRequest, responses::NotificationSummaryResponse};
|
||||
use application::use_cases::notifications::{
|
||||
count_unread_notifications, list_notifications as uc_list_notifications,
|
||||
mark_all_notifications_read, mark_notification_read as uc_mark_notification_read,
|
||||
@@ -22,17 +22,17 @@ deps_struct!(NotificationsDeps {
|
||||
pub async fn list_notifications(
|
||||
Deps(d): Deps<NotificationsDeps>,
|
||||
AuthUser(uid): AuthUser,
|
||||
) -> Result<Json<serde_json::Value>, ApiError> {
|
||||
) -> Result<Json<NotificationSummaryResponse>, ApiError> {
|
||||
let page = PageParams {
|
||||
page: 1,
|
||||
per_page: 20,
|
||||
};
|
||||
let result = uc_list_notifications(&*d.notifications, &uid, page).await?;
|
||||
let unread = count_unread_notifications(&*d.notifications, &uid).await?;
|
||||
Ok(Json(serde_json::json!({
|
||||
"total": result.total,
|
||||
"unread": unread
|
||||
})))
|
||||
Ok(Json(NotificationSummaryResponse {
|
||||
total: result.total,
|
||||
unread,
|
||||
}))
|
||||
}
|
||||
|
||||
#[utoipa::path(patch, path = "/notifications/{id}", params(("id" = uuid::Uuid, Path, description = "Notification ID")), request_body = NotificationUpdateRequest, responses((status = 204, description = "Marked read")), security(("bearer_auth" = [])))]
|
||||
|
||||
@@ -6,12 +6,12 @@ use crate::{
|
||||
};
|
||||
use api_types::{
|
||||
requests::{PaginationQuery, UpdateProfileRequest},
|
||||
responses::{ErrorResponse, ProfileField, RemoteActorResponse, UserResponse},
|
||||
responses::{ErrorResponse, PagedResponse, ProfileField, RemoteActorResponse, UserResponse},
|
||||
};
|
||||
use application::use_cases::profile::{
|
||||
count_local_users, get_user as fetch_user, get_user_by_id_or_username, get_user_profile,
|
||||
list_local_following, list_users, update_profile, upload_avatar as upload_avatar_uc,
|
||||
upload_banner as upload_banner_uc, UploadConfig,
|
||||
upload_banner as upload_banner_uc, UploadConfig, UploadContext,
|
||||
};
|
||||
use axum::{
|
||||
extract::{Multipart, Path, Query},
|
||||
@@ -54,6 +54,13 @@ impl FromAppState for UsersDeps {
|
||||
}
|
||||
}
|
||||
|
||||
fn wants_activity_json(headers: &HeaderMap) -> bool {
|
||||
headers
|
||||
.get(header::ACCEPT)
|
||||
.and_then(|v| v.to_str().ok())
|
||||
.is_some_and(|a| a.contains("application/activity+json"))
|
||||
}
|
||||
|
||||
#[utoipa::path(
|
||||
get, path = "/users/{username}",
|
||||
params(("username" = String, Path, description = "Username")),
|
||||
@@ -68,12 +75,7 @@ pub async fn get_user(
|
||||
OptionalAuthUser(viewer): OptionalAuthUser,
|
||||
headers: HeaderMap,
|
||||
) -> Result<Response, ApiError> {
|
||||
let accept = headers
|
||||
.get(header::ACCEPT)
|
||||
.and_then(|v| v.to_str().ok())
|
||||
.unwrap_or("");
|
||||
|
||||
if accept.contains("application/activity+json") {
|
||||
if wants_activity_json(&headers) {
|
||||
let user = get_user_by_id_or_username(&*d.users, &username).await?;
|
||||
let json = d.federation.actor_json(&user.id).await?;
|
||||
Ok(([(header::CONTENT_TYPE, "application/activity+json")], json).into_response())
|
||||
@@ -145,17 +147,19 @@ pub async fn get_me_following(
|
||||
Deps(d): Deps<UsersDeps>,
|
||||
AuthUser(uid): AuthUser,
|
||||
Query(q): Query<PaginationQuery>,
|
||||
) -> Result<Json<serde_json::Value>, ApiError> {
|
||||
) -> Result<Json<PagedResponse<UserResponse>>, ApiError> {
|
||||
use domain::models::feed::PageParams;
|
||||
let page = PageParams {
|
||||
page: q.page(),
|
||||
per_page: q.per_page(),
|
||||
};
|
||||
let result = list_local_following(&*d.follows, &uid, page).await?;
|
||||
Ok(Json(serde_json::json!({
|
||||
"total": result.total,
|
||||
"items": result.items.iter().map(to_user_response).collect::<Vec<_>>(),
|
||||
})))
|
||||
Ok(Json(PagedResponse {
|
||||
items: result.items.iter().map(to_user_response).collect(),
|
||||
total: result.total,
|
||||
page: result.page,
|
||||
per_page: result.per_page,
|
||||
}))
|
||||
}
|
||||
|
||||
#[utoipa::path(
|
||||
@@ -170,7 +174,7 @@ pub async fn get_me_following(
|
||||
pub async fn get_users(
|
||||
Deps(d): Deps<UsersDeps>,
|
||||
Query(params): Query<std::collections::HashMap<String, String>>,
|
||||
) -> Result<Json<serde_json::Value>, ApiError> {
|
||||
) -> Result<Json<PagedResponse<UserResponse>>, ApiError> {
|
||||
use domain::models::feed::PageParams;
|
||||
let page = params
|
||||
.get("page")
|
||||
@@ -184,38 +188,37 @@ pub async fn get_users(
|
||||
|
||||
if let Some(q) = params.get("q").filter(|q| !q.trim().is_empty()) {
|
||||
let result = d.search.search_users(q, &page_params).await?;
|
||||
let users: Vec<_> = result
|
||||
.items
|
||||
.iter()
|
||||
.map(crate::handlers::auth::to_user_response)
|
||||
.collect();
|
||||
return Ok(Json(serde_json::json!({
|
||||
"items": users, "total": result.total, "page": result.page, "per_page": result.per_page
|
||||
})));
|
||||
return Ok(Json(PagedResponse {
|
||||
items: result.items.iter().map(to_user_response).collect(),
|
||||
total: result.total,
|
||||
page: result.page,
|
||||
per_page: result.per_page,
|
||||
}));
|
||||
}
|
||||
|
||||
let result = list_users(&*d.users, page_params).await?;
|
||||
let items: Vec<_> = result
|
||||
let items: Vec<UserResponse> = result
|
||||
.items
|
||||
.iter()
|
||||
.map(|u| {
|
||||
serde_json::json!({
|
||||
"id": u.id.as_uuid(),
|
||||
"username": u.username,
|
||||
"displayName": u.display_name,
|
||||
"avatarUrl": u.avatar_url,
|
||||
"bio": u.bio,
|
||||
"headerUrl": null,
|
||||
"customCss": null,
|
||||
"local": true,
|
||||
"isFollowedByViewer": false,
|
||||
"joinedAt": null,
|
||||
})
|
||||
.map(|u| UserResponse {
|
||||
id: u.id.as_uuid(),
|
||||
username: u.username.clone(),
|
||||
display_name: u.display_name.clone(),
|
||||
bio: u.bio.clone(),
|
||||
avatar_url: u.avatar_url.clone(),
|
||||
header_url: None,
|
||||
custom_css: None,
|
||||
local: true,
|
||||
is_followed_by_viewer: false,
|
||||
created_at: chrono::Utc::now(),
|
||||
})
|
||||
.collect();
|
||||
Ok(Json(serde_json::json!({
|
||||
"items": items, "total": result.total, "page": result.page, "per_page": result.per_page
|
||||
})))
|
||||
Ok(Json(PagedResponse {
|
||||
items,
|
||||
total: result.total,
|
||||
page: result.page,
|
||||
per_page: result.per_page,
|
||||
}))
|
||||
}
|
||||
|
||||
#[utoipa::path(
|
||||
@@ -266,6 +269,25 @@ pub async fn lookup_handler(
|
||||
}))
|
||||
}
|
||||
|
||||
async fn extract_upload_field(
|
||||
mut multipart: Multipart,
|
||||
) -> Result<(String, axum::body::Bytes), ApiError> {
|
||||
let field = multipart
|
||||
.next_field()
|
||||
.await
|
||||
.map_err(|_| ApiError::BadRequest("invalid multipart".into()))?
|
||||
.ok_or_else(|| ApiError::BadRequest("no file field".into()))?;
|
||||
let content_type = field
|
||||
.content_type()
|
||||
.ok_or_else(|| ApiError::BadRequest("missing content-type on field".into()))?
|
||||
.to_string();
|
||||
let data = field
|
||||
.bytes()
|
||||
.await
|
||||
.map_err(|_| ApiError::BadRequest("failed to read upload".into()))?;
|
||||
Ok((content_type, data))
|
||||
}
|
||||
|
||||
#[utoipa::path(
|
||||
put, path = "/users/me/avatar",
|
||||
request_body(content = String, content_type = "multipart/form-data", description = "Image file (JPEG, PNG, WebP, AVIF, GIF)"),
|
||||
@@ -278,35 +300,17 @@ pub async fn lookup_handler(
|
||||
pub async fn upload_avatar(
|
||||
Deps(d): Deps<UsersDeps>,
|
||||
AuthUser(uid): AuthUser,
|
||||
mut multipart: Multipart,
|
||||
multipart: Multipart,
|
||||
) -> Result<Json<UserResponse>, ApiError> {
|
||||
let field = multipart
|
||||
.next_field()
|
||||
.await
|
||||
.map_err(|_| ApiError::BadRequest("invalid multipart".into()))?
|
||||
.ok_or_else(|| ApiError::BadRequest("no file field".into()))?;
|
||||
// Content-type is client-supplied; the use-case allowlist prevents obviously
|
||||
// wrong types, but magic-byte validation is not performed. Serve media files
|
||||
// from an isolated origin to prevent MIME-based XSS.
|
||||
let content_type = field
|
||||
.content_type()
|
||||
.ok_or_else(|| ApiError::BadRequest("missing content-type on field".into()))?
|
||||
.to_string();
|
||||
let data = field
|
||||
.bytes()
|
||||
.await
|
||||
.map_err(|_| ApiError::BadRequest("failed to read upload".into()))?;
|
||||
upload_avatar_uc(
|
||||
&*d.users,
|
||||
&*d.media,
|
||||
&*d.events,
|
||||
&uid,
|
||||
&d.base_url,
|
||||
&d.upload_config,
|
||||
&content_type,
|
||||
data,
|
||||
)
|
||||
.await?;
|
||||
let (content_type, data) = extract_upload_field(multipart).await?;
|
||||
let ctx = UploadContext {
|
||||
users: &*d.users,
|
||||
media: &*d.media,
|
||||
events: &*d.events,
|
||||
upload_config: &d.upload_config,
|
||||
base_url: &d.base_url,
|
||||
};
|
||||
upload_avatar_uc(&ctx, &uid, &content_type, data).await?;
|
||||
let user = fetch_user(&*d.users, &uid).await?;
|
||||
Ok(Json(to_user_response(&user)))
|
||||
}
|
||||
@@ -323,35 +327,17 @@ pub async fn upload_avatar(
|
||||
pub async fn upload_banner(
|
||||
Deps(d): Deps<UsersDeps>,
|
||||
AuthUser(uid): AuthUser,
|
||||
mut multipart: Multipart,
|
||||
multipart: Multipart,
|
||||
) -> Result<Json<UserResponse>, ApiError> {
|
||||
let field = multipart
|
||||
.next_field()
|
||||
.await
|
||||
.map_err(|_| ApiError::BadRequest("invalid multipart".into()))?
|
||||
.ok_or_else(|| ApiError::BadRequest("no file field".into()))?;
|
||||
// Content-type is client-supplied; the use-case allowlist prevents obviously
|
||||
// wrong types, but magic-byte validation is not performed. Serve media files
|
||||
// from an isolated origin to prevent MIME-based XSS.
|
||||
let content_type = field
|
||||
.content_type()
|
||||
.ok_or_else(|| ApiError::BadRequest("missing content-type on field".into()))?
|
||||
.to_string();
|
||||
let data = field
|
||||
.bytes()
|
||||
.await
|
||||
.map_err(|_| ApiError::BadRequest("failed to read upload".into()))?;
|
||||
upload_banner_uc(
|
||||
&*d.users,
|
||||
&*d.media,
|
||||
&*d.events,
|
||||
&uid,
|
||||
&d.base_url,
|
||||
&d.upload_config,
|
||||
&content_type,
|
||||
data,
|
||||
)
|
||||
.await?;
|
||||
let (content_type, data) = extract_upload_field(multipart).await?;
|
||||
let ctx = UploadContext {
|
||||
users: &*d.users,
|
||||
media: &*d.media,
|
||||
events: &*d.events,
|
||||
upload_config: &d.upload_config,
|
||||
base_url: &d.base_url,
|
||||
};
|
||||
upload_banner_uc(&ctx, &uid, &content_type, data).await?;
|
||||
let user = fetch_user(&*d.users, &uid).await?;
|
||||
Ok(Json(to_user_response(&user)))
|
||||
}
|
||||
|
||||
@@ -31,73 +31,60 @@ impl PasswordHasher for NoOpHasher {
|
||||
}
|
||||
}
|
||||
|
||||
/// No-op ActivityPubRepository for presentation layer tests.
|
||||
pub struct NoOpApRepo;
|
||||
|
||||
#[async_trait]
|
||||
impl ActivityPubRepository for NoOpApRepo {
|
||||
async fn outbox_entries_for_actor(
|
||||
&self,
|
||||
_uid: &UserId,
|
||||
) -> Result<Vec<OutboxEntry>, DomainError> {
|
||||
async fn outbox_entries_for_actor(&self, _: &UserId) -> Result<Vec<OutboxEntry>, DomainError> {
|
||||
Ok(vec![])
|
||||
}
|
||||
async fn outbox_page_for_actor(
|
||||
&self,
|
||||
_uid: &UserId,
|
||||
_before: Option<chrono::DateTime<chrono::Utc>>,
|
||||
_limit: usize,
|
||||
_: &UserId,
|
||||
_: Option<chrono::DateTime<chrono::Utc>>,
|
||||
_: usize,
|
||||
) -> Result<Vec<OutboxEntry>, DomainError> {
|
||||
Ok(vec![])
|
||||
}
|
||||
async fn find_remote_actor_id(
|
||||
&self,
|
||||
_actor_ap_url: &str,
|
||||
) -> Result<Option<UserId>, DomainError> {
|
||||
async fn find_remote_actor_id(&self, _: &str) -> Result<Option<UserId>, DomainError> {
|
||||
Ok(None)
|
||||
}
|
||||
async fn intern_remote_actor(&self, _actor_ap_url: &str) -> Result<UserId, DomainError> {
|
||||
async fn intern_remote_actor(&self, _: &str) -> Result<UserId, DomainError> {
|
||||
Err(DomainError::NotFound)
|
||||
}
|
||||
async fn update_remote_actor_display(
|
||||
&self,
|
||||
_user_id: &UserId,
|
||||
_display_name: Option<&str>,
|
||||
_avatar_url: Option<&str>,
|
||||
_: &UserId,
|
||||
_: Option<&str>,
|
||||
_: Option<&str>,
|
||||
) -> Result<(), DomainError> {
|
||||
Ok(())
|
||||
}
|
||||
async fn accept_note(
|
||||
&self,
|
||||
_input: activitypub::AcceptNoteInput<'_>,
|
||||
_: activitypub::AcceptNoteInput<'_>,
|
||||
) -> Result<ThoughtId, DomainError> {
|
||||
Ok(ThoughtId::from_uuid(uuid::Uuid::new_v4()))
|
||||
}
|
||||
async fn apply_note_update(&self, _ap_id: &str, _new_content: &str) -> Result<(), DomainError> {
|
||||
async fn apply_note_update(&self, _: &str, _: &str) -> Result<(), DomainError> {
|
||||
Ok(())
|
||||
}
|
||||
async fn retract_note(&self, _ap_id: &str) -> Result<(), DomainError> {
|
||||
async fn retract_note(&self, _: &str) -> Result<(), DomainError> {
|
||||
Ok(())
|
||||
}
|
||||
async fn retract_actor_notes(&self, _actor_ap_url: &str) -> Result<(), DomainError> {
|
||||
async fn retract_actor_notes(&self, _: &str) -> Result<(), DomainError> {
|
||||
Ok(())
|
||||
}
|
||||
async fn count_local_notes(&self) -> Result<u64, DomainError> {
|
||||
Ok(0)
|
||||
}
|
||||
async fn get_thought_ap_id(
|
||||
&self,
|
||||
_thought_id: &ThoughtId,
|
||||
) -> Result<Option<String>, DomainError> {
|
||||
async fn get_thought_ap_id(&self, _: &ThoughtId) -> Result<Option<String>, DomainError> {
|
||||
Ok(None)
|
||||
}
|
||||
async fn get_actor_ap_urls(
|
||||
&self,
|
||||
_user_id: &UserId,
|
||||
) -> Result<Option<ActorApUrls>, DomainError> {
|
||||
async fn get_actor_ap_urls(&self, _: &UserId) -> Result<Option<ActorApUrls>, DomainError> {
|
||||
Ok(None)
|
||||
}
|
||||
async fn sync_remote_actor_to_user(&self, _actor_ap_url: &str) -> Result<(), DomainError> {
|
||||
async fn sync_remote_actor_to_user(&self, _: &str) -> Result<(), DomainError> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user