mirror of
https://github.com/NLnetLabs/krill.git
synced 2026-09-28 04:14:53 +02:00
354 lines
9.0 KiB
Rust
354 lines
9.0 KiB
Rust
//! Support for requests sent to the Json API
|
|
use std::ops;
|
|
|
|
use rpki::uri;
|
|
|
|
use crate::commons::api::{Base64, HexEncodedHash};
|
|
use crate::commons::util::file::CurrentFile;
|
|
|
|
//------------ PublishRequest ------------------------------------------------
|
|
|
|
/// This type provides a convenience wrapper to contain the request found
|
|
/// inside of a validated RFC8181 request.
|
|
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
|
|
pub enum PublishRequest {
|
|
List, // See https://tools.ietf.org/html/rfc8181#section-2.3
|
|
Delta(PublishDelta),
|
|
}
|
|
|
|
//------------ PublishDelta ------------------------------------------------
|
|
|
|
/// This type represents a multi element query as described in
|
|
/// https://tools.ietf.org/html/rfc8181#section-3.7
|
|
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
|
|
pub struct PublishDelta {
|
|
publishes: Vec<Publish>,
|
|
updates: Vec<Update>,
|
|
withdraws: Vec<Withdraw>,
|
|
}
|
|
|
|
impl PublishDelta {
|
|
pub fn new(publishes: Vec<Publish>, updates: Vec<Update>, withdraws: Vec<Withdraw>) -> Self {
|
|
PublishDelta {
|
|
publishes,
|
|
updates,
|
|
withdraws,
|
|
}
|
|
}
|
|
|
|
pub fn empty() -> Self {
|
|
Self::default()
|
|
}
|
|
|
|
pub fn publishes(&self) -> &Vec<Publish> {
|
|
&self.publishes
|
|
}
|
|
pub fn updates(&self) -> &Vec<Update> {
|
|
&self.updates
|
|
}
|
|
pub fn withdraws(&self) -> &Vec<Withdraw> {
|
|
&self.withdraws
|
|
}
|
|
|
|
pub fn len(&self) -> usize {
|
|
self.publishes.len() + self.updates.len() + self.withdraws.len()
|
|
}
|
|
|
|
pub fn is_empty(&self) -> bool {
|
|
self.len() == 0
|
|
}
|
|
|
|
pub fn unwrap(self) -> (Vec<Publish>, Vec<Update>, Vec<Withdraw>) {
|
|
(self.publishes, self.updates, self.withdraws)
|
|
}
|
|
}
|
|
|
|
impl Default for PublishDelta {
|
|
fn default() -> Self {
|
|
PublishDelta {
|
|
publishes: vec![],
|
|
updates: vec![],
|
|
withdraws: vec![],
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ops::Add for PublishDelta {
|
|
type Output = PublishDelta;
|
|
|
|
fn add(mut self, mut other: Self) -> Self::Output {
|
|
self.publishes.append(&mut other.publishes);
|
|
self.updates.append(&mut other.updates);
|
|
self.withdraws.append(&mut other.withdraws);
|
|
self
|
|
}
|
|
}
|
|
|
|
//------------ PublishDeltaBuilder -------------------------------------------
|
|
|
|
#[derive(Default)]
|
|
pub struct PublishDeltaBuilder {
|
|
publishes: Vec<Publish>,
|
|
updates: Vec<Update>,
|
|
withdraws: Vec<Withdraw>,
|
|
}
|
|
|
|
impl PublishDeltaBuilder {
|
|
pub fn new() -> Self {
|
|
Self::default()
|
|
}
|
|
|
|
pub fn add_publish(&mut self, publish: Publish) {
|
|
self.publishes.push(publish);
|
|
}
|
|
|
|
pub fn add_update(&mut self, update: Update) {
|
|
self.updates.push(update);
|
|
}
|
|
|
|
pub fn add_withdraw(&mut self, withdraw: Withdraw) {
|
|
self.withdraws.push(withdraw);
|
|
}
|
|
|
|
pub fn finish(self) -> PublishDelta {
|
|
PublishDelta {
|
|
publishes: self.publishes,
|
|
updates: self.updates,
|
|
withdraws: self.withdraws,
|
|
}
|
|
}
|
|
}
|
|
|
|
//------------ Publish ------------------------------------------------------
|
|
|
|
/// Type representing a json equivalent to the publish element, that does not
|
|
/// update any existing object, defined in:
|
|
/// https://tools.ietf.org/html/rfc8181#section-3.1
|
|
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
|
|
pub struct Publish {
|
|
tag: Option<String>,
|
|
uri: uri::Rsync,
|
|
content: Base64,
|
|
}
|
|
|
|
impl Publish {
|
|
pub fn new(tag: Option<String>, uri: uri::Rsync, content: Base64) -> Self {
|
|
Publish { tag, uri, content }
|
|
}
|
|
pub fn with_hash_tag(uri: uri::Rsync, content: Base64) -> Self {
|
|
let tag = Some(content.to_hex_hash());
|
|
Publish { tag, uri, content }
|
|
}
|
|
|
|
pub fn tag(&self) -> &Option<String> {
|
|
&self.tag
|
|
}
|
|
pub fn tag_for_xml(&self) -> String {
|
|
match &self.tag {
|
|
None => "".to_string(),
|
|
Some(t) => t.clone(),
|
|
}
|
|
}
|
|
pub fn uri(&self) -> &uri::Rsync {
|
|
&self.uri
|
|
}
|
|
pub fn content(&self) -> &Base64 {
|
|
&self.content
|
|
}
|
|
|
|
pub fn unwrap(self) -> (Option<String>, uri::Rsync, Base64) {
|
|
(self.tag, self.uri, self.content)
|
|
}
|
|
}
|
|
|
|
//------------ Update --------------------------------------------------------
|
|
|
|
/// Type representing a json equivalent to the publish element, that updates
|
|
/// an existing object:
|
|
/// https://tools.ietf.org/html/rfc8181#section-3.2
|
|
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
|
|
pub struct Update {
|
|
tag: Option<String>,
|
|
uri: uri::Rsync,
|
|
content: Base64,
|
|
hash: HexEncodedHash,
|
|
}
|
|
|
|
impl Update {
|
|
pub fn new(
|
|
tag: Option<String>,
|
|
uri: uri::Rsync,
|
|
content: Base64,
|
|
old_hash: HexEncodedHash,
|
|
) -> Self {
|
|
Update {
|
|
tag,
|
|
uri,
|
|
content,
|
|
hash: old_hash,
|
|
}
|
|
}
|
|
pub fn with_hash_tag(uri: uri::Rsync, content: Base64, old_hash: HexEncodedHash) -> Self {
|
|
let tag = Some(content.to_hex_hash());
|
|
Update {
|
|
tag,
|
|
uri,
|
|
content,
|
|
hash: old_hash,
|
|
}
|
|
}
|
|
|
|
pub fn tag(&self) -> &Option<String> {
|
|
&self.tag
|
|
}
|
|
pub fn tag_for_xml(&self) -> String {
|
|
match &self.tag {
|
|
Some(t) => t.clone(),
|
|
None => "".to_string(),
|
|
}
|
|
}
|
|
pub fn uri(&self) -> &uri::Rsync {
|
|
&self.uri
|
|
}
|
|
pub fn content(&self) -> &Base64 {
|
|
&self.content
|
|
}
|
|
pub fn hash(&self) -> &HexEncodedHash {
|
|
&self.hash
|
|
}
|
|
|
|
pub fn unwrap(self) -> (Option<String>, uri::Rsync, Base64, HexEncodedHash) {
|
|
(self.tag, self.uri, self.content, self.hash)
|
|
}
|
|
}
|
|
|
|
//------------ Withdraw ------------------------------------------------------
|
|
|
|
/// Type representing a json equivalent to a withdraw element that removes an
|
|
/// object from the repository:
|
|
/// https://tools.ietf.org/html/rfc8181#section-3.3
|
|
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
|
|
pub struct Withdraw {
|
|
tag: Option<String>,
|
|
uri: uri::Rsync,
|
|
hash: HexEncodedHash,
|
|
}
|
|
|
|
impl Withdraw {
|
|
pub fn new(tag: Option<String>, uri: uri::Rsync, hash: HexEncodedHash) -> Self {
|
|
Withdraw { tag, uri, hash }
|
|
}
|
|
|
|
pub fn with_hash_tag(uri: uri::Rsync, hash: HexEncodedHash) -> Self {
|
|
let tag = Some(hash.to_string());
|
|
Withdraw { tag, uri, hash }
|
|
}
|
|
|
|
pub fn from_list_element(el: &ListElement) -> Self {
|
|
Withdraw {
|
|
tag: None,
|
|
uri: el.uri().clone(),
|
|
hash: el.hash().clone(),
|
|
}
|
|
}
|
|
|
|
pub fn tag(&self) -> &Option<String> {
|
|
&self.tag
|
|
}
|
|
pub fn tag_for_xml(&self) -> String {
|
|
match &self.tag {
|
|
Some(t) => t.clone(),
|
|
None => "".to_string(),
|
|
}
|
|
}
|
|
pub fn uri(&self) -> &uri::Rsync {
|
|
&self.uri
|
|
}
|
|
pub fn hash(&self) -> &HexEncodedHash {
|
|
&self.hash
|
|
}
|
|
|
|
pub fn unwrap(self) -> (Option<String>, uri::Rsync, HexEncodedHash) {
|
|
(self.tag, self.uri, self.hash)
|
|
}
|
|
}
|
|
|
|
//------------ PublishReply --------------------------------------------------
|
|
|
|
/// This type is used to wrap API responses for publication requests.
|
|
pub enum PublishReply {
|
|
Success, // See https://tools.ietf.org/html/rfc8181#section-3.4
|
|
List(ListReply),
|
|
}
|
|
|
|
//------------ ListReply -----------------------------------------------------
|
|
|
|
/// This type represents the list reply as described in
|
|
/// https://tools.ietf.org/html/rfc8181#section-2.3
|
|
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
|
|
pub struct ListReply {
|
|
elements: Vec<ListElement>,
|
|
}
|
|
|
|
impl ListReply {
|
|
pub fn new(elements: Vec<ListElement>) -> Self {
|
|
ListReply { elements }
|
|
}
|
|
|
|
pub fn from_files(files: Vec<CurrentFile>) -> Self {
|
|
let elements = files
|
|
.into_iter()
|
|
.map(CurrentFile::into_list_element)
|
|
.collect();
|
|
ListReply { elements }
|
|
}
|
|
|
|
pub fn elements(&self) -> &Vec<ListElement> {
|
|
&self.elements
|
|
}
|
|
|
|
pub fn into_elements(self) -> Vec<ListElement> {
|
|
self.elements
|
|
}
|
|
|
|
pub fn into_withdraw_delta(self) -> PublishDelta {
|
|
let withdraws: Vec<Withdraw> = self
|
|
.elements
|
|
.into_iter()
|
|
.map(|el| {
|
|
let (uri, hash) = el.unpack();
|
|
Withdraw::new(None, uri, hash)
|
|
})
|
|
.collect();
|
|
|
|
PublishDelta::new(vec![], vec![], withdraws)
|
|
}
|
|
}
|
|
|
|
//------------ ListElement ---------------------------------------------------
|
|
|
|
/// This type represents a single object that is published at a publication
|
|
/// server.
|
|
#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
|
|
pub struct ListElement {
|
|
uri: uri::Rsync,
|
|
hash: HexEncodedHash,
|
|
}
|
|
|
|
impl ListElement {
|
|
pub fn new(uri: uri::Rsync, hash: HexEncodedHash) -> Self {
|
|
ListElement { uri, hash }
|
|
}
|
|
|
|
pub fn uri(&self) -> &uri::Rsync {
|
|
&self.uri
|
|
}
|
|
pub fn hash(&self) -> &HexEncodedHash {
|
|
&self.hash
|
|
}
|
|
|
|
pub fn unpack(self) -> (uri::Rsync, HexEncodedHash) {
|
|
(self.uri, self.hash)
|
|
}
|
|
}
|