implemented 0.db as admin database architecture + updated test file
This commit is contained in:
79
src/cmd.rs
79
src/cmd.rs
@@ -768,43 +768,64 @@ async fn flushdb_cmd(server: &mut Server) -> Result<Protocol, DBError> {
|
||||
}
|
||||
|
||||
async fn select_cmd(server: &mut Server, db: u64, key: Option<String>) -> Result<Protocol, DBError> {
|
||||
// Load database metadata
|
||||
let meta = match crate::rpc::RpcServerImpl::load_meta_static(&server.option.dir, db).await {
|
||||
Ok(m) => m,
|
||||
Err(_) => {
|
||||
// If meta doesn't exist, create default
|
||||
let default_meta = crate::rpc::DatabaseMeta {
|
||||
public: true,
|
||||
keys: std::collections::HashMap::new(),
|
||||
};
|
||||
if let Err(_) = crate::rpc::RpcServerImpl::save_meta_static(&server.option.dir, db, &default_meta).await {
|
||||
return Ok(Protocol::err("ERR failed to initialize database metadata"));
|
||||
// Authorization and existence checks via admin DB 0
|
||||
// DB 0: require KEY admin-secret
|
||||
if db == 0 {
|
||||
match key {
|
||||
Some(k) if k == server.option.admin_secret => {
|
||||
server.selected_db = 0;
|
||||
server.current_permissions = Some(crate::rpc::Permissions::ReadWrite);
|
||||
// Will create encrypted 0.db if missing
|
||||
match server.current_storage() {
|
||||
Ok(_) => return Ok(Protocol::SimpleString("OK".to_string())),
|
||||
Err(e) => return Ok(Protocol::err(&e.0)),
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
return Ok(Protocol::err("ERR invalid access key"));
|
||||
}
|
||||
default_meta
|
||||
}
|
||||
}
|
||||
|
||||
// DB > 0: must exist in admin:dbs
|
||||
let exists = match crate::admin_meta::db_exists(
|
||||
&server.option.dir,
|
||||
server.option.backend.clone(),
|
||||
&server.option.admin_secret,
|
||||
db,
|
||||
) {
|
||||
Ok(b) => b,
|
||||
Err(e) => return Ok(Protocol::err(&e.0)),
|
||||
};
|
||||
|
||||
// Check access permissions
|
||||
let permissions = if meta.public {
|
||||
// Public database - full access
|
||||
Some(crate::rpc::Permissions::ReadWrite)
|
||||
} else if let Some(key_str) = key {
|
||||
// Private database - check key
|
||||
let hash = crate::rpc::hash_key(&key_str);
|
||||
if let Some(access_key) = meta.keys.get(&hash) {
|
||||
Some(access_key.permissions.clone())
|
||||
} else {
|
||||
return Ok(Protocol::err("ERR invalid access key"));
|
||||
}
|
||||
} else {
|
||||
return Ok(Protocol::err("ERR access key required for private database"));
|
||||
if !exists {
|
||||
return Ok(Protocol::err(&format!(
|
||||
"Cannot open database instance {}, as that database instance does not exist.",
|
||||
db
|
||||
)));
|
||||
}
|
||||
|
||||
// Verify permissions (public => RW; private => use key)
|
||||
let perms_opt = match crate::admin_meta::verify_access(
|
||||
&server.option.dir,
|
||||
server.option.backend.clone(),
|
||||
&server.option.admin_secret,
|
||||
db,
|
||||
key.as_deref(),
|
||||
) {
|
||||
Ok(p) => p,
|
||||
Err(e) => return Ok(Protocol::err(&e.0)),
|
||||
};
|
||||
|
||||
// Set selected database and permissions
|
||||
let perms = match perms_opt {
|
||||
Some(p) => p,
|
||||
None => return Ok(Protocol::err("ERR invalid access key")),
|
||||
};
|
||||
|
||||
// Set selected database and permissions, then open storage
|
||||
server.selected_db = db;
|
||||
server.current_permissions = permissions;
|
||||
server.current_permissions = Some(perms);
|
||||
|
||||
// Test if we can access the database (this will create it if needed)
|
||||
match server.current_storage() {
|
||||
Ok(_) => Ok(Protocol::SimpleString("OK".to_string())),
|
||||
Err(e) => Ok(Protocol::err(&e.0)),
|
||||
|
Reference in New Issue
Block a user