feat: require auth for search

This commit is contained in:
Zomatree
2025-08-08 00:44:01 +01:00
committed by Angelo Kontaxis
parent b0c977b324
commit b5cd5e30ef
5 changed files with 37 additions and 11 deletions

1
Cargo.lock generated
View File

@@ -6517,6 +6517,7 @@ dependencies = [
"reqwest 0.12.23", "reqwest 0.12.23",
"revolt-coalesced", "revolt-coalesced",
"revolt-config", "revolt-config",
"revolt-database",
"revolt-models", "revolt-models",
"revolt-result", "revolt-result",
"serde", "serde",

View File

@@ -1,21 +1,20 @@
use axum::{ use axum::{extract::{FromRef, FromRequestParts}, http::request::Parts};
extract::{FromRef, FromRequestParts},
http::request::Parts,
};
use revolt_result::{create_error, Error, Result}; use revolt_result::{create_error, Error, Result};
use crate::{Database, User}; use crate::{Database, User};
#[async_trait::async_trait] #[async_trait::async_trait]
impl<S: Send + Sync> FromRequestParts<S> for User impl<S> FromRequestParts<S> for User
where where
Database: FromRef<S>, Database: FromRef<S>,
S: Send + Sync
{ {
type Rejection = Error; type Rejection = Error;
async fn from_request_parts(parts: &mut Parts, state: &S) -> Result<User> { async fn from_request_parts(parts: &mut Parts, state: &S) -> Result<User> {
let db = Database::from_ref(state); let db = Database::from_ref(state);
if let Some(Ok(bot_token)) = parts.headers.get("x-bot-token").map(|v| v.to_str()) { if let Some(Ok(bot_token)) = parts.headers.get("x-bot-token").map(|v| v.to_str()) {
let bot = db.fetch_bot_by_token(bot_token).await?; let bot = db.fetch_bot_by_token(bot_token).await?;
db.fetch_user(&bot.id).await db.fetch_user(&bot.id).await

View File

@@ -23,7 +23,7 @@ revolt-result = { version = "0.8.8", path = "../../core/result", features = [
"axum", "axum",
] } ] }
revolt-coalesced = { version = "0.8.8", path = "../../core/coalesced" } revolt-coalesced = { version = "0.8.8", path = "../../core/coalesced" }
revolt-database = { version = "0.8.8", path = "../../core/database", features = ["axum-impl"] }
# Axum / web server # Axum / web server
axum = { version = "0.7.5" } axum = { version = "0.7.5" }
axum-extra = { version = "0.9", features = ["typed-header"] } axum-extra = { version = "0.9", features = ["typed-header"] }

View File

@@ -4,10 +4,11 @@ use axum::{extract::{Query, State}, routing::get, Json, Router};
use revolt_result::{create_error, Result}; use revolt_result::{create_error, Result};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use utoipa::ToSchema; use utoipa::ToSchema;
use revolt_database::User;
use crate::tenor::{Tenor, types}; use crate::{AppState, tenor::{Tenor, types}};
pub async fn router() -> Router<Tenor> { pub async fn router() -> Router<AppState> {
Router::new() Router::new()
.route("/", get(root)) .route("/", get(root))
.route("/search", get(search)) .route("/search", get(search))
@@ -53,6 +54,7 @@ struct SearchQueryParams {
) )
)] )]
async fn search( async fn search(
_user: User,
Query(params): Query<SearchQueryParams>, Query(params): Query<SearchQueryParams>,
State(tenor): State<Tenor>, State(tenor): State<Tenor>,
) -> Result<Json<Arc<types::SearchResponse>>> { ) -> Result<Json<Arc<types::SearchResponse>>> {

View File

@@ -1,8 +1,9 @@
use std::net::{Ipv4Addr, SocketAddr}; use std::net::{Ipv4Addr, SocketAddr};
use axum::Router; use axum::{extract::FromRef, Router};
use revolt_config::config; use revolt_config::config;
use revolt_database::{Database, DatabaseInfo};
use tokio::net::TcpListener; use tokio::net::TcpListener;
use utoipa::{ use utoipa::{
openapi::security::{Http, HttpAuthScheme, SecurityScheme}, openapi::security::{Http, HttpAuthScheme, SecurityScheme},
@@ -10,9 +11,29 @@ use utoipa::{
}; };
use utoipa_scalar::{Scalar, Servable as ScalarServable}; use utoipa_scalar::{Scalar, Servable as ScalarServable};
use crate::tenor::Tenor;
mod api; mod api;
mod tenor; mod tenor;
#[derive(Clone)]
struct AppState {
pub database: Database,
pub tenor: Tenor
}
impl FromRef<AppState> for Database {
fn from_ref(state: &AppState) -> Self {
state.database.clone()
}
}
impl FromRef<AppState> for Tenor {
fn from_ref(state: &AppState) -> Self {
state.tenor.clone()
}
}
#[tokio::main] #[tokio::main]
async fn main() -> Result<(), std::io::Error> { async fn main() -> Result<(), std::io::Error> {
// Configure logging and environment // Configure logging and environment
@@ -48,13 +69,16 @@ async fn main() -> Result<(), std::io::Error> {
} }
let config = config().await; let config = config().await;
let tenor = tenor::Tenor::new(&config.api.security.tenor_key); let state = AppState {
database: DatabaseInfo::Auto.connect().await.expect("Unable to connect to database"),
tenor: tenor::Tenor::new(&config.api.security.tenor_key)
};
// Configure Axum and router // Configure Axum and router
let app = Router::new() let app = Router::new()
.merge(Scalar::with_url("/scalar", ApiDoc::openapi())) .merge(Scalar::with_url("/scalar", ApiDoc::openapi()))
.nest("/", api::router().await) .nest("/", api::router().await)
.with_state(tenor); .with_state(state);
// Configure TCP listener and bind // Configure TCP listener and bind
tracing::info!("Listening on 0.0.0.0:14706"); tracing::info!("Listening on 0.0.0.0:14706");