diff --git a/crates/handlers/src/lib.rs b/crates/handlers/src/lib.rs index b1f709b8..c619757e 100644 --- a/crates/handlers/src/lib.rs +++ b/crates/handlers/src/lib.rs @@ -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())) diff --git a/crates/handlers/src/views/mod.rs b/crates/handlers/src/views/mod.rs index 240ba4e3..d842fc54 100644 --- a/crates/handlers/src/views/mod.rs +++ b/crates/handlers/src/views/mod.rs @@ -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,)> { 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() } diff --git a/crates/handlers/src/views/verify.rs b/crates/handlers/src/views/verify.rs index 24a8ac6b..06e235f9 100644 --- a/crates/handlers/src/views/verify.rs +++ b/crates/handlers/src/views/verify.rs @@ -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,)> { - 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, + Extension(pool): Extension, + Path(code): Path, + cookie_jar: PrivateCookieJar, +) -> Result { + 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>, - mut txn: Transaction<'_, Postgres>, -) -> Result, 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))) }