diff options
Diffstat (limited to 'src/database.rs')
| -rw-r--r-- | src/database.rs | 121 |
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( |
