80 lines
2.2 KiB
Rust
80 lines
2.2 KiB
Rust
//! Realm API handlers for user UI (READ-ONLY).
|
|
|
|
use axum::{
|
|
extract::{Path, Query, State},
|
|
Json,
|
|
};
|
|
use serde::{Deserialize, Serialize};
|
|
use sqlx::PgPool;
|
|
|
|
use chattyness_db::{
|
|
models::{RealmSummary, RealmWithUserRole},
|
|
queries::{memberships, realms},
|
|
};
|
|
use chattyness_error::AppError;
|
|
|
|
use crate::auth::OptionalAuthUser;
|
|
|
|
/// List query params.
|
|
#[derive(Debug, Deserialize)]
|
|
pub struct ListParams {
|
|
pub include_nsfw: Option<bool>,
|
|
pub page: Option<i64>,
|
|
pub limit: Option<i64>,
|
|
}
|
|
|
|
/// List response.
|
|
#[derive(Debug, Serialize)]
|
|
pub struct ListResponse {
|
|
pub realms: Vec<RealmSummary>,
|
|
}
|
|
|
|
/// List public realms.
|
|
pub async fn list_realms(
|
|
State(pool): State<PgPool>,
|
|
Query(params): Query<ListParams>,
|
|
) -> Result<Json<ListResponse>, AppError> {
|
|
let limit = params.limit.unwrap_or(20).min(100);
|
|
let offset = params.page.unwrap_or(0) * limit;
|
|
let include_nsfw = params.include_nsfw.unwrap_or(false);
|
|
|
|
let realm_list = realms::list_public_realms(&pool, include_nsfw, limit, offset).await?;
|
|
|
|
Ok(Json(ListResponse { realms: realm_list }))
|
|
}
|
|
|
|
/// Get a realm by slug with user role.
|
|
pub async fn get_realm(
|
|
State(pool): State<PgPool>,
|
|
OptionalAuthUser(maybe_user): OptionalAuthUser,
|
|
Path(slug): Path<String>,
|
|
) -> Result<Json<RealmWithUserRole>, AppError> {
|
|
let realm = realms::get_realm_by_slug(&pool, &slug)
|
|
.await?
|
|
.ok_or_else(|| AppError::NotFound(format!("Realm '{}' not found", slug)))?;
|
|
|
|
// Get the user's role if authenticated
|
|
let user_role = if let Some(user) = maybe_user {
|
|
let membership = memberships::get_user_membership(&pool, user.id, realm.id).await?;
|
|
membership.map(|m| m.role)
|
|
} else {
|
|
None
|
|
};
|
|
|
|
Ok(Json(RealmWithUserRole { realm, user_role }))
|
|
}
|
|
|
|
/// Check slug availability response.
|
|
#[derive(Debug, Serialize)]
|
|
pub struct SlugAvailableResponse {
|
|
pub available: bool,
|
|
}
|
|
|
|
/// Check if a realm slug is available.
|
|
pub async fn check_slug_available(
|
|
State(pool): State<PgPool>,
|
|
Path(slug): Path<String>,
|
|
) -> Result<Json<SlugAvailableResponse>, AppError> {
|
|
let available = realms::is_slug_available(&pool, &slug).await?;
|
|
Ok(Json(SlugAvailableResponse { available }))
|
|
}
|