pinakes-server: update remaining route imports and handlers

Signed-off-by: NotAShelf <raf@notashelf.dev>
Change-Id: I67206fd813d514f8903041eea0a4cd266a6a6964
This commit is contained in:
raf 2026-03-08 00:42:20 +03:00
commit eb6c0a3577
Signed by: NotAShelf
GPG key ID: 29D95B64378DB4BF
20 changed files with 169 additions and 87 deletions

View file

@ -19,6 +19,7 @@ use pinakes_core::{
ManagedStorageConfig,
PhotoConfig,
PluginsConfig,
RateLimitConfig,
ScanningConfig,
ServerConfig,
SharingConfig,
@ -41,19 +42,19 @@ use pinakes_core::{
use tokio::sync::RwLock;
use tower::ServiceExt;
/// Fake socket address for tests (governor needs ConnectInfo<SocketAddr>)
/// Fake socket address for tests (governor needs `ConnectInfo`<SocketAddr>)
fn test_addr() -> ConnectInfo<SocketAddr> {
ConnectInfo("127.0.0.1:9999".parse().unwrap())
}
/// Build a GET request with ConnectInfo for rate limiter compatibility
/// Build a GET request with `ConnectInfo` for rate limiter compatibility
fn get(uri: &str) -> Request<Body> {
let mut req = Request::builder().uri(uri).body(Body::empty()).unwrap();
req.extensions_mut().insert(test_addr());
req
}
/// Build a POST request with ConnectInfo
/// Build a POST request with `ConnectInfo`
fn post_json(uri: &str, body: &str) -> Request<Body> {
let mut req = Request::builder()
.method("POST")
@ -69,7 +70,7 @@ fn post_json(uri: &str, body: &str) -> Request<Body> {
fn get_authed(uri: &str, token: &str) -> Request<Body> {
let mut req = Request::builder()
.uri(uri)
.header("authorization", format!("Bearer {}", token))
.header("authorization", format!("Bearer {token}"))
.body(Body::empty())
.unwrap();
req.extensions_mut().insert(test_addr());
@ -82,7 +83,7 @@ fn post_json_authed(uri: &str, body: &str, token: &str) -> Request<Body> {
.method("POST")
.uri(uri)
.header("content-type", "application/json")
.header("authorization", format!("Bearer {}", token))
.header("authorization", format!("Bearer {token}"))
.body(Body::from(body.to_string()))
.unwrap();
req.extensions_mut().insert(test_addr());
@ -94,7 +95,7 @@ fn delete_authed(uri: &str, token: &str) -> Request<Body> {
let mut req = Request::builder()
.method("DELETE")
.uri(uri)
.header("authorization", format!("Bearer {}", token))
.header("authorization", format!("Bearer {token}"))
.body(Body::empty())
.unwrap();
req.extensions_mut().insert(test_addr());
@ -107,7 +108,7 @@ fn patch_json_authed(uri: &str, body: &str, token: &str) -> Request<Body> {
.method("PATCH")
.uri(uri)
.header("content-type", "application/json")
.header("authorization", format!("Bearer {}", token))
.header("authorization", format!("Bearer {token}"))
.body(Body::from(body.to_string()))
.unwrap();
req.extensions_mut().insert(test_addr());
@ -136,7 +137,10 @@ fn default_config() -> Config {
api_key: None,
tls: TlsConfig::default(),
authentication_disabled: true,
cors_enabled: false,
cors_origins: vec![],
},
rate_limits: RateLimitConfig::default(),
ui: UiConfig::default(),
accounts: AccountsConfig::default(),
jobs: JobsConfig::default(),
@ -164,7 +168,7 @@ async fn setup_app() -> axum::Router {
let config = default_config();
let job_queue =
JobQueue::new(1, |_id, _kind, _cancel, _jobs| tokio::spawn(async {}));
JobQueue::new(1, 0, |_id, _kind, _cancel, _jobs| tokio::spawn(async {}));
let config = Arc::new(RwLock::new(config));
let scheduler = pinakes_core::scheduler::TaskScheduler::new(
job_queue.clone(),
@ -186,9 +190,10 @@ async fn setup_app() -> axum::Router {
managed_storage: None,
chunked_upload_manager: None,
session_semaphore: Arc::new(tokio::sync::Semaphore::new(64)),
webhook_dispatcher: None,
};
pinakes_server::app::create_router(state)
pinakes_server::app::create_router(state, &RateLimitConfig::default())
}
/// Hash a password for test user accounts
@ -197,7 +202,7 @@ fn hash_password(password: &str) -> String {
}
/// Set up an app with accounts enabled and three pre-seeded users.
/// Returns (Router, admin_token, editor_token, viewer_token).
/// Returns (Router, `admin_token`, `editor_token`, `viewer_token`).
async fn setup_app_with_auth() -> (axum::Router, String, String, String) {
let backend = SqliteBackend::in_memory().expect("in-memory SQLite");
backend.run_migrations().await.expect("migrations");
@ -239,7 +244,7 @@ async fn setup_app_with_auth() -> (axum::Router, String, String, String) {
];
let job_queue =
JobQueue::new(1, |_id, _kind, _cancel, _jobs| tokio::spawn(async {}));
JobQueue::new(1, 0, |_id, _kind, _cancel, _jobs| tokio::spawn(async {}));
let config = Arc::new(RwLock::new(config));
let scheduler = pinakes_core::scheduler::TaskScheduler::new(
job_queue.clone(),
@ -261,9 +266,11 @@ async fn setup_app_with_auth() -> (axum::Router, String, String, String) {
managed_storage: None,
chunked_upload_manager: None,
session_semaphore: Arc::new(tokio::sync::Semaphore::new(64)),
webhook_dispatcher: None,
};
let app = pinakes_server::app::create_router(state);
let app =
pinakes_server::app::create_router(state, &RateLimitConfig::default());
// Login each user to get tokens
let admin_token = login_user(app.clone(), "admin", "adminpass").await;
@ -278,8 +285,7 @@ async fn login_user(
username: &str,
password: &str,
) -> String {
let body =
format!(r#"{{"username":"{}","password":"{}"}}"#, username, password);
let body = format!(r#"{{"username":"{username}","password":"{password}"}}"#);
let response = app
.oneshot(post_json("/api/v1/auth/login", &body))
.await
@ -287,8 +293,7 @@ async fn login_user(
assert_eq!(
response.status(),
StatusCode::OK,
"login failed for user {}",
username
"login failed for user {username}"
);
let body = response.into_body().collect().await.unwrap().to_bytes();
let result: serde_json::Value = serde_json::from_slice(&body).unwrap();
@ -449,7 +454,7 @@ async fn test_user_management_crud() {
// Get specific user
let response = app
.clone()
.oneshot(get(&format!("/api/v1/users/{}", user_id)))
.oneshot(get(&format!("/api/v1/users/{user_id}")))
.await
.unwrap();
@ -462,7 +467,7 @@ async fn test_user_management_crud() {
// Delete user
let mut req = Request::builder()
.method("DELETE")
.uri(&format!("/api/v1/users/{}", user_id))
.uri(format!("/api/v1/users/{user_id}"))
.body(Body::empty())
.unwrap();
req.extensions_mut().insert(test_addr());
@ -472,7 +477,7 @@ async fn test_user_management_crud() {
// Verify user is deleted
let response = app
.oneshot(get(&format!("/api/v1/users/{}", user_id)))
.oneshot(get(&format!("/api/v1/users/{user_id}")))
.await
.unwrap();
assert_eq!(response.status(), StatusCode::NOT_FOUND);
@ -796,7 +801,7 @@ async fn test_playlist_crud() {
let response = app
.clone()
.oneshot(get_authed(
&format!("/api/v1/playlists/{}", playlist_id),
&format!("/api/v1/playlists/{playlist_id}"),
&editor_token,
))
.await
@ -807,7 +812,7 @@ async fn test_playlist_crud() {
let response = app
.clone()
.oneshot(patch_json_authed(
&format!("/api/v1/playlists/{}", playlist_id),
&format!("/api/v1/playlists/{playlist_id}"),
r#"{"name":"Updated Playlist","description":"A test description"}"#,
&editor_token,
))
@ -821,7 +826,7 @@ async fn test_playlist_crud() {
let response = app
.clone()
.oneshot(delete_authed(
&format!("/api/v1/playlists/{}", playlist_id),
&format!("/api/v1/playlists/{playlist_id}"),
&editor_token,
))
.await
@ -972,7 +977,7 @@ async fn test_oversized_comment() {
let (app, _, editor_token, _) = setup_app_with_auth().await;
let long_text: String = "x".repeat(10_001);
let body = format!(r#"{{"text":"{}"}}"#, long_text);
let body = format!(r#"{{"text":"{long_text}"}}"#);
let response = app
.oneshot(post_json_authed(
"/api/v1/media/00000000-0000-0000-0000-000000000000/comments",