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
identifieris 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/certificateURLs), 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: i64Implementations§
Source§impl Authorization
impl Authorization
Sourcepub fn new(
order_id: Uuid,
identifier: Identifier,
expires: i64,
) -> Authorization
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.
Sourcepub async fn insert<'e>(
&self,
executor: impl Into<Exec<'e>>,
) -> Result<(), Error>
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).
Sourcepub async fn create(
order_id: Uuid,
identifier: Identifier,
expires: i64,
database: &Database,
) -> Result<Authorization, Error>
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.
Sourcepub async fn find_by_id(
id: &str,
database: &Database,
) -> Result<Option<Authorization>, Error>
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.
Sourcepub async fn find_by_order(
order_id: Uuid,
database: &Database,
) -> Result<Vec<Authorization>, Error>
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.
Sourcepub async fn count_by_order(
order_id: Uuid,
database: &Database,
) -> Result<i64, Error>
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.
Sourcepub async fn find_ids_by_orders(
order_ids: &[Uuid],
database: &Database,
) -> Result<HashMap<Uuid, Vec<Uuid>>, Error>
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().
Sourcepub async fn find_by_order_with<'e>(
order_id: Uuid,
executor: impl Into<Exec<'e>>,
) -> Result<Vec<Authorization>, Error>
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.
Sourcepub async fn set_valid<'e>(
id: Uuid,
executor: impl Into<Exec<'e>>,
) -> Result<bool, Error>
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.
Sourcepub async fn set_invalid<'e>(
id: Uuid,
executor: impl Into<Exec<'e>>,
) -> Result<bool, Error>
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.
Sourcepub async fn set_deactivated<'e>(
id: Uuid,
executor: impl Into<Exec<'e>>,
) -> Result<bool, Error>
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.
Sourcepub async fn mark_valid(&mut self, database: &Database) -> Result<bool, Error>
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.
Sourcepub async fn mark_invalid(&mut self, database: &Database) -> Result<bool, Error>
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.
Sourcepub fn is_wildcard(&self) -> bool
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.
Sourcepub fn base_identifier(&self) -> &str
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.
Trait Implementations§
Auto Trait Implementations§
impl Freeze for Authorization
impl RefUnwindSafe for Authorization
impl Send for Authorization
impl Sync for Authorization
impl Unpin for Authorization
impl UnsafeUnpin for Authorization
impl UnwindSafe for Authorization
Blanket Implementations§
Source§impl<'a, T, E> AsTaggedExplicit<'a, E> for Twhere
T: 'a,
impl<'a, T, E> AsTaggedExplicit<'a, E> for Twhere
T: 'a,
Source§impl<'a, T, E> AsTaggedImplicit<'a, E> for Twhere
T: 'a,
impl<'a, T, E> AsTaggedImplicit<'a, E> for Twhere
T: 'a,
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<A, B, T> HttpServerConnExec<A, B> for Twhere
B: Body,
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
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 moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
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