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

Axum migration: /verify route

This commit is contained in:
Quentin Gliech
2022-03-28 10:03:30 +02:00
parent 6fb4d27046
commit b4d0906e75
3 changed files with 36 additions and 58 deletions

View File

@ -95,6 +95,7 @@ where
"/register",
get(self::views::register::get).post(self::views::register::post),
)
.route("/verify/:code", get(self::views::verify::get))
.fallback(mas_static_files::Assets)
.layer(Extension(pool.clone()))
.layer(Extension(templates.clone()))

View File

@ -27,7 +27,7 @@ pub mod register;
pub mod shared;
pub mod verify;
use self::{account::filter as account, verify::filter as verify};
use self::account::filter as account;
pub(crate) use self::{
login::LoginRequest, reauth::ReauthRequest, register::RegisterRequest, shared::PostAuthAction,
};
@ -41,7 +41,6 @@ pub(super) fn filter(
csrf_config: &CsrfConfig,
) -> BoxedFilter<(Box<dyn Reply>,)> {
let account = account(pool, templates, mailer, encrypter, http_config, csrf_config);
let verify = verify(pool, templates, encrypter, csrf_config);
account.or(verify).unify().boxed()
account.boxed()
}

View File

@ -12,81 +12,59 @@
// See the License for the specific language governing permissions and
// limitations under the License.
use axum::{
extract::{Extension, Path},
response::{Html, IntoResponse},
};
use chrono::Duration;
use mas_config::{CsrfConfig, Encrypter};
use mas_data_model::BrowserSession;
use mas_storage::{
user::{
consume_email_verification, lookup_user_email_verification_code,
mark_user_email_as_verified,
},
PostgresqlBackend,
use mas_axum_utils::{csrf::CsrfExt, fancy_error, FancyError, PrivateCookieJar, SessionInfoExt};
use mas_config::Encrypter;
use mas_storage::user::{
consume_email_verification, lookup_user_email_verification_code, mark_user_email_as_verified,
};
use mas_templates::{EmptyContext, TemplateContext, Templates};
use mas_warp_utils::{
errors::WrapError,
filters::{
self,
cookies::{encrypted_cookie_saver, EncryptedCookieSaver},
csrf::updated_csrf_token,
database::transaction,
session::optional_session,
with_templates, CsrfToken,
},
};
use sqlx::{PgPool, Postgres, Transaction};
use warp::{filters::BoxedFilter, reply::html, Filter, Rejection, Reply};
use sqlx::PgPool;
pub(super) fn filter(
pool: &PgPool,
templates: &Templates,
encrypter: &Encrypter,
csrf_config: &CsrfConfig,
) -> BoxedFilter<(Box<dyn Reply>,)> {
warp::path!("verify" / String)
.and(filters::trace::name("GET /verify"))
.and(warp::get())
.and(with_templates(templates))
.and(encrypted_cookie_saver(encrypter))
.and(updated_csrf_token(encrypter, csrf_config))
.and(optional_session(pool, encrypter))
.and(transaction(pool))
.and_then(get)
.boxed()
}
pub(crate) async fn get(
Extension(templates): Extension<Templates>,
Extension(pool): Extension<PgPool>,
Path(code): Path<String>,
cookie_jar: PrivateCookieJar<Encrypter>,
) -> Result<impl IntoResponse, FancyError> {
let mut txn = pool.begin().await.map_err(fancy_error(templates.clone()))?;
async fn get(
code: String,
templates: Templates,
cookie_saver: EncryptedCookieSaver,
csrf_token: CsrfToken,
maybe_session: Option<BrowserSession<PostgresqlBackend>>,
mut txn: Transaction<'_, Postgres>,
) -> Result<Box<dyn Reply>, Rejection> {
// TODO: make those 8 hours configurable
let verification = lookup_user_email_verification_code(&mut txn, &code, Duration::hours(8))
.await
.wrap_error()?;
.map_err(fancy_error(templates.clone()))?;
// TODO: display nice errors if the code was already consumed or expired
let verification = consume_email_verification(&mut txn, verification)
.await
.wrap_error()?;
.map_err(fancy_error(templates.clone()))?;
let _email = mark_user_email_as_verified(&mut txn, verification.email)
.await
.wrap_error()?;
.map_err(fancy_error(templates.clone()))?;
let (csrf_token, cookie_jar) = cookie_jar.csrf_token();
let (session_info, cookie_jar) = cookie_jar.session_info();
let maybe_session = session_info
.load_session(&mut txn)
.await
.map_err(fancy_error(templates.clone()))?;
let ctx = EmptyContext
.maybe_with_session(maybe_session)
.with_csrf(csrf_token.form_value());
let content = templates.render_email_verification_done(&ctx).await?;
let reply = html(content);
let reply = cookie_saver.save_encrypted(&csrf_token, reply)?;
let content = templates
.render_email_verification_done(&ctx)
.await
.map_err(fancy_error(templates.clone()))?;
txn.commit().await.wrap_error()?;
txn.commit().await.map_err(fancy_error(templates.clone()))?;
Ok(Box::new(reply))
Ok((cookie_jar.headers(), Html(content)))
}