diff options
| author | Owen Jacobson <owen@grimoire.ca> | 2024-10-11 21:16:11 -0400 |
|---|---|---|
| committer | Owen Jacobson <owen@grimoire.ca> | 2024-10-11 21:16:11 -0400 |
| commit | 864febeefc5213928bf88f89a714a006326e5b41 (patch) | |
| tree | b684ab871771044d2b8153f018eb49a001610f72 | |
| parent | 62349ab4ce463b6aafd818021849c63f60f6bf49 (diff) | |
Stop creating accounts during login.
| -rw-r--r-- | src/app.rs | 2 | ||||
| -rw-r--r-- | src/login/routes/test/login.rs | 32 | ||||
| -rw-r--r-- | src/token/app.rs | 44 | ||||
| -rw-r--r-- | src/token/repo/auth.rs | 10 | ||||
| -rw-r--r-- | ui/routes/(login)/login/+page.svelte | 3 | ||||
| -rw-r--r-- | ui/routes/(login)/setup/+page.svelte | 2 |
6 files changed, 25 insertions, 68 deletions
@@ -58,6 +58,6 @@ impl App { } pub const fn tokens(&self) -> Tokens { - Tokens::new(&self.db, &self.events, &self.token_events) + Tokens::new(&self.db, &self.token_events) } } diff --git a/src/login/routes/test/login.rs b/src/login/routes/test/login.rs index 6a3b79c..68c92de 100644 --- a/src/login/routes/test/login.rs +++ b/src/login/routes/test/login.rs @@ -6,16 +6,16 @@ use axum::{ use crate::{login::routes, test::fixtures, token::app}; #[tokio::test] -async fn new_identity() { +async fn correct_credentials() { // Set up the environment let app = fixtures::scratch_app().await; + let (name, password) = fixtures::login::create_with_password(&app, &fixtures::now()).await; // Call the endpoint let identity = fixtures::identity::not_logged_in(); let logged_in_at = fixtures::now(); - let (name, password) = fixtures::login::propose(); let request = routes::LoginRequest { name: name.clone(), password, @@ -33,54 +33,42 @@ async fn new_identity() { // Verify the semantics let validated_at = fixtures::now(); - let (_, validated) = app + let (_, validated_login) = app .tokens() .validate(&secret, &validated_at) .await .expect("identity secret is valid"); - assert_eq!(name, validated.name); + assert_eq!(name, validated_login.name); } #[tokio::test] -async fn existing_identity() { +async fn invalid_name() { // Set up the environment let app = fixtures::scratch_app().await; - let (name, password) = fixtures::login::create_with_password(&app, &fixtures::now()).await; // Call the endpoint let identity = fixtures::identity::not_logged_in(); let logged_in_at = fixtures::now(); + let (name, password) = fixtures::login::propose(); let request = routes::LoginRequest { name: name.clone(), password, }; - let (identity, status) = + let routes::LoginError(error) = routes::on_login(State(app.clone()), logged_in_at, identity, Json(request)) .await - .expect("logged in with valid credentials"); + .expect_err("logged in with an incorrect password"); // Verify the return value's basic structure - assert_eq!(StatusCode::NO_CONTENT, status); - let secret = identity.secret().expect("logged in with valid credentials"); - - // Verify the semantics - - let validated_at = fixtures::now(); - let (_, validated_login) = app - .tokens() - .validate(&secret, &validated_at) - .await - .expect("identity secret is valid"); - - assert_eq!(name, validated_login.name); + assert!(matches!(error, app::LoginError::Rejected)); } #[tokio::test] -async fn authentication_failed() { +async fn incorrect_password() { // Set up the environment let app = fixtures::scratch_app().await; diff --git a/src/token/app.rs b/src/token/app.rs index b8af637..04f8747 100644 --- a/src/token/app.rs +++ b/src/token/app.rs @@ -12,27 +12,17 @@ use super::{ use crate::{ clock::DateTime, db::NotFound as _, - event::{self, repo::Provider as _, Event as ServiceEvent}, - login::{repo::Provider as _, Login, Password}, + login::{Login, Password}, }; pub struct Tokens<'a> { db: &'a SqlitePool, - events: &'a event::Broadcaster, token_events: &'a Broadcaster, } impl<'a> Tokens<'a> { - pub const fn new( - db: &'a SqlitePool, - events: &'a event::Broadcaster, - token_events: &'a Broadcaster, - ) -> Self { - Self { - db, - events, - token_events, - } + pub const fn new(db: &'a SqlitePool, token_events: &'a Broadcaster) -> Self { + Self { db, token_events } } pub async fn login( @@ -42,31 +32,21 @@ impl<'a> Tokens<'a> { login_at: &DateTime, ) -> Result<Secret, LoginError> { let mut tx = self.db.begin().await?; + let (login, stored_hash) = tx + .auth() + .for_name(name) + .await + .optional()? + .ok_or(LoginError::Rejected)?; - let (login, created) = if let Some((login, stored_hash)) = tx.auth().for_name(name).await? { - if stored_hash.verify(password)? { - // Password verified, proceed with login - (login, false) - } else { - // Password NOT verified. - return Err(LoginError::Rejected); - } + let token = if stored_hash.verify(password)? { + tx.tokens().issue(&login, login_at).await? } else { - let password_hash = password.hash()?; - let created = tx.sequence().next(login_at).await?; - let login = tx.logins().create(name, &password_hash, &created).await?; - - (login, true) + Err(LoginError::Rejected)? }; - let token = tx.tokens().issue(&login, login_at).await?; tx.commit().await?; - if created { - self.events - .broadcast(login.events().map(ServiceEvent::from).collect::<Vec<_>>()); - } - Ok(token) } diff --git a/src/token/repo/auth.rs b/src/token/repo/auth.rs index ddb5136..9aee81f 100644 --- a/src/token/repo/auth.rs +++ b/src/token/repo/auth.rs @@ -19,13 +19,7 @@ impl<'c> Provider for Transaction<'c, Sqlite> { pub struct Auth<'t>(&'t mut SqliteConnection); impl<'t> Auth<'t> { - // Retrieves a login by name, plus its stored password hash for - // verification. If there's no login with the requested name, this will - // return [None]. - pub async fn for_name( - &mut self, - name: &str, - ) -> Result<Option<(History, StoredHash)>, sqlx::Error> { + pub async fn for_name(&mut self, name: &str) -> Result<(History, StoredHash), sqlx::Error> { let found = sqlx::query!( r#" select @@ -54,7 +48,7 @@ impl<'t> Auth<'t> { row.password_hash, ) }) - .fetch_optional(&mut *self.0) + .fetch_one(&mut *self.0) .await?; Ok(found) diff --git a/ui/routes/(login)/login/+page.svelte b/ui/routes/(login)/login/+page.svelte index a349660..29dba54 100644 --- a/ui/routes/(login)/login/+page.svelte +++ b/ui/routes/(login)/login/+page.svelte @@ -1,7 +1,6 @@ <script> import { goto } from '$app/navigation'; import { logIn } from '$lib/apiServer'; - import { currentUser } from '$lib/store'; import LogIn from '$lib/components/LogIn.svelte'; @@ -10,11 +9,9 @@ let password; async function onSubmit() { - debugger; disabled = true; const response = await logIn(username, password); if (200 <= response.status && response.status < 300) { - currentUser.update(() => ({ username })); username = ''; password = ''; goto('/'); diff --git a/ui/routes/(login)/setup/+page.svelte b/ui/routes/(login)/setup/+page.svelte index 252e79b..2503502 100644 --- a/ui/routes/(login)/setup/+page.svelte +++ b/ui/routes/(login)/setup/+page.svelte @@ -1,7 +1,6 @@ <script> import { goto } from '$app/navigation'; import { setup } from '$lib/apiServer'; - import { currentUser } from '$lib/store'; import LogIn from '$lib/components/LogIn.svelte'; @@ -13,7 +12,6 @@ disabled = true; const response = await setup(username, password); if (200 <= response.status && response.status < 300) { - currentUser.update(() => ({ username })); username = ''; password = ''; goto('/'); |
