2021-05-18 17:04:06 +00:00
|
|
|
use crate::cookies::set_cookie;
|
2021-05-13 17:33:57 +00:00
|
|
|
use anyhow::{anyhow, Result};
|
2021-05-09 11:26:50 +00:00
|
|
|
use lldap_model::*;
|
|
|
|
|
|
|
|
use yew::callback::Callback;
|
|
|
|
use yew::format::Json;
|
2021-05-13 17:33:57 +00:00
|
|
|
use yew::services::fetch::{Credentials, FetchOptions, FetchService, FetchTask, Request, Response};
|
2021-05-09 11:26:50 +00:00
|
|
|
|
|
|
|
#[derive(Default)]
|
|
|
|
pub struct HostService {}
|
|
|
|
|
2021-05-13 17:33:57 +00:00
|
|
|
fn get_default_options() -> FetchOptions {
|
|
|
|
FetchOptions {
|
|
|
|
credentials: Some(Credentials::SameOrigin),
|
|
|
|
..FetchOptions::default()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn get_claims_from_jwt(jwt: &str) -> Result<JWTClaims> {
|
|
|
|
use jwt::*;
|
|
|
|
let token = Token::<header::Header, JWTClaims, token::Unverified>::parse_unverified(jwt)?;
|
|
|
|
Ok(token.claims().clone())
|
|
|
|
}
|
|
|
|
|
2021-05-09 11:26:50 +00:00
|
|
|
impl HostService {
|
2021-05-10 08:21:24 +00:00
|
|
|
pub fn list_users(
|
|
|
|
request: ListUsersRequest,
|
|
|
|
callback: Callback<Result<Vec<User>>>,
|
|
|
|
) -> Result<FetchTask> {
|
2021-05-13 17:33:57 +00:00
|
|
|
let url = "/api/users";
|
|
|
|
let handler = move |response: Response<Result<String>>| {
|
|
|
|
let (meta, maybe_data) = response.into_parts();
|
2021-05-18 17:04:06 +00:00
|
|
|
let message = maybe_data
|
|
|
|
.map_err(|e| anyhow!("Could not fetch: {}", e))
|
|
|
|
.and_then(|data| {
|
2021-05-13 17:33:57 +00:00
|
|
|
if meta.status.is_success() {
|
2021-05-18 17:04:06 +00:00
|
|
|
serde_json::from_str(&data)
|
|
|
|
.map_err(|e| anyhow!("Could not parse response: {}", e))
|
2021-05-13 17:33:57 +00:00
|
|
|
} else {
|
2021-05-18 17:04:06 +00:00
|
|
|
Err(anyhow!("[{}]: {}", meta.status, data))
|
2021-05-13 17:33:57 +00:00
|
|
|
}
|
2021-05-18 17:04:06 +00:00
|
|
|
});
|
|
|
|
callback.emit(message)
|
2021-05-13 17:33:57 +00:00
|
|
|
};
|
|
|
|
let request = Request::post(url)
|
|
|
|
.header("Content-Type", "application/json")
|
|
|
|
.body(Json(&request))?;
|
|
|
|
FetchService::fetch_with_options(request, get_default_options(), handler.into())
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn authenticate(
|
|
|
|
request: BindRequest,
|
|
|
|
callback: Callback<Result<String>>,
|
|
|
|
) -> Result<FetchTask> {
|
2021-05-20 15:41:30 +00:00
|
|
|
let url = "/auth";
|
2021-05-13 17:33:57 +00:00
|
|
|
let handler = move |response: Response<Result<String>>| {
|
|
|
|
let (meta, maybe_data) = response.into_parts();
|
2021-05-18 17:04:06 +00:00
|
|
|
let message = maybe_data
|
|
|
|
.map_err(|e| anyhow!("Could not reach authentication server: {}", e))
|
|
|
|
.and_then(|data| {
|
2021-05-13 17:33:57 +00:00
|
|
|
if meta.status.is_success() {
|
2021-05-18 17:04:06 +00:00
|
|
|
get_claims_from_jwt(&data)
|
|
|
|
.map_err(|e| anyhow!("Could not parse response: {}", e))
|
|
|
|
.and_then(|jwt_claims| {
|
|
|
|
set_cookie("user_id", &jwt_claims.user, &jwt_claims.exp)
|
|
|
|
.map(|_| jwt_claims.user.clone())
|
|
|
|
.map_err(|e| anyhow!("Error clearing cookie: {}", e))
|
|
|
|
})
|
2021-05-13 17:33:57 +00:00
|
|
|
} else if meta.status == 401 {
|
2021-05-18 17:04:06 +00:00
|
|
|
Err(anyhow!("Invalid username or password"))
|
2021-05-13 17:33:57 +00:00
|
|
|
} else {
|
2021-05-18 17:04:06 +00:00
|
|
|
Err(anyhow!(
|
2021-05-13 17:33:57 +00:00
|
|
|
"Could not authenticate: [{}]: {}",
|
|
|
|
meta.status,
|
|
|
|
data
|
2021-05-18 17:04:06 +00:00
|
|
|
))
|
2021-05-10 08:21:24 +00:00
|
|
|
}
|
2021-05-18 17:04:06 +00:00
|
|
|
});
|
|
|
|
callback.emit(message)
|
2021-05-13 17:33:57 +00:00
|
|
|
};
|
|
|
|
let request = Request::post(url)
|
2021-05-10 08:21:24 +00:00
|
|
|
.header("Content-Type", "application/json")
|
2021-05-13 17:33:57 +00:00
|
|
|
.body(Json(&request))?;
|
|
|
|
FetchService::fetch_with_options(request, get_default_options(), handler.into())
|
2021-05-09 11:26:50 +00:00
|
|
|
}
|
2021-05-23 15:07:02 +00:00
|
|
|
|
|
|
|
pub fn logout(callback: Callback<Result<()>>) -> Result<FetchTask> {
|
|
|
|
let url = "/auth/logout";
|
|
|
|
let handler = move |response: Response<Result<String>>| {
|
|
|
|
let (meta, maybe_data) = response.into_parts();
|
|
|
|
let message = maybe_data
|
|
|
|
.map_err(|e| anyhow!("Could not reach authentication server: {}", e))
|
|
|
|
.and_then(|data| {
|
|
|
|
if meta.status.is_success() {
|
|
|
|
Ok(())
|
|
|
|
} else {
|
|
|
|
Err(anyhow!("Could not logout: [{}]: {}", meta.status, data))
|
|
|
|
}
|
|
|
|
});
|
|
|
|
callback.emit(message)
|
|
|
|
};
|
|
|
|
let request = Request::post(url).body(yew::format::Nothing)?;
|
|
|
|
FetchService::fetch_with_options(request, get_default_options(), handler.into())
|
|
|
|
}
|
2021-05-09 11:26:50 +00:00
|
|
|
}
|