- add: roles to user

- add: register calls for auth server
- add: user lookup by email
- add: start of password reset
- add: Cache trait to allow redis cache mocking
This commit is contained in:
2024-11-26 01:58:26 -05:00
parent 3fc6c6252c
commit 113ab5a4ac
8 changed files with 303 additions and 26 deletions

View File

@@ -2,7 +2,7 @@ use sqlx::Error;
use sqlx::PgPool;
use serde::{Serialize, Deserialize};
use std::sync::Arc;
use crate::redis_cache::RedisCache;
use crate::redis_cache::{Cache, RedisCache};
use tracing::{debug, error};
@@ -12,6 +12,7 @@ pub struct User {
pub username: String,
pub email: String,
pub hashed_password: String,
pub roles: Vec<String>,
}
pub struct UsersService {
@@ -50,13 +51,20 @@ impl UsersService {
}
// Fetch from PostgreSQL
let user = sqlx::query_as!(
User,
"SELECT id, username, email, hashed_password FROM users WHERE id = $1",
let row = sqlx::query!(
"SELECT id, username, email, hashed_password, roles FROM users WHERE id = $1",
user_id
)
.fetch_one(&self.pool)
.await?;
let user = User {
id: row.id,
username: row.username,
email: row.email,
hashed_password: row.hashed_password,
roles: row.roles.unwrap_or_default(),
};
// Store result in Redis
self.cache
@@ -74,14 +82,21 @@ impl UsersService {
}
// Fetch from PostgreSQL
let user = sqlx::query_as!(
User,
"SELECT id, username, email, hashed_password FROM users WHERE username = $1",
let row = sqlx::query!(
"SELECT id, username, email, hashed_password, roles FROM users WHERE username = $1",
username
)
.fetch_one(&self.pool)
.await?;
let user = User {
id: row.id,
username: row.username,
email: row.email,
hashed_password: row.hashed_password,
roles: row.roles.unwrap_or_default(),
};
// Store result in Redis
self.cache
.set(&format!("user_by_username:{}", username), &user, 3600)
@@ -91,6 +106,37 @@ impl UsersService {
Ok(user)
}
pub async fn get_user_by_email(&self, email: &str) -> Result<User, Error> {
// Check Redis cache first
if let Ok(Some(cached_user)) = self.cache.get::<User>(&format!("user_by_email:{}", email)).await {
return Ok(cached_user);
}
// Fetch from PostgreSQL
let row = sqlx::query!(
"SELECT id, username, email, hashed_password, roles FROM users WHERE email = $1",
email
)
.fetch_one(&self.pool)
.await?;
let user = User {
id: row.id,
username: row.username,
email: row.email,
hashed_password: row.hashed_password,
roles: row.roles.unwrap_or_default(),
};
// Store result in Redis
self.cache
.set(&format!("user_by_email:{}", email), &user, 3600)
.await
.unwrap_or_else(|err| eprintln!("Failed to cache user: {:?}", err));
Ok(user)
}
pub async fn update_user_email(&self, user_id: i32, new_email: &str) -> Result<(), Error> {
sqlx::query!(
r#"