digitalocean-api 0.2.2

A pure Rust DigitalOcean API binding.
Documentation
use super::{ApiLinks, ApiMeta};
use super::{HasPagination, HasResponse, HasValue};
use crate::method::{Create, Delete, Get, List, Update};
use crate::request::Request;
use crate::request::SshKeyRequest;
use crate::{ROOT_URL, STATIC_URL_ERROR};
use getset::{Getters, Setters};
use serde::Deserialize;
use serde::Serialize;
use std::fmt::Display;
use url::Url;

const ACCOUNT_SEGMENT: &str = "account";
const KEYS_SEGMENT: &str = "keys";

/// DigitalOcean allows you to add SSH public keys to the interface so that you
/// can embed your public key into a Droplet at the time of creation. Only the
/// public key is required to take advantage of this functionality.
///
/// [Digital Ocean Documentation.](https://developers.digitalocean.com/documentation/v2/#ssh-keys)
#[derive(Deserialize, Serialize, Debug, Clone, Getters, Setters)]
#[get = "pub"]
pub struct SshKey {
    /// This is a unique identification number for the key. This can be used
    /// to reference a specific SSH key when you wish to embed a key into a
    /// Droplet.
    ///
    /// *Note:* This is a `String` to allow for `id` and `fingerprint` to be
    /// used in `Get`, `Update`, and `Delete` calls like the API describes.
    id: usize,

    /// This attribute contains the fingerprint value that is generated from
    /// the public key. This is a unique identifier that will differentiate
    /// it from other keys using a format that SSH recognizes.
    fingerprint: String,

    /// This attribute contains the entire public key string that was uploaded.
    /// This is what is embedded into the root user's authorized_keys file if
    /// you choose to include this SSH key during Droplet creation.
    public_key: String,

    /// This is the human-readable display name for the given SSH key. This
    /// is used to easily identify the SSH keys when they are displayed.
    name: String,
}

impl SshKey {
    /// [Digital Ocean Documentation.](https://developers.digitalocean.com/documentation/v2/#create-a-new-key)
    pub fn create<N>(name: N, public_key: N) -> SshKeyRequest<Create, SshKey>
    where
        N: AsRef<str> + Serialize + Display,
    {
        let mut url = ROOT_URL.clone();
        url.path_segments_mut()
            .expect(STATIC_URL_ERROR)
            .push(ACCOUNT_SEGMENT)
            .push(KEYS_SEGMENT);

        let mut req = Request::new(url);
        req.set_body(json!({
            "name": name,
            "public_key": public_key,
        }));
        req
    }

    /// [Digital Ocean Documentation.](https://developers.digitalocean.com/documentation/v2/#list-all-keys)
    pub fn list() -> SshKeyRequest<List, Vec<SshKey>> {
        let mut url = ROOT_URL.clone();
        url.path_segments_mut()
            .expect(STATIC_URL_ERROR)
            .push(ACCOUNT_SEGMENT)
            .push(KEYS_SEGMENT);

        Request::new(url)
    }

    /// [Digital Ocean Documentation.](https://developers.digitalocean.com/documentation/v2/#retrieve-an-existing-key)
    pub fn get<S: Serialize + Display>(id: S) -> SshKeyRequest<Get, SshKey> {
        let mut url = ROOT_URL.clone();
        url.path_segments_mut()
            .expect(STATIC_URL_ERROR)
            .push(ACCOUNT_SEGMENT)
            .push(KEYS_SEGMENT)
            .push(&format!("{id}"));

        Request::new(url)
    }

    /// [Digital Ocean Documentation.](https://developers.digitalocean.com/documentation/v2/#retrieve-an-existing-key)
    pub fn update<S: Serialize + Display>(id: S) -> SshKeyRequest<Update, SshKey> {
        let mut url = ROOT_URL.clone();
        url.path_segments_mut()
            .expect(STATIC_URL_ERROR)
            .push(ACCOUNT_SEGMENT)
            .push(KEYS_SEGMENT)
            .push(&format!("{id}"));

        Request::new(url)
    }

    /// [Digital Ocean Documentation.](https://developers.digitalocean.com/documentation/v2/#delete-a-domain)
    pub fn delete<S: Serialize + Display>(id: S) -> SshKeyRequest<Delete, ()> {
        let mut url = ROOT_URL.clone();
        url.path_segments_mut()
            .expect(STATIC_URL_ERROR)
            .push(ACCOUNT_SEGMENT)
            .push(KEYS_SEGMENT)
            .push(&format!("{id}"));

        Request::new(url)
    }
}

impl SshKeyRequest<Update, SshKey> {
    /// The name to give the new SSH key in your account.
    ///
    /// [Digital Ocean Documentation.](https://developers.digitalocean.com/documentation/v2/#domain-records)
    pub fn name<S: AsRef<str> + Display + Serialize>(mut self, val: S) -> Self {
        self.body_mut()["name"] = json!(val);
        self
    }
}

/// Response type returned from Digital Ocean.
#[derive(Deserialize, Serialize, Debug, Clone)]
pub struct SshKeyListResponse {
    ssh_keys: Vec<SshKey>,
    links: ApiLinks,
    meta: ApiMeta,
}

impl HasResponse for Vec<SshKey> {
    type Response = SshKeyListResponse;
}

impl HasPagination for SshKeyListResponse {
    fn next_page(&self) -> Option<Url> {
        self.links.next()
    }
}

impl HasValue for SshKeyListResponse {
    type Value = Vec<SshKey>;

    fn value(self) -> Vec<SshKey> {
        self.ssh_keys
    }
}

/// Response type returned from Digital Ocean.
#[derive(Deserialize, Serialize, Debug, Clone)]
pub struct SshKeyResponse {
    ssh_key: SshKey,
}

impl HasResponse for SshKey {
    type Response = SshKeyResponse;
}

impl HasValue for SshKeyResponse {
    type Value = SshKey;

    fn value(self) -> SshKey {
        self.ssh_key
    }
}