1
0
mirror of https://github.com/matrix-org/matrix-authentication-service.git synced 2025-07-29 22:01:14 +03:00

Move storage module to its own crate

This commit is contained in:
Quentin Gliech
2021-12-17 12:15:07 +01:00
parent 584294538b
commit ceb17d3646
46 changed files with 116 additions and 71 deletions

22
Cargo.lock generated
View File

@ -1513,6 +1513,7 @@ dependencies = [
"indoc", "indoc",
"mas-config", "mas-config",
"mas-core", "mas-core",
"mas-storage",
"mas-templates", "mas-templates",
"opentelemetry", "opentelemetry",
"opentelemetry-http", "opentelemetry-http",
@ -1584,6 +1585,7 @@ dependencies = [
"mas-config", "mas-config",
"mas-data-model", "mas-data-model",
"mas-static-files", "mas-static-files",
"mas-storage",
"mas-templates", "mas-templates",
"mime", "mime",
"oauth2-types", "oauth2-types",
@ -1628,6 +1630,26 @@ dependencies = [
"warp", "warp",
] ]
[[package]]
name = "mas-storage"
version = "0.1.0"
dependencies = [
"anyhow",
"argon2",
"chrono",
"mas-data-model",
"oauth2-types",
"password-hash",
"rand",
"serde",
"sqlx",
"thiserror",
"tokio",
"tracing",
"url",
"warp",
]
[[package]] [[package]]
name = "mas-templates" name = "mas-templates"
version = "0.1.0" version = "0.1.0"

View File

@ -34,6 +34,7 @@ opentelemetry-zipkin = { version = "0.14.0", features = ["reqwest-client", "reqw
mas-config = { path = "../config" } mas-config = { path = "../config" }
mas-core = { path = "../core" } mas-core = { path = "../core" }
mas-templates = { path = "../templates" } mas-templates = { path = "../templates" }
mas-storage = { path = "../storage" }
watchman_client = "0.7.1" watchman_client = "0.7.1"
[dev-dependencies] [dev-dependencies]

View File

@ -15,7 +15,7 @@
use anyhow::Context; use anyhow::Context;
use clap::Parser; use clap::Parser;
use mas_config::DatabaseConfig; use mas_config::DatabaseConfig;
use mas_core::storage::MIGRATOR; use mas_storage::MIGRATOR;
use super::RootCommand; use super::RootCommand;

View File

@ -15,7 +15,7 @@
use argon2::Argon2; use argon2::Argon2;
use clap::Parser; use clap::Parser;
use mas_config::DatabaseConfig; use mas_config::DatabaseConfig;
use mas_core::storage::register_user; use mas_storage::user::register_user;
use tracing::{info, warn}; use tracing::{info, warn};
use super::RootCommand; use super::RootCommand;

View File

@ -22,10 +22,8 @@ use clap::Parser;
use futures::{future::TryFutureExt, stream::TryStreamExt}; use futures::{future::TryFutureExt, stream::TryStreamExt};
use hyper::{header, Server, Version}; use hyper::{header, Server, Version};
use mas_config::RootConfig; use mas_config::RootConfig;
use mas_core::{ use mas_core::tasks::{self, TaskQueue};
storage::MIGRATOR, use mas_storage::MIGRATOR;
tasks::{self, TaskQueue},
};
use mas_templates::Templates; use mas_templates::Templates;
use opentelemetry_http::HeaderExtractor; use opentelemetry_http::HeaderExtractor;
use tower::{make::Shared, ServiceBuilder}; use tower::{make::Shared, ServiceBuilder};

View File

@ -67,6 +67,7 @@ mas-config = { path = "../config" }
mas-data-model = { path = "../data-model" } mas-data-model = { path = "../data-model" }
mas-templates = { path = "../templates" } mas-templates = { path = "../templates" }
mas-static-files = { path = "../static-files" } mas-static-files = { path = "../static-files" }
mas-storage = { path = "../storage" }
[dev-dependencies] [dev-dependencies]
indoc = "1.0.3" indoc = "1.0.3"

View File

@ -17,6 +17,10 @@
use headers::{authorization::Bearer, Authorization}; use headers::{authorization::Bearer, Authorization};
use hyper::StatusCode; use hyper::StatusCode;
use mas_data_model::{AccessToken, Session}; use mas_data_model::{AccessToken, Session};
use mas_storage::{
oauth2::access_token::{lookup_active_access_token, AccessTokenLookupError},
PostgresqlBackend,
};
use sqlx::{pool::PoolConnection, PgPool, Postgres}; use sqlx::{pool::PoolConnection, PgPool, Postgres};
use thiserror::Error; use thiserror::Error;
use warp::{ use warp::{
@ -31,10 +35,6 @@ use super::{
}; };
use crate::{ use crate::{
errors::wrapped_error, errors::wrapped_error,
storage::{
oauth2::access_token::{lookup_active_access_token, AccessTokenLookupError},
PostgresqlBackend,
},
tokens::{TokenFormatError, TokenType}, tokens::{TokenFormatError, TokenType},
}; };

View File

@ -16,6 +16,10 @@
use mas_config::CookiesConfig; use mas_config::CookiesConfig;
use mas_data_model::BrowserSession; use mas_data_model::BrowserSession;
use mas_storage::{
user::{lookup_active_session, ActiveSessionLookupError},
PostgresqlBackend,
};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use sqlx::{pool::PoolConnection, Executor, PgPool, Postgres}; use sqlx::{pool::PoolConnection, Executor, PgPool, Postgres};
use thiserror::Error; use thiserror::Error;
@ -30,7 +34,6 @@ use super::{
database::connection, database::connection,
none_on_error, none_on_error,
}; };
use crate::storage::{lookup_active_session, user::ActiveSessionLookupError, PostgresqlBackend};
/// The session is missing or failed to load /// The session is missing or failed to load
#[derive(Error, Debug)] #[derive(Error, Debug)]

View File

@ -25,6 +25,16 @@ use mas_data_model::{
Authentication, AuthorizationCode, AuthorizationGrant, AuthorizationGrantStage, BrowserSession, Authentication, AuthorizationCode, AuthorizationGrant, AuthorizationGrantStage, BrowserSession,
Pkce, StorageBackend, Pkce, StorageBackend,
}; };
use mas_storage::{
oauth2::{
access_token::add_access_token,
authorization_grant::{
derive_session, fulfill_grant, get_grant_by_id, new_authorization_grant,
},
refresh_token::add_refresh_token,
},
PostgresqlBackend,
};
use mas_templates::{FormPostContext, Templates}; use mas_templates::{FormPostContext, Templates};
use oauth2_types::{ use oauth2_types::{
errors::{ errors::{
@ -58,16 +68,6 @@ use crate::{
with_templates, with_templates,
}, },
handlers::views::{LoginRequest, PostAuthAction, ReauthRequest}, handlers::views::{LoginRequest, PostAuthAction, ReauthRequest},
storage::{
oauth2::{
access_token::add_access_token,
authorization_grant::{
derive_session, fulfill_grant, get_grant_by_id, new_authorization_grant,
},
refresh_token::add_refresh_token,
},
PostgresqlBackend,
},
tokens::{AccessToken, RefreshToken}, tokens::{AccessToken, RefreshToken},
}; };

View File

@ -14,6 +14,9 @@
use hyper::Method; use hyper::Method;
use mas_config::{OAuth2ClientConfig, OAuth2Config}; use mas_config::{OAuth2ClientConfig, OAuth2Config};
use mas_storage::oauth2::{
access_token::lookup_active_access_token, refresh_token::lookup_active_refresh_token,
};
use oauth2_types::requests::{ use oauth2_types::requests::{
ClientAuthenticationMethod, IntrospectionRequest, IntrospectionResponse, TokenTypeHint, ClientAuthenticationMethod, IntrospectionRequest, IntrospectionResponse, TokenTypeHint,
}; };
@ -24,9 +27,6 @@ use warp::{Filter, Rejection, Reply};
use crate::{ use crate::{
errors::WrapError, errors::WrapError,
filters::{client::client_authentication, cors::cors, database::connection}, filters::{client::client_authentication, cors::cors, database::connection},
storage::oauth2::{
access_token::lookup_active_access_token, refresh_token::lookup_active_refresh_token,
},
tokens::{self, TokenType}, tokens::{self, TokenType},
}; };

View File

@ -20,6 +20,14 @@ use hyper::{Method, StatusCode};
use jwt_compact::{Claims, Header, TimeOptions}; use jwt_compact::{Claims, Header, TimeOptions};
use mas_config::{KeySet, OAuth2ClientConfig, OAuth2Config}; use mas_config::{KeySet, OAuth2ClientConfig, OAuth2Config};
use mas_data_model::AuthorizationGrantStage; use mas_data_model::AuthorizationGrantStage;
use mas_storage::{
oauth2::{
access_token::{add_access_token, revoke_access_token},
authorization_grant::{exchange_grant, lookup_grant_by_code},
refresh_token::{add_refresh_token, lookup_active_refresh_token, replace_refresh_token},
},
DatabaseInconsistencyError,
};
use oauth2_types::{ use oauth2_types::{
errors::{InvalidGrant, InvalidRequest, OAuth2Error, OAuth2ErrorCode, UnauthorizedClient}, errors::{InvalidGrant, InvalidRequest, OAuth2Error, OAuth2ErrorCode, UnauthorizedClient},
requests::{ requests::{
@ -45,16 +53,6 @@ use crate::{
errors::WrapError, errors::WrapError,
filters::{client::client_authentication, cors::cors, database::connection, with_keys}, filters::{client::client_authentication, cors::cors, database::connection, with_keys},
reply::with_typed_header, reply::with_typed_header,
storage::{
oauth2::{
access_token::{add_access_token, revoke_access_token},
authorization_grant::{exchange_grant, lookup_grant_by_code},
refresh_token::{
add_refresh_token, lookup_active_refresh_token, replace_refresh_token,
},
},
DatabaseInconsistencyError,
},
tokens::{AccessToken, RefreshToken}, tokens::{AccessToken, RefreshToken},
}; };

View File

@ -15,16 +15,14 @@
use hyper::Method; use hyper::Method;
use mas_config::OAuth2Config; use mas_config::OAuth2Config;
use mas_data_model::{AccessToken, Session}; use mas_data_model::{AccessToken, Session};
use mas_storage::PostgresqlBackend;
use serde::Serialize; use serde::Serialize;
use sqlx::PgPool; use sqlx::PgPool;
use warp::{Filter, Rejection, Reply}; use warp::{Filter, Rejection, Reply};
use crate::{ use crate::filters::{
filters::{ authenticate::{authentication, recover_unauthorized},
authenticate::{authentication, recover_unauthorized}, cors::cors,
cors::cors,
},
storage::PostgresqlBackend,
}; };
#[derive(Serialize)] #[derive(Serialize)]

View File

@ -15,6 +15,10 @@
use argon2::Argon2; use argon2::Argon2;
use mas_config::{CookiesConfig, CsrfConfig}; use mas_config::{CookiesConfig, CsrfConfig};
use mas_data_model::BrowserSession; use mas_data_model::BrowserSession;
use mas_storage::{
user::{authenticate_session, count_active_sessions, set_password},
PostgresqlBackend,
};
use mas_templates::{AccountContext, TemplateContext, Templates}; use mas_templates::{AccountContext, TemplateContext, Templates};
use serde::Deserialize; use serde::Deserialize;
use sqlx::{pool::PoolConnection, PgExecutor, PgPool, Postgres, Transaction}; use sqlx::{pool::PoolConnection, PgExecutor, PgPool, Postgres, Transaction};
@ -29,10 +33,6 @@ use crate::{
session::session, session::session,
with_templates, CsrfToken, with_templates, CsrfToken,
}, },
storage::{
user::{authenticate_session, count_active_sessions, set_password},
PostgresqlBackend,
},
}; };
pub(super) fn filter( pub(super) fn filter(

View File

@ -14,19 +14,17 @@
use mas_config::{CookiesConfig, CsrfConfig, OAuth2Config}; use mas_config::{CookiesConfig, CsrfConfig, OAuth2Config};
use mas_data_model::BrowserSession; use mas_data_model::BrowserSession;
use mas_storage::PostgresqlBackend;
use mas_templates::{IndexContext, TemplateContext, Templates}; use mas_templates::{IndexContext, TemplateContext, Templates};
use sqlx::PgPool; use sqlx::PgPool;
use url::Url; use url::Url;
use warp::{reply::html, Filter, Rejection, Reply}; use warp::{reply::html, Filter, Rejection, Reply};
use crate::{ use crate::filters::{
filters::{ cookies::{encrypted_cookie_saver, EncryptedCookieSaver},
cookies::{encrypted_cookie_saver, EncryptedCookieSaver}, csrf::updated_csrf_token,
csrf::updated_csrf_token, session::optional_session,
session::optional_session, with_templates, CsrfToken,
with_templates, CsrfToken,
},
storage::PostgresqlBackend,
}; };
pub(super) fn filter( pub(super) fn filter(

View File

@ -15,6 +15,7 @@
use hyper::http::uri::{Parts, PathAndQuery, Uri}; use hyper::http::uri::{Parts, PathAndQuery, Uri};
use mas_config::{CookiesConfig, CsrfConfig}; use mas_config::{CookiesConfig, CsrfConfig};
use mas_data_model::{errors::WrapFormError, BrowserSession, StorageBackend}; use mas_data_model::{errors::WrapFormError, BrowserSession, StorageBackend};
use mas_storage::{user::login, PostgresqlBackend};
use mas_templates::{LoginContext, LoginFormField, TemplateContext, Templates}; use mas_templates::{LoginContext, LoginFormField, TemplateContext, Templates};
use serde::Deserialize; use serde::Deserialize;
use sqlx::{pool::PoolConnection, PgPool, Postgres}; use sqlx::{pool::PoolConnection, PgPool, Postgres};
@ -30,7 +31,6 @@ use crate::{
session::{optional_session, SessionCookie}, session::{optional_session, SessionCookie},
with_templates, CsrfToken, with_templates, CsrfToken,
}, },
storage::{login, PostgresqlBackend},
}; };
#[derive(Deserialize)] #[derive(Deserialize)]
@ -155,7 +155,7 @@ async fn post(
form: LoginForm, form: LoginForm,
query: LoginRequest<PostgresqlBackend>, query: LoginRequest<PostgresqlBackend>,
) -> Result<Box<dyn Reply>, Rejection> { ) -> Result<Box<dyn Reply>, Rejection> {
use crate::storage::user::LoginError; use mas_storage::user::LoginError;
// TODO: recover // TODO: recover
match login(&mut conn, &form.username, form.password).await { match login(&mut conn, &form.username, form.password).await {
Ok(session_info) => { Ok(session_info) => {

View File

@ -14,13 +14,13 @@
use mas_config::CookiesConfig; use mas_config::CookiesConfig;
use mas_data_model::BrowserSession; use mas_data_model::BrowserSession;
use mas_storage::{user::end_session, PostgresqlBackend};
use sqlx::{PgPool, Postgres, Transaction}; use sqlx::{PgPool, Postgres, Transaction};
use warp::{hyper::Uri, Filter, Rejection, Reply}; use warp::{hyper::Uri, Filter, Rejection, Reply};
use crate::{ use crate::{
errors::WrapError, errors::WrapError,
filters::{csrf::protected_form, database::transaction, session::session}, filters::{csrf::protected_form, database::transaction, session::session},
storage::{user::end_session, PostgresqlBackend},
}; };
pub(super) fn filter( pub(super) fn filter(

View File

@ -15,6 +15,7 @@
use hyper::http::uri::{Parts, PathAndQuery}; use hyper::http::uri::{Parts, PathAndQuery};
use mas_config::{CookiesConfig, CsrfConfig}; use mas_config::{CookiesConfig, CsrfConfig};
use mas_data_model::{BrowserSession, StorageBackend}; use mas_data_model::{BrowserSession, StorageBackend};
use mas_storage::{user::authenticate_session, PostgresqlBackend};
use mas_templates::{ReauthContext, TemplateContext, Templates}; use mas_templates::{ReauthContext, TemplateContext, Templates};
use serde::Deserialize; use serde::Deserialize;
use sqlx::{pool::PoolConnection, PgPool, Postgres, Transaction}; use sqlx::{pool::PoolConnection, PgPool, Postgres, Transaction};
@ -30,8 +31,8 @@ use crate::{
session::session, session::session,
with_templates, CsrfToken, with_templates, CsrfToken,
}, },
storage::{user::authenticate_session, PostgresqlBackend},
}; };
#[derive(Deserialize)] #[derive(Deserialize)]
#[serde(bound(deserialize = "S::AuthorizationGrantData: std::str::FromStr, #[serde(bound(deserialize = "S::AuthorizationGrantData: std::str::FromStr,
<S::AuthorizationGrantData as std::str::FromStr>::Err: std::fmt::Display"))] <S::AuthorizationGrantData as std::str::FromStr>::Err: std::fmt::Display"))]

View File

@ -16,6 +16,10 @@ use argon2::Argon2;
use hyper::http::uri::{Parts, PathAndQuery, Uri}; use hyper::http::uri::{Parts, PathAndQuery, Uri};
use mas_config::{CookiesConfig, CsrfConfig}; use mas_config::{CookiesConfig, CsrfConfig};
use mas_data_model::{BrowserSession, StorageBackend}; use mas_data_model::{BrowserSession, StorageBackend};
use mas_storage::{
user::{register_user, start_session},
PostgresqlBackend,
};
use mas_templates::{RegisterContext, TemplateContext, Templates}; use mas_templates::{RegisterContext, TemplateContext, Templates};
use serde::Deserialize; use serde::Deserialize;
use sqlx::{pool::PoolConnection, PgPool, Postgres, Transaction}; use sqlx::{pool::PoolConnection, PgPool, Postgres, Transaction};
@ -31,7 +35,6 @@ use crate::{
session::{optional_session, SessionCookie}, session::{optional_session, SessionCookie},
with_templates, CsrfToken, with_templates, CsrfToken,
}, },
storage::{register_user, user::start_session, PostgresqlBackend},
}; };
#[derive(Deserialize)] #[derive(Deserialize)]

View File

@ -14,12 +14,12 @@
use hyper::Uri; use hyper::Uri;
use mas_data_model::StorageBackend; use mas_data_model::StorageBackend;
use mas_storage::PostgresqlBackend;
use mas_templates::PostAuthContext; use mas_templates::PostAuthContext;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use sqlx::PgExecutor; use sqlx::PgExecutor;
use super::super::oauth2::ContinueAuthorizationGrant; use super::super::oauth2::ContinueAuthorizationGrant;
use crate::storage::PostgresqlBackend;
#[derive(Deserialize, Serialize, Clone)] #[derive(Deserialize, Serialize, Clone)]
#[serde(rename_all = "snake_case", tag = "next")] #[serde(rename_all = "snake_case", tag = "next")]

View File

@ -25,7 +25,6 @@ pub mod errors;
pub mod filters; pub mod filters;
pub mod handlers; pub mod handlers;
pub mod reply; pub mod reply;
pub mod storage;
pub mod tasks; pub mod tasks;
pub mod tokens; pub mod tokens;

View File

@ -29,7 +29,7 @@ impl std::fmt::Debug for CleanupExpired {
#[async_trait::async_trait] #[async_trait::async_trait]
impl Task for CleanupExpired { impl Task for CleanupExpired {
async fn run(&self) { async fn run(&self) {
let res = crate::storage::oauth2::access_token::cleanup_expired(&self.0).await; let res = mas_storage::oauth2::access_token::cleanup_expired(&self.0).await;
match res { match res {
Ok(0) => { Ok(0) => {
debug!("no token to clean up"); debug!("no token to clean up");

25
crates/storage/Cargo.toml Normal file
View File

@ -0,0 +1,25 @@
[package]
name = "mas-storage"
version = "0.1.0"
authors = ["Quentin Gliech <quenting@element.io>"]
edition = "2021"
license = "Apache-2.0"
[dependencies]
tokio = "1.14.0"
sqlx = { version = "0.5.9", features = ["runtime-tokio-rustls", "postgres", "migrate", "chrono", "offline"] }
chrono = { version = "0.4.19", features = ["serde"] }
serde = { version = "1.0.131", features = ["derive"] }
thiserror = "1.0.30"
anyhow = "1.0.51"
tracing = "0.1.29"
warp = "0.3.2"
# Password hashing
argon2 = { version = "0.3.2", features = ["password-hash"] }
password-hash = { version = "0.3.2", features = ["std"] }
rand = "0.8.4"
url = { version = "2.2.2", features = ["serde"] }
oauth2-types = { path = "../oauth2-types", features = ["sqlx_type"] }
mas-data-model = { path = "../data-model" }

View File

@ -47,10 +47,8 @@ struct IdAndCreationTime {
created_at: DateTime<Utc>, created_at: DateTime<Utc>,
} }
pub(crate) mod oauth2; pub mod oauth2;
pub(crate) mod user; pub mod user;
pub use self::user::{login, lookup_active_session, register_user};
/// Embedded migrations, allowing them to run on startup /// Embedded migrations, allowing them to run on startup
pub static MIGRATOR: Migrator = sqlx::migrate!(); pub static MIGRATOR: Migrator = sqlx::migrate!();

View File

@ -18,7 +18,7 @@ use mas_data_model::{AccessToken, Authentication, BrowserSession, Client, Sessio
use sqlx::PgExecutor; use sqlx::PgExecutor;
use thiserror::Error; use thiserror::Error;
use crate::storage::{DatabaseInconsistencyError, IdAndCreationTime, PostgresqlBackend}; use crate::{DatabaseInconsistencyError, IdAndCreationTime, PostgresqlBackend};
pub async fn add_access_token( pub async fn add_access_token(
executor: impl PgExecutor<'_>, executor: impl PgExecutor<'_>,

View File

@ -26,7 +26,7 @@ use oauth2_types::{pkce::CodeChallengeMethod, requests::ResponseMode, scope::Sco
use sqlx::PgExecutor; use sqlx::PgExecutor;
use url::Url; use url::Url;
use crate::storage::{DatabaseInconsistencyError, IdAndCreationTime, PostgresqlBackend}; use crate::{DatabaseInconsistencyError, IdAndCreationTime, PostgresqlBackend};
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]
pub async fn new_authorization_grant( pub async fn new_authorization_grant(

View File

@ -12,6 +12,6 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
pub(crate) mod access_token; pub mod access_token;
pub(crate) mod authorization_grant; pub mod authorization_grant;
pub(crate) mod refresh_token; pub mod refresh_token;

View File

@ -19,7 +19,7 @@ use mas_data_model::{
}; };
use sqlx::PgExecutor; use sqlx::PgExecutor;
use crate::storage::{DatabaseInconsistencyError, IdAndCreationTime, PostgresqlBackend}; use crate::{DatabaseInconsistencyError, IdAndCreationTime, PostgresqlBackend};
pub async fn add_refresh_token( pub async fn add_refresh_token(
executor: impl PgExecutor<'_>, executor: impl PgExecutor<'_>,

View File

@ -27,7 +27,7 @@ use tracing::{info_span, Instrument};
use warp::reject::Reject; use warp::reject::Reject;
use super::{DatabaseInconsistencyError, PostgresqlBackend}; use super::{DatabaseInconsistencyError, PostgresqlBackend};
use crate::storage::IdAndCreationTime; use crate::IdAndCreationTime;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
struct UserLookup { struct UserLookup {