@@ -15,7 +15,12 @@ use regex::Regex;
1515use ring:: digest:: { Context , SHA256 } ;
1616use serde:: Deserialize ;
1717use serde_json:: json;
18- use std:: { collections:: HashMap , convert:: TryFrom , convert:: TryInto , io:: BufReader } ;
18+ use std:: {
19+ collections:: HashMap ,
20+ convert:: { TryFrom , TryInto } ,
21+ fmt:: Display ,
22+ io:: BufReader ,
23+ } ;
1924use thiserror:: Error ;
2025use version:: { Range , Version } ;
2126use x509_parser:: prelude:: FromDer ;
@@ -538,23 +543,123 @@ pub fn revert_release_response(response: http::Response<Vec<u8>>) -> Result<(),
538543 }
539544}
540545
541- pub fn revert_package_request (
546+ /// See: https://github.com/hexpm/hex/blob/main/lib/mix/tasks/hex.owner.ex#L47
547+ #[ derive( Debug , Clone , Copy , PartialEq , Eq , PartialOrd , Ord ) ]
548+ pub enum OwnerLevel {
549+ /// Has every package permission EXCEPT the ability to change who owns the package
550+ Maintainer ,
551+ /// Has every package permission including the ability to change who owns the package
552+ Full ,
553+ }
554+
555+ impl Display for OwnerLevel {
556+ fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
557+ match self {
558+ OwnerLevel :: Maintainer => write ! ( f, "maintainer" ) ,
559+ OwnerLevel :: Full => write ! ( f, "full" ) ,
560+ }
561+ }
562+ }
563+
564+ /// API Docs:
565+ ///
566+ /// https://github.com/hexpm/hex/blob/main/lib/mix/tasks/hex.owner.ex#L107
567+ ///
568+ /// https://github.com/hexpm/hex/blob/main/lib/hex/api/package.ex#L19
569+ pub fn add_owner_request (
542570 package_name : & str ,
543571 owner : & str ,
572+ level : OwnerLevel ,
544573 api_key : & str ,
545574 config : & Config ,
546- ) -> Result < http:: Request < Vec < u8 > > , ApiError > {
547- Ok ( config
575+ ) -> http:: Request < Vec < u8 > > {
576+ let body = json ! ( {
577+ "level" : level. to_string( ) ,
578+ "transfer" : false ,
579+ } ) ;
580+
581+ config
582+ . api_request (
583+ Method :: PUT ,
584+ & format ! ( "packages/{}/owners/{}" , package_name, owner) ,
585+ Some ( api_key) ,
586+ )
587+ . body ( body. to_string ( ) . into_bytes ( ) )
588+ . expect ( "add_owner_request request" )
589+ }
590+
591+ pub fn add_owner_response ( response : http:: Response < Vec < u8 > > ) -> Result < ( ) , ApiError > {
592+ let ( parts, body) = response. into_parts ( ) ;
593+ match parts. status {
594+ StatusCode :: NO_CONTENT => Ok ( ( ) ) ,
595+ StatusCode :: NOT_FOUND => Err ( ApiError :: NotFound ) ,
596+ StatusCode :: TOO_MANY_REQUESTS => Err ( ApiError :: RateLimited ) ,
597+ StatusCode :: UNAUTHORIZED => Err ( ApiError :: InvalidApiKey ) ,
598+ StatusCode :: FORBIDDEN => Err ( ApiError :: Forbidden ) ,
599+ status => Err ( ApiError :: unexpected_response ( status, body) ) ,
600+ }
601+ }
602+
603+ /// API Docs:
604+ ///
605+ /// https://github.com/hexpm/hex/blob/main/lib/mix/tasks/hex.owner.ex#L125
606+ ///
607+ /// https://github.com/hexpm/hex/blob/main/lib/hex/api/package.ex#L19
608+ pub fn transfer_owner_request (
609+ package_name : & str ,
610+ owner : & str ,
611+ api_key : & str ,
612+ config : & Config ,
613+ ) -> http:: Request < Vec < u8 > > {
614+ let body = json ! ( {
615+ "level" : OwnerLevel :: Full . to_string( ) ,
616+ "transfer" : true ,
617+ } ) ;
618+
619+ config
620+ . api_request (
621+ Method :: PUT ,
622+ & format ! ( "packages/{}/owners/{}" , package_name, owner) ,
623+ Some ( api_key) ,
624+ )
625+ . body ( body. to_string ( ) . into_bytes ( ) )
626+ . expect ( "transfer_owner_request request" )
627+ }
628+
629+ pub fn transfer_owner_response ( response : http:: Response < Vec < u8 > > ) -> Result < ( ) , ApiError > {
630+ let ( parts, body) = response. into_parts ( ) ;
631+ match parts. status {
632+ StatusCode :: NO_CONTENT => Ok ( ( ) ) ,
633+ StatusCode :: NOT_FOUND => Err ( ApiError :: NotFound ) ,
634+ StatusCode :: TOO_MANY_REQUESTS => Err ( ApiError :: RateLimited ) ,
635+ StatusCode :: UNAUTHORIZED => Err ( ApiError :: InvalidApiKey ) ,
636+ StatusCode :: FORBIDDEN => Err ( ApiError :: Forbidden ) ,
637+ status => Err ( ApiError :: unexpected_response ( status, body) ) ,
638+ }
639+ }
640+
641+ /// API Docs:
642+ ///
643+ /// https://github.com/hexpm/hex/blob/main/lib/mix/tasks/hex.owner.ex#L139
644+ ///
645+ /// https://github.com/hexpm/hex/blob/main/lib/hex/api/package.ex#L28
646+ pub fn remove_owner_request (
647+ package_name : & str ,
648+ owner : & str ,
649+ api_key : & str ,
650+ config : & Config ,
651+ ) -> http:: Request < Vec < u8 > > {
652+ config
548653 . api_request (
549654 Method :: DELETE ,
550655 & format ! ( "packages/{}/owners/{}" , package_name, owner) ,
551656 Some ( api_key) ,
552657 )
553658 . body ( vec ! [ ] )
554- . expect ( "publish_package_request request" ) )
659+ . expect ( "remove_owner_request request" )
555660}
556661
557- pub fn revert_package_response ( response : http:: Response < Vec < u8 > > ) -> Result < ( ) , ApiError > {
662+ pub fn remove_owner_response ( response : http:: Response < Vec < u8 > > ) -> Result < ( ) , ApiError > {
558663 let ( parts, body) = response. into_parts ( ) ;
559664 match parts. status {
560665 StatusCode :: NO_CONTENT => Ok ( ( ) ) ,
0 commit comments