summaryrefslogtreecommitdiff
path: root/src/repo
diff options
context:
space:
mode:
authorOwen Jacobson <owen@grimoire.ca>2024-10-02 01:02:58 -0400
committerOwen Jacobson <owen@grimoire.ca>2024-10-02 01:02:58 -0400
commit5d3392799f88c5a3d3f9c656c73d6e8ac5c4d793 (patch)
tree426c568d82b67a98095d25952d2b5b2345a6545b /src/repo
parent357116366c1307bedaac6a3dfe9c5ed8e0e0c210 (diff)
Split login and token handling.
Diffstat (limited to 'src/repo')
-rw-r--r--src/repo/login.rs50
-rw-r--r--src/repo/mod.rs2
-rw-r--r--src/repo/token.rs151
3 files changed, 0 insertions, 203 deletions
diff --git a/src/repo/login.rs b/src/repo/login.rs
deleted file mode 100644
index d1a02c4..0000000
--- a/src/repo/login.rs
+++ /dev/null
@@ -1,50 +0,0 @@
-use sqlx::{sqlite::Sqlite, SqliteConnection, Transaction};
-
-use crate::login::{password::StoredHash, Id, Login};
-
-pub trait Provider {
- fn logins(&mut self) -> Logins;
-}
-
-impl<'c> Provider for Transaction<'c, Sqlite> {
- fn logins(&mut self) -> Logins {
- Logins(self)
- }
-}
-
-pub struct Logins<'t>(&'t mut SqliteConnection);
-
-impl<'c> Logins<'c> {
- pub async fn create(
- &mut self,
- name: &str,
- password_hash: &StoredHash,
- ) -> Result<Login, sqlx::Error> {
- let id = Id::generate();
-
- let login = sqlx::query_as!(
- Login,
- r#"
- insert or fail
- into login (id, name, password_hash)
- values ($1, $2, $3)
- returning
- id as "id: Id",
- name
- "#,
- id,
- name,
- password_hash,
- )
- .fetch_one(&mut *self.0)
- .await?;
-
- Ok(login)
- }
-}
-
-impl<'t> From<&'t mut SqliteConnection> for Logins<'t> {
- fn from(tx: &'t mut SqliteConnection) -> Self {
- Self(tx)
- }
-}
diff --git a/src/repo/mod.rs b/src/repo/mod.rs
index 69ad82c..7abd46b 100644
--- a/src/repo/mod.rs
+++ b/src/repo/mod.rs
@@ -1,6 +1,4 @@
pub mod channel;
pub mod error;
-pub mod login;
pub mod pool;
pub mod sequence;
-pub mod token;
diff --git a/src/repo/token.rs b/src/repo/token.rs
deleted file mode 100644
index 5f64dac..0000000
--- a/src/repo/token.rs
+++ /dev/null
@@ -1,151 +0,0 @@
-use sqlx::{sqlite::Sqlite, SqliteConnection, Transaction};
-use uuid::Uuid;
-
-use crate::{
- clock::DateTime,
- login::{self, Login},
- token::{Id, Secret},
-};
-
-pub trait Provider {
- fn tokens(&mut self) -> Tokens;
-}
-
-impl<'c> Provider for Transaction<'c, Sqlite> {
- fn tokens(&mut self) -> Tokens {
- Tokens(self)
- }
-}
-
-pub struct Tokens<'t>(&'t mut SqliteConnection);
-
-impl<'c> Tokens<'c> {
- // Issue a new token for an existing login. The issued_at timestamp will
- // be used to control expiry, until the token is actually used.
- pub async fn issue(
- &mut self,
- login: &Login,
- issued_at: &DateTime,
- ) -> Result<Secret, sqlx::Error> {
- let id = Id::generate();
- let secret = Uuid::new_v4().to_string();
-
- let secret = sqlx::query_scalar!(
- r#"
- insert
- into token (id, secret, login, issued_at, last_used_at)
- values ($1, $2, $3, $4, $4)
- returning secret as "secret!: Secret"
- "#,
- id,
- secret,
- login.id,
- issued_at,
- )
- .fetch_one(&mut *self.0)
- .await?;
-
- Ok(secret)
- }
-
- pub async fn require(&mut self, token: &Id) -> Result<(), sqlx::Error> {
- sqlx::query_scalar!(
- r#"
- select id as "id: Id"
- from token
- where id = $1
- "#,
- token,
- )
- .fetch_one(&mut *self.0)
- .await?;
-
- Ok(())
- }
-
- // Revoke a token by its secret.
- pub async fn revoke(&mut self, token: &Id) -> Result<(), sqlx::Error> {
- sqlx::query_scalar!(
- r#"
- delete
- from token
- where id = $1
- returning id as "id: Id"
- "#,
- token,
- )
- .fetch_one(&mut *self.0)
- .await?;
-
- Ok(())
- }
-
- // Expire and delete all tokens that haven't been used more recently than
- // `expire_at`.
- pub async fn expire(&mut self, expire_at: &DateTime) -> Result<Vec<Id>, sqlx::Error> {
- let tokens = sqlx::query_scalar!(
- r#"
- delete
- from token
- where last_used_at < $1
- returning id as "id: Id"
- "#,
- expire_at,
- )
- .fetch_all(&mut *self.0)
- .await?;
-
- Ok(tokens)
- }
-
- // Validate a token by its secret, retrieving the associated Login record.
- // Will return [None] if the token is not valid. The token's last-used
- // timestamp will be set to `used_at`.
- pub async fn validate(
- &mut self,
- secret: &Secret,
- used_at: &DateTime,
- ) -> Result<(Id, Login), sqlx::Error> {
- // I would use `update … returning` to do this in one query, but
- // sqlite3, as of this writing, does not allow an update's `returning`
- // clause to reference columns from tables joined into the update. Two
- // queries is fine, but it feels untidy.
- sqlx::query!(
- r#"
- update token
- set last_used_at = $1
- where secret = $2
- "#,
- used_at,
- secret,
- )
- .execute(&mut *self.0)
- .await?;
-
- let login = sqlx::query!(
- r#"
- select
- token.id as "token_id: Id",
- login.id as "login_id: login::Id",
- name as "login_name"
- from login
- join token on login.id = token.login
- where token.secret = $1
- "#,
- secret,
- )
- .map(|row| {
- (
- row.token_id,
- Login {
- id: row.login_id,
- name: row.login_name,
- },
- )
- })
- .fetch_one(&mut *self.0)
- .await?;
-
- Ok(login)
- }
-}