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 tokio::sync::{mpsc, oneshot};
use crate::call::Call;
use crate::call::{Call, Response, ResponseAuthenticate, ResponseRegister};
struct ApiState {
tx: mpsc::Sender<(Call, oneshot::Sender<Result<()>>)>,
tx: mpsc::Sender<(Call, oneshot::Sender<Result<Response>>)>,
}
#[derive(Debug, Deserialize)]
@ -15,6 +15,11 @@ struct AuthenticateData {
password: String,
}
/// Possible Responses:
/// * 200 -> Authentication was successfull
/// * 401 -> Authentication failed (wrong password)
/// * 404 -> User not found
/// * 500 -> Internal Server Error
#[post("/authenticate")]
async fn authenticate(
data: web::Data<ApiState>,
@ -34,8 +39,15 @@ async fn authenticate(
}
match rx.await.unwrap() {
Ok(_) => HttpResponse::Ok().finish(),
Err(_) => HttpResponse::Unauthorized().finish(),
Ok(resp) => match resp {
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,
}
/// Possible Responses:
/// * 200 -> User created successfully
/// * 409 -> The requested username is already in use
/// * 500 -> Internal Server Error
#[post("/register")]
async fn register(data: web::Data<ApiState>, body: web::Json<RegisterData>) -> impl Responder {
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() {
Ok(_) => HttpResponse::Ok().finish(),
Err(_) => HttpResponse::Unauthorized().finish(),
Ok(resp) => match resp {
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(
port: u16,
tx: mpsc::Sender<(Call, oneshot::Sender<Result<()>>)>,
tx: mpsc::Sender<(Call, oneshot::Sender<Result<Response>>)>,
) -> Result<()> {
tokio::task::spawn(
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 crate::backend::Backend;
#[derive(Debug)]
pub enum Call {
Register(String, String),
@ -8,19 +10,59 @@ pub enum Call {
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 {
if let Some((call, tx)) = rx.recv().await {
println!("{:#?}", call);
tx.send(Err(anyhow::Error::msg("test"))).unwrap();
tx.send(call.handle(&mut backend).await).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);
tokio::task::spawn(async {
if let Err(e) = worker(rx).await {
tokio::task::spawn(async move {
if let Err(e) = worker(rx, backend).await {
panic!("{e}");
};
});

View File

@ -1,4 +1,5 @@
mod api;
mod backend;
mod call;
use anyhow::Result;
@ -7,9 +8,10 @@ use anyhow::Result;
async fn main() -> Result<()> {
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?;
loop {}
Ok(())
}