[][src]Module activitystreams::unparsed

Types and Traits for dealing with Unparsed data

Since ActivityStreams is extensible, and structured in a heirarchy of types, Data that was not required to construct a given type might still come in handy when extending a into a subobject.

For example, a Create activity is an extension of an Object, but if we need to store that type on another object, we need to make the type system happy. Since any number of types both provided and extended might need to be stored in the same key, a type called AnyBase exists. AnyBase, when containing a Base, can be extended into a Create activity so long as the required keys are present in it's Unparsed struct.

For the most part, users of this library won't care about this module, but if you need to create an Extension, it will come in handy.

Let's implement a part of the Security extension to be compatible with Mastodon.

use activitystreams::{
    actor::{AsApActor, ApActor},
    base::{AsBase, Base, Extends},
    markers,
    object::{AsObject, Object},
    prelude::*,
    primitives::*,
    unparsed::*,
    url::Url,
};

/// First, we'll define our public key types

#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
#[serde(rename_all = "camelCase")]
pub struct PublicKeyValues {
    pub id: Url,
    pub owner: Url,
    pub public_key_pem: String,
}

#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
#[serde(rename_all = "camelCase")]
pub struct PublicKey<Inner> {
    pub public_key: PublicKeyValues,
    pub inner: Inner,
}


/// Then, we'll implement Extends so we can produce a PublicKey<Object> from an AnyBase.

impl<Inner, Kind> Extends<Kind> for PublicKey<Inner>
where
    Inner: Extends<Kind, Error=serde_json::Error> + UnparsedMut,
{
    type Error = serde_json::Error;

    fn extends(base: Base<Kind>) -> Result<Self, Self::Error> {
        let mut inner = Inner::extends(base)?;

        Ok(PublicKey {
            public_key: inner.unparsed_mut().remove("publicKey")?,
            inner,
        })
    }

    fn retracts(self) -> Result<Base<Kind>, Self::Error> {
        let PublicKey {
            public_key,
            mut inner,
        } = self;

        inner.unparsed_mut().insert("publicKey", public_key)?;

        inner.retracts()
    }
}


/// Auto-implement Base, Object, and Actor when Inner supports it
impl<Inner> markers::Base for PublicKey<Inner> where Inner: markers::Base {}
impl<Inner> markers::Object for PublicKey<Inner> where Inner: markers::Object {}
impl<Inner> markers::Actor for PublicKey<Inner> where Inner: markers::Actor {}


/// If we want to easily access getters and setters for internal types, we'll need to forward
/// those, too.

/// Forward for base methods
///
/// This allows us to access methods related to `context`, `id`, `kind`, `name`,
/// `media_type`, and `preview` directly from the PublicKey struct
impl<Inner, Kind> AsBase<Kind> for PublicKey<Inner>
where
    Inner: AsBase<Kind>,
{
    fn base_ref(&self) -> &Base<Kind> {
        self.inner.base_ref()
    }

    fn base_mut(&mut self) -> &mut Base<Kind> {
        self.inner.base_mut()
    }
}

/// Forward for object methods
///
/// This allows us to access methods related to `url`, `generator`, `start_time`, `duration`,
/// and more directly from the PublicKey struct
impl<Inner, Kind> AsObject<Kind> for PublicKey<Inner>
where
    Inner: AsObject<Kind>,
{
    fn object_ref(&self) -> &Object<Kind> {
        self.inner.object_ref()
    }

    fn object_mut(&mut self) -> &mut Object<Kind> {
        self.inner.object_mut()
    }
}

/// Forward for ActivityPub actor methods
///
/// This allows us to access methods related to `inbox`, `outbox`, `following`, `followers`,
/// `liked`, `streams`, `endpoints`, and more directly from the PublicKey struct
impl<Inner1, Inner2> AsApActor<Inner2> for PublicKey<Inner1>
where
    Inner1: AsApActor<Inner2>,
{
    fn ap_actor_ref(&self) -> &ApActor<Inner2> {
        self.inner.ap_actor_ref()
    }

    fn ap_actor_mut(&mut self) -> &mut ApActor<Inner2> {
        self.inner.ap_actor_mut()
    }
}


/// If we want to be able to extend from our own type, we'll need to forward some
/// implementations, and create some traits

/// Make it easy for downstreams to get an Unparsed
impl<Inner> UnparsedMut for PublicKey<Inner>
where
    Inner: UnparsedMut,
{
    fn unparsed_mut(&mut self) -> &mut Unparsed {
        self.inner.unparsed_mut()
    }
}

/// Create our own extensible trait
pub trait AsPublicKey<Inner> {
    fn public_key_ref(&self) -> &PublicKey<Inner>;
    fn public_key_mut(&mut self) -> &mut PublicKey<Inner>;
}

/// Implement it
impl<Inner> AsPublicKey<Inner> for PublicKey<Inner> {
    fn public_key_ref(&self) -> &Self {
        self
    }

    fn public_key_mut(&mut self) -> &mut Self {
        self
    }
}

/// And now create helper methods
pub trait PublicKeyExt<Inner>: AsPublicKey<Inner> {
    /// Borrow the public key's ID
    fn key_id<'a>(&'a self) -> &'a Url
    where
        Inner: 'a,
    {
        &self.public_key_ref().public_key.id
    }

    /// Set the public key's ID
    fn set_key_id(&mut self, id: Url) -> &mut Self {
        self.public_key_mut().public_key.id = id;
        self
    }

    /// Borrow the public key's Owner
    fn key_owner<'a>(&'a self) -> &'a Url
    where
        Inner: 'a,
    {
        &self.public_key_ref().public_key.owner
    }

    /// Set the public key's Owner
    fn set_key_owner(&mut self, owner: Url) -> &mut Self {
        self.public_key_mut().public_key.owner = owner;
        self
    }

    /// Borrow the public key's PEM encoded value
    fn key_pem<'a>(&'a self) -> &'a str
    where
        Inner: 'a,
    {
        &self.public_key_ref().public_key.public_key_pem
    }

    /// Set the public key's PEM encoded value
    ///
    /// In a real application, this might take a different type, such as RSA's RSAPublicKey, or
    /// OpenSSL's or Ring's version
    fn set_key_pem<T>(&mut self, pem: T) -> &mut Self
    where
        T: Into<String>,
    {
        self.public_key_mut().public_key.public_key_pem = pem.into();
        self
    }
}

/// Finally, we'll automatically implement PublicKeyExt for any type implementing AsPublicKey
impl<T, Inner> PublicKeyExt<Inner> for T where T: AsPublicKey<Inner> {}


/// Now that eveything is implemented, we can use it like so:
use activitystreams::{actor::{kind::PersonType, Person}, uri};

pub type ExtendedPerson = PublicKey<ApActor<Person>>;

impl ExtendedPerson {
    pub fn new(inbox: Url, mut owner: Url) -> Self {
        let id = owner.clone();
        owner.set_fragment(Some("main-key"));
        PublicKey {
            public_key: PublicKeyValues {
                id,
                owner,
                public_key_pem: String::new(),
            },
            inner: ApActor::new(inbox, Person::new()),
        }
    }
}

fn main() -> Result<(), anyhow::Error> {
    let mut extended_person = ExtendedPerson::new(
        uri!("https://example.com/user/inbox"),
        uri!("https://example.com/user"),
    );

    extended_person
        .set_kind(PersonType::Person)
        .set_id("https://example.com/user".parse()?)
        .set_name("Demo User")
        .set_preferred_username("user")
        .set_outbox("https://example.com/user/outbox".parse()?)
        .set_key_pem(
            "------ BEGIN PUBLIC KEY ------\nasdfasdfasdfasdfasdfasdf..."
        )
        .set_key_owner("https://example.com/user".parse()?)
        .set_key_id("https://example.com/user#main-key".parse()?);

    let string = serde_json::to_string(&extended_person)?;
    println!("{}", string);
    Ok(())
}

Structs

Unparsed

The Unparsed struct itself,

Traits

UnparsedMut

A trait granting mutable access to an Unparsed struct

UnparsedMutExt

A helper trait providing two methods, 'insert' and 'remove', that is auto-implemented for UnparsedMut types.