summaryrefslogtreecommitdiff
path: root/src/database.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/database.rs')
-rw-r--r--src/database.rs121
1 files changed, 121 insertions, 0 deletions
diff --git a/src/database.rs b/src/database.rs
index 178eee3..0611efd 100644
--- a/src/database.rs
+++ b/src/database.rs
@@ -342,6 +342,127 @@ impl Database {
Ok(())
}
+ // Refresh Token operations
+ pub fn create_refresh_token(&self, token: &DbRefreshToken) -> Result<i64> {
+ let mut stmt = self.conn.prepare(
+ "INSERT INTO refresh_tokens
+ (token_id, access_token_id, client_id, user_id, scope, expires_at, created_at, is_revoked, token_hash)
+ VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9)",
+ )?;
+
+ let id = stmt.insert(params![
+ token.token_id,
+ token.access_token_id,
+ token.client_id,
+ token.user_id,
+ token.scope,
+ token.expires_at.to_rfc3339(),
+ token.created_at.to_rfc3339(),
+ token.is_revoked,
+ token.token_hash
+ ])?;
+
+ Ok(id)
+ }
+
+ pub fn get_refresh_token(&self, token_hash: &str) -> Result<Option<DbRefreshToken>> {
+ let mut stmt = self.conn.prepare(
+ "SELECT id, token_id, access_token_id, client_id, user_id, scope, expires_at,
+ created_at, is_revoked, token_hash
+ FROM refresh_tokens WHERE token_hash = ?1"
+ )?;
+
+ let token = stmt.query_row([token_hash], |row| {
+ Ok(DbRefreshToken {
+ id: row.get(0)?,
+ token_id: row.get(1)?,
+ access_token_id: row.get(2)?,
+ client_id: row.get(3)?,
+ user_id: row.get(4)?,
+ scope: row.get(5)?,
+ expires_at: DateTime::parse_from_rfc3339(&row.get::<_, String>(6)?)
+ .map_err(|_| {
+ rusqlite::Error::InvalidColumnType(
+ 6,
+ "expires_at".to_string(),
+ rusqlite::types::Type::Text,
+ )
+ })?
+ .with_timezone(&Utc),
+ created_at: DateTime::parse_from_rfc3339(&row.get::<_, String>(7)?)
+ .map_err(|_| {
+ rusqlite::Error::InvalidColumnType(
+ 7,
+ "created_at".to_string(),
+ rusqlite::types::Type::Text,
+ )
+ })?
+ .with_timezone(&Utc),
+ is_revoked: row.get(8)?,
+ token_hash: row.get(9)?,
+ })
+ });
+
+ match token {
+ Ok(token) => Ok(Some(token)),
+ Err(rusqlite::Error::QueryReturnedNoRows) => Ok(None),
+ Err(e) => Err(e.into()),
+ }
+ }
+
+ pub fn revoke_refresh_token(&self, token_hash: &str) -> Result<()> {
+ self.conn.execute(
+ "UPDATE refresh_tokens SET is_revoked = 1 WHERE token_hash = ?1",
+ [token_hash],
+ )?;
+ Ok(())
+ }
+
+ pub fn get_refresh_token_by_access_token(&self, access_token_id: i64) -> Result<Option<DbRefreshToken>> {
+ let mut stmt = self.conn.prepare(
+ "SELECT id, token_id, access_token_id, client_id, user_id, scope, expires_at,
+ created_at, is_revoked, token_hash
+ FROM refresh_tokens WHERE access_token_id = ?1 AND is_revoked = 0"
+ )?;
+
+ let token = stmt.query_row([access_token_id], |row| {
+ Ok(DbRefreshToken {
+ id: row.get(0)?,
+ token_id: row.get(1)?,
+ access_token_id: row.get(2)?,
+ client_id: row.get(3)?,
+ user_id: row.get(4)?,
+ scope: row.get(5)?,
+ expires_at: DateTime::parse_from_rfc3339(&row.get::<_, String>(6)?)
+ .map_err(|_| {
+ rusqlite::Error::InvalidColumnType(
+ 6,
+ "expires_at".to_string(),
+ rusqlite::types::Type::Text,
+ )
+ })?
+ .with_timezone(&Utc),
+ created_at: DateTime::parse_from_rfc3339(&row.get::<_, String>(7)?)
+ .map_err(|_| {
+ rusqlite::Error::InvalidColumnType(
+ 7,
+ "created_at".to_string(),
+ rusqlite::types::Type::Text,
+ )
+ })?
+ .with_timezone(&Utc),
+ is_revoked: row.get(8)?,
+ token_hash: row.get(9)?,
+ })
+ });
+
+ match token {
+ Ok(token) => Ok(Some(token)),
+ Err(rusqlite::Error::QueryReturnedNoRows) => Ok(None),
+ Err(e) => Err(e.into()),
+ }
+ }
+
// RSA Key operations
pub fn create_rsa_key(&self, key: &DbRsaKey) -> Result<i64> {
let mut stmt = self.conn.prepare(