feat: implement friends API with routes to get friends list and update thought visibility logic

This commit is contained in:
2025-09-06 22:14:47 +02:00
parent bf7c6501c6
commit dc92945962
11 changed files with 241 additions and 11 deletions

View File

@@ -16,7 +16,7 @@ use sea_orm::prelude::Uuid;
#[utoipa::path(
get,
path = "/me/api-keys",
path = "",
responses(
(status = 200, description = "List of API keys", body = ApiKeyListSchema),
(status = 401, description = "Unauthorized", body = ApiErrorResponse),
@@ -36,7 +36,7 @@ async fn get_keys(
#[utoipa::path(
post,
path = "/me/api-keys",
path = "",
request_body = ApiKeyRequest,
responses(
(status = 201, description = "API key created", body = ApiKeyResponse),
@@ -63,7 +63,7 @@ async fn create_key(
#[utoipa::path(
delete,
path = "/me/api-keys/{key_id}",
path = "/{key_id}",
responses(
(status = 204, description = "API key deleted"),
(status = 401, description = "Unauthorized", body = ApiErrorResponse),

View File

@@ -0,0 +1,24 @@
use crate::{error::ApiError, extractor::AuthUser};
use app::{persistence::user, state::AppState};
use axum::{extract::State, response::IntoResponse, routing::get, Json, Router};
use models::schemas::user::UserListSchema;
#[utoipa::path(
get,
path = "",
responses(
(status = 200, description = "List of authenticated user's friends", body = UserListSchema)
),
security(("bearer_auth" = []))
)]
async fn get_friends_list(
State(state): State<AppState>,
auth_user: AuthUser,
) -> Result<impl IntoResponse, ApiError> {
let friends = user::get_friends(&state.conn, auth_user.id).await?;
Ok(Json(UserListSchema::from(friends)))
}
pub fn create_friends_router() -> Router<AppState> {
Router::new().route("/", get(get_friends_list))
}

View File

@@ -3,6 +3,7 @@ use axum::Router;
pub mod api_key;
pub mod auth;
pub mod feed;
pub mod friends;
pub mod root;
pub mod tag;
pub mod thought;
@@ -28,6 +29,7 @@ pub fn create_router(state: AppState) -> Router {
.nest("/thoughts", create_thought_router())
.nest("/feed", create_feed_router())
.nest("/tags", tag::create_tag_router())
.nest("/friends", friends::create_friends_router())
.with_state(state)
.layer(cors)
}

View File

@@ -2,7 +2,7 @@ use axum::{
extract::{Path, State},
http::StatusCode,
response::IntoResponse,
routing::{delete, post},
routing::{get, post},
Router,
};
@@ -16,11 +16,40 @@ use sea_orm::prelude::Uuid;
use crate::{
error::ApiError,
extractor::{AuthUser, Json, Valid},
extractor::{AuthUser, Json, OptionalAuthUser, Valid},
federation,
models::{ApiErrorResponse, ParamsErrorResponse},
};
#[utoipa::path(
get,
path = "/{id}",
params(
("id" = Uuid, Path, description = "Thought ID")
),
responses(
(status = 200, description = "Thought found", body = ThoughtSchema),
(status = 404, description = "Not Found", body = ApiErrorResponse)
)
)]
async fn get_thought_by_id(
State(state): State<AppState>,
Path(id): Path<Uuid>,
viewer: OptionalAuthUser,
) -> Result<impl IntoResponse, ApiError> {
let viewer_id = viewer.0.map(|u| u.id);
let thought = get_thought(&state.conn, id, viewer_id)
.await?
.ok_or(UserError::NotFound)?;
let author = app::persistence::user::get_user(&state.conn, thought.author_id)
.await?
.ok_or(UserError::NotFound)?;
let schema = ThoughtSchema::from_models(&thought, &author);
Ok(Json(schema))
}
#[utoipa::path(
post,
path = "",
@@ -77,7 +106,7 @@ async fn thoughts_delete(
auth_user: AuthUser,
Path(id): Path<Uuid>,
) -> Result<impl IntoResponse, ApiError> {
let thought = get_thought(&state.conn, id)
let thought = get_thought(&state.conn, id, Some(auth_user.id))
.await?
.ok_or(UserError::NotFound)?;
@@ -92,5 +121,5 @@ async fn thoughts_delete(
pub fn create_thought_router() -> Router<AppState> {
Router::new()
.route("/", post(thoughts_post))
.route("/{id}", delete(thoughts_delete))
.route("/{id}", get(get_thought_by_id).delete(thoughts_delete))
}