Skip to main content

Builder

Struct Builder 

Source
pub struct Builder<D> { /* private fields */ }
Expand description

Builds a Federation.

Implementations§

Source§

impl<D: Clone + Send + Sync + 'static> Builder<D>

Source

pub fn origin(self, origin: Url) -> Self

Serve every request in origin’s URIs, whatever host it came to: for an application with one host.

Source

pub fn origin_with( self, origin: impl Fn(&str, &D) -> Option<Url> + Send + Sync + 'static, ) -> Self

The canonical origin for a request to a host, or None for a host Ojak should not answer for. A host this maps to the canonical origin is one of its aliases: its IRIs are ours, and its handles are.

Source

pub fn actor<F, Fut, E>(self, kind: &str, template: &str, load: F) -> Self
where F: Fn(Context<D>, String) -> Fut + Send + Sync + 'static, Fut: Future<Output = Result<Found<Value>, E>> + Send + 'static, E: Into<Error>,

Serve actors of kind at template, whose one expression, if it has one, is the actor’s identifier.

Source

pub fn object<F, Fut, E>(self, kind: &str, template: &str, load: F) -> Self
where F: Fn(Context<D>, Values) -> Fut + Send + Sync + 'static, Fut: Future<Output = Result<Found<Value>, E>> + Send + 'static, E: Into<Error>,

Serve objects of kind at template, whose expressions the dispatcher receives by name.

Source

pub fn object_alias(self, kind: &str, template: &str) -> Self

Serve the objects of kind at template as well, and recognise it in Context::parse_uri and Context::parse_object: another path the same objects are known by, such as Mastodon’s /@{username}/{id} beside /users/{username}/statuses/{id}. URIs are still built from the template kind was registered with. The dispatcher receives this template’s values, so it has to name every expression the first template does, and may name more.

Source

pub fn collection_alias(self, kind: &str, template: &str) -> Self

Serve the collection kind at template as well, and recognise it in Context::parse_uri: another path the same collection is known by, such as Mastodon’s /@{username}/followers beside /users/{username}/followers. The collection is still named by the template kind was registered with, in its id and its pages’ links. The alias names the owner in as many expressions as that template does: one, or none.

Source

pub fn collection( self, kind: &str, template: &str, collection: Collection<D>, ) -> Self

Serve the collection kind at template, whose one expression, if it has one, is the identifier of what it belongs to.

Source

pub fn authorize<F, Fut, E>(self, kind: &str, authorize: F) -> Self
where F: Fn(Context<D>, Values, Option<Url>) -> Fut + Send + Sync + 'static, Fut: Future<Output = Result<bool, E>> + Send + 'static, E: Into<Error>,

Serve what is registered as kind only to requests authorize allows. It receives the verified signer of the request, if it was signed and signed fetches are configured. A request it refuses is 401.

Source

pub fn guard<F, Fut, E>(self, kind: &str, guard: F) -> Self
where F: Fn(Context<D>, Values) -> Fut + Send + Sync + 'static, Fut: Future<Output = Result<Access, E>> + Send + 'static, E: Into<Error>,

Serve what is registered as kind only as guard says: to all, or refused as unauthorized (401), forbidden (403) or not there (404). Unlike Builder::authorize, nothing is verified before it is asked: the guard asks Context::signing or Context::signer when it needs to know who signed, so a guard that lets everyone through costs no signature check, nor a key fetched to make one.

Source

pub fn key_pairs<F, Fut, E>(self, keys: F) -> Self
where F: Fn(Context<D>, ActorRef) -> Fut + Send + Sync + 'static, Fut: Future<Output = Result<Vec<PublicKey>, E>> + Send + 'static, E: Into<Error>,

Where actors’ public keys come from, read by Context::actor_keys.

Source

pub fn handle<F, Fut, E>(self, lookup: F) -> Self
where F: Fn(Context<D>, String) -> Fut + Send + Sync + 'static, Fut: Future<Output = Result<Option<ActorRef>, E>> + Send + 'static, E: Into<Error>,

Which actor a WebFinger handle’s username names.

Source

pub fn map_alias<F, Fut, E>(self, lookup: F) -> Self
where F: Fn(Context<D>, Url) -> Fut + Send + Sync + 'static, Fut: Future<Output = Result<Option<ActorRef>, E>> + Send + 'static, E: Into<Error>,

Which actor another URL of ours, such as a profile page, names, for WebFinger.

Links a WebFinger answer carries beside self and profile-page, such as Mastodon’s subscribe template.

Source

pub fn nodeinfo<F, Fut, E>(self, nodeinfo: F) -> Self
where F: Fn(Context<D>) -> Fut + Send + Sync + 'static, Fut: Future<Output = Result<NodeInfo, E>> + Send + 'static, E: Into<Error>,

Serve NodeInfo, 2.0 and 2.1, from nodeinfo.

Source

pub fn signed_fetch<K, F, Fut, E>( self, fetcher: Arc<Fetcher>, kv: K, key_ttl: Duration, key: F, ) -> Self
where K: KvStore, F: Fn(Context<D>) -> Fut + Send + Sync + 'static, Fut: Future<Output = Result<Option<SenderKey>, E>> + Send + 'static, E: Into<Error>,

Verify signed GETs, for Context::signer and authorize: keys are fetched with fetcher, signed with the key key returns when there is one, and kept in kv for key_ttl.

Source

pub fn fetcher_for( self, fetcher: impl Fn(&D) -> Arc<Fetcher> + Send + Sync + 'static, ) -> Self

The fetcher for a request’s data, in place of the one given to Builder::signed_fetch: an application serving several instances fetches with each one’s own. Call after signed_fetch.

Source

pub fn kv_for<K: KvStore>( self, kv: impl Fn(&D) -> Arc<K> + Send + Sync + 'static, ) -> Self

The key-value store for a request’s data, in place of the one given to Builder::signed_fetch: an application serving several instances keeps each one’s cached keys and the activities it has seen in that instance’s own store, such as its own namespace of a shared Redis. Call after signed_fetch.

Source

pub fn known_key<F, Fut, E>(self, known: F) -> Self
where F: Fn(Context<D>, String) -> Fut + Send + Sync + 'static, Fut: Future<Output = Result<Option<KnownKey>, E>> + Send + 'static, E: Into<Error>,

A key the application already holds for a key ID, tried before the key-value store and a fetch: an application that stores remote actors’ keys, as Mastodon’s schema does, need not fetch them again. A key that does not verify is fetched fresh. Call after signed_fetch.

Source

pub fn key_fetched<F, Fut>(self, hook: F) -> Self
where F: Fn(Context<D>, Value) -> Fut + Send + Sync + 'static, Fut: Future<Output = ()> + Send + 'static,

See the document of an actor Ojak fetched for its key, once the key has verified a request: an application that stores actors stores this one, so a new actor’s first activity does not fetch it twice. Call after signed_fetch.

Source

pub fn on_any<F, Fut, E>(self, listen: F) -> Self
where F: Fn(Context<D>, Received<AnyObject>) -> Fut + Send + Sync + 'static, Fut: Future<Output = Result<(), E>> + Send + 'static, E: Into<Error>,

Run listen for every activity no typed listener is registered for, read as whatever it is: for an application with a dispatcher of its own, which reads Received::vouched.

Source

pub fn inbox(self, kind: &str, template: &str) -> Self

Receive activities at template, the inbox of the actors of kind, whose one expression is the actor’s identifier; or, for an actor whose own template has no expression, such as an instance actor at /actor, with none.

Source

pub fn shared_inbox(self, path: &str) -> Self

Receive activities at path, the shared inbox.

Source

pub fn on<T, F, Fut, E>(self, listen: F) -> Self
where T: Typed + FromJson + ToJson + Send + 'static, F: Fn(Context<D>, Received<T>) -> Fut + Send + Sync + 'static, Fut: Future<Output = Result<(), E>> + Send + 'static, E: Into<Error>,

Run listen for every activity of type T an inbox receives from a sender Ojak has authenticated. Types with no listener are accepted and dropped.

Source

pub fn read_inbox_as_written(self) -> Self

Hand listeners each activity as its sender wrote it, without JSON-LD processing: its @context removed and what it embeds reduced to what the sender can vouch for, as always, but its terms left as spelled.

By default an activity is expanded and compacted against ojak’s context first, so that a sender’s aliases, prefixes and extension terms read as ojak’s vocabulary expects. That is what a listener typed to a vocabulary type relies on. An application that reads the JSON itself, as Mastodon reads it, needs none of it, and this skips the work — and the refusal of a document whose context cannot be processed.

Source

pub fn linked_data_before_proof(self) -> Self

Check a forwarded activity’s Linked Data signature before its FEP-8b32 proof, rather than after.

An activity signed by a server other than its actor’s is taken on its actor’s proof by default, and on its Linked Data signature only when it has no proof that holds: a proof is the cheaper check, needing no JSON-LD processing. Mastodon and Fedify check the signature first, and what an activity is taken on decides whether it can be passed on (Received::vouched_by): Mastodon passes on only an activity taken on its Linked Data signature. An application that forwards as Mastodon does asks for this, so that an activity carrying both is taken on its signature. A request signed by the actor’s own server, and one whose signature does not verify, are unaffected.

Source

pub fn blocked<F, Fut, E>(self, blocked: F) -> Self
where F: Fn(Context<D>, String) -> Fut + Send + Sync + 'static, Fut: Future<Output = Result<bool, E>> + Send + 'static, E: Into<Error>,

Whether activities from host are refused, asked before any key is fetched for them. A refused activity is answered 202 and dropped.

A request signed with a key on host is refused too, before the key is looked for: its signer is not verified, an inbox POST is answered as one that does not verify, and a GET’s signing is Signing::Blocked.

Source

pub fn remote_contexts<F, Fut, E>(self, limits: Limits, load: F) -> Self
where F: Fn(Context<D>, String) -> Fut + Send + Sync + 'static, Fut: Future<Output = Result<String, E>> + Send + 'static, E: Into<Error>,

Check a Linked Data Signature over contexts ojak does not ship, as Mastodon does: load returns the context an IRI names, the body crate::contexts::fetch returns, from the application’s cache or fetched with its client (crate::contexts::fetch_cached does both). Without it, an activity naming such a context is not taken on its signature, and is fetched from its origin instead.

Only that check loads contexts, and only within limits; the activity is then read over the same contexts, so that what it is taken to say is what was signed.

Source

pub fn on_unverified<F, Fut>(self, hook: F) -> Self
where F: Fn(Context<D>, Value) -> Fut + Send + Sync + 'static, Fut: Future<Output = ()> + Send + 'static,

See every activity whose sender could not be authenticated, which is where an application removes an actor whose Delete it could not verify because the actor, key and all, is gone.

Source

pub fn inbox_queue( self, queue: impl Fn(&D) -> Option<SharedQueue> + Send + Sync + 'static, ) -> Self

The queue activities wait in for an InboxWorker, for the data of a request: an application with a database per tenant has a queue per tenant. Without one, or when it gives None, listeners run inside the request.

Source

pub fn gateway<F, Fut, E>(self, load: F) -> Self
where F: Fn(Context<D>, ApUri) -> Fut + Send + Sync + 'static, Fut: Future<Output = Result<Found<Value>, E>> + Send + 'static, E: Into<Error>,

Serve the portable objects (FEP-ef61) this server is a gateway for, at /.well-known/apgateway/{did}/{+path}. load returns the object an ap URI names, as the signed document the application stored: its proof covers it, and Ojak serves it as it is. An object that is not public is the application’s to refuse, as for any dispatcher.

What is served is checked first, as whoever fetches it will check it: a document whose id is another object is answered 404, and one whose proof does not verify, 500, both reported to on_error. A collection may have no proof. A signed Tombstone is served with 410; Found::Gone serves an unsigned one, which says the object is gone but that nobody can take for its owner’s word.

Source

pub fn gateway_media<F, Fut, E>(self, load: F) -> Self
where F: Fn(Context<D>, Hashlink) -> Fut + Send + Sync + 'static, Fut: Future<Output = Result<Option<Media>, E>> + Send + 'static, E: Into<Error>,

Serve the media portable objects refer to by hashlink (FEP-ef61), at /.well-known/apgateway/hl:zQm…. load returns what the hashlink names; it is served only if it is that, since it is checked against the digest wherever it is fetched, and a mismatch is reported to on_error and answered 500. Anyone who knows a digest can fetch what it names: media with an audience is the application’s to refuse.

Source

pub fn gateway_inbox<F, Fut, E>(self, inbox_for: F) -> Self
where F: Fn(Context<D>, ApUri) -> Fut + Send + Sync + 'static, Fut: Future<Output = Result<Option<GatewayInbox>, E>> + Send + 'static, E: Into<Error>,

Accept deliveries to portable inboxes: inbox_for maps the ap URI of an inbox POSTed to at /.well-known/apgateway/… to the actor the application hosts it for, who the listeners see as the recipient, and the gateways that actor lists, which what arrives is forwarded to. An inbox it maps to None is answered 404.

Source

pub fn forward<F, Fut, E>(self, forward: F) -> Self
where F: Fn(Context<D>, Forward) -> Fut + Send + Sync + 'static, Fut: Future<Output = Result<(), E>> + Send + 'static, E: Into<Error>,

Forward what arrives to where it has to go on to: a portable actor’s other gateways, as FEP-ef61 asks, and the members of collections of ours an activity concerning something of ours is addressed to, as ActivityPub asks (§7.1.2). forward is called once for each activity and kind of forward, however many times it arrives, and sends it. Without it, nothing is forwarded.

Source

pub fn on_error(self, report: impl Fn(&Error) + Send + Sync + 'static) -> Self

See every error a dispatcher returns, which is otherwise a bare 500.

Source

pub fn build(self) -> Result<Federation<D>, BuildError>

The federation.

§Errors

When there is no origin, a template is malformed, two templates could match one path, a template claims a path Ojak serves itself, two dispatchers share a kind, an actor or collection template has more than one expression, or authorize names no kind.

Auto Trait Implementations§

§

impl<D> !RefUnwindSafe for Builder<D>

§

impl<D> !UnwindSafe for Builder<D>

§

impl<D> Freeze for Builder<D>

§

impl<D> Send for Builder<D>

§

impl<D> Sync for Builder<D>

§

impl<D> Unpin for Builder<D>

§

impl<D> UnsafeUnpin for Builder<D>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self> ⓘ

Instruments this type with the provided [Span], returning an Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self> ⓘ

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

§

impl<T> PolicyExt for T
where T: ?Sized,

§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns [Action::Follow] only if self and other return Action::Follow. Read more
§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns [Action::Follow] if either self or other returns Action::Follow. Read more
§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self> ⓘ
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self> ⓘ

Attaches the current default Subscriber to this type, returning a [WithDispatch] wrapper. Read more