Skip to main content

auth/
admin.rs

1use crate::models::{AuthUser, AuthUserId};
2use crate::repositories::AuthUserRepository;
3use platform_core::{AppError, AppResult, ErrorCode};
4use platform_module::{AdminDataSource, AdminListQuery, AdminPage};
5use serde_json::Value;
6use std::sync::Arc;
7
8#[derive(Debug)]
9pub struct AuthAdminData {
10    repository: Arc<dyn AuthUserRepository>,
11}
12
13impl AuthAdminData {
14    #[must_use]
15    pub fn new(repository: Arc<dyn AuthUserRepository>) -> Self {
16        Self { repository }
17    }
18}
19
20#[async_trait::async_trait]
21impl AdminDataSource for AuthAdminData {
22    async fn list(&self, entity: &str, query: &AdminListQuery) -> AppResult<AdminPage> {
23        match entity {
24            "users" => {
25                let rows = self
26                    .repository
27                    .list(query.limit.saturating_add(1), query.cursor.as_deref())
28                    .await?;
29                let has_more = rows.len() as i64 > query.limit.max(0);
30                let take = rows.len().min(query.limit.max(0) as usize);
31                let page_rows = &rows[..take];
32                let next_cursor = if has_more {
33                    page_rows.last().map(|user| user.id.0.clone())
34                } else {
35                    None
36                };
37                Ok(AdminPage {
38                    records: page_rows.iter().map(user_to_value).collect(),
39                    next_cursor,
40                })
41            }
42            other => Err(unknown_entity(other)),
43        }
44    }
45
46    async fn get(&self, entity: &str, id: &str) -> AppResult<Option<Value>> {
47        match entity {
48            "users" => Ok(self
49                .repository
50                .find_by_id(&AuthUserId(id.to_owned()))
51                .await?
52                .as_ref()
53                .map(user_to_value)),
54            other => Err(unknown_entity(other)),
55        }
56    }
57}
58
59fn unknown_entity(entity: &str) -> AppError {
60    AppError::new(
61        ErrorCode::NotFound,
62        format!("unknown admin entity: {entity}"),
63    )
64}
65
66fn user_to_value(user: &AuthUser) -> Value {
67    serde_json::json!({
68        "id": user.id.0,
69        "created_at": user.created_at,
70        "disabled_at": user.disabled_at,
71    })
72}
73
74#[cfg(test)]
75mod tests {
76    use super::*;
77    use chrono::Utc;
78
79    #[test]
80    fn user_to_value_keys_match_schema_fields() {
81        let now = Utc::now();
82        let value = user_to_value(&AuthUser {
83            id: AuthUserId("usr_1".to_owned()),
84            created_at: now,
85            disabled_at: None,
86        });
87        let object = value.as_object().expect("object");
88        let mut keys = object.keys().collect::<Vec<_>>();
89        keys.sort();
90        assert_eq!(keys, vec!["created_at", "disabled_at", "id"]);
91    }
92}