fixed key-based access control for Tantivy backends
This commit is contained in:
@@ -162,8 +162,8 @@ pub async fn ft_add_cmd(
|
||||
if !is_tantivy {
|
||||
return Ok(Protocol::err("ERR DB backend is not Tantivy; FT.* commands are not allowed"));
|
||||
}
|
||||
if !server.has_read_permission() {
|
||||
return Ok(Protocol::err("ERR read permission denied"));
|
||||
if !server.has_write_permission() {
|
||||
return Ok(Protocol::err("ERR write permission denied"));
|
||||
}
|
||||
let indexes = server.search_indexes.read().unwrap();
|
||||
let search_index = indexes
|
||||
@@ -199,8 +199,8 @@ pub async fn ft_search_cmd(
|
||||
if !is_tantivy {
|
||||
return Ok(Protocol::err("ERR DB backend is not Tantivy; FT.* commands are not allowed"));
|
||||
}
|
||||
if !server.has_write_permission() {
|
||||
return Ok(Protocol::err("ERR write permission denied"));
|
||||
if !server.has_read_permission() {
|
||||
return Ok(Protocol::err("ERR read permission denied"));
|
||||
}
|
||||
let indexes = server.search_indexes.read().unwrap();
|
||||
let search_index = indexes
|
||||
@@ -225,30 +225,29 @@ pub async fn ft_search_cmd(
|
||||
};
|
||||
|
||||
let results = search_index.search_with_options(&query, options)?;
|
||||
|
||||
// Format results as Redis protocol
|
||||
|
||||
// Format results as a flattened Redis protocol array to match client expectations:
|
||||
// [ total, doc_id, score, field, value, field, value, ... , doc_id, score, ... ]
|
||||
let mut response = Vec::new();
|
||||
// First element is the total count
|
||||
response.push(Protocol::SimpleString(results.total.to_string()));
|
||||
// Then each document
|
||||
for doc in results.documents {
|
||||
let mut doc_array = Vec::new();
|
||||
response.push(Protocol::BulkString(results.total.to_string()));
|
||||
// Then each document flattened
|
||||
for mut doc in results.documents {
|
||||
// Add document ID if it exists
|
||||
if let Some(id) = doc.fields.get("_id") {
|
||||
doc_array.push(Protocol::BulkString(id.clone()));
|
||||
response.push(Protocol::BulkString(id.clone()));
|
||||
}
|
||||
// Add score
|
||||
doc_array.push(Protocol::BulkString(doc.score.to_string()));
|
||||
response.push(Protocol::BulkString(doc.score.to_string()));
|
||||
// Add fields as key-value pairs
|
||||
for (field_name, field_value) in doc.fields {
|
||||
for (field_name, field_value) in std::mem::take(&mut doc.fields) {
|
||||
if field_name != "_id" {
|
||||
doc_array.push(Protocol::BulkString(field_name));
|
||||
doc_array.push(Protocol::BulkString(field_value));
|
||||
response.push(Protocol::BulkString(field_name));
|
||||
response.push(Protocol::BulkString(field_value));
|
||||
}
|
||||
}
|
||||
response.push(Protocol::Array(doc_array));
|
||||
}
|
||||
|
||||
|
||||
Ok(Protocol::Array(response))
|
||||
}
|
||||
|
||||
@@ -278,12 +277,11 @@ pub async fn ft_del_cmd(
|
||||
return Ok(Protocol::err("ERR write permission denied"));
|
||||
}
|
||||
let indexes = server.search_indexes.read().unwrap();
|
||||
let _search_index = indexes
|
||||
let search_index = indexes
|
||||
.get(&index_name)
|
||||
.ok_or_else(|| DBError(format!("Index '{}' not found", index_name)))?;
|
||||
// Not fully implemented yet: Tantivy delete by term would require a writer session and commit coordination.
|
||||
println!("Deleting document '{}' from index '{}'", doc_id, index_name);
|
||||
Ok(Protocol::SimpleString("1".to_string()))
|
||||
let existed = search_index.delete_document_by_id(&doc_id)?;
|
||||
Ok(Protocol::SimpleString(if existed { "1".to_string() } else { "0".to_string() }))
|
||||
}
|
||||
|
||||
pub async fn ft_info_cmd(server: &Server, index_name: String) -> Result<Protocol, DBError> {
|
||||
@@ -355,10 +353,13 @@ pub async fn ft_drop_cmd(server: &Server, index_name: String) -> Result<Protocol
|
||||
return Ok(Protocol::err("ERR write permission denied"));
|
||||
}
|
||||
|
||||
// Remove from registry
|
||||
// Remove from registry and files; report error if nothing to drop
|
||||
let mut existed = false;
|
||||
{
|
||||
let mut indexes = server.search_indexes.write().unwrap();
|
||||
indexes.remove(&index_name);
|
||||
if indexes.remove(&index_name).is_some() {
|
||||
existed = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Remove the index files from disk
|
||||
@@ -366,6 +367,11 @@ pub async fn ft_drop_cmd(server: &Server, index_name: String) -> Result<Protocol
|
||||
if index_path.exists() {
|
||||
std::fs::remove_dir_all(&index_path)
|
||||
.map_err(|e| DBError(format!("Failed to remove index files: {}", e)))?;
|
||||
existed = true;
|
||||
}
|
||||
|
||||
if !existed {
|
||||
return Ok(Protocol::err(&format!("ERR Index '{}' not found", index_name)));
|
||||
}
|
||||
|
||||
Ok(Protocol::SimpleString("OK".to_string()))
|
||||
|
Reference in New Issue
Block a user