11use crate :: middleware:: AdminUser ;
22use crate :: models:: {
3- AdminAccessTokenResponse , AdminUserResponse , BatchUpdateModelApiRequest ,
4- CreateAdminAccessTokenRequest , DecimalPrice , DeleteAdminAccessTokenRequest , ErrorResponse ,
5- ListUsersResponse , ModelHistoryEntry , ModelHistoryResponse , ModelMetadata , ModelWithPricing ,
6- OrgLimitsHistoryEntry , OrgLimitsHistoryResponse , SpendLimit , UpdateOrganizationLimitsRequest ,
3+ AdminAccessTokenResponse , AdminUserOrganizationDetails , AdminUserResponse ,
4+ BatchUpdateModelApiRequest , CreateAdminAccessTokenRequest , DecimalPrice ,
5+ DeleteAdminAccessTokenRequest , ErrorResponse , ListUsersResponse , ModelHistoryEntry ,
6+ ModelHistoryResponse , ModelMetadata , ModelWithPricing , OrgLimitsHistoryEntry ,
7+ OrgLimitsHistoryResponse , SpendLimit , UpdateOrganizationLimitsRequest ,
78 UpdateOrganizationLimitsResponse ,
89} ;
910use axum:: {
@@ -159,8 +160,8 @@ pub async fn batch_upsert_models(
159160 tag = "Admin" ,
160161 params(
161162 ( "model_name" = String , Path , description = "Model name to get complete history for (URL-encode if it contains slashes)" ) ,
162- ( "limit" = i64 , Query , description = "Maximum number of history entries to return (default: 50)" ) ,
163- ( "offset" = i64 , Query , description = "Number of history entries to skip (default: 0)" )
163+ ( "limit" = Option < i64 > , Query , description = "Maximum number of history entries to return (default: 50)" ) ,
164+ ( "offset" = Option < i64 > , Query , description = "Number of history entries to skip (default: 0)" )
164165 ) ,
165166 responses(
166167 ( status = 200 , description = "Model history retrieved successfully" , body = ModelHistoryResponse ) ,
@@ -372,8 +373,8 @@ pub async fn update_organization_limits(
372373 tag = "Admin" ,
373374 params(
374375 ( "organization_id" = String , Path , description = "The organization's ID (as a UUID)" ) ,
375- ( "limit" = i64 , Query , description = "Maximum number of history records to return (default: 50)" ) ,
376- ( "offset" = i64 , Query , description = "Number of records to skip (default: 0)" )
376+ ( "limit" = Option < i64 > , Query , description = "Maximum number of history records to return (default: 50)" ) ,
377+ ( "offset" = Option < i64 > , Query , description = "Number of records to skip (default: 0)" )
377378 ) ,
378379 responses(
379380 ( status = 200 , description = "Limits history retrieved successfully" , body = OrgLimitsHistoryResponse ) ,
@@ -543,8 +544,9 @@ pub async fn delete_model(
543544 path = "/admin/users" ,
544545 tag = "Admin" ,
545546 params(
546- ( "limit" = i64 , Query , description = "Maximum number of users to return (default: 50)" ) ,
547- ( "offset" = i64 , Query , description = "Number of users to skip (default: 0)" )
547+ ( "limit" = Option <i64 >, Query , description = "Maximum number of users to return (default: 100)" ) ,
548+ ( "offset" = Option <i64 >, Query , description = "Number of users to skip (default: 0)" ) ,
549+ ( "include_organizations" = Option <bool >, Query , description = "Whether to include organization information and spend limits for the first organization owned by each user (default: false)" )
548550 ) ,
549551 responses(
550552 ( status = 200 , description = "Users retrieved successfully" , body = ListUsersResponse ) ,
@@ -563,44 +565,104 @@ pub async fn list_users(
563565 crate :: routes:: common:: validate_limit_offset ( params. limit , params. offset ) ?;
564566
565567 debug ! (
566- "List users request with limit={}, offset={}" ,
567- params. limit, params. offset
568+ "List users request with limit={}, offset={}, include_organizations={} " ,
569+ params. limit, params. offset, params . include_organizations
568570 ) ;
569571
570- let ( users, total) = app_state
571- . admin_service
572- . list_users ( params. limit , params. offset )
573- . await
574- . map_err ( |e| {
575- error ! ( "Failed to list users" ) ;
576- match e {
577- services:: admin:: AdminError :: Unauthorized ( msg) => (
578- StatusCode :: UNAUTHORIZED ,
579- ResponseJson ( ErrorResponse :: new ( msg, "unauthorized" . to_string ( ) ) ) ,
580- ) ,
581- _ => (
582- StatusCode :: INTERNAL_SERVER_ERROR ,
583- ResponseJson ( ErrorResponse :: new (
584- "Failed to retrieve users" . to_string ( ) ,
585- "internal_server_error" . to_string ( ) ,
586- ) ) ,
587- ) ,
588- }
589- } ) ?;
590-
591- let user_responses: Vec < AdminUserResponse > = users
592- . into_iter ( )
593- . map ( |u| AdminUserResponse {
594- id : u. id . to_string ( ) ,
595- email : u. email ,
596- username : Some ( u. username ) ,
597- display_name : u. display_name ,
598- avatar_url : u. avatar_url ,
599- created_at : u. created_at ,
600- last_login_at : u. last_login_at ,
601- is_active : u. is_active ,
602- } )
603- . collect ( ) ;
572+ let ( user_responses, total) = if params. include_organizations {
573+ // Fetch users with their default organization and spend limit
574+ let ( users_with_orgs, total) = app_state
575+ . admin_service
576+ . list_users_with_organizations ( params. limit , params. offset )
577+ . await
578+ . map_err ( |e| {
579+ error ! ( "Failed to list users with organizations" ) ;
580+ match e {
581+ services:: admin:: AdminError :: Unauthorized ( msg) => (
582+ StatusCode :: UNAUTHORIZED ,
583+ ResponseJson ( ErrorResponse :: new ( msg, "unauthorized" . to_string ( ) ) ) ,
584+ ) ,
585+ _ => (
586+ StatusCode :: INTERNAL_SERVER_ERROR ,
587+ ResponseJson ( ErrorResponse :: new (
588+ "Failed to retrieve users" . to_string ( ) ,
589+ "internal_server_error" . to_string ( ) ,
590+ ) ) ,
591+ ) ,
592+ }
593+ } ) ?;
594+
595+ let responses: Vec < AdminUserResponse > = users_with_orgs
596+ . into_iter ( )
597+ . map ( |( u, org_data) | {
598+ let organizations = org_data. map ( |org_info| {
599+ vec ! [ AdminUserOrganizationDetails {
600+ id: org_info. id. to_string( ) ,
601+ name: org_info. name,
602+ description: org_info. description,
603+ spend_limit: org_info. spend_limit. map( |amount| SpendLimit {
604+ amount,
605+ scale: 9 ,
606+ currency: "USD" . to_string( ) ,
607+ } ) ,
608+ } ]
609+ } ) ;
610+
611+ AdminUserResponse {
612+ id : u. id . to_string ( ) ,
613+ email : u. email ,
614+ username : Some ( u. username ) ,
615+ display_name : u. display_name ,
616+ avatar_url : u. avatar_url ,
617+ created_at : u. created_at ,
618+ last_login_at : u. last_login_at ,
619+ is_active : u. is_active ,
620+ organizations,
621+ }
622+ } )
623+ . collect ( ) ;
624+
625+ ( responses, total)
626+ } else {
627+ // Return users data only
628+ let ( users, total) = app_state
629+ . admin_service
630+ . list_users ( params. limit , params. offset )
631+ . await
632+ . map_err ( |e| {
633+ error ! ( "Failed to list users" ) ;
634+ match e {
635+ services:: admin:: AdminError :: Unauthorized ( msg) => (
636+ StatusCode :: UNAUTHORIZED ,
637+ ResponseJson ( ErrorResponse :: new ( msg, "unauthorized" . to_string ( ) ) ) ,
638+ ) ,
639+ _ => (
640+ StatusCode :: INTERNAL_SERVER_ERROR ,
641+ ResponseJson ( ErrorResponse :: new (
642+ "Failed to retrieve users" . to_string ( ) ,
643+ "internal_server_error" . to_string ( ) ,
644+ ) ) ,
645+ ) ,
646+ }
647+ } ) ?;
648+
649+ let responses: Vec < AdminUserResponse > = users
650+ . into_iter ( )
651+ . map ( |u| AdminUserResponse {
652+ id : u. id . to_string ( ) ,
653+ email : u. email ,
654+ username : Some ( u. username ) ,
655+ display_name : u. display_name ,
656+ avatar_url : u. avatar_url ,
657+ created_at : u. created_at ,
658+ last_login_at : u. last_login_at ,
659+ is_active : u. is_active ,
660+ organizations : None ,
661+ } )
662+ . collect ( ) ;
663+
664+ ( responses, total)
665+ } ;
604666
605667 let response = ListUsersResponse {
606668 users : user_responses,
@@ -703,7 +765,7 @@ pub async fn create_admin_access_token(
703765 path = "/admin/access-tokens" ,
704766 tag = "Admin" ,
705767 params(
706- ( "limit" = Option <i64 >, Query , description = "Number of records to return (default: 50 )" ) ,
768+ ( "limit" = Option <i64 >, Query , description = "Number of records to return (default: 100 )" ) ,
707769 ( "offset" = Option <i64 >, Query , description = "Number of records to skip (default: 0)" )
708770 ) ,
709771 responses(
@@ -858,6 +920,8 @@ pub struct ListUsersQueryParams {
858920 pub limit : i64 ,
859921 #[ serde( default ) ]
860922 pub offset : i64 ,
923+ #[ serde( default ) ]
924+ pub include_organizations : bool ,
861925}
862926
863927#[ derive( Debug , serde:: Deserialize ) ]
0 commit comments