mirror of
https://github.com/storytold/artcraft.git
synced 2026-11-11 04:16:55 +00:00
fix pagination cursors (#1776)
This commit is contained in:
1 parent
7dffc5fb5c
commit
2a9e71f5b8
6 files changed
+56
-23
No files matched your search
+3
-15
@@ -84,11 +84,7 @@ pub async fn list_user_tts_inference_results_handler(
|
||||
let cursor_is_reversed = query.cursor_is_reversed.unwrap_or(false);
|
||||
|
||||
let cursor = if let Some(cursor) = query.cursor.as_deref() {
|
||||
let cursor = server_state.sort_key_crypto.decrypt_id(cursor)
|
||||
.map_err(|e| {
|
||||
warn!("crypto error: {:?}", e);
|
||||
CommonWebError::from_anyhow_error(e)
|
||||
})?;
|
||||
let cursor = server_state.sort_key_crypto.decrypt_id(cursor)?;
|
||||
Some(cursor)
|
||||
} else {
|
||||
None
|
||||
@@ -117,22 +113,14 @@ pub async fn list_user_tts_inference_results_handler(
|
||||
};
|
||||
|
||||
let cursor_next = if let Some(id) = results_page.last_id {
|
||||
let cursor = server_state.sort_key_crypto.encrypt_id(id as u64)
|
||||
.map_err(|e| {
|
||||
warn!("crypto error: {:?}", e);
|
||||
CommonWebError::from_anyhow_error(e)
|
||||
})?;
|
||||
let cursor = server_state.sort_key_crypto.encrypt_id(id as u64)?;
|
||||
Some(cursor)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let cursor_previous = if let Some(id) = results_page.first_id {
|
||||
let cursor = server_state.sort_key_crypto.encrypt_id(id as u64)
|
||||
.map_err(|e| {
|
||||
warn!("crypto error: {:?}", e);
|
||||
CommonWebError::from_anyhow_error(e)
|
||||
})?;
|
||||
let cursor = server_state.sort_key_crypto.encrypt_id(id as u64)?;
|
||||
Some(cursor)
|
||||
} else {
|
||||
None
|
||||
|
||||
+5
-4
@@ -107,6 +107,7 @@ pub struct ModelWeightForList {
|
||||
|
||||
#[derive(Debug,ToSchema)]
|
||||
pub enum ListWeightError {
|
||||
BadInput,
|
||||
NotAuthorized,
|
||||
ServerError,
|
||||
}
|
||||
@@ -120,6 +121,7 @@ impl std::fmt::Display for ListWeightError {
|
||||
impl ResponseError for ListWeightError {
|
||||
fn status_code(&self) -> StatusCode {
|
||||
match *self {
|
||||
ListWeightError::BadInput => StatusCode::BAD_REQUEST,
|
||||
ListWeightError::NotAuthorized => StatusCode::UNAUTHORIZED,
|
||||
ListWeightError::ServerError => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
}
|
||||
@@ -165,11 +167,10 @@ pub async fn list_available_weights_handler(
|
||||
let cursor_is_reversed = query.cursor_is_reversed.unwrap_or(false);
|
||||
|
||||
let cursor = if let Some(cursor) = query.cursor.as_deref() {
|
||||
// Cursors arrive from clients verbatim; garbage is bad input, not a
|
||||
// server fault.
|
||||
let cursor = server_state.sort_key_crypto.decrypt_id(cursor)
|
||||
.map_err(|e| {
|
||||
warn!("crypto error: {:?}", e);
|
||||
ListWeightError::ServerError
|
||||
})?;
|
||||
.map_err(|_| ListWeightError::BadInput)?;
|
||||
Some(cursor)
|
||||
} else {
|
||||
None
|
||||
|
||||
@@ -13,3 +13,4 @@ pub mod response_success_helpers;
|
||||
pub mod scoped_temp_dir_creator;
|
||||
pub mod serialize_as_json_error;
|
||||
pub mod try_delete_session_cache;
|
||||
pub mod web_sort_key_crypto;
|
||||
@@ -0,0 +1,43 @@
|
||||
use log::warn;
|
||||
|
||||
use crate::http_server::common_responses::common_web_error::CommonWebError;
|
||||
use crate::util::encrypted_sort_id::SortKeyCrypto;
|
||||
|
||||
/// [`SortKeyCrypto`] with a web-facing interface: results map to
|
||||
/// [`CommonWebError`] so handlers can use `?` directly, with the right HTTP
|
||||
/// status for each direction. This is the flavor injected into Actix via
|
||||
/// `ServerState`.
|
||||
#[derive(Clone)]
|
||||
pub struct WebSortKeyCrypto {
|
||||
crypto: SortKeyCrypto,
|
||||
}
|
||||
|
||||
impl WebSortKeyCrypto {
|
||||
pub fn new(secret: &str) -> Self {
|
||||
Self {
|
||||
crypto: SortKeyCrypto::new(secret),
|
||||
}
|
||||
}
|
||||
|
||||
/// Encrypt a row id into an opaque pagination cursor.
|
||||
/// Failure is a genuine server fault (500).
|
||||
pub fn encrypt_id(&self, id: u64) -> Result<String, CommonWebError> {
|
||||
self.crypto.encrypt_id(id)
|
||||
.map_err(|err| {
|
||||
warn!("Failed to encrypt pagination cursor: {:?}", err);
|
||||
CommonWebError::from_anyhow_error(err)
|
||||
})
|
||||
}
|
||||
|
||||
/// Decrypt a client-supplied pagination cursor.
|
||||
/// Cursors arrive from clients verbatim, so garbage is bad input (400),
|
||||
/// not a server fault — a 500 here would trip the error-alerting
|
||||
/// middleware on any bot or stale client.
|
||||
pub fn decrypt_id(&self, cursor: &str) -> Result<u64, CommonWebError> {
|
||||
self.crypto.decrypt_id(cursor)
|
||||
.map_err(|err| {
|
||||
warn!("Invalid pagination cursor: {:?}", err);
|
||||
CommonWebError::BadInputWithSimpleMessage("Invalid pagination cursor.".to_string())
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -46,7 +46,7 @@ use crate::state::server_state::{
|
||||
ServerState, TrollBans,
|
||||
};
|
||||
use crate::threads::db_health_checker_thread::db_health_check_status::HealthCheckStatus;
|
||||
use crate::util::encrypted_sort_id::SortKeyCrypto;
|
||||
use crate::http_server::web_utils::web_sort_key_crypto::WebSortKeyCrypto;
|
||||
|
||||
// Bucket config
|
||||
const ENV_ACCESS_KEY: &str = "ACCESS_KEY";
|
||||
@@ -156,7 +156,7 @@ pub async fn setup_dependencies(server_hostname: &str) -> AnyhowResult<SetupResu
|
||||
);
|
||||
|
||||
let sort_key_crypto_secret = easyenv::get_env_string_or_default("SORT_KEY_SECRET", "webscale");
|
||||
let sort_key_crypto = SortKeyCrypto::new(&sort_key_crypto_secret);
|
||||
let sort_key_crypto = WebSortKeyCrypto::new(&sort_key_crypto_secret);
|
||||
let opaque_cursor_encoder = OpaqueCursorEncoderV2::new(&sort_key_crypto_secret);
|
||||
|
||||
let health_check_interval = easyenv::get_env_duration_seconds_or_default(
|
||||
|
||||
@@ -11,7 +11,7 @@ use crate::state::certs::google_sign_in_cert::GoogleSignInCert;
|
||||
use crate::state::flags::paging_flags::PagingFlags;
|
||||
use crate::state::memory_cache::model_token_to_info_cache::ModelTokenToInfoCache;
|
||||
use crate::threads::db_health_checker_thread::db_health_check_status::HealthCheckStatus;
|
||||
use crate::util::encrypted_sort_id::SortKeyCrypto;
|
||||
use crate::http_server::web_utils::web_sort_key_crypto::WebSortKeyCrypto;
|
||||
use crate::util::troll_user_bans::troll_user_ban_list::TrollUserBanList;
|
||||
|
||||
use actix_artcraft::sessions::anonymous_visitor_tracking::avt_cookie_manager::AvtCookieManager;
|
||||
@@ -98,7 +98,7 @@ pub struct ServerState {
|
||||
/// Where to store audio uploads for w2l
|
||||
pub audio_uploads_bucket_root: String,
|
||||
|
||||
pub sort_key_crypto: SortKeyCrypto,
|
||||
pub sort_key_crypto: WebSortKeyCrypto,
|
||||
pub opaque_cursors: OpaqueCursorEncoderV2,
|
||||
|
||||
pub ip_ban_list: IpBanList,
|
||||
|
||||
Reference in new issue
Block a user