Make handlers asynchronous
This commit is contained in:
parent
82e41d711b
commit
b2a7577c9d
@ -126,6 +126,14 @@ impl Core {
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn create_user(&self, username: &str) -> ResultExt<(), AppError, FatalError> {
|
||||
let state = self.0.read().await;
|
||||
match return_error!(self.user_by_username(username).await) {
|
||||
Some(_) => error(AppError::UsernameUnavailable),
|
||||
None => unimplemented!(),
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn list_games(&self) -> ResultExt<Vec<Game>, AppError, FatalError> {
|
||||
let games = self.0.write().await.db.games().await;
|
||||
match games {
|
||||
|
@ -74,16 +74,38 @@ pub async fn check_password(
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn authenticated<F, A>(
|
||||
pub async fn auth_required<F, A, Fut>(
|
||||
core: Core,
|
||||
headers: HeaderMap,
|
||||
f: F,
|
||||
) -> (StatusCode, Json<Option<A>>)
|
||||
where
|
||||
F: FnOnce(User) -> (StatusCode, Json<Option<A>>),
|
||||
F: FnOnce(User) -> Fut,
|
||||
Fut: Future<Output = (StatusCode, Json<Option<A>>)>,
|
||||
{
|
||||
match check_session(&core, headers).await {
|
||||
ResultExt::Ok(Some(user)) => f(user),
|
||||
ResultExt::Ok(Some(user)) => f(user).await,
|
||||
ResultExt::Ok(None) => (StatusCode::UNAUTHORIZED, Json(None)),
|
||||
ResultExt::Err(_err) => (StatusCode::BAD_REQUEST, Json(None)),
|
||||
ResultExt::Fatal(err) => panic!("{}", err),
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn admin_required<F, A, Fut>(
|
||||
core: Core,
|
||||
headers: HeaderMap,
|
||||
f: F,
|
||||
) -> (StatusCode, Json<Option<A>>)
|
||||
where
|
||||
F: FnOnce(User) -> Fut,
|
||||
Fut: Future<Output = (StatusCode, Json<Option<A>>)>,
|
||||
{
|
||||
match check_session(&core, headers).await {
|
||||
ResultExt::Ok(Some(user)) => if user.admin {
|
||||
f(user).await
|
||||
} else {
|
||||
(StatusCode::FORBIDDEN, Json(None))
|
||||
},
|
||||
ResultExt::Ok(None) => (StatusCode::UNAUTHORIZED, Json(None)),
|
||||
ResultExt::Err(_err) => (StatusCode::BAD_REQUEST, Json(None)),
|
||||
ResultExt::Fatal(err) => panic!("{}", err),
|
||||
@ -95,21 +117,39 @@ where
|
||||
pub struct UserProfile {
|
||||
pub userid: UserId,
|
||||
pub username: String,
|
||||
pub is_admin: bool,
|
||||
}
|
||||
|
||||
pub async fn get_user(core: Core, headers: HeaderMap) -> (StatusCode, Json<Option<UserProfile>>) {
|
||||
authenticated(core.clone(), headers, |user| {
|
||||
auth_required(core.clone(), headers, |user| async move {
|
||||
(
|
||||
StatusCode::OK,
|
||||
Json(Some(UserProfile {
|
||||
userid: UserId::from(user.id),
|
||||
username: user.name,
|
||||
is_admin: user.admin,
|
||||
})),
|
||||
)
|
||||
})
|
||||
.await
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize)]
|
||||
#[typeshare]
|
||||
pub struct CreateUserRequest {
|
||||
username: String,
|
||||
}
|
||||
|
||||
pub async fn create_user(core: Core, headers: HeaderMap, req: CreateUserRequest) -> (StatusCode, Json<Option<()>>) {
|
||||
auth_required(core.clone(), headers, |_admin| async {
|
||||
match core.create_user(&req.username).await {
|
||||
ResultExt::Ok(_) => (StatusCode::OK, Json(None)),
|
||||
ResultExt::Err(err) => (StatusCode::BAD_REQUEST, Json(None)),
|
||||
ResultExt::Fatal(fatal) => panic!("{}", fatal),
|
||||
}
|
||||
}).await
|
||||
}
|
||||
|
||||
/*
|
||||
pub async fn handle_auth(
|
||||
auth_ctx: &AuthDB,
|
||||
|
@ -8,7 +8,9 @@ use axum::{
|
||||
|
||||
use crate::{
|
||||
core::Core,
|
||||
handlers::{check_password, get_user, healthcheck, AuthRequest},
|
||||
handlers::{
|
||||
check_password, create_user, get_user, healthcheck, AuthRequest, CreateUserRequest,
|
||||
},
|
||||
};
|
||||
|
||||
pub fn routes(core: Core) -> Router {
|
||||
@ -34,6 +36,13 @@ pub fn routes(core: Core) -> Router {
|
||||
let core = core.clone();
|
||||
move |headers: HeaderMap| get_user(core, headers)
|
||||
})
|
||||
.put({
|
||||
let core = core.clone();
|
||||
move |headers: HeaderMap, req: Json<CreateUserRequest>| {
|
||||
let Json(req) = req;
|
||||
create_user(core, headers, req)
|
||||
}
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
||||
@ -163,4 +172,16 @@ mod test {
|
||||
async fn an_admin_can_create_a_user() {
|
||||
unimplemented!();
|
||||
}
|
||||
|
||||
#[ignore]
|
||||
#[tokio::test]
|
||||
async fn a_user_can_create_a_game() {
|
||||
unimplemented!();
|
||||
}
|
||||
|
||||
#[ignore]
|
||||
#[tokio::test]
|
||||
async fn gms_can_invite_others_into_a_game() {
|
||||
unimplemented!();
|
||||
}
|
||||
}
|
||||
|
@ -50,6 +50,9 @@ pub enum AppError {
|
||||
|
||||
#[error("wat {0}")]
|
||||
UnexpectedError(String),
|
||||
|
||||
#[error("this username is not available")]
|
||||
UsernameUnavailable,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
|
||||
|
Loading…
Reference in New Issue
Block a user