darkwing/database/user/
repository.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
//! User repository module providing database access layer for user-related
//! operations.
//!
//! This module implements the repository pattern for user data access,
//! providing a trait-based abstraction over the actual database implementation.

use anyhow::Context;
use std::sync::Arc;

use crate::database::Database;
use async_trait::async_trait;
use mockall::automock;
use sqlx::query_as;

use super::User;

/// A thread-safe reference-counted pointer to a dynamic `UsersRepository` trait
/// object.
///
/// This type alias provides a convenient way to handle user repository
/// instances across multiple threads while maintaining proper reference
/// counting.
pub type DynUsersRepository = Arc<dyn UsersRepository + Send + Sync>;

/// Defines the interface for user-related database operations.
///
/// This trait provides a contract for implementing user repository operations,
/// allowing for different implementations (like production database, mock for
/// testing).
#[automock]
#[async_trait]
pub trait UsersRepository {
  /// Retrieves a user by their unique identifier.
  async fn get_user_by_id(&self, id: u64) -> anyhow::Result<User>;
}

/// Implementation of `UsersRepository` for the main database.
///
/// This implementation provides the actual database operations using SQLx
/// to interact with the underlying database.
#[async_trait]
impl UsersRepository for Database {
  async fn get_user_by_id(&self, id: u64) -> anyhow::Result<User> {
    query_as!(
      User,
      r#"
        SELECT id, teamId, username, role
        FROM users
        WHERE id = ?
        AND deleted_at IS NULL
            "#,
      id,
    )
    .fetch_one(&self.pool)
    .await
    .context("user was not found")
  }
}