Refactor API client

This commit is contained in:
Valentin Tolmer 2021-06-23 10:11:32 +02:00 committed by nitnelave
parent 659eab3706
commit eec0903052

View File

@ -39,103 +39,138 @@ where
}) })
} }
struct RequestBody<T>(T);
impl<'a, R> From<&'a R> for RequestBody<Json<&'a R>>
where
R: serde::ser::Serialize,
{
fn from(request: &'a R) -> Self {
Self(Json(&request))
}
}
impl From<yew::format::Nothing> for RequestBody<yew::format::Nothing> {
fn from(request: yew::format::Nothing) -> Self {
Self(request)
}
}
fn call_server<Req, CallbackResult, Resp, F, RB>(
url: &str,
request: RB,
callback: Callback<Result<CallbackResult>>,
handler: F,
) -> Result<FetchTask>
where
F: Fn(http::StatusCode, Resp) -> Result<CallbackResult> + 'static,
CallbackResult: 'static,
RB: Into<RequestBody<Req>>,
Req: Into<yew::format::Text>,
Result<Resp>: From<Result<String>> + 'static,
{
let request = Request::post(url)
.header("Content-Type", "application/json")
.body(request.into().0)?;
let handler = create_handler(callback, handler);
FetchService::fetch_with_options(request, get_default_options(), handler)
}
impl HostService { impl HostService {
pub fn list_users( pub fn list_users(
request: ListUsersRequest, request: ListUsersRequest,
callback: Callback<Result<Vec<User>>>, callback: Callback<Result<Vec<User>>>,
) -> Result<FetchTask> { ) -> Result<FetchTask> {
let url = "/api/users"; call_server("/api/users", &request, callback, |status, data: String| {
let request = Request::post(url)
.header("Content-Type", "application/json")
.body(Json(&request))?;
let handler = create_handler(callback, |status, data: String| {
if status.is_success() { if status.is_success() {
serde_json::from_str(&data).map_err(|e| anyhow!("Could not parse response: {}", e)) serde_json::from_str(&data).map_err(|e| anyhow!("Could not parse response: {}", e))
} else { } else {
Err(anyhow!("[{}]: {}", status, data)) Err(anyhow!("[{}]: {}", status, data))
} }
}); })
FetchService::fetch_with_options(request, get_default_options(), handler)
} }
pub fn login_start( pub fn login_start(
request: login::ClientLoginStartRequest, request: login::ClientLoginStartRequest,
callback: Callback<Result<login::ServerLoginStartResponse>>, callback: Callback<Result<login::ServerLoginStartResponse>>,
) -> Result<FetchTask> { ) -> Result<FetchTask> {
let url = "/auth/opaque/login/start"; call_server(
let request = Request::post(url) "/auth/opaque/login/start",
.header("Content-Type", "application/json") &request,
.body(Json(&request))?; callback,
let handler = create_handler(callback, |status, data: String| { |status, data: String| {
if status.is_success() { if status.is_success() {
serde_json::from_str(&data).map_err(|e| anyhow!("Could not parse response: {}", e)) serde_json::from_str(&data)
} else { .map_err(|e| anyhow!("Could not parse response: {}", e))
Err(anyhow!( } else {
"Could not start authentication: [{}]: {}", Err(anyhow!(
status, "Could not start authentication: [{}]: {}",
data status,
)) data
} ))
}); }
FetchService::fetch_with_options(request, get_default_options(), handler) },
)
} }
pub fn login_finish( pub fn login_finish(
request: login::ClientLoginFinishRequest, request: login::ClientLoginFinishRequest,
callback: Callback<Result<String>>, callback: Callback<Result<String>>,
) -> Result<FetchTask> { ) -> Result<FetchTask> {
let url = "/auth/opaque/login/finish"; call_server(
let request = Request::post(url) "/auth/opaque/login/finish",
.header("Content-Type", "application/json") &request,
.body(Json(&request))?; callback,
let handler = create_handler(callback, |status, data: String| { |status, data: String| {
if status.is_success() { if status.is_success() {
get_claims_from_jwt(&data) get_claims_from_jwt(&data)
.map_err(|e| anyhow!("Could not parse response: {}", e)) .map_err(|e| anyhow!("Could not parse response: {}", e))
.and_then(|jwt_claims| { .and_then(|jwt_claims| {
set_cookie("user_id", &jwt_claims.user, &jwt_claims.exp) set_cookie("user_id", &jwt_claims.user, &jwt_claims.exp)
.map(|_| jwt_claims.user.clone()) .map(|_| jwt_claims.user.clone())
.map_err(|e| anyhow!("Error clearing cookie: {}", e)) .map_err(|e| anyhow!("Error clearing cookie: {}", e))
}) })
} else { } else {
Err(anyhow!( Err(anyhow!(
"Could not finish authentication: [{}]: {}", "Could not finish authentication: [{}]: {}",
status, status,
data data
)) ))
} }
}); },
FetchService::fetch_with_options(request, get_default_options(), handler) )
} }
pub fn logout(callback: Callback<Result<()>>) -> Result<FetchTask> { pub fn logout(callback: Callback<Result<()>>) -> Result<FetchTask> {
let url = "/auth/logout"; call_server(
let request = Request::post(url).body(yew::format::Nothing)?; "/auth/logout",
let handler = create_handler(callback, |status, data: String| { yew::format::Nothing,
if status.is_success() { callback,
Ok(()) |status, data: String| {
} else { if status.is_success() {
Err(anyhow!("Could not logout: [{}]: {}", status, data)) Ok(())
} } else {
}); Err(anyhow!("Could not logout: [{}]: {}", status, data))
FetchService::fetch_with_options(request, get_default_options(), handler) }
},
)
} }
pub fn create_user( pub fn create_user(
request: CreateUserRequest, request: CreateUserRequest,
callback: Callback<Result<()>>, callback: Callback<Result<()>>,
) -> Result<FetchTask> { ) -> Result<FetchTask> {
let url = "/api/users/create"; call_server(
let request = Request::post(url) "/api/users/create",
.header("Content-Type", "application/json") &request,
.body(Json(&request))?; callback,
let handler = create_handler(callback, |status, data: String| { |status, data: String| {
if status.is_success() { if status.is_success() {
Ok(()) Ok(())
} else { } else {
Err(anyhow!("Could not create a user: [{}]: {}", status, data)) Err(anyhow!("Could not create a user: [{}]: {}", status, data))
} }
}); },
FetchService::fetch_with_options(request, get_default_options(), handler) )
} }
} }