From ab6d5cefbea1e8ddf41f385dd85918f651958287 Mon Sep 17 00:00:00 2001 From: benj Date: Mon, 19 Jun 2023 17:18:21 -0700 Subject: hack to allow impersonator to impersonate target --- crates/secd/src/auth/n.rs | 91 ++++++++++++++++++++-- crates/secd/src/auth/z/mod.rs | 3 - crates/secd/src/client/store/mod.rs | 53 +++++++++++-- crates/secd/src/client/store/sql_db.rs | 70 +++++++++++++++++ crates/secd/src/lib.rs | 85 ++++++++++++-------- .../pg/migrations/20221222002434_bootstrap.sql | 33 ++------ crates/secd/store/pg/sql/find_impersonator.sql | 10 +++ crates/secd/store/pg/sql/write_impersonator.sql | 11 +++ .../sqlite/migrations/20221125051738_bootstrap.sql | 21 ++--- crates/secd/store/sqlite/sql/find_credential.sql | 2 +- crates/secd/store/sqlite/sql/find_identity.sql | 2 - crates/secd/store/sqlite/sql/find_impersonator.sql | 10 +++ crates/secd/store/sqlite/sql/find_session.sql | 11 --- crates/secd/store/sqlite/sql/write_credential.sql | 4 +- .../secd/store/sqlite/sql/write_impersonator.sql | 11 +++ crates/secd/store/sqlite/sql/write_session.sql | 11 --- 16 files changed, 311 insertions(+), 117 deletions(-) create mode 100644 crates/secd/store/pg/sql/find_impersonator.sql create mode 100644 crates/secd/store/pg/sql/write_impersonator.sql create mode 100644 crates/secd/store/sqlite/sql/find_impersonator.sql delete mode 100644 crates/secd/store/sqlite/sql/find_session.sql create mode 100644 crates/secd/store/sqlite/sql/write_impersonator.sql delete mode 100644 crates/secd/store/sqlite/sql/write_session.sql (limited to 'crates/secd') diff --git a/crates/secd/src/auth/n.rs b/crates/secd/src/auth/n.rs index dde6e7d..12a5411 100644 --- a/crates/secd/src/auth/n.rs +++ b/crates/secd/src/auth/n.rs @@ -5,12 +5,13 @@ use crate::{ DEFAULT_SIGNUP_EMAIL, }, store::{ - AddressLens, AddressValidationLens, CredentialLens, IdentityLens, Storable, StoreError, + AddressLens, AddressValidationLens, CredentialLens, IdentityLens, ImpersonatorLens, + Storable, StoreError, }, }, util::{self, ErrorContext}, Address, AddressType, AddressValidation, AddressValidationId, AddressValidationMethod, - Credential, CredentialId, CredentialType, Identity, IdentityId, Secd, SecdError, + Credential, CredentialId, CredentialType, Identity, IdentityId, Impersonator, Secd, SecdError, ADDRESSS_VALIDATION_CODE_SIZE, ADDRESS_VALIDATION_ALLOWS_ATTEMPTS, ADDRESS_VALIDATION_IDENTITY_SURJECTION, EMAIL_VALIDATION_DURATION, }; @@ -19,6 +20,7 @@ use log::warn; use rand::Rng; use std::str::FromStr; use time::{Duration, OffsetDateTime}; +use tokio::join; use uuid::Uuid; impl Secd { @@ -363,13 +365,13 @@ impl Secd { Ok(identity) } - pub async fn validate_credential(&self, t: CredentialType) -> Result { + pub async fn validate_credential(&self, t: &CredentialType) -> Result { let mut retrieved = Credential::find( self.store.clone(), &CredentialLens { id: None, identity_id: None, - t: Some(&t), + t: Some(t), }, ) .await? @@ -396,7 +398,7 @@ impl Secd { retrieved.hash_compare(&t, &self.crypter)?; // Return the initially provided plaintext credential since it's valid - retrieved.t = t; + retrieved.t = t.clone(); Ok(retrieved) } @@ -503,4 +505,83 @@ impl Secd { credential.write(self.store.clone()).await?; Ok(()) } + + pub async fn impersonate( + &self, + impersonator_id: &IdentityId, + target_id: &IdentityId, + ) -> Result { + let impersonator_lens = IdentityLens { + id: Some(&impersonator_id), + address_type: None, + validated_address: None, + }; + let target_lens = IdentityLens { + id: Some(&target_id), + address_type: None, + validated_address: None, + }; + let (i, t) = join!( + Identity::find(self.store.clone(), &impersonator_lens,), + Identity::find(self.store.clone(), &target_lens,) + ); + + let (i, t) = ( + i.ctx("failed to retrieve impersonator identity")?, + t.ctx("failed to retrieve target identity")?, + ); + if i.is_empty() || t.is_empty() { + return Err(SecdError::IdentityNotFound) + .ctx("failed to retrieve impersonator or target identity for impersonation"); + } + + let existing_impersonation = Impersonator::find( + self.store.clone(), + &ImpersonatorLens { + impersonator_id: Some(impersonator_id), + target_id: Some(target_id), + }, + ) + .await + .ctx("failed to find existing impersonation")?; + + // TODO: We could expire the session chain, but I think we want to handle this more intelligently. + // For now, just revoke the credential manually...pita I know... + if !existing_impersonation.is_empty() { + return Err(SecdError::ImpersonatorAlreadyExists) + .ctx("Target already being impersonated by the provided impersonator identity"); + } + + let new_identity = self + .create_credential( + Credential::new_session(*target_id)?.t, + Some(*target_id), + OffsetDateTime::now_utc().checked_add(Duration::minutes(30)), + ) + .await + .ctx("failed to create new credential for target identity")?; + + let new_session = new_identity + .new_credentials + .iter() + .next() + .ok_or(SecdError::InvalidCredential) + .ctx("failed to retrieve new session from newly created target credential")? + .clone(); + + Impersonator { + impersonator: i + .into_iter() + .next() + .ok_or(SecdError::IdentityNotFound) + .ctx("failed to find impersonator identity")?, + target: new_identity, + created_at: OffsetDateTime::now_utc(), + } + .write(self.store.clone()) + .await + .ctx("failed to write new impersonator")?; + + Ok(new_session) + } } diff --git a/crates/secd/src/auth/z/mod.rs b/crates/secd/src/auth/z/mod.rs index d64f674..bde319a 100644 --- a/crates/secd/src/auth/z/mod.rs +++ b/crates/secd/src/auth/z/mod.rs @@ -49,9 +49,6 @@ impl Authorization for Secd { .map(|e| Uuid::parse_str(e).unwrap()) .collect()) } - async fn check_list_subjects(&self) -> Result, SecdError> { - unimplemented!() - } async fn write(&self, ts: &[Relationship]) -> Result<(), SecdError> { let spice = self .spice diff --git a/crates/secd/src/client/store/mod.rs b/crates/secd/src/client/store/mod.rs index 6c42dba..f08aa41 100644 --- a/crates/secd/src/client/store/mod.rs +++ b/crates/secd/src/client/store/mod.rs @@ -1,4 +1,4 @@ -pub(crate) mod sql_db; +pub mod sql_db; use async_trait::async_trait; use sqlx::{Postgres, Sqlite}; @@ -7,7 +7,7 @@ use uuid::Uuid; use crate::{ Address, AddressType, AddressValidation, Credential, CredentialId, CredentialType, Identity, - IdentityId, + IdentityId, Impersonator, }; use self::sql_db::SqlClient; @@ -19,6 +19,7 @@ pub enum StoreError { ParseError(#[from] strum::ParseError), StoreValueCannotBeParsedInvariant, IdempotentCheckAlreadyExists, + ExpectedEntity, } #[async_trait] @@ -32,7 +33,7 @@ pub enum StoreType { } #[async_trait] -pub(crate) trait Storable<'a> { +pub trait Storable<'a> { type Item; type Lens; @@ -43,33 +44,39 @@ pub(crate) trait Storable<'a> { ) -> Result, StoreError>; } -pub(crate) trait Lens {} +pub trait Lens {} -pub(crate) struct AddressLens<'a> { +pub struct AddressLens<'a> { pub id: Option<&'a Uuid>, pub t: Option<&'a AddressType>, } impl<'a> Lens for AddressLens<'a> {} -pub(crate) struct AddressValidationLens<'a> { +pub struct AddressValidationLens<'a> { pub id: Option<&'a Uuid>, } impl<'a> Lens for AddressValidationLens<'a> {} -pub(crate) struct IdentityLens<'a> { +pub struct IdentityLens<'a> { pub id: Option<&'a Uuid>, pub address_type: Option<&'a AddressType>, pub validated_address: Option, } impl<'a> Lens for IdentityLens<'a> {} -pub(crate) struct CredentialLens<'a> { +pub struct CredentialLens<'a> { pub id: Option, pub identity_id: Option, pub t: Option<&'a CredentialType>, } impl<'a> Lens for CredentialLens<'a> {} +pub struct ImpersonatorLens<'a> { + pub impersonator_id: Option<&'a IdentityId>, + pub target_id: Option<&'a IdentityId>, +} +impl<'a> Lens for ImpersonatorLens<'a> {} + #[async_trait] impl<'a> Storable<'a> for Address { type Item = Address; @@ -179,3 +186,33 @@ impl<'a> Storable<'a> for Credential { }) } } + +#[async_trait] +impl<'a> Storable<'a> for Impersonator { + type Item = Impersonator; + type Lens = ImpersonatorLens<'a>; + + async fn write(&self, store: Arc) -> Result<(), StoreError> { + match store.get_type() { + StoreType::Postgres { c } => c.write_impersonator(self).await?, + StoreType::Sqlite { c } => c.write_impersonator(self).await?, + } + Ok(()) + } + + async fn find( + store: Arc, + lens: &'a Self::Lens, + ) -> Result, StoreError> { + Ok(match store.get_type() { + StoreType::Postgres { c } => { + c.find_impersonator(lens.impersonator_id, lens.target_id) + .await? + } + StoreType::Sqlite { c } => { + c.find_impersonator(lens.impersonator_id, lens.target_id) + .await? + } + }) + } +} diff --git a/crates/secd/src/client/store/sql_db.rs b/crates/secd/src/client/store/sql_db.rs index 7b3a68e..5777704 100644 --- a/crates/secd/src/client/store/sql_db.rs +++ b/crates/secd/src/client/store/sql_db.rs @@ -1,4 +1,5 @@ use super::{Store, StoreError, StoreType}; +use crate::Impersonator; use crate::{ util::ErrorContext, Address, AddressType, AddressValidation, AddressValidationMethod, Credential, CredentialId, CredentialType, Identity, IdentityId, @@ -26,6 +27,8 @@ const WRITE_CREDENTIAL: &str = "write_credential"; const FIND_CREDENTIAL: &str = "find_credential"; const WRITE_IDENTITY: &str = "write_identity"; const FIND_IDENTITY: &str = "find_identity"; +const WRITE_IMPERSONATOR: &str = "write_impersonator"; +const FIND_IMPERSONATOR: &str = "find_impersonator"; const ERR_MSG_MIGRATION_FAILED: &str = "Failed to apply secd migrations to a sql db. File a bug at https://www.github.com/branchcontrol/secdiam"; @@ -64,6 +67,14 @@ lazy_static! { FIND_CREDENTIAL, include_str!("../../../store/sqlite/sql/find_credential.sql"), ), + ( + WRITE_IMPERSONATOR, + include_str!("../../../store/sqlite/sql/write_impersonator.sql"), + ), + ( + FIND_IMPERSONATOR, + include_str!("../../../store/sqlite/sql/find_impersonator.sql"), + ), ] .iter() .cloned() @@ -102,6 +113,14 @@ lazy_static! { FIND_CREDENTIAL, include_str!("../../../store/pg/sql/find_credential.sql"), ), + ( + WRITE_IMPERSONATOR, + include_str!("../../../store/pg/sql/write_impersonator.sql"), + ), + ( + FIND_IMPERSONATOR, + include_str!("../../../store/pg/sql/find_impersonator.sql"), + ), ] .iter() .cloned() @@ -525,6 +544,57 @@ where Ok(res) } + + pub async fn write_impersonator(&self, i: &Impersonator) -> Result<(), StoreError> { + let sqls = get_sqls(&self.sqls_root, WRITE_IMPERSONATOR); + sqlx::query(&sqls[0]) + .bind(i.impersonator.id) + .bind(i.target.id) + .bind(i.target.new_credentials.get(0).map(|e| &e.id)) + .bind(i.created_at) + .fetch_all(&self.pool) + .await + .extend_err()?; + Ok(()) + } + pub async fn find_impersonator( + &self, + impersonator_id: Option<&Uuid>, + target_id: Option<&Uuid>, + ) -> Result, StoreError> { + let sqls = get_sqls(&self.sqls_root, FIND_IMPERSONATOR); + let rs = sqlx::query_as::<_, (Uuid, Uuid, OffsetDateTime)>(&sqls[0]) + .bind(impersonator_id) + .bind(target_id) + .bind(OffsetDateTime::now_utc()) + .fetch_all(&self.pool) + .await + .extend_err()?; + + let mut res = vec![]; + for (impersonator_id, target_id, created_at) in rs.into_iter() { + let impersonator = self + .find_identity(Some(&impersonator_id), None, None) + .await? + .into_iter() + .next() + .ok_or(StoreError::ExpectedEntity)?; + let target = self + .find_identity(Some(&target_id), None, None) + .await? + .into_iter() + .next() + .ok_or(StoreError::ExpectedEntity)?; + + res.push(Impersonator { + impersonator, + target, + created_at, + }) + } + + Ok(res) + } } fn get_sqls(root: &str, file: &str) -> Vec { diff --git a/crates/secd/src/lib.rs b/crates/secd/src/lib.rs index c84ce44..7fa1755 100644 --- a/crates/secd/src/lib.rs +++ b/crates/secd/src/lib.rs @@ -41,9 +41,7 @@ pub type AddressId = Uuid; pub type AddressValidationId = Uuid; pub type CredentialId = Uuid; pub type IdentityId = Uuid; -pub type MotifId = Uuid; pub type PhoneNumber = String; -pub type RefId = Uuid; #[derive(Debug, derive_more::Display, thiserror::Error)] pub enum SecdError { @@ -60,10 +58,15 @@ pub enum SecdError { CrypterError(#[from] CrypterError), + CfgMissingSpiceSecret, + CfgMissingSpiceServer, + TooManyIdentities, IdentityNotFound, IdentityAlreadyExists, + ImpersonatorAlreadyExists, + EmailMessengerError(#[from] EmailMessengerError), InvalidEmaillAddress(#[from] email_address::Error), @@ -103,43 +106,40 @@ struct Cfg { email_signup_message_asset_loc: Option, email_signin_message: Option, email_signup_message: Option, - spice_secret: String, - spice_server: String, + spice_secret: Option, + spice_server: Option, } #[async_trait] pub trait Authentication { - async fn validate_address( - &self, - address_type: AddressType, - identity_id: Option, - ) -> Result; - - async fn complete_address_validation( - &self, - validation_id: &AddressValidationId, - plaintext_token: Option, - plaintext_code: Option, - ) -> Result; - + async fn check_credential(&self, t: &CredentialType) -> Result; async fn create_credential( &self, t: &CredentialType, identity_id: Option, - ) -> Result; - // async fn update_credential(&self, t: &CredentialType) -> Result<(), SecdError>; - async fn reset_credential( + expires_at: Option, + ) -> Result; + async fn create_identity( &self, + i: &Identity, t: &CredentialType, - address: &AddressType, + md: Option, + ) -> Result; + async fn impersonate( + &self, + impersonator: &Identity, + target: &Identity, ) -> Result; - async fn validate_credential(&self, t: &CredentialType) -> Result; - - // async fn expire_session_chain(&self, t: &SessionToken) -> Result<(), SecdError>; - // async fn expire_sessions(&self, i: &IdentityId) -> Result<(), SecdError>; - + async fn revoke_credential(&self, credential_id: &CredentialId) -> Result; + async fn send_address_validation(&self, t: AddressType) + -> Result; + async fn validate_address( + &self, + v_id: &AddressValidationId, + plaintext_token: Option, + plaintext_code: Option, + ) -> Result; // async fn get_identity(&self, t: &SessionToken) -> Result; - // async fn get_session(&self, t: &SessionToken) -> Result; } #[async_trait] @@ -151,7 +151,6 @@ pub trait Authorization { subj: &Subject, relation: &Relation, ) -> Result, SecdError>; - async fn check_list_subjects(&self) -> Result, SecdError>; async fn write(&self, relationships: &[Relationship]) -> Result<(), SecdError>; } @@ -218,7 +217,7 @@ pub enum AddressType { } #[serde_as] -#[derive(Debug, Serialize)] +#[derive(Clone, Debug, Serialize)] pub struct Credential { pub id: CredentialId, pub identity_id: IdentityId, @@ -263,6 +262,15 @@ pub struct Identity { pub deleted_at: Option, } +#[serde_with::skip_serializing_none] +#[derive(Debug, Serialize)] +pub struct Impersonator { + pub impersonator: Identity, + pub target: Identity, + #[serde(with = "time::serde::timestamp")] + pub created_at: OffsetDateTime, +} + impl Cfg { fn resolve(&mut self) -> Result<(), SecdError> { if let Some(path) = &self.email_signin_message_asset_loc { @@ -313,8 +321,8 @@ impl Secd { CRYPTER_SECRET_KEY_DEFAULT.to_string() }); - info!("starting client with auth_store: {:?}", auth_store); - info!("starting client with email_messenger: {:?}", auth_store); + info!("init with auth_store: {:?}", auth_store); + info!("init with email_messenger: {:?}", email_messenger); let store = match auth_store { AuthStore::Sqlite { conn } => { @@ -340,7 +348,7 @@ impl Secd { .connect(&conn) .await .map_err(|e| { - SecdError::StoreInitFailure(format!("failed to init sqlite: {}", e)) + SecdError::StoreInitFailure(format!("failed to init postgres: {}", e)) })?, ) .await @@ -366,8 +374,17 @@ impl Secd { let spice = match z_schema { Some(schema) => { - let c: Arc = - Arc::new(Spice::new(cfg.spice_secret.clone(), cfg.spice_server.clone()).await); + let c: Arc = Arc::new( + Spice::new( + cfg.spice_secret + .clone() + .ok_or(SecdError::CfgMissingSpiceSecret)?, + cfg.spice_server + .clone() + .ok_or(SecdError::CfgMissingSpiceServer)?, + ) + .await, + ); c.write_schema(schema) .await .unwrap_or_else(|_| panic!("{}", "failed to write authorization schema")); diff --git a/crates/secd/store/pg/migrations/20221222002434_bootstrap.sql b/crates/secd/store/pg/migrations/20221222002434_bootstrap.sql index 0fd423e..8f0a9c0 100644 --- a/crates/secd/store/pg/migrations/20221222002434_bootstrap.sql +++ b/crates/secd/store/pg/migrations/20221222002434_bootstrap.sql @@ -66,16 +66,6 @@ create table if not exists secd.address_validation ( , unique(address_validation_public_id) ); -create table if not exists secd.session ( - session_id bigserial primary key - , identity_id bigint not null references secd.identity(identity_id) - , token_hash bytea not null - , created_at timestamptz not null - , expired_at timestamptz not null - , revoked_at timestamptz - , unique(token_hash) -); - create table if not exists secd.message ( message_id bigserial primary key , address_id bigint not null references secd.address(address_id) @@ -87,22 +77,9 @@ create table if not exists secd.message ( , sent_at timestamptz ); -create table if not exists secd.namespace_config ( - namespace text not null - , serialized_config text not null - , created_at xid8 not null - , deleted_at xid8 - -- TODO: indexes and stuff -); - -create table if not exists secd.relation_tuple ( - namespace text not null - , object_id text not null - , relation text not null - , userset_namespace text not null - , userset_object_id text not null - , userset_relation text not null - , created_at xid8 not null - , deleted_at xid8 not null - -- TODO: indexes and stuff +create table if not exists secd.impersonator ( + impersonator_id bigint not null references secd.identity(identity_id) + , target_id bigint not null references secd.identity(identity_id) + , credential_id bigint not null references secd.credential(credential_id) + , created_at timestamptz not null ); diff --git a/crates/secd/store/pg/sql/find_impersonator.sql b/crates/secd/store/pg/sql/find_impersonator.sql new file mode 100644 index 0000000..e544598 --- /dev/null +++ b/crates/secd/store/pg/sql/find_impersonator.sql @@ -0,0 +1,10 @@ +select i2.identity_public_id as impersonator_public_id + , i3.identity_public_id as target_public_id + , i.created_at +from secd.impersonator i +join secd.identity i2 on i.impersonator_id = i2.identity_id +join secd.identity i3 on i.target_id = i3.identity_id +join secd.credential c using (credential_id) +where (($1::uuid is null) or (i2.identity_public_id = $1)) +and (($2::uuid is null) or (i3.identity_public_id = $2)) +and c.revoked_at > $3; diff --git a/crates/secd/store/pg/sql/write_impersonator.sql b/crates/secd/store/pg/sql/write_impersonator.sql new file mode 100644 index 0000000..b67b738 --- /dev/null +++ b/crates/secd/store/pg/sql/write_impersonator.sql @@ -0,0 +1,11 @@ +insert into secd.impersonator ( + impersonator_id + , target_id + , credential_id + , created_at +) values ( + (select identity_id from secd.identity where identity_public_id = $1) + , (select identity_id from secd.identity where identity_public_id = $2) + , (select credential_id from secd.credential where credential_public_id = $3) + , $4 +); diff --git a/crates/secd/store/sqlite/migrations/20221125051738_bootstrap.sql b/crates/secd/store/sqlite/migrations/20221125051738_bootstrap.sql index b2ce45d..0a182e1 100644 --- a/crates/secd/store/sqlite/migrations/20221125051738_bootstrap.sql +++ b/crates/secd/store/sqlite/migrations/20221125051738_bootstrap.sql @@ -34,9 +34,7 @@ create table if not exists credential ( , deleted_at integer ); -create unique index if not exists credential_passphrase_type_key_ix -on credential (partial_key) -where type = 'Passphrase'; +create unique index if not exists credential_partial_key_type_key_ix on credential (partial_key); create table if not exists address ( address_id integer primary key @@ -63,16 +61,6 @@ create table if not exists address_validation ( , unique(address_validation_public_id) ); -create table if not exists session ( - session_id integer primary key - , identity_id integer not null references identity(identity_id) - , token_hash blob not null - , created_at integer not null - , expired_at integer not null - , revoked_at integer - , unique(token_hash) -); - create table if not exists message ( message_id integer primary key , address_id integer not null references address(address_id) @@ -83,3 +71,10 @@ create table if not exists message ( , created_at integer not null , sent_at integer ); + +create table if not exists impersonator ( + impersonator_id integer not null references identity(identity_id) + , target_id integer not null references identity(identity_id) + , credential_id integer not null references credential(credential_id) + , created_at integer not null +); diff --git a/crates/secd/store/sqlite/sql/find_credential.sql b/crates/secd/store/sqlite/sql/find_credential.sql index 9062914..0590dee 100644 --- a/crates/secd/store/sqlite/sql/find_credential.sql +++ b/crates/secd/store/sqlite/sql/find_credential.sql @@ -9,4 +9,4 @@ join identity i using (identity_id) where (($1 is null) or (c.credential_public_id = $1)) and (($2 is null) or (i.identity_public_id = $2)) and (($3 is null) or (c.type = $3)) -and (($3 is null or $4 is null) or (c.data->$3->>'key' = $4)) +and (($3 is null or $4 is null) or (c.partial_key = $4)) diff --git a/crates/secd/store/sqlite/sql/find_identity.sql b/crates/secd/store/sqlite/sql/find_identity.sql index 1528407..0d32a9b 100644 --- a/crates/secd/store/sqlite/sql/find_identity.sql +++ b/crates/secd/store/sqlite/sql/find_identity.sql @@ -7,9 +7,7 @@ select distinct from identity i left join address_validation av using (identity_id) left join address a using (address_id) -left join session s using (identity_id) where (($1 is null) or (i.identity_public_id = $1)) and (($2 is null) or (a.value = $2)) and (($3 is null) or (($3 is true) and (av.validated_at is not null))) -and (($4 is null) or (s.token_hash = $4)) and i.deleted_at is null; diff --git a/crates/secd/store/sqlite/sql/find_impersonator.sql b/crates/secd/store/sqlite/sql/find_impersonator.sql new file mode 100644 index 0000000..786e9ba --- /dev/null +++ b/crates/secd/store/sqlite/sql/find_impersonator.sql @@ -0,0 +1,10 @@ +select i2.identity_public_id as impersonator_public_id + , i3.identity_public_id as target_public_id + , i.created_at +from impersonator i +join identity i2 on i.impersonator_id = i2.identity_id +join identity i3 on i.target_id = i3.identity_id +join credential c using (credential_id) +where (($1 is null) or (i2.identity_public_id = $1)) +and (($2 is null) or (i3.identity_public_id = $2)) +and c.revoked_at > $3; diff --git a/crates/secd/store/sqlite/sql/find_session.sql b/crates/secd/store/sqlite/sql/find_session.sql deleted file mode 100644 index 31640dd..0000000 --- a/crates/secd/store/sqlite/sql/find_session.sql +++ /dev/null @@ -1,11 +0,0 @@ -select distinct - i.identity_public_id - , s.created_at - , s.expired_at - , s.revoked_at -from session s -join identity i using (identity_id) -where (($1 is null) or (s.token_hash = $1)) -and (($2 is null) or (i.identity_public_id = $2)) -and (($3 is null) or (s.expired_at > $3)) -and ((revoked_at is null) or ($4 is null) or (s.revoked_at > $4)); diff --git a/crates/secd/store/sqlite/sql/write_credential.sql b/crates/secd/store/sqlite/sql/write_credential.sql index 3319226..06cb389 100644 --- a/crates/secd/store/sqlite/sql/write_credential.sql +++ b/crates/secd/store/sqlite/sql/write_credential.sql @@ -16,4 +16,6 @@ insert into credential ( , $6 , $7 , $8 -); +) on conflict (partial_key) do update + set revoked_at = excluded.revoked_at + , deleted_at = excluded.deleted_at; diff --git a/crates/secd/store/sqlite/sql/write_impersonator.sql b/crates/secd/store/sqlite/sql/write_impersonator.sql new file mode 100644 index 0000000..ae81466 --- /dev/null +++ b/crates/secd/store/sqlite/sql/write_impersonator.sql @@ -0,0 +1,11 @@ +insert into impersonator ( + impersonator_id + , target_id + , credential_id + , created_at +) values ( + (select identity_id from identity where identity_public_id = $1) + , (select identity_id from identity where identity_public_id = $2) + , (select credential_id from credential where credential_public_id = $3) + , $4 +); diff --git a/crates/secd/store/sqlite/sql/write_session.sql b/crates/secd/store/sqlite/sql/write_session.sql deleted file mode 100644 index 9ffb105..0000000 --- a/crates/secd/store/sqlite/sql/write_session.sql +++ /dev/null @@ -1,11 +0,0 @@ -insert into session ( - identity_id - , token_hash - , created_at - , expired_at - , revoked_at -) values ( - (select identity_id from identity where identity_public_id = $1) - , $2, $3, $4, $5 -) on conflict (token_hash) do update - set revoked_at = excluded.revoked_at; -- cgit v1.2.3