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}