summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOwen Jacobson <owen@grimoire.ca>2024-10-11 21:16:11 -0400
committerOwen Jacobson <owen@grimoire.ca>2024-10-11 21:16:11 -0400
commit864febeefc5213928bf88f89a714a006326e5b41 (patch)
treeb684ab871771044d2b8153f018eb49a001610f72
parent62349ab4ce463b6aafd818021849c63f60f6bf49 (diff)
Stop creating accounts during login.
-rw-r--r--src/app.rs2
-rw-r--r--src/login/routes/test/login.rs32
-rw-r--r--src/token/app.rs44
-rw-r--r--src/token/repo/auth.rs10
-rw-r--r--ui/routes/(login)/login/+page.svelte3
-rw-r--r--ui/routes/(login)/setup/+page.svelte2
6 files changed, 25 insertions, 68 deletions
diff --git a/src/app.rs b/src/app.rs
index cf49070..69831ee 100644
--- a/src/app.rs
+++ b/src/app.rs
@@ -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('/');