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> {
|
pub async fn list_games(&self) -> ResultExt<Vec<Game>, AppError, FatalError> {
|
||||||
let games = self.0.write().await.db.games().await;
|
let games = self.0.write().await.db.games().await;
|
||||||
match games {
|
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,
|
core: Core,
|
||||||
headers: HeaderMap,
|
headers: HeaderMap,
|
||||||
f: F,
|
f: F,
|
||||||
) -> (StatusCode, Json<Option<A>>)
|
) -> (StatusCode, Json<Option<A>>)
|
||||||
where
|
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 {
|
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::Ok(None) => (StatusCode::UNAUTHORIZED, Json(None)),
|
||||||
ResultExt::Err(_err) => (StatusCode::BAD_REQUEST, Json(None)),
|
ResultExt::Err(_err) => (StatusCode::BAD_REQUEST, Json(None)),
|
||||||
ResultExt::Fatal(err) => panic!("{}", err),
|
ResultExt::Fatal(err) => panic!("{}", err),
|
||||||
@ -95,21 +117,39 @@ where
|
|||||||
pub struct UserProfile {
|
pub struct UserProfile {
|
||||||
pub userid: UserId,
|
pub userid: UserId,
|
||||||
pub username: String,
|
pub username: String,
|
||||||
|
pub is_admin: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_user(core: Core, headers: HeaderMap) -> (StatusCode, Json<Option<UserProfile>>) {
|
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,
|
StatusCode::OK,
|
||||||
Json(Some(UserProfile {
|
Json(Some(UserProfile {
|
||||||
userid: UserId::from(user.id),
|
userid: UserId::from(user.id),
|
||||||
username: user.name,
|
username: user.name,
|
||||||
|
is_admin: user.admin,
|
||||||
})),
|
})),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
.await
|
.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(
|
pub async fn handle_auth(
|
||||||
auth_ctx: &AuthDB,
|
auth_ctx: &AuthDB,
|
||||||
|
@ -8,7 +8,9 @@ use axum::{
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
core::Core,
|
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 {
|
pub fn routes(core: Core) -> Router {
|
||||||
@ -34,6 +36,13 @@ pub fn routes(core: Core) -> Router {
|
|||||||
let core = core.clone();
|
let core = core.clone();
|
||||||
move |headers: HeaderMap| get_user(core, headers)
|
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() {
|
async fn an_admin_can_create_a_user() {
|
||||||
unimplemented!();
|
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}")]
|
#[error("wat {0}")]
|
||||||
UnexpectedError(String),
|
UnexpectedError(String),
|
||||||
|
|
||||||
|
#[error("this username is not available")]
|
||||||
|
UsernameUnavailable,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
|
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
|
||||||
|
Loading…
Reference in New Issue
Block a user