Skip to content

Commit 941ab21

Browse files
committed
Make the password registration create a user_registration
1 parent d94fd25 commit 941ab21

File tree

6 files changed

+95
-43
lines changed

6 files changed

+95
-43
lines changed

crates/handlers/src/views/register/password.rs

+46-31
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@ use mas_matrix::BoxHomeserverConnection;
2424
use mas_policy::Policy;
2525
use mas_router::UrlBuilder;
2626
use mas_storage::{
27-
queue::{ProvisionUserJob, QueueJobRepositoryExt as _},
28-
user::{BrowserSessionRepository, UserEmailRepository, UserPasswordRepository, UserRepository},
27+
queue::{QueueJobRepositoryExt as _, SendEmailAuthenticationCodeJob},
28+
user::{UserEmailRepository, UserRepository},
2929
BoxClock, BoxRepository, BoxRng, RepositoryAccess,
3030
};
3131
use mas_templates::{
@@ -141,6 +141,8 @@ pub(crate) async fn post(
141141
Form(form): Form<ProtectedForm<RegisterForm>>,
142142
) -> Result<Response, FancyError> {
143143
let user_agent = user_agent.map(|ua| UserAgent::parse(ua.as_str().to_owned()));
144+
145+
let ip_address = activity_tracker.ip();
144146
if !site_config.password_registration_enabled {
145147
return Ok(StatusCode::METHOD_NOT_ALLOWED.into_response());
146148
}
@@ -296,49 +298,62 @@ pub(crate) async fn post(
296298
return Ok((cookie_jar, Html(content)).into_response());
297299
}
298300

299-
let user = repo.user().add(&mut rng, &clock, form.username).await?;
300-
301-
if let Some(tos_uri) = &site_config.tos_uri {
302-
repo.user_terms()
303-
.accept_terms(&mut rng, &clock, &user, tos_uri.clone())
304-
.await?;
305-
}
301+
let post_auth_action = query
302+
.post_auth_action
303+
.map(serde_json::to_value)
304+
.transpose()?;
305+
let registration = repo
306+
.user_registration()
307+
.add(&mut rng, &clock, ip_address, user_agent, post_auth_action)
308+
.await?;
306309

307-
let password = Zeroizing::new(form.password.into_bytes());
308-
let (version, hashed_password) = password_manager.hash(&mut rng, password).await?;
309-
let user_password = repo
310-
.user_password()
311-
.add(&mut rng, &clock, &user, version, hashed_password, None)
310+
let registration = repo
311+
.user_registration()
312+
.set_username(registration, form.username)
312313
.await?;
313314

314-
let user_email = repo
315+
let registration = if let Some(tos_uri) = &site_config.tos_uri {
316+
repo.user_registration()
317+
.set_terms_url(registration, tos_uri.clone())
318+
.await?
319+
} else {
320+
registration
321+
};
322+
323+
// Create a new user email authentication session
324+
let user_email_authentication = repo
315325
.user_email()
316-
.add(&mut rng, &clock, &user, form.email)
326+
.add_authentication_for_registration(&mut rng, &clock, form.email, &registration)
317327
.await?;
318328

319-
let next = mas_router::AccountVerifyEmail::new(user_email.id).and_maybe(query.post_auth_action);
320-
321-
let session = repo
322-
.browser_session()
323-
.add(&mut rng, &clock, &user, user_agent)
329+
// Schedule a job to verify the email
330+
repo.queue_job()
331+
.schedule_job(
332+
&mut rng,
333+
&clock,
334+
SendEmailAuthenticationCodeJob::new(&user_email_authentication, locale.to_string()),
335+
)
324336
.await?;
325337

326-
repo.browser_session()
327-
.authenticate_with_password(&mut rng, &clock, &session, &user_password)
338+
let registration = repo
339+
.user_registration()
340+
.set_email_authentication(registration, &user_email_authentication)
328341
.await?;
329342

330-
repo.queue_job()
331-
.schedule_job(&mut rng, &clock, ProvisionUserJob::new(&user))
343+
// Hash the password
344+
let password = Zeroizing::new(form.password.into_bytes());
345+
let (version, hashed_password) = password_manager.hash(&mut rng, password).await?;
346+
347+
// Add the password to the registration
348+
let registration = repo
349+
.user_registration()
350+
.set_password(registration, hashed_password, version)
332351
.await?;
333352

334353
repo.save().await?;
335354

336-
activity_tracker
337-
.record_browser_session(&clock, &session)
338-
.await;
339-
340-
let cookie_jar = cookie_jar.set_session(&session);
341-
Ok((cookie_jar, url_builder.redirect(&next)).into_response())
355+
// TODO: redirect to the next step on the registration
356+
Ok(format!("{}", registration.id).into_response())
342357
}
343358

344359
async fn render(

crates/tasks/src/email.rs

+21-2
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,22 @@ impl RunnableJob for SendEmailAuthenticationCodeJob {
7878
None
7979
};
8080

81+
// Load the registration, if any
82+
let registration =
83+
if let Some(registration_id) = user_email_authentication.user_registration_id {
84+
Some(
85+
repo.user_registration()
86+
.lookup(registration_id)
87+
.await
88+
.map_err(JobError::retry)?
89+
.ok_or(JobError::fail(anyhow::anyhow!(
90+
"Failed to load user registration"
91+
)))?,
92+
)
93+
} else {
94+
None
95+
};
96+
8197
// Generate a new 6-digit authentication code
8298
let range = Uniform::<u32>::from(0..1_000_000);
8399
let code = rng.sample(range);
@@ -98,14 +114,17 @@ impl RunnableJob for SendEmailAuthenticationCodeJob {
98114
.email
99115
.parse()
100116
.map_err(JobError::fail)?;
101-
let username = browser_session.as_ref().map(|s| s.user.username.clone());
117+
let username_from_session = browser_session.as_ref().map(|s| s.user.username.clone());
118+
let username_from_registration = registration.as_ref().and_then(|r| r.username.clone());
119+
let username = username_from_registration.or(username_from_session);
102120
let mailbox = Mailbox::new(username, address);
103121

104122
info!("Sending email verification code to {}", mailbox);
105123

106124
let language = self.language().parse().map_err(JobError::fail)?;
107125

108-
let context = EmailVerificationContext::new(code, browser_session).with_language(language);
126+
let context = EmailVerificationContext::new(code, browser_session, registration)
127+
.with_language(language);
109128
mailer
110129
.send_verification_email(mailbox, &context)
111130
.await

crates/templates/src/context.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ use mas_data_model::{
2323
DeviceCodeGrant, UpstreamOAuthLink, UpstreamOAuthProvider, UpstreamOAuthProviderClaimsImports,
2424
UpstreamOAuthProviderDiscoveryMode, UpstreamOAuthProviderPkceMode,
2525
UpstreamOAuthProviderTokenAuthMethod, User, UserAgent, UserEmail, UserEmailAuthenticationCode,
26-
UserRecoverySession,
26+
UserRecoverySession, UserRegistration,
2727
};
2828
use mas_i18n::DataLocale;
2929
use mas_iana::jose::JsonWebSignatureAlg;
@@ -878,7 +878,10 @@ impl TemplateContext for EmailRecoveryContext {
878878
/// Context used by the `emails/verification.{txt,html,subject}` templates
879879
#[derive(Serialize)]
880880
pub struct EmailVerificationContext {
881+
#[serde(skip_serializing_if = "Option::is_none")]
881882
browser_session: Option<BrowserSession>,
883+
#[serde(skip_serializing_if = "Option::is_none")]
884+
user_registration: Option<UserRegistration>,
882885
authentication_code: UserEmailAuthenticationCode,
883886
}
884887

@@ -888,9 +891,11 @@ impl EmailVerificationContext {
888891
pub fn new(
889892
authentication_code: UserEmailAuthenticationCode,
890893
browser_session: Option<BrowserSession>,
894+
user_registration: Option<UserRegistration>,
891895
) -> Self {
892896
Self {
893897
browser_session,
898+
user_registration,
894899
authentication_code,
895900
}
896901
}
@@ -926,6 +931,7 @@ impl TemplateContext for EmailVerificationContext {
926931

927932
Self {
928933
browser_session: Some(browser_session),
934+
user_registration: None,
929935
authentication_code,
930936
}
931937
})

templates/emails/verification.html

+7-1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,12 @@
88

99
{%- set _ = translator(lang) -%}
1010

11-
{{ _("mas.emails.greeting", username=browser_session.user.username | default("user")) }}<br />
11+
{%- if browser_session is defined -%}
12+
{%- set username = browser_session.user.username -%}
13+
{%- elif user_registration is defined -%}
14+
{%- set username = user_registration.username -%}
15+
{%- endif -%}
16+
17+
{{ _("mas.emails.greeting", username=(username|default("user"))) }}<br />
1218
<br />
1319
{{ _("mas.emails.verify.body_html", code=authentication_code.code) }}<br />

templates/emails/verification.txt

+7-1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,12 @@ Please see LICENSE in the repository root for full details.
88

99
{%- set _ = translator(lang) -%}
1010

11-
{{ _("mas.emails.greeting", username=browser_session.user.username | default("user")) }}
11+
{%- if browser_session is defined -%}
12+
{%- set username = browser_session.user.username -%}
13+
{%- elif user_registration is defined -%}
14+
{%- set username = user_registration.username -%}
15+
{%- endif -%}
16+
17+
{{ _("mas.emails.greeting", username=(username|default("user"))) }}
1218

1319
{{ _("mas.emails.verify.body_text", code=authentication_code.code) }}

translations/en.json

+7-7
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@
219219
"emails": {
220220
"greeting": "Hello %(username)s,",
221221
"@greeting": {
222-
"context": "emails/verification.html:11:3-85, emails/verification.txt:11:3-85",
222+
"context": "emails/verification.html:17:3-64, emails/verification.txt:17:3-64",
223223
"description": "Greeting at the top of emails sent to the user"
224224
},
225225
"recovery": {
@@ -251,12 +251,12 @@
251251
"verify": {
252252
"body_html": "Your verification code to confirm this email address is: <strong>%(code)s</strong>",
253253
"@body_html": {
254-
"context": "emails/verification.html:13:3-66",
254+
"context": "emails/verification.html:19:3-66",
255255
"description": "The body of the email sent to verify an email address (HTML)"
256256
},
257257
"body_text": "Your verification code to confirm this email address is: %(code)s",
258258
"@body_text": {
259-
"context": "emails/verification.txt:13:3-66",
259+
"context": "emails/verification.txt:19:3-66",
260260
"description": "The body of the email sent to verify an email address (text)"
261261
},
262262
"subject": "Your email verification code is: %(code)s",
@@ -327,7 +327,7 @@
327327
},
328328
"continue_with_provider": "Continue with %(provider)s",
329329
"@continue_with_provider": {
330-
"context": "pages/login.html:75:15-67, pages/register/index.html:49:15-67",
330+
"context": "pages/login.html:75:15-67, pages/register/index.html:53:15-67",
331331
"description": "Button to log in with an upstream provider"
332332
},
333333
"description": "Please sign in to continue:",
@@ -513,12 +513,12 @@
513513
"register": {
514514
"call_to_login": "Already have an account?",
515515
"@call_to_login": {
516-
"context": "pages/register/index.html:55:35-66, pages/register/password.html:77:33-64",
516+
"context": "pages/register/index.html:59:35-66, pages/register/password.html:77:33-64",
517517
"description": "Displayed on the registration page to suggest to log in instead"
518518
},
519519
"continue_with_email": "Continue with email address",
520520
"@continue_with_email": {
521-
"context": "pages/register/index.html:40:30-67"
521+
"context": "pages/register/index.html:44:30-67"
522522
},
523523
"create_account": {
524524
"description": "Choose a username to continue.",
@@ -682,4 +682,4 @@
682682
}
683683
}
684684
}
685-
}
685+
}

0 commit comments

Comments
 (0)