feat(api,backend): added a dummy backend, improved internal response handling and documented api http response codes

This commit is contained in:
antifallobst 2023-08-12 14:41:28 +02:00
parent 49eb7cb524
commit 3832d15887
Signed by: antifallobst
GPG Key ID: 2B4F402172791BAF
4 changed files with 116 additions and 16 deletions

View File

@ -3,10 +3,10 @@ use anyhow::Result;
use serde::Deserialize; use serde::Deserialize;
use tokio::sync::{mpsc, oneshot}; use tokio::sync::{mpsc, oneshot};
use crate::call::Call; use crate::call::{Call, Response, ResponseAuthenticate, ResponseRegister};
struct ApiState { struct ApiState {
tx: mpsc::Sender<(Call, oneshot::Sender<Result<()>>)>, tx: mpsc::Sender<(Call, oneshot::Sender<Result<Response>>)>,
} }
#[derive(Debug, Deserialize)] #[derive(Debug, Deserialize)]
@ -15,6 +15,11 @@ struct AuthenticateData {
password: String, password: String,
} }
/// Possible Responses:
/// * 200 -> Authentication was successfull
/// * 401 -> Authentication failed (wrong password)
/// * 404 -> User not found
/// * 500 -> Internal Server Error
#[post("/authenticate")] #[post("/authenticate")]
async fn authenticate( async fn authenticate(
data: web::Data<ApiState>, data: web::Data<ApiState>,
@ -34,8 +39,15 @@ async fn authenticate(
} }
match rx.await.unwrap() { match rx.await.unwrap() {
Ok(_) => HttpResponse::Ok().finish(), Ok(resp) => match resp {
Err(_) => HttpResponse::Unauthorized().finish(), Response::Authenticate(r) => match r {
ResponseAuthenticate::Success => HttpResponse::Ok().finish(),
ResponseAuthenticate::UserNotFound => HttpResponse::NotFound().finish(),
ResponseAuthenticate::WrongPassword => HttpResponse::Unauthorized().finish(),
},
_ => HttpResponse::InternalServerError().finish(),
},
_ => HttpResponse::InternalServerError().finish(),
} }
} }
@ -45,6 +57,10 @@ struct RegisterData {
password: String, password: String,
} }
/// Possible Responses:
/// * 200 -> User created successfully
/// * 409 -> The requested username is already in use
/// * 500 -> Internal Server Error
#[post("/register")] #[post("/register")]
async fn register(data: web::Data<ApiState>, body: web::Json<RegisterData>) -> impl Responder { async fn register(data: web::Data<ApiState>, body: web::Json<RegisterData>) -> impl Responder {
let (tx, rx) = oneshot::channel(); let (tx, rx) = oneshot::channel();
@ -61,14 +77,20 @@ async fn register(data: web::Data<ApiState>, body: web::Json<RegisterData>) -> i
} }
match rx.await.unwrap() { match rx.await.unwrap() {
Ok(_) => HttpResponse::Ok().finish(), Ok(resp) => match resp {
Err(_) => HttpResponse::Unauthorized().finish(), Response::Register(r) => match r {
ResponseRegister::Success => HttpResponse::Ok().finish(),
ResponseRegister::NameAlreadyInUse => HttpResponse::Conflict().finish(),
},
_ => HttpResponse::InternalServerError().finish(),
},
_ => HttpResponse::InternalServerError().finish(),
} }
} }
pub async fn start_worker( pub async fn start_worker(
port: u16, port: u16,
tx: mpsc::Sender<(Call, oneshot::Sender<Result<()>>)>, tx: mpsc::Sender<(Call, oneshot::Sender<Result<Response>>)>,
) -> Result<()> { ) -> Result<()> {
tokio::task::spawn( tokio::task::spawn(
HttpServer::new(move || { HttpServer::new(move || {

34
src/backend.rs Normal file
View File

@ -0,0 +1,34 @@
use anyhow::Result;
use crate::call::{Response, ResponseAuthenticate, ResponseDelete, ResponseRegister};
pub struct Backend {}
impl Backend {
pub fn register(&mut self, username: &String, password: &String) -> Result<Response> {
println!(
"<Dummy> Registered Account: (Username: '{}' | Password: '{}')",
username, password
);
Ok(Response::Register(ResponseRegister::Success))
}
pub fn authenticate(&mut self, username: &String, password: &String) -> Result<Response> {
println!(
"<Dummy> Authentication Request: (Username: '{}' | Password: '{}')",
username, password
);
println!(" -> Accepted");
Ok(Response::Authenticate(ResponseAuthenticate::Success))
}
pub fn delete(&mut self, username: &String) -> Result<Response> {
println!("<Dummy> Deletion Request: (Username: '{}')", username);
println!(" -> Accepted");
Ok(Response::Delete(ResponseDelete::Success))
}
pub fn new() -> Result<Self> {
Ok(Self {})
}
}

View File

@ -1,6 +1,8 @@
use anyhow::{anyhow, Result}; use anyhow::Result;
use tokio::sync::{mpsc, oneshot}; use tokio::sync::{mpsc, oneshot};
use crate::backend::Backend;
#[derive(Debug)] #[derive(Debug)]
pub enum Call { pub enum Call {
Register(String, String), Register(String, String),
@ -8,19 +10,59 @@ pub enum Call {
Delete(String), Delete(String),
} }
async fn worker(mut rx: mpsc::Receiver<(Call, oneshot::Sender<Result<()>>)>) -> Result<()> { #[derive(Debug)]
pub enum ResponseRegister {
Success,
NameAlreadyInUse,
}
#[derive(Debug)]
pub enum ResponseAuthenticate {
Success,
UserNotFound,
WrongPassword,
}
#[derive(Debug)]
pub enum ResponseDelete {
Success,
UserNotFound,
}
#[derive(Debug)]
pub enum Response {
Register(ResponseRegister),
Authenticate(ResponseAuthenticate),
Delete(ResponseDelete),
}
impl Call {
async fn handle(&self, backend: &mut Backend) -> Result<Response> {
match self {
Self::Register(username, password) => backend.register(username, password),
Self::Authenticate(username, password) => backend.authenticate(username, password),
Self::Delete(username) => backend.delete(username),
}
}
}
async fn worker(
mut rx: mpsc::Receiver<(Call, oneshot::Sender<Result<Response>>)>,
mut backend: Backend,
) -> Result<()> {
loop { loop {
if let Some((call, tx)) = rx.recv().await { if let Some((call, tx)) = rx.recv().await {
println!("{:#?}", call); tx.send(call.handle(&mut backend).await).unwrap();
tx.send(Err(anyhow::Error::msg("test"))).unwrap();
}; };
} }
} }
pub async fn start_worker() -> Result<mpsc::Sender<(Call, oneshot::Sender<Result<()>>)>> { pub async fn start_worker(
backend: Backend,
) -> Result<mpsc::Sender<(Call, oneshot::Sender<Result<Response>>)>> {
let (tx, rx) = mpsc::channel(128); let (tx, rx) = mpsc::channel(128);
tokio::task::spawn(async { tokio::task::spawn(async move {
if let Err(e) = worker(rx).await { if let Err(e) = worker(rx, backend).await {
panic!("{e}"); panic!("{e}");
}; };
}); });

View File

@ -1,4 +1,5 @@
mod api; mod api;
mod backend;
mod call; mod call;
use anyhow::Result; use anyhow::Result;
@ -7,9 +8,10 @@ use anyhow::Result;
async fn main() -> Result<()> { async fn main() -> Result<()> {
println!("Starting BaseAuth server v0.1"); println!("Starting BaseAuth server v0.1");
let tx = call::start_worker().await?; let backend = backend::Backend::new()?;
let tx = call::start_worker(backend).await?;
api::start_worker(8080, tx).await?; api::start_worker(8080, tx).await?;
loop {} loop {}
Ok(())
} }