@@ -2,8 +2,8 @@ use chrono::{DateTime, Utc};
22
33use  crate :: external_urls:: remove_blocked_urls; 
44use  crate :: models:: { 
5-     ApiToken ,  Category ,  Crate ,  Dependency ,  DependencyKind ,  Keyword ,  Owner ,   ReverseDependency ,   Team , 
6-     TopVersions ,  User ,  Version ,  VersionDownload ,  VersionOwnerAction , 
5+     ApiToken ,  Category ,  Crate ,  Dependency ,  DependencyKind ,  Keyword ,  LinkedAccount ,   Owner , 
6+     ReverseDependency ,   Team ,   TopVersions ,  User ,  Version ,  VersionDownload ,  VersionOwnerAction , 
77} ; 
88use  crates_io_github as  github; 
99
@@ -790,9 +790,15 @@ pub struct EncodablePublicUser {
790790    /// The user's GitHub profile URL. 
791791#[ schema( example = "https://github.com/ghost" ) ]  
792792    pub  url :  String , 
793+ 
794+     /// The accounts linked to this crates.io account. 
795+ #[ serde( skip_serializing_if = "Option::is_none" ) ]  
796+     #[ schema( no_recursion,  example = json!( [ ] ) ) ]  
797+     pub  linked_accounts :  Option < Vec < EncodableLinkedAccount > > , 
793798} 
794799
795- /// Converts a `User` model into an `EncodablePublicUser` for JSON serialization. 
800+ /// Converts a `User` model into an `EncodablePublicUser` for JSON serialization. Does not include 
801+ /// linked accounts. 
796802impl  From < User >  for  EncodablePublicUser  { 
797803    fn  from ( user :  User )  -> Self  { 
798804        let  User  { 
@@ -805,13 +811,87 @@ impl From<User> for EncodablePublicUser {
805811        }  = user; 
806812        let  url = format ! ( "https://github.com/{gh_login}" ) ; 
807813        let  username = username. unwrap_or ( gh_login) ; 
814+ 
815+         EncodablePublicUser  { 
816+             id, 
817+             login :  username. clone ( ) , 
818+             username, 
819+             name, 
820+             avatar :  gh_avatar, 
821+             url, 
822+             linked_accounts :  None , 
823+         } 
824+     } 
825+ } 
826+ 
827+ impl  EncodablePublicUser  { 
828+     pub  fn  with_linked_accounts ( user :  User ,  linked_accounts :  & [ LinkedAccount ] )  -> Self  { 
829+         let  User  { 
830+             id, 
831+             name, 
832+             username, 
833+             gh_login, 
834+             gh_avatar, 
835+             ..
836+         }  = user; 
837+         let  url = format ! ( "https://github.com/{gh_login}" ) ; 
838+         let  username = username. unwrap_or ( gh_login) ; 
839+ 
840+         let  linked_accounts = if  linked_accounts. is_empty ( )  { 
841+             None 
842+         }  else  { 
843+             Some ( linked_accounts. iter ( ) . map ( Into :: into) . collect ( ) ) 
844+         } ; 
845+ 
808846        EncodablePublicUser  { 
809847            id, 
810848            login :  username. clone ( ) , 
811849            username, 
812850            name, 
813851            avatar :  gh_avatar, 
814852            url, 
853+             linked_accounts, 
854+         } 
855+     } 
856+ } 
857+ 
858+ #[ derive( Deserialize ,  Serialize ,  Debug ,  PartialEq ,  Eq ,  utoipa:: ToSchema ) ]  
859+ #[ schema( as  = LinkedAccount ) ]  
860+ pub  struct  EncodableLinkedAccount  { 
861+     /// The service providing this linked account. 
862+ #[ schema( example = "GitHub" ) ]  
863+     pub  provider :  String , 
864+ 
865+     /// The linked account's login name. 
866+ #[ schema( example = "ghost" ) ]  
867+     pub  login :  String , 
868+ 
869+     /// The linked account's avatar URL, if set. 
870+ #[ schema( example = "https://avatars2.githubusercontent.com/u/1234567?v=4" ) ]  
871+     pub  avatar :  Option < String > , 
872+ 
873+     /// The linked account's profile URL on the provided service. 
874+ #[ schema( example = "https://github.com/ghost" ) ]  
875+     pub  url :  String , 
876+ } 
877+ 
878+ /// Converts a `LinkedAccount` model into an `EncodableLinkedAccount` for JSON serialization. 
879+ impl  From < & LinkedAccount >  for  EncodableLinkedAccount  { 
880+     fn  from ( linked_account :  & LinkedAccount )  -> Self  { 
881+         let  LinkedAccount  { 
882+             provider, 
883+             login, 
884+             avatar, 
885+             ..
886+         }  = linked_account; 
887+ 
888+         let  url = provider. url ( login) ; 
889+ 
890+         Self  { 
891+             provider :  provider. to_string ( ) , 
892+             login :  login. clone ( ) , 
893+             avatar :  avatar. clone ( ) , 
894+             url, 
815895        } 
816896    } 
817897} 
@@ -1140,6 +1220,7 @@ mod tests {
11401220                    name:  None , 
11411221                    avatar:  None , 
11421222                    url:  String :: new( ) , 
1223+                     linked_accounts:  None , 
11431224                } , 
11441225                time:  NaiveDate :: from_ymd_opt( 2017 ,  1 ,  6 ) 
11451226                    . unwrap( ) 
0 commit comments