use hyper::Method;
use rpki::ca::idexchange::PublisherHandle;
use crate::api::admin::{PublisherList, PublisherSummary};
use super::super::auth::Permission;
use super::super::request::{PathIter, Request};
use super::super::response::HttpResponse;
use super::error::DispatchError;
pub async fn dispatch(
request: Request<'_>,
mut path: PathIter<'_>,
) -> Result<HttpResponse, DispatchError> {
request.check_permission(Permission::PubAdmin, None)?;
match path.next() {
Some("delete") => delete(request, path).await,
Some("init") => init(request, path).await,
Some("publishers") => publishers(request, path).await,
Some("session_reset") => session_reset(request, path),
Some("stale") => stale(request, path).await,
_ => Ok(HttpResponse::not_found())
}
}
async fn delete(
request: Request<'_>,
path: PathIter<'_>,
) -> Result<HttpResponse, DispatchError> {
path.check_exhausted()?;
request.check_post()?;
let (request, _) = request.proceed_permitted(
Permission::PubAdmin, None
)?;
let (server, criteria) = request.read_json().await?;
server.krill().delete_matching_files(criteria)?;
Ok(HttpResponse::ok())
}
async fn init(
request: Request<'_>,
path: PathIter<'_>,
) -> Result<HttpResponse, DispatchError> {
path.check_exhausted()?;
match *request.method() {
Method::POST => {
let (request, _) = request.proceed_permitted(
Permission::PubAdmin, None
)?;
let (server, uris) = request.read_json().await?;
server.krill().repository_init(uris)?;
Ok(HttpResponse::ok())
}
Method::DELETE => {
let (request, _) = request.proceed_permitted(
Permission::PubAdmin, None
)?;
let server = request.empty()?;
server.krill().repository_clear()?;
Ok(HttpResponse::ok())
}
_ => Ok(HttpResponse::method_not_allowed())
}
}
async fn publishers(
request: Request<'_>,
mut path: PathIter<'_>,
) -> Result<HttpResponse, DispatchError> {
match path.parse_opt_next()? {
None => publishers_index(request).await,
Some(publisher) => {
publishers_publisher(request, path, publisher)
}
}
}
async fn publishers_index(
request: Request<'_>,
) -> Result<HttpResponse, DispatchError> {
match *request.method() {
Method::GET => {
let (request, _) = request.proceed_permitted(
Permission::PubList, None
)?;
let server = request.empty()?;
Ok(HttpResponse::json(
&PublisherList {
publishers: {
server.krill().publishers()?.into_iter().map(
PublisherSummary::from_handle
).collect()
}
}
))
}
Method::POST => {
let (request, auth) = request.proceed_permitted(
Permission::PubCreate, None
)?;
let (server, pbl) = request.read_json().await?;
Ok(HttpResponse::json(
&server.krill().add_publisher(pbl, auth.actor())?
))
}
_ => Ok(HttpResponse::method_not_allowed())
}
}
fn publishers_publisher(
request: Request<'_>,
mut path: PathIter<'_>,
publisher: PublisherHandle,
) -> Result<HttpResponse, DispatchError> {
match path.next() {
None => publishers_publisher_index(request, publisher),
Some("response.json") => {
publishers_publisher_response(request, path, publisher)
}
Some("response.xml") => {
publishers_publisher_response_xml(request, path, publisher)
}
_ => Ok(HttpResponse::not_found())
}
}
fn publishers_publisher_index(
request: Request<'_>,
publisher: PublisherHandle,
) -> Result<HttpResponse, DispatchError> {
match *request.method() {
Method::GET => {
let (request, _) = request.proceed_permitted(
Permission::PubRead, None
)?;
let server = request.empty()?;
Ok(HttpResponse::json(
&server.krill().get_publisher(publisher)?
))
}
Method::DELETE => {
let (request, auth) = request.proceed_permitted(
Permission::PubDelete, None
)?;
let server = request.empty()?;
server.krill().remove_publisher(publisher, auth.actor())?;
Ok(HttpResponse::ok())
}
_ => Ok(HttpResponse::method_not_allowed())
}
}
fn publishers_publisher_response(
request: Request<'_>,
path: PathIter<'_>,
publisher: PublisherHandle,
) -> Result<HttpResponse, DispatchError> {
path.check_exhausted()?;
request.check_get()?;
let (request, _) = request.proceed_permitted(Permission::PubRead, None)?;
let server = request.empty()?;
Ok(HttpResponse::json(
&server.krill().repository_response(&publisher)?
))
}
fn publishers_publisher_response_xml(
request: Request<'_>,
path: PathIter<'_>,
publisher: PublisherHandle,
) -> Result<HttpResponse, DispatchError> {
path.check_exhausted()?;
request.check_get()?;
let (request, _) = request.proceed_permitted(Permission::PubRead, None)?;
let server = request.empty()?;
Ok(HttpResponse::xml(
server.krill().repository_response(&publisher)?.to_xml_vec()
))
}
fn session_reset(
request: Request<'_>,
path: PathIter<'_>,
) -> Result<HttpResponse, DispatchError> {
path.check_exhausted()?;
request.check_post()?;
let (request, _) = request.proceed_permitted(Permission::PubAdmin, None)?;
let server = request.empty()?;
server.krill().repository_session_reset()?;
Ok(HttpResponse::ok())
}
async fn stale(
request: Request<'_>,
mut path: PathIter<'_>,
) -> Result<HttpResponse, DispatchError> {
let seconds = path.parse_opt_next()?.unwrap_or(0);
path.check_exhausted()?;
request.check_get()?;
let (request, _) = request.proceed_permitted( Permission::PubList, None)?;
let server = request.empty()?;
let stats = server.krill().repo_stats()?;
Ok(HttpResponse::json(
&PublisherList {
publishers: {
stats.stale_publishers(seconds).map(
PublisherSummary::from_handle
).collect()
}
}
))
}