1
0
mirror of https://github.com/matrix-org/matrix-authentication-service.git synced 2025-07-31 09:24:31 +03:00

Loads of docs & enabling more clippy lints

This commit is contained in:
Quentin Gliech
2022-02-01 12:02:32 +01:00
parent dd7449b92e
commit a45381828c
28 changed files with 188 additions and 51 deletions

View File

@ -16,7 +16,6 @@
#![deny(clippy::all)]
#![warn(clippy::pedantic)]
#![allow(clippy::module_name_repetitions)]
#![allow(clippy::suspicious_else_formatting)]
use std::path::PathBuf;

View File

@ -13,13 +13,14 @@
// limitations under the License.
#![forbid(unsafe_code)]
#![deny(clippy::all)]
#![deny(missing_docs)]
#![deny(rustdoc::broken_intra_doc_links)]
#![deny(
clippy::all,
missing_docs,
rustdoc::missing_crate_level_docs,
rustdoc::broken_intra_doc_links
)]
#![warn(clippy::pedantic)]
#![allow(clippy::module_name_repetitions)]
#![allow(clippy::missing_panics_doc)]
#![allow(clippy::missing_errors_doc)]
//! Application configuration logic

View File

@ -51,6 +51,10 @@ impl Encrypter {
}
/// Encrypt a payload
///
/// # Errors
///
/// Will return `Err` when the payload failed to encrypt
pub fn encrypt(&self, nonce: &[u8; 12], decrypted: &[u8]) -> anyhow::Result<Vec<u8>> {
let nonce = GenericArray::from_slice(&nonce[..]);
let encrypted = self.aead.encrypt(nonce, decrypted)?;
@ -58,6 +62,10 @@ impl Encrypter {
}
/// Decrypts a payload
///
/// # Errors
///
/// Will return `Err` when the payload failed to decrypt
pub fn decrypt(&self, nonce: &[u8; 12], encrypted: &[u8]) -> anyhow::Result<Vec<u8>> {
let nonce = GenericArray::from_slice(&nonce[..]);
let encrypted = self.aead.decrypt(nonce, encrypted)?;
@ -110,6 +118,10 @@ pub struct SecretsConfig {
impl SecretsConfig {
/// Derive a signing and verifying keystore out of the config
///
/// # Errors
///
/// Returns an error when a key could not be imported
pub async fn key_store(&self) -> anyhow::Result<StaticKeystore> {
let mut store = StaticKeystore::new();

View File

@ -13,13 +13,14 @@
// limitations under the License.
#![forbid(unsafe_code)]
#![deny(clippy::all)]
#![deny(rustdoc::broken_intra_doc_links)]
#![deny(clippy::all, rustdoc::broken_intra_doc_links)]
#![warn(clippy::pedantic)]
#![allow(clippy::module_name_repetitions)]
#![allow(clippy::missing_panics_doc)]
#![allow(clippy::missing_errors_doc)]
#![allow(clippy::trait_duplication_in_bounds)]
#![allow(
clippy::module_name_repetitions,
clippy::missing_panics_doc,
clippy::missing_errors_doc,
clippy::trait_duplication_in_bounds
)]
pub mod errors;
pub(crate) mod oauth2;

View File

@ -12,6 +12,12 @@
// See the License for the specific language governing permissions and
// limitations under the License.
//! Helps sending emails to users, with different email backends
#![forbid(unsafe_code)]
#![deny(clippy::all, missing_docs, rustdoc::broken_intra_doc_links)]
#![warn(clippy::pedantic)]
mod mailer;
mod transport;

View File

@ -12,6 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
//! Send emails to users
use lettre::{
message::{Mailbox, MessageBuilder, MultiPart},
AsyncTransport, Message,
@ -20,6 +22,7 @@ use mas_templates::{EmailVerificationContext, Templates};
use crate::MailTransport;
/// Helps sending mails to users
#[derive(Clone)]
pub struct Mailer {
templates: Templates,
@ -29,6 +32,8 @@ pub struct Mailer {
}
impl Mailer {
/// Constructs a new [`Mailer`]
#[must_use]
pub fn new(
templates: &Templates,
transport: &MailTransport,
@ -76,6 +81,11 @@ impl Mailer {
Ok(message)
}
/// Send the verification email to a user
///
/// # Errors
///
/// Will return `Err` if the email failed rendering or failed sending
pub async fn send_verification_email(
&self,
to: Mailbox,

View File

@ -19,16 +19,21 @@ use aws_sdk_sesv2::{
};
use lettre::{address::Envelope, AsyncTransport};
/// An asynchronous email transport that sends email via the AWS Simple Email
/// Service v2 API
pub struct Transport {
client: Client,
}
impl Transport {
/// Construct a [`Transport`] from the environment
pub async fn from_env() -> Self {
let config = aws_config::from_env().load().await;
Self::new(&config)
}
/// Constructs a [`Transport`] from a given AWS shared config
#[must_use]
pub fn new(config: &aws_config::Config) -> Self {
let client = Client::new(config);
Self { client }

View File

@ -12,6 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
//! Email transport backends
use std::sync::Arc;
use async_trait::async_trait;
@ -27,6 +29,7 @@ use mas_config::{EmailSmtpMode, EmailTransportConfig};
pub mod aws_ses;
/// A wrapper around many [`AsyncTransport`]s
#[derive(Default, Clone)]
pub struct Transport {
inner: Arc<TransportInner>,
@ -40,6 +43,11 @@ enum TransportInner {
}
impl Transport {
/// Construct a transport from a user configration
///
/// # Errors
///
/// Will return `Err` on invalid confiuration
pub async fn from_config(config: &EmailTransportConfig) -> Result<Self, anyhow::Error> {
let inner = match config {
EmailTransportConfig::Blackhole => TransportInner::Blackhole,
@ -85,14 +93,19 @@ impl Transport {
}
impl Transport {
/// Test the connection to the underlying transport. Only works with the
/// SMTP backend for now
///
/// # Errors
///
/// Will return `Err` if the connection test failed
pub async fn test_connection(&self) -> anyhow::Result<()> {
match self.inner.as_ref() {
TransportInner::Blackhole => {}
TransportInner::Smtp(t) => {
t.test_connection().await?;
}
&TransportInner::Sendmail(_) => {}
TransportInner::AwsSes(_) => {}
TransportInner::Blackhole | TransportInner::Sendmail(_) | TransportInner::AwsSes(_) => {
}
}
Ok(())

View File

@ -13,14 +13,11 @@
// limitations under the License.
#![forbid(unsafe_code)]
#![deny(clippy::all)]
#![deny(rustdoc::broken_intra_doc_links)]
#![deny(clippy::all, rustdoc::broken_intra_doc_links)]
#![warn(clippy::pedantic)]
#![allow(clippy::module_name_repetitions)]
#![allow(clippy::missing_panics_doc)]
#![allow(clippy::missing_errors_doc)]
#![allow(clippy::implicit_hasher)]
#![allow(clippy::unused_async)] // Some warp filters need that
#![allow(
clippy::unused_async // Some warp filters need that
)]
use std::sync::Arc;

View File

@ -40,7 +40,7 @@ use warp::{filters::BoxedFilter, reply::html, Filter, Rejection, Reply};
use super::{LoginRequest, PostAuthAction};
#[derive(Deserialize)]
pub struct RegisterRequest {
pub(crate) struct RegisterRequest {
#[serde(flatten)]
post_auth_action: Option<PostAuthAction>,
}

View File

@ -13,8 +13,7 @@
// limitations under the License.
#![forbid(unsafe_code)]
#![deny(clippy::all)]
#![deny(rustdoc::broken_intra_doc_links)]
#![deny(clippy::all, rustdoc::broken_intra_doc_links)]
#![warn(clippy::pedantic)]
use std::{collections::HashMap, fmt::Display, path::PathBuf, sync::Arc};
@ -135,6 +134,8 @@ pub enum {} {{"#,
writeln!(f)?;
if let Some(description) = &member.description {
writeln!(f, " /// {}", description)?;
} else {
writeln!(f, " /// `{}`", member.value)?;
}
writeln!(f, " #[serde(rename = \"{}\")]", member.value)?;
writeln!(f, " #[display(\"{}\")]", member.value)?;

View File

@ -12,9 +12,10 @@
// See the License for the specific language governing permissions and
// limitations under the License.
//! Values from IANA registries, generated by the `mas-iana-codegen` crate
#![forbid(unsafe_code)]
#![deny(clippy::all)]
#![deny(rustdoc::broken_intra_doc_links)]
#![deny(clippy::all, missing_docs, rustdoc::broken_intra_doc_links)]
#![warn(clippy::pedantic)]
#![allow(clippy::module_name_repetitions)]

View File

@ -28,14 +28,17 @@ use serde::{Deserialize, Serialize};
Debug, Clone, Copy, PartialEq, Eq, Hash, Display, FromStr, Serialize, Deserialize, JsonSchema,
)]
pub enum OAuthAccessTokenType {
/// `Bearer`
#[serde(rename = "Bearer")]
#[display("Bearer")]
Bearer,
/// `N_A`
#[serde(rename = "N_A")]
#[display("N_A")]
Na,
/// `PoP`
#[serde(rename = "PoP")]
#[display("PoP")]
PoP,
@ -48,34 +51,42 @@ pub enum OAuthAccessTokenType {
Debug, Clone, Copy, PartialEq, Eq, Hash, Display, FromStr, Serialize, Deserialize, JsonSchema,
)]
pub enum OAuthAuthorizationEndpointResponseType {
/// `code`
#[serde(rename = "code")]
#[display("code")]
Code,
/// `code id_token`
#[serde(rename = "code id_token")]
#[display("code id_token")]
CodeIdToken,
/// `code id_token token`
#[serde(rename = "code id_token token")]
#[display("code id_token token")]
CodeIdTokenToken,
/// `code token`
#[serde(rename = "code token")]
#[display("code token")]
CodeToken,
/// `id_token`
#[serde(rename = "id_token")]
#[display("id_token")]
IdToken,
/// `id_token token`
#[serde(rename = "id_token token")]
#[display("id_token token")]
IdTokenToken,
/// `none`
#[serde(rename = "none")]
#[display("none")]
None,
/// `token`
#[serde(rename = "token")]
#[display("token")]
Token,
@ -88,14 +99,17 @@ pub enum OAuthAuthorizationEndpointResponseType {
Debug, Clone, Copy, PartialEq, Eq, Hash, Display, FromStr, Serialize, Deserialize, JsonSchema,
)]
pub enum OAuthTokenTypeHint {
/// `access_token`
#[serde(rename = "access_token")]
#[display("access_token")]
AccessToken,
/// `refresh_token`
#[serde(rename = "refresh_token")]
#[display("refresh_token")]
RefreshToken,
/// `pct`
#[serde(rename = "pct")]
#[display("pct")]
Pct,
@ -108,30 +122,37 @@ pub enum OAuthTokenTypeHint {
Debug, Clone, Copy, PartialEq, Eq, Hash, Display, FromStr, Serialize, Deserialize, JsonSchema,
)]
pub enum OAuthClientAuthenticationMethod {
/// `none`
#[serde(rename = "none")]
#[display("none")]
None,
/// `client_secret_post`
#[serde(rename = "client_secret_post")]
#[display("client_secret_post")]
ClientSecretPost,
/// `client_secret_basic`
#[serde(rename = "client_secret_basic")]
#[display("client_secret_basic")]
ClientSecretBasic,
/// `client_secret_jwt`
#[serde(rename = "client_secret_jwt")]
#[display("client_secret_jwt")]
ClientSecretJwt,
/// `private_key_jwt`
#[serde(rename = "private_key_jwt")]
#[display("private_key_jwt")]
PrivateKeyJwt,
/// `tls_client_auth`
#[serde(rename = "tls_client_auth")]
#[display("tls_client_auth")]
TlsClientAuth,
/// `self_signed_tls_client_auth`
#[serde(rename = "self_signed_tls_client_auth")]
#[display("self_signed_tls_client_auth")]
SelfSignedTlsClientAuth,
@ -144,10 +165,12 @@ pub enum OAuthClientAuthenticationMethod {
Debug, Clone, Copy, PartialEq, Eq, Hash, Display, FromStr, Serialize, Deserialize, JsonSchema,
)]
pub enum PkceCodeChallengeMethod {
/// `plain`
#[serde(rename = "plain")]
#[display("plain")]
Plain,
/// `S256`
#[serde(rename = "S256")]
#[display("S256")]
S256,

View File

@ -13,11 +13,9 @@
// limitations under the License.
#![forbid(unsafe_code)]
#![deny(clippy::all)]
#![deny(rustdoc::broken_intra_doc_links)]
#![deny(clippy::all, rustdoc::broken_intra_doc_links)]
#![warn(clippy::pedantic)]
#![allow(clippy::missing_errors_doc)]
#![allow(clippy::module_name_repetitions)]
#![allow(clippy::missing_errors_doc, clippy::module_name_repetitions)]
pub mod claims;
pub(crate) mod jwk;

View File

@ -13,7 +13,7 @@
// limitations under the License.
#![forbid(unsafe_code)]
#![deny(clippy::all)]
#![deny(clippy::all, rustdoc::broken_intra_doc_links)]
#![warn(clippy::pedantic)]
use mas_iana::oauth::OAuthAuthorizationEndpointResponseType;

View File

@ -198,7 +198,7 @@ pub struct Metadata {
// TODO: type
/// Languages and scripts supported for values in Claims being returned,
/// represented as a JSON array of BCP 47 [RFC5646] language tag values.
/// represented as a JSON array of BCP 47 language tag values.
pub claims_locales_supported: Option<HashSet<String>>,
/// Boolean value specifying whether the OP supports use of the "claims"

View File

@ -12,14 +12,11 @@
// See the License for the specific language governing permissions and
// limitations under the License.
//! Serve static files used by the web frontend
#![forbid(unsafe_code)]
#![deny(clippy::all)]
#![deny(rustdoc::broken_intra_doc_links)]
#![deny(clippy::all, missing_docs, rustdoc::broken_intra_doc_links)]
#![warn(clippy::pedantic)]
#![allow(clippy::module_name_repetitions)]
#![allow(clippy::missing_panics_doc)]
#![allow(clippy::missing_errors_doc)]
#![allow(clippy::unused_async)]
use std::path::PathBuf;
@ -40,6 +37,7 @@ mod builtin {
#[folder = "public/"]
struct Asset;
#[allow(clippy::unused_async)]
async fn serve_embed(
path: Tail,
if_none_match: Option<String>,
@ -101,6 +99,7 @@ fn filter_for_path(path: PathBuf) -> BoxedFilter<(impl Reply,)> {
warp::fs::dir(path).boxed()
}
/// [`warp`] filter that serves static files
#[must_use]
pub fn filter(path: Option<PathBuf>) -> BoxedFilter<(Box<dyn Reply>,)> {
let f = self::builtin::filter();

View File

@ -14,7 +14,14 @@
//! Interactions with the database
#![allow(clippy::used_underscore_binding)] // This is needed by sqlx macros
#![forbid(unsafe_code)]
#![deny(clippy::all, rustdoc::broken_intra_doc_links)]
#![warn(clippy::pedantic)]
#![allow(
clippy::missing_errors_doc,
clippy::missing_panics_doc,
clippy::module_name_repetitions
)]
use chrono::{DateTime, Utc};
use mas_data_model::{StorageBackend, StorageBackendMarker};

View File

@ -93,6 +93,7 @@ impl AccessTokenLookupError {
}
}
#[allow(clippy::too_many_lines)]
pub async fn lookup_active_access_token(
executor: impl PgExecutor<'_>,
token: &str,

View File

@ -12,6 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
//! Database-related tasks
use sqlx::{Pool, Postgres};
use tracing::{debug, error, info};
@ -44,6 +46,7 @@ impl Task for CleanupExpired {
}
}
/// Cleanup expired tokens
#[must_use]
pub fn cleanup_expired(pool: &Pool<Postgres>) -> impl Task + Clone {
CleanupExpired(pool.clone())

View File

@ -18,6 +18,10 @@
//! resources and avoid database conflicts. Tasks are not persisted, which is
//! considered "good enough" for now.
#![forbid(unsafe_code)]
#![deny(clippy::all, missing_docs, rustdoc::broken_intra_doc_links)]
#![warn(clippy::pedantic)]
use std::{collections::VecDeque, sync::Arc, time::Duration};
use futures_util::StreamExt;
@ -32,8 +36,10 @@ mod database;
pub use self::database::cleanup_expired;
/// A [`Task`] can be executed by a [`TaskQueue`]
#[async_trait::async_trait]
pub trait Task: std::fmt::Debug + Send + Sync + 'static {
/// Execute the [`Task`]
async fn run(&self);
}
@ -81,12 +87,14 @@ impl TaskQueueInner {
}
}
/// A [`TaskQueue`] executes tasks inserted in it in order
#[derive(Default)]
pub struct TaskQueue {
inner: Arc<TaskQueueInner>,
}
impl TaskQueue {
/// Start the task queue to run forever
pub fn start(&self) {
let queue = self.inner.clone();
tokio::task::spawn(async move {
@ -100,6 +108,7 @@ impl TaskQueue {
queue.schedule(task).await;
}
/// Schedule a task in the queue at regular intervals
pub fn recuring(&self, every: Duration, task: impl Task + Clone + std::fmt::Debug) {
debug!(?task, period = every.as_secs(), "Scheduling recuring task");
let queue = self.inner.clone();

View File

@ -197,6 +197,8 @@ pub struct IndexContext {
}
impl IndexContext {
/// Constructs the context for the index page from the OIDC discovery
/// document URL
#[must_use]
pub fn new(discovery_url: Url) -> Self {
Self { discovery_url }
@ -216,10 +218,14 @@ impl TemplateContext for IndexContext {
}
}
/// Fields of the login form
#[derive(Serialize, Debug, Clone, Copy, Hash, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]
pub enum LoginFormField {
/// The username field
Username,
/// The password field
Password,
}
@ -227,7 +233,11 @@ pub enum LoginFormField {
#[derive(Serialize)]
#[serde(tag = "kind", rename_all = "snake_case")]
pub enum PostAuthContext {
ContinueAuthorizationGrant { grant: AuthorizationGrant<()> },
/// Continue an authorization grant
ContinueAuthorizationGrant {
/// The authorization grant that will be continued after authentication
grant: AuthorizationGrant<()>,
},
}
/// Context used by the `login.html` template
@ -253,11 +263,13 @@ impl TemplateContext for LoginContext {
}
impl LoginContext {
/// Add an error on the login form
#[must_use]
pub fn with_form_error(self, form: ErroredForm<LoginFormField>) -> Self {
Self { form, ..self }
}
/// Add a post authentication action to the context
#[must_use]
pub fn with_post_action(self, next: PostAuthContext) -> Self {
Self {
@ -266,6 +278,7 @@ impl LoginContext {
}
}
/// Add a registration link to the context
#[must_use]
pub fn with_register_link(self, register_link: String) -> Self {
Self {
@ -285,11 +298,17 @@ impl Default for LoginContext {
}
}
/// Fields of the registration form
#[derive(Serialize, Debug, Clone, Copy, Hash, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]
pub enum RegisterFormField {
/// The username field
Username,
/// The password field
Password,
/// The password confirmation field
PasswordConfirm,
}
@ -316,11 +335,13 @@ impl TemplateContext for RegisterContext {
}
impl RegisterContext {
/// Add an error on the registration form
#[must_use]
pub fn with_form_error(self, form: ErroredForm<LoginFormField>) -> Self {
Self { form, ..self }
}
/// Add a post authentication action to the context
#[must_use]
pub fn with_post_action(self, next: PostAuthContext) -> Self {
Self {
@ -329,6 +350,7 @@ impl RegisterContext {
}
}
/// Add a login link to the context
#[must_use]
pub fn with_login_link(self, login_link: String) -> Self {
Self { login_link, ..self }
@ -345,9 +367,11 @@ impl Default for RegisterContext {
}
}
/// Fields of the reauthentication form
#[derive(Serialize, Debug, Clone, Copy, Hash, PartialEq, Eq)]
#[serde(rename_all = "kebab-case")]
pub enum ReauthFormField {
/// The password field
Password,
}
@ -365,11 +389,13 @@ impl TemplateContext for ReauthContext {
}
impl ReauthContext {
/// Add an error on the reauthentication form
#[must_use]
pub fn with_form_error(self, form: ErroredForm<ReauthFormField>) -> Self {
Self { form, ..self }
}
/// Add a post authentication action to the context
#[must_use]
pub fn with_post_action(self, next: PostAuthContext) -> Self {
Self {
@ -403,6 +429,7 @@ pub struct AccountContext {
}
impl AccountContext {
/// Constructs a context for the "my account" page
#[must_use]
pub fn new<T>(active_sessions: usize, emails: Vec<T>) -> Self
where
@ -433,6 +460,7 @@ pub struct AccountEmailsContext<T: StorageBackend> {
}
impl<T: StorageBackend> AccountEmailsContext<T> {
/// Constructs a context for the email management page
#[must_use]
pub fn new(emails: Vec<UserEmail<T>>) -> Self {
Self { emails }
@ -457,6 +485,7 @@ pub struct EmailVerificationContext {
}
impl EmailVerificationContext {
/// Constructs a context for the verification email
#[must_use]
pub fn new(user: User<()>, verification_link: Url) -> Self {
Self {
@ -507,6 +536,7 @@ impl<T: TemplateContext> TemplateContext for FormPostContext<T> {
}
impl<T> FormPostContext<T> {
/// Constructs a context for the `form_post` response mode form
pub fn new(redirect_uri: Url, params: T) -> Self {
Self {
redirect_uri,
@ -540,23 +570,27 @@ impl TemplateContext for ErrorContext {
}
impl ErrorContext {
/// Constructs a context for the error page
#[must_use]
pub fn new() -> Self {
Self::default()
}
/// Add the error code to the context
#[must_use]
pub fn with_code(mut self, code: &'static str) -> Self {
self.code = Some(code);
self
}
/// Add the error description to the context
#[must_use]
pub fn with_description(mut self, description: String) -> Self {
self.description = Some(description);
self
}
/// Add the error details to the context
#[allow(dead_code)]
#[must_use]
pub fn with_details(mut self, details: String) -> Self {

View File

@ -13,13 +13,9 @@
// limitations under the License.
#![forbid(unsafe_code)]
#![deny(missing_docs)]
#![deny(clippy::all)]
#![deny(rustdoc::broken_intra_doc_links)]
#![deny(clippy::all, missing_docs, rustdoc::broken_intra_doc_links)]
#![warn(clippy::pedantic)]
#![allow(clippy::module_name_repetitions)]
#![allow(clippy::missing_panics_doc)]
#![allow(clippy::missing_errors_doc)]
#![allow(clippy::module_name_repetitions, clippy::missing_errors_doc)]
//! Templates rendering
@ -40,7 +36,6 @@ use thiserror::Error;
use tokio::{fs::OpenOptions, io::AsyncWriteExt, sync::RwLock, task::JoinError};
use tracing::{debug, info, warn};
#[allow(missing_docs)] // TODO
mod context;
mod functions;

View File

@ -12,6 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
//! Helper to deal with various unstructured errors in application code
use warp::{reject::Reject, Rejection};
#[derive(Debug)]
@ -19,11 +21,14 @@ pub(crate) struct WrappedError(anyhow::Error);
impl warp::reject::Reject for WrappedError {}
/// Wrap any error in a [`Rejection`]
pub fn wrapped_error<T: Into<anyhow::Error>>(e: T) -> impl Reject {
WrappedError(e.into())
}
/// Extension trait that wraps errors in [`Rejection`]s
pub trait WrapError<T> {
/// Wrap transform the [`Result`] error type to a [`Rejection`]
fn wrap_error(self) -> Result<T, Rejection>;
}

View File

@ -94,6 +94,7 @@ enum ClientAuthenticationError {
impl Reject for ClientAuthenticationError {}
#[allow(clippy::too_many_lines)]
async fn authenticate_client<T>(
clients_config: ClientsConfig,
audience: String,

View File

@ -134,12 +134,12 @@ where
warp::cookie::cookie(T::cookie_key()).and_then(move |value: String| {
let encrypter = encrypter.clone();
async move {
let encrypted =
let encrypted_payload =
EncryptedCookie::from_cookie_value(&value).map_err(decryption_error::<T>)?;
let decrypted = encrypted
let decrypted_payload = encrypted_payload
.decrypt(&encrypter)
.map_err(decryption_error::<T>)?;
Ok::<_, Rejection>(decrypted)
Ok::<_, Rejection>(decrypted_payload)
}
})
}

View File

@ -37,11 +37,13 @@ pub struct UrlBuilder {
impl UrlBuilder {
/// OIDC issuer
#[must_use]
pub fn oidc_issuer(&self) -> Url {
self.base.clone()
}
/// OIDC dicovery document URL
#[must_use]
pub fn oidc_discovery(&self) -> Url {
self.base
.join(".well-known/openid-configuration")
@ -49,31 +51,37 @@ impl UrlBuilder {
}
/// OAuth 2.0 authorization endpoint
#[must_use]
pub fn oauth_authorization_endpoint(&self) -> Url {
self.base.join("oauth2/authorize").expect("build URL")
}
/// OAuth 2.0 token endpoint
#[must_use]
pub fn oauth_token_endpoint(&self) -> Url {
self.base.join("oauth2/token").expect("build URL")
}
/// OAuth 2.0 introspection endpoint
#[must_use]
pub fn oauth_introspection_endpoint(&self) -> Url {
self.base.join("oauth2/introspect").expect("build URL")
}
/// OAuth 2.0 introspection endpoint
#[must_use]
pub fn oidc_userinfo_endpoint(&self) -> Url {
self.base.join("oauth2/userinfo").expect("build URL")
}
/// JWKS URI
#[must_use]
pub fn jwks_uri(&self) -> Url {
self.base.join("oauth2/keys.json").expect("build URL")
}
/// Email verification URL
#[must_use]
pub fn email_verification(&self, code: &str) -> Url {
self.base
.join("verify")
@ -84,6 +92,7 @@ impl UrlBuilder {
}
/// Injects an [`UrlBuilder`] to help building absolute URLs
#[must_use]
pub fn url_builder(
config: &HttpConfig,
) -> impl Filter<Extract = (UrlBuilder,), Error = Infallible> + Clone + Send + Sync + 'static {

View File

@ -12,6 +12,13 @@
// See the License for the specific language governing permissions and
// limitations under the License.
//! Various warp filters and replies
#![forbid(unsafe_code)]
#![deny(clippy::all, missing_docs, rustdoc::broken_intra_doc_links)]
#![warn(clippy::pedantic)]
#![allow(clippy::module_name_repetitions, clippy::missing_errors_doc)]
pub mod errors;
pub mod filters;
pub mod reply;