11use aide:: NoApi ;
22use axum:: Json ;
3- use axum:: extract:: Path ;
3+ use axum:: extract:: { Path , Query } ;
44use axum:: {
55 Extension ,
66 extract:: State ,
@@ -9,7 +9,7 @@ use axum::{
99} ;
1010
1111use schemars:: JsonSchema ;
12- use serde:: Serialize ;
12+ use serde:: { Deserialize , Serialize } ;
1313use tower_cookies:: Cookies ;
1414
1515use crate :: models:: heartbeat:: Heartbeat ;
@@ -20,6 +20,18 @@ use crate::utils::cache::CachedAdminStats;
2020use crate :: utils:: session:: { ImpersonationContext , SessionManager } ;
2121use crate :: { db_query, get_db_conn} ;
2222
23+ #[ derive( Deserialize , JsonSchema ) ]
24+ pub struct AdminQuery {
25+ #[ serde( default = "default_limit" ) ]
26+ pub limit : i64 ,
27+ #[ serde( default ) ]
28+ pub offset : i64 ,
29+ }
30+
31+ fn default_limit ( ) -> i64 {
32+ 50
33+ }
34+
2335#[ derive( Serialize , JsonSchema ) ]
2436pub struct FormattedDailyActivity {
2537 pub date : String ,
@@ -35,10 +47,13 @@ pub struct AdminDashboardResponse {
3547 pub requests_per_second : f64 ,
3648 pub daily_activity : Vec < FormattedDailyActivity > ,
3749 pub all_users : Vec < PartialUser > ,
50+ pub limit : i64 ,
51+ pub offset : i64 ,
3852}
3953
4054pub async fn admin_dashboard (
4155 State ( app_state) : State < AppState > ,
56+ Query ( query) : Query < AdminQuery > ,
4257 user : NoApi < Option < Extension < User > > > ,
4358) -> Result < Json < AdminDashboardResponse > , Response > {
4459 // check if user is an admin
@@ -52,60 +67,58 @@ pub async fn admin_dashboard(
5267 }
5368
5469 let include_api_key = current_user. is_owner ( ) ;
70+ let limit = query. limit . clamp ( 1 , 100 ) ;
71+ let offset = query. offset . max ( 0 ) ;
5572
5673 let cached = app_state. cache . admin . get ( & ( ) ) ;
57- let (
58- total_users,
59- total_heartbeats,
60- heartbeats_last_hour,
61- heartbeats_last_24h,
62- daily_activity,
63- all_users,
64- ) = if let Some ( cached) = cached {
65- (
66- cached. total_users ,
67- cached. total_heartbeats ,
68- cached. heartbeats_last_hour ,
69- cached. heartbeats_last_24h ,
70- cached. daily_activity ,
71- cached. all_users ,
72- )
73- } else {
74- let mut conn = get_db_conn ! ( app_state) ;
75-
76- let raw_daily_activity = db_query ! (
77- Heartbeat :: get_daily_activity_last_week( & mut conn) ,
78- "Failed to fetch daily activity"
79- ) ;
80- let all_users = db_query ! ( User :: list_all_users( & mut conn) , "Failed to fetch users" ) ;
81- let total_users = db_query ! ( User :: count_total_users( & mut conn, false ) ) ;
82- let total_heartbeats = db_query ! ( Heartbeat :: count_total_heartbeats( & mut conn) ) ;
83- let heartbeats_last_hour = db_query ! ( Heartbeat :: count_heartbeats_last_hour( & mut conn) ) ;
84- let heartbeats_last_24h = db_query ! ( Heartbeat :: count_heartbeats_last_24h( & mut conn) ) ;
85-
86- app_state. cache . admin . insert (
87- ( ) ,
88- CachedAdminStats {
74+ let ( total_users, total_heartbeats, heartbeats_last_hour, heartbeats_last_24h, daily_activity) =
75+ if let Some ( cached) = cached {
76+ (
77+ cached. total_users ,
78+ cached. total_heartbeats ,
79+ cached. heartbeats_last_hour ,
80+ cached. heartbeats_last_24h ,
81+ cached. daily_activity ,
82+ )
83+ } else {
84+ let mut conn = get_db_conn ! ( app_state) ;
85+
86+ let raw_daily_activity = db_query ! (
87+ Heartbeat :: get_daily_activity_last_week( & mut conn) ,
88+ "Failed to fetch daily activity"
89+ ) ;
90+ let total_users = db_query ! ( User :: count_total_users( & mut conn, false ) ) ;
91+ let total_heartbeats = db_query ! ( Heartbeat :: count_total_heartbeats_estimate( & mut conn) ) ;
92+ let heartbeats_last_hour = db_query ! ( Heartbeat :: count_heartbeats_last_hour( & mut conn) ) ;
93+ let heartbeats_last_24h = db_query ! ( Heartbeat :: count_heartbeats_last_24h( & mut conn) ) ;
94+
95+ app_state. cache . admin . insert (
96+ ( ) ,
97+ CachedAdminStats {
98+ total_users,
99+ total_heartbeats,
100+ heartbeats_last_hour,
101+ heartbeats_last_24h,
102+ daily_activity : raw_daily_activity. clone ( ) ,
103+ } ,
104+ ) ;
105+
106+ (
89107 total_users,
90108 total_heartbeats,
91109 heartbeats_last_hour,
92110 heartbeats_last_24h,
93- daily_activity : raw_daily_activity. clone ( ) ,
94- all_users : all_users. clone ( ) ,
95- } ,
96- ) ;
97-
98- (
99- total_users,
100- total_heartbeats,
101- heartbeats_last_hour,
102- heartbeats_last_24h,
103- raw_daily_activity,
104- all_users,
105- )
106- } ;
111+ raw_daily_activity,
112+ )
113+ } ;
114+
115+ let mut conn = get_db_conn ! ( app_state) ;
116+ let paginated_users = db_query ! (
117+ User :: list_users_paginated( & mut conn, limit, offset) ,
118+ "Failed to fetch users"
119+ ) ;
107120
108- let partial_users = all_users
121+ let partial_users = paginated_users
109122 . iter ( )
110123 . map ( |user| PartialUser {
111124 id : user. id ,
@@ -137,6 +150,8 @@ pub async fn admin_dashboard(
137150 / 1000.0 ,
138151 daily_activity,
139152 all_users : partial_users,
153+ limit,
154+ offset,
140155 } ) )
141156}
142157
0 commit comments