53
crates/adapters/sqlite/src/repositories/user/command.rs
Normal file
53
crates/adapters/sqlite/src/repositories/user/command.rs
Normal file
@@ -0,0 +1,53 @@
|
||||
use sqlx::SqlitePool;
|
||||
|
||||
use domain::errors::DomainError;
|
||||
use domain::user::{User, UserId};
|
||||
|
||||
use super::super::shared::db_err;
|
||||
|
||||
pub struct SqliteUserCommandRepository {
|
||||
pool: SqlitePool,
|
||||
}
|
||||
|
||||
impl SqliteUserCommandRepository {
|
||||
pub fn new(pool: SqlitePool) -> Self {
|
||||
Self { pool }
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl domain::ports::UserCommandPort for SqliteUserCommandRepository {
|
||||
async fn save(&self, user: &User) -> Result<(), DomainError> {
|
||||
sqlx::query(
|
||||
"INSERT INTO users (id, username, email, password_hash, display_name, timezone, role, created_at, updated_at)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
ON CONFLICT(id) DO UPDATE SET
|
||||
username = excluded.username, email = excluded.email,
|
||||
password_hash = excluded.password_hash, display_name = excluded.display_name,
|
||||
timezone = excluded.timezone, role = excluded.role,
|
||||
updated_at = excluded.updated_at"
|
||||
)
|
||||
.bind(user.id().value().to_string())
|
||||
.bind(user.username().value())
|
||||
.bind(user.email().value())
|
||||
.bind(user.password_hash().value())
|
||||
.bind(user.display_name().map(|d| d.value().to_string()))
|
||||
.bind(user.timezone().map(|t| t.value().to_string()))
|
||||
.bind(format!("{:?}", user.role()))
|
||||
.bind(user.created_at().to_rfc3339())
|
||||
.bind(user.updated_at().to_rfc3339())
|
||||
.execute(&self.pool)
|
||||
.await
|
||||
.map_err(db_err)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn delete(&self, id: &UserId) -> Result<(), DomainError> {
|
||||
sqlx::query("DELETE FROM users WHERE id = ?")
|
||||
.bind(id.value().to_string())
|
||||
.execute(&self.pool)
|
||||
.await
|
||||
.map_err(db_err)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user