From ea64e212b30dcf6062433af29cd48c997ec4cef1 Mon Sep 17 00:00:00 2001 From: Brandon Thomas Date: Fri, 11 Jun 2021 20:49:32 -0400 Subject: [PATCH] sorting both ways seems to work --- .../list_tts_inference_results.rs | 38 +++++++++++++++++-- .../users/list_user_tts_inference_results.rs | 10 ++++- src/util/encrypted_sort_id.rs | 15 +++++++- 3 files changed, 56 insertions(+), 7 deletions(-) diff --git a/src/common_queries/list_tts_inference_results.rs b/src/common_queries/list_tts_inference_results.rs index ec5f29208f..89b2601873 100644 --- a/src/common_queries/list_tts_inference_results.rs +++ b/src/common_queries/list_tts_inference_results.rs @@ -289,6 +289,7 @@ pub async fn list_tts_inference_page( mysql_pool: &MySqlPool, scope_creator_username: Option<&str>, sort_ascending: bool, + cursor_is_previous: bool, block_mod_disabled : bool, limit: u16, offset: Option, @@ -298,6 +299,7 @@ pub async fn list_tts_inference_page( mysql_pool, scope_creator_username, sort_ascending, + cursor_is_previous, block_mod_disabled, limit, offset @@ -339,6 +341,7 @@ async fn list_tts_inference_results_query ( mysql_pool: &MySqlPool, scope_creator_username: Option<&str>, sort_ascending: bool, + cursor_is_previous: bool, block_mod_disabled : bool, limit: u16, offset: Option, @@ -370,14 +373,39 @@ LEFT OUTER JOIN users ON tts_results.maybe_creator_user_token = users.token "#.to_string(); + let mut sort_ascending = sort_ascending; // NB: We may need to change the direction. + let mut reverse_results = false; + let mut first_predicate_added = false; if let Some(offset) = offset { if !first_predicate_added { - query.push_str(r#" WHERE tts_results.id < ? "#); + query.push_str(" WHERE "); first_predicate_added = true; } else { - query.push_str(r#" AND tts_results.id < ? "#); + query.push_str(" AND "); + } + + // TODO: Cleanup, builder class, tests. + + if sort_ascending { + if cursor_is_previous { + // NB: We're searching backwards. + query.push_str(" tts_results.id < ? "); + sort_ascending = !sort_ascending; + reverse_results = true; + } else { + query.push_str(" tts_results.id > ? "); + } + } else { + if cursor_is_previous { + // NB: We're searching backwards. + query.push_str(" tts_results.id > ? "); + sort_ascending = !sort_ascending; + reverse_results = true; + } else { + query.push_str(" tts_results.id < ? "); + } } } @@ -425,8 +453,12 @@ LEFT OUTER JOIN users query = query.bind(limit); - let results = query.fetch_all(mysql_pool) + let mut results = query.fetch_all(mysql_pool) .await?; + if reverse_results { + results.reverse() + } + Ok(results) } diff --git a/src/http_server/endpoints/users/list_user_tts_inference_results.rs b/src/http_server/endpoints/users/list_user_tts_inference_results.rs index 73d4ddc6e3..f8d4549f7a 100644 --- a/src/http_server/endpoints/users/list_user_tts_inference_results.rs +++ b/src/http_server/endpoints/users/list_user_tts_inference_results.rs @@ -40,6 +40,7 @@ pub struct ListTtsInferenceResultsForUserQuery { pub sort_ascending: Option, pub limit: Option, pub cursor: Option, + pub cursor_is_previous: Option, } #[derive(Serialize)] @@ -83,7 +84,11 @@ pub async fn list_user_tts_inference_results_handler( let mod_disabled = false; let limit = query.limit.unwrap_or(25); - let limit = std::cmp::max(limit, 100); + //let limit = std::cmp::max(limit, 100); + + let sort_ascending = query.sort_ascending.unwrap_or(false); + + let cursor_is_previous = query.cursor_is_previous.unwrap_or(false); let cursor = if let Some(cursor) = query.cursor.as_deref() { let cursor = server_state.sort_key_crypto.decrypt_id(cursor) @@ -99,7 +104,8 @@ pub async fn list_user_tts_inference_results_handler( let query_results = list_tts_inference_page( &server_state.mysql_pool, Some(path.username.as_ref()), - false, + sort_ascending, + cursor_is_previous, mod_disabled, limit, cursor, diff --git a/src/util/encrypted_sort_id.rs b/src/util/encrypted_sort_id.rs index 85f93bee76..6c10953054 100644 --- a/src/util/encrypted_sort_id.rs +++ b/src/util/encrypted_sort_id.rs @@ -6,6 +6,7 @@ use std::io::Cursor; use magic_crypt::new_magic_crypt; use crate::util::anyhow_result::AnyhowResult; use rand::RngCore; +use base64::{Config, CharacterSet}; // TODO: A protobuf would be more compact! /// This gets encrypted and sent to the frontend as an opaque handle. @@ -21,12 +22,16 @@ pub struct SortId { #[derive(Clone)] pub struct SortKeyCrypto { crypt: MagicCrypt256, + base64_config: Config, } impl SortKeyCrypto { pub fn new(secret: &str) -> Self { + let base64_config = Config::new(CharacterSet::UrlSafe, false) + .decode_allow_trailing_bits(true); Self { crypt: new_magic_crypt!(secret, 256), + base64_config, } } @@ -44,14 +49,20 @@ impl SortKeyCrypto { let mut writer = Vec::new(); self.crypt.encrypt_reader_to_writer2::(&mut reader, &mut writer)?; - let encoded = base64::encode(&writer); + let encoded = base64::encode_config(&writer, self.base64_config.clone()); Ok(encoded) } pub fn decrypt_id(&self, base_64_payload: &str) -> AnyhowResult { - let payload = self.crypt.decrypt_base64_to_string(base_64_payload)?; + //let payload = self.crypt.decrypt_base64_to_string(base_64_payload)?; + + let decoded_bytes= base64::decode_config(base_64_payload, self.base64_config)?; + let decrypted_bytes = self.crypt.decrypt_bytes_to_bytes(&decoded_bytes)?; + + let payload = String::from_utf8(decrypted_bytes)?; let payload = serde_json::from_str::(&payload)?; + Ok(payload.column_id) } }