Skip to main content

Authorization

Struct Authorization 

Source
pub struct Authorization {
    pub id: Uuid,
    pub order_id: Uuid,
    pub identifier: Identifier,
    pub status: AuthzStatus,
    pub expires: i64,
    pub created_at: i64,
}
Expand description

An ACME authorization (RFC 8555 §7.1.4). One authorization is created per order identifier when the order is created, starting in the pending state and carrying the challenges the client can satisfy to prove control of the identifier.

§Storage Details

  • identifier is persisted as a JSON {type, value} object.
  • Timestamps are epoch seconds (matching orders/accounts/nonces) and rendered as RFC3339 strings in Authorization::to_json.
  • The authorization URL is derived from the id + base URL (like the order’s finalize/certificate URLs), never stored.

§Wildcards

A wildcard authorization stores its identifier in the wildcard form (*.example.com), while the ACME object shows the base name plus a separate "wildcard": true member (RFC 8555 §7.1.4). Storing the base name instead would collide: the canonical wildcard order ["example.com", "*.example.com"] creates two authorizations, and UNIQUE(order_id, identifier) compares the serialized JSON — both rows would be identical and the order would fail to persist. Deriving with Authorization::base_identifier costs a strip_prefix and no migration.

Fields§

§id: Uuid§order_id: Uuid§identifier: Identifier§status: AuthzStatus§expires: i64§created_at: i64

Implementations§

Source§

impl Authorization

Source

pub fn new( order_id: Uuid, identifier: Identifier, expires: i64, ) -> Authorization

Builds a new pending authorization for identifier. Pure — nothing is persisted until Authorization::insert runs.

Source

pub async fn insert<'e>( &self, executor: impl Into<Exec<'e>>, ) -> Result<(), Error>

Inserts the authorization using any executor — a pool, or a transaction (see crate::order::Order::insert for why that matters).

Source

pub async fn create( order_id: Uuid, identifier: Identifier, expires: i64, database: &Database, ) -> Result<Authorization, Error>

Creates a new authorization for identifier in the pending state.

Source

pub async fn find_by_id( id: &str, database: &Database, ) -> Result<Option<Authorization>, Error>

Looks an authorization up by id. An id that does not parse as one is None, like an unknown one: it came from a URL.

Source

pub async fn find_by_order( order_id: Uuid, database: &Database, ) -> Result<Vec<Authorization>, Error>

Lists an order’s authorizations, oldest first (creation order), for the order object’s authorizations array and the all-valid readiness check.

Source

pub async fn count_by_order( order_id: Uuid, database: &Database, ) -> Result<i64, Error>

How many authorizations an order has. crate::order::Order::count_by_account’s counterpart, and for the same reason.

Source

pub async fn find_ids_by_orders( order_ids: &[Uuid], database: &Database, ) -> Result<HashMap<Uuid, Vec<Uuid>>, Error>

The authorization ids of several orders at once, keyed by order id.

The listing paths need nothing but the ids — Order::to_json builds its authorizations URLs from them — and were calling Authorization::find_by_order once per row: 51 queries for a default page of 50. One IN (…) instead.

An order with no authorizations is simply absent from the map, which is what a caller wants: map.remove(id).unwrap_or_default().

Source

pub async fn find_by_order_with<'e>( order_id: Uuid, executor: impl Into<Exec<'e>>, ) -> Result<Vec<Authorization>, Error>

Authorization::find_by_order over any executor — a pool, or a transaction.

Reading inside the transaction that just wrote is what makes “is every authorization of this order valid now?” answerable at all: from the pool, two concurrent validations of two authorizations of one order can each read before the other’s write commits, so neither sees a complete set and neither promotes the order.

Source

pub async fn set_valid<'e>( id: Uuid, executor: impl Into<Exec<'e>>, ) -> Result<bool, Error>

The valid transition as a bare statement, over any executor, returning whether it happened.

Split from Authorization::mark_valid so a validation verdict can compose the challenge, authorization and order transitions into one transaction. The in-memory sync stays in mark_valid: it must not happen until the transaction has committed, or a rollback leaves the object claiming a status the database never took.

Guarded on pending. The verdict is computed by a queued job, long after the request that claimed the challenge read this row: by then the client may have deactivated the authorization (RFC 8555 §7.5.2), or a sibling challenge may have decided it. An unguarded write would walk a deactivated or invalid authorization back to valid.

Source

pub async fn set_invalid<'e>( id: Uuid, executor: impl Into<Exec<'e>>, ) -> Result<bool, Error>

The invalid transition as a bare statement, guarded on pending for the same reason; see Authorization::set_valid.

Source

pub async fn set_deactivated<'e>( id: Uuid, executor: impl Into<Exec<'e>>, ) -> Result<bool, Error>

The deactivated transition as a bare statement; see Authorization::set_valid.

The terminal state a client asks for itself (RFC 8555 §7.5.2). Like Authorization::mark_invalid it does not stamp validated: §8 defines that as the time of a successful validation, and relinquishing an authorization is the opposite.

Bare-statement only: §7.5.2’s deactivate-and-demote pair is committed in one transaction (handlers::authz), so there is no persist-and-sync twin to go with it.

Guarded on the two states §7.5.2 lets a client leave, so a verdict that landed since the caller read the row is never overwritten.

Source

pub async fn mark_valid(&mut self, database: &Database) -> Result<bool, Error>

Moves a pending authorization to the valid state and keeps self in sync (the same persist-and-sync pattern as crate::order::Order::finalize); false when it was not pending.

Source

pub async fn mark_invalid(&mut self, database: &Database) -> Result<bool, Error>

Moves the authorization to the terminal invalid state, after one of its challenges failed validation (RFC 8555 §7.1.6).

No error is stored: the RFC puts the problem document on the challenge, and the authorization object has no error member — a client reads the reason from the challenge it triggered.

Source

pub fn is_wildcard(&self) -> bool

Whether this authorization covers the wildcard of its identifier.

Derived from the stored value rather than stored separately — see the type’s doc comment for why the row keeps the *. prefix.

Source

pub fn base_identifier(&self) -> &str

The name to actually prove control of: the identifier with any *. stripped.

A wildcard is proved by controlling the zone, so the DNS record lives at _acme-challenge.example.com, not at _acme-challenge.*.example.com.

Source

pub fn to_json(&self, base_url: &str, challenges: &[Challenge]) -> Value

The RFC 8555 authorization object: identifier, status, expires (RFC3339), the challenges array (each rendered by Challenge::to_json), and wildcard when the authorization covers one.

Trait Implementations§

Source§

impl Debug for Authorization

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

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<'a, T, E> AsTaggedExplicit<'a, E> for T
where T: 'a,

Source§

fn explicit(self, class: Class, tag: u32) -> TaggedParser<'a, Explicit, Self, E>

Source§

impl<'a, T, E> AsTaggedImplicit<'a, E> for T
where T: 'a,

Source§

fn implicit( self, class: Class, constructed: bool, tag: u32, ) -> TaggedParser<'a, Implicit, Self, E>

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
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<A, B, T> HttpServerConnExec<A, B> for T
where B: Body,

Source§

impl<T> Instrument for T

Source§

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

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

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.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
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 = !

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

fn try_from(value: U) -> Result<T, !>

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.
Source§

impl<T> WithSubscriber for T

Source§

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
Source§

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

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