Add server database interaction

This commit is contained in:
Michael Mikovsky
2025-12-01 16:38:33 -07:00
parent 97bd45571b
commit d1a0050f45
10 changed files with 229 additions and 38 deletions
+41 -16
View File
@@ -1,6 +1,6 @@
use axum::{
Extension, Router,
extract::Path,
Extension, Json, Router,
extract::{Path, State},
middleware,
response::IntoResponse,
routing::{get, post},
@@ -8,34 +8,59 @@ use axum::{
use tokio::net::TcpListener;
use unshell_lib::info;
use crate::api::{auth, structs::CurrentUser};
use crate::{
api::{auth, structs::CurrentUser},
database::Database,
};
pub async fn start_api(address: &str) {
pub async fn start_api(address: &str, database: Database) {
let listener = TcpListener::bind(address)
.await
.expect("Unable to start listener");
info!("Listening on {}", listener.local_addr().unwrap());
let app = Router::new().route("/auth", post(auth::sign_in)).route(
"/api/{*path}",
get(protected).layer(middleware::from_fn(auth::authorize)),
);
let app = Router::new()
.route("/api/auth", post(auth::sign_in))
.route(
"/api/{*path}",
get(get_data).layer(middleware::from_fn(auth::authorize)),
)
.route(
"/api/{*path}",
post(post_data).layer(middleware::from_fn(auth::authorize)),
)
.with_state(database);
axum::serve(listener, app)
.await
.expect("Error serving application");
}
pub async fn protected(
pub async fn get_data(
State(database): State<Database>,
Path(path): Path<String>,
Extension(_): Extension<CurrentUser>,
) -> impl IntoResponse {
info!("{}", path);
// Json(UserResponse {
// email: currentUser.email,
// first_name: currentUser.first_name,
// last_name: currentUser.last_name,
// })
"Test"
let result = database.get_value(&path);
Json(serde_json::to_value(result).unwrap())
}
pub async fn post_data(
State(database): State<Database>,
Path(path): Path<String>,
Extension(_): Extension<CurrentUser>,
body: String,
) -> impl IntoResponse {
let result = database.put_value(&path, &body);
Json(serde_json::to_value(result).unwrap())
}
// impl IntoResponse for Option<StrW> {
// // impl IntoResponse for Option<String> {
// fn into_response(self) -> axum::response::Response {
// todo!()
// }
// }
+34 -2
View File
@@ -1,5 +1,37 @@
// Calc 3 ends Tuesday next week
use unshell_lib::error;
#[derive(Clone)]
pub struct Database {
// db:
db: sled::Db,
}
impl Database {
pub fn new(database: String) -> Self {
Self {
db: sled::open(database).expect("Failed to open database"),
}
}
pub fn put_value(&self, key: &str, value: &str) -> Result<(), String> {
match self.db.insert(key, value) {
Ok(_) => Ok(()),
Err(e) => {
error!("Failed to load '{}' from database: {}", key, e);
Err(e.to_string())
}
}
}
pub fn get_value(&self, key: &str) -> Result<String, String> {
match self.db.get(key) {
Ok(v) => match v {
Some(v) => Ok(String::from_utf8_lossy(&v.to_vec()).to_string()),
None => Err(format!("Could not find key '{}'", key)),
},
Err(e) => {
error!("Failed to load '{}' from database: {}", key, e);
Err(e.to_string())
}
}
}
}
+1 -1
View File
@@ -1,5 +1,5 @@
// #![macro_use]
mod api;
mod database;
pub mod database;
pub use api::app::start_api;
+10 -2
View File
@@ -1,10 +1,12 @@
use unshell_server::start_api;
use unshell_server::{database::Database, start_api};
use clap::Parser;
use static_init::dynamic;
#[dynamic]
static DEFAULT_HOST: String = "localhost".to_string();
#[dynamic]
static DATABASE_NAME: String = "database".to_string();
/// A fictional versioning CLI
#[derive(Debug, Parser)]
@@ -18,6 +20,10 @@ pub struct Args {
/// Port to listen
#[arg(short, long, default_value_t = 3000)]
port: usize,
/// Name of database folder
#[clap(short, long, default_value_t = DATABASE_NAME.clone())]
database_name: String,
}
#[tokio::main]
@@ -26,5 +32,7 @@ async fn main() {
unshell_lib::logger::PrettyLogger::init();
start_api(&format!("{}:{}", args.host, args.port)).await;
let database = Database::new(args.database_name);
start_api(&format!("{}:{}", args.host, args.port), database).await;
}