11use crate :: auth:: AuthenticationParseError :: {
22 DuplicateAPIKeyArgument , DuplicateApplicationArgument , MissingAPIKeyArgument ,
3- MissingApplicationArgument , NoData , TooManyComponents ,
3+ MissingApplicationArgument , MissingRateLimitArgument , NoData , TooManyComponents ,
44} ;
55use std:: collections:: { HashMap , HashSet } ;
66
77#[ derive( Clone , Debug ) ]
88pub struct Authentication {
99 key_to_application : HashMap < String , String > ,
10+ app_to_rate_limit : HashMap < String , usize > ,
1011}
1112
1213#[ derive( Debug , PartialEq ) ]
1314pub enum AuthenticationParseError {
1415 NoData ( ) ,
1516 MissingApplicationArgument ( String ) ,
1617 MissingAPIKeyArgument ( String ) ,
18+ MissingRateLimitArgument ( String ) ,
1719 TooManyComponents ( String ) ,
1820 DuplicateApplicationArgument ( String ) ,
1921 DuplicateAPIKeyArgument ( String ) ,
@@ -23,9 +25,10 @@ impl std::fmt::Display for AuthenticationParseError {
2325 fn fmt ( & self , f : & mut std:: fmt:: Formatter ) -> std:: fmt:: Result {
2426 match self {
2527 NoData ( ) => write ! ( f, "No API Keys Provided" ) ,
26- MissingApplicationArgument ( arg) => write ! ( f, "Missing application argument: [{arg}]" ) ,
27- MissingAPIKeyArgument ( app) => write ! ( f, "Missing API Key argument: [{app}]" ) ,
28- TooManyComponents ( app) => write ! ( f, "Too many components: [{app}]" ) ,
28+ MissingApplicationArgument ( arg) => write ! ( f, "Missing application argument: [{}]" , arg) ,
29+ MissingAPIKeyArgument ( app) => write ! ( f, "Missing API Key argument: [{}]" , app) ,
30+ MissingRateLimitArgument ( app) => write ! ( f, "Missing rate limit argument: [{}]" , app) ,
31+ TooManyComponents ( app) => write ! ( f, "Too many components: [{}]" , app) ,
2932 DuplicateApplicationArgument ( app) => {
3033 write ! ( f, "Duplicate application argument: [{app}]" )
3134 }
@@ -42,6 +45,7 @@ impl TryFrom<Vec<String>> for Authentication {
4245 fn try_from ( args : Vec < String > ) -> Result < Self , Self :: Error > {
4346 let mut applications = HashSet :: new ( ) ;
4447 let mut key_to_application: HashMap < String , String > = HashMap :: new ( ) ;
48+ let mut app_to_rate_limit: HashMap < String , usize > = HashMap :: new ( ) ;
4549
4650 if args. is_empty ( ) {
4751 return Err ( NoData ( ) ) ;
@@ -61,6 +65,13 @@ impl TryFrom<Vec<String>> for Authentication {
6165 return Err ( MissingAPIKeyArgument ( app. to_string ( ) ) ) ;
6266 }
6367
68+ let rate_limit = parts
69+ . next ( )
70+ . ok_or ( MissingRateLimitArgument ( app. to_string ( ) ) ) ?;
71+ if rate_limit. is_empty ( ) {
72+ return Err ( MissingRateLimitArgument ( app. to_string ( ) ) ) ;
73+ }
74+
6475 if parts. count ( ) > 0 {
6576 return Err ( TooManyComponents ( app. to_string ( ) ) ) ;
6677 }
@@ -75,29 +86,42 @@ impl TryFrom<Vec<String>> for Authentication {
7586
7687 applications. insert ( app. to_string ( ) ) ;
7788 key_to_application. insert ( key. to_string ( ) , app. to_string ( ) ) ;
89+ app_to_rate_limit. insert ( app. to_string ( ) , rate_limit. parse ( ) . unwrap ( ) ) ;
7890 }
7991
80- Ok ( Self { key_to_application } )
92+ Ok ( Self {
93+ key_to_application,
94+ app_to_rate_limit,
95+ } )
8196 }
8297}
8398
8499impl Authentication {
85100 pub fn none ( ) -> Self {
86101 Self {
87102 key_to_application : HashMap :: new ( ) ,
103+ app_to_rate_limit : HashMap :: new ( ) ,
88104 }
89105 }
90106
91107 #[ allow( dead_code) ]
92- pub fn new ( api_keys : HashMap < String , String > ) -> Self {
108+ pub fn new (
109+ api_keys : HashMap < String , String > ,
110+ app_to_rate_limit : HashMap < String , usize > ,
111+ ) -> Self {
93112 Self {
94113 key_to_application : api_keys,
114+ app_to_rate_limit,
95115 }
96116 }
97117
98118 pub fn get_application_for_key ( & self , api_key : & String ) -> Option < & String > {
99119 self . key_to_application . get ( api_key)
100120 }
121+
122+ pub fn get_rate_limits ( & self ) -> HashMap < String , usize > {
123+ self . app_to_rate_limit . clone ( )
124+ }
101125}
102126
103127#[ cfg( test) ]
@@ -107,69 +131,90 @@ mod tests {
107131 #[ test]
108132 fn test_parsing ( ) {
109133 let auth = Authentication :: try_from ( vec ! [
110- "app1:key1" . to_string( ) ,
111- "app2:key2" . to_string( ) ,
112- "app3:key3" . to_string( ) ,
134+ "app1:key1:10 " . to_string( ) ,
135+ "app2:key2:10 " . to_string( ) ,
136+ "app3:key3:10 " . to_string( ) ,
113137 ] )
114138 . unwrap ( ) ;
115139
116140 assert_eq ! ( auth. key_to_application. len( ) , 3 ) ;
117141 assert_eq ! ( auth. key_to_application[ "key1" ] , "app1" ) ;
118142 assert_eq ! ( auth. key_to_application[ "key2" ] , "app2" ) ;
119143 assert_eq ! ( auth. key_to_application[ "key3" ] , "app3" ) ;
144+ assert_eq ! ( auth. app_to_rate_limit. len( ) , 3 ) ;
145+ assert_eq ! ( auth. app_to_rate_limit[ "app1" ] , 10 ) ;
146+ assert_eq ! ( auth. app_to_rate_limit[ "app2" ] , 10 ) ;
147+ assert_eq ! ( auth. app_to_rate_limit[ "app3" ] , 10 ) ;
120148
121149 let auth = Authentication :: try_from ( vec ! [
122- "app1:key1" . to_string( ) ,
150+ "app1:key1:10 " . to_string( ) ,
123151 "" . to_string( ) ,
124- "app3:key3" . to_string( ) ,
152+ "app3:key3:10 " . to_string( ) ,
125153 ] ) ;
126154 assert ! ( auth. is_err( ) ) ;
127155 assert_eq ! ( auth. unwrap_err( ) , MissingApplicationArgument ( "" . into( ) ) ) ;
128156
129157 let auth = Authentication :: try_from ( vec ! [
130- "app1:key1" . to_string( ) ,
158+ "app1:key1:10 " . to_string( ) ,
131159 "app2" . to_string( ) ,
132- "app3:key3" . to_string( ) ,
160+ "app3:key3:10 " . to_string( ) ,
133161 ] ) ;
134162 assert ! ( auth. is_err( ) ) ;
135163 assert_eq ! ( auth. unwrap_err( ) , MissingAPIKeyArgument ( "app2" . into( ) ) ) ;
136164
137165 let auth = Authentication :: try_from ( vec ! [
138- "app1:key1" . to_string( ) ,
139- ": " . to_string( ) ,
166+ "app1:key1:10 " . to_string( ) ,
167+ "app2:key2:10 " . to_string( ) ,
140168 "app3:key3" . to_string( ) ,
141169 ] ) ;
142170 assert ! ( auth. is_err( ) ) ;
171+ assert_eq ! ( auth. unwrap_err( ) , MissingRateLimitArgument ( "app3" . into( ) ) ) ;
172+
173+ let auth = Authentication :: try_from ( vec ! [
174+ "app1:key1:10" . to_string( ) ,
175+ ":" . to_string( ) ,
176+ "app3:key3:10" . to_string( ) ,
177+ ] ) ;
178+ assert ! ( auth. is_err( ) ) ;
143179 assert_eq ! ( auth. unwrap_err( ) , MissingApplicationArgument ( ":" . into( ) ) ) ;
144180
145181 let auth = Authentication :: try_from ( vec ! [
146- "app1:key1" . to_string( ) ,
182+ "app1:key1:10 " . to_string( ) ,
147183 "app2:" . to_string( ) ,
148- "app3:key3" . to_string( ) ,
184+ "app3:key3:10 " . to_string( ) ,
149185 ] ) ;
150186 assert ! ( auth. is_err( ) ) ;
151187 assert_eq ! ( auth. unwrap_err( ) , MissingAPIKeyArgument ( "app2" . into( ) ) ) ;
152188
153189 let auth = Authentication :: try_from ( vec ! [
154- "app1:key1" . to_string( ) ,
155- "app2:key2:unexpected2" . to_string( ) ,
156- "app3:key3" . to_string( ) ,
190+ "app1:key1:10" . to_string( ) ,
191+ "app2:key2:10" . to_string( ) ,
192+ "app3:key3:" . to_string( ) ,
193+ ] ) ;
194+ assert ! ( auth. is_err( ) ) ;
195+ assert_eq ! ( auth. unwrap_err( ) , MissingRateLimitArgument ( "app3" . into( ) ) ) ;
196+
197+ let auth = Authentication :: try_from ( vec ! [
198+ "app1:key1:10" . to_string( ) ,
199+ "app2:key2:10:unexpected2" . to_string( ) ,
200+ "app3:key3:10" . to_string( ) ,
157201 ] ) ;
158202 assert ! ( auth. is_err( ) ) ;
159203 assert_eq ! ( auth. unwrap_err( ) , TooManyComponents ( "app2" . into( ) ) ) ;
160204
161205 let auth = Authentication :: try_from ( vec ! [
162- "app1:key1" . to_string( ) ,
163- "app1:key3" . to_string( ) ,
164- "app2:key2" . to_string( ) ,
206+ "app1:key1:10 " . to_string( ) ,
207+ "app1:key3:10 " . to_string( ) ,
208+ "app2:key2:10 " . to_string( ) ,
165209 ] ) ;
166210 assert ! ( auth. is_err( ) ) ;
167211 assert_eq ! (
168212 auth. unwrap_err( ) ,
169213 DuplicateApplicationArgument ( "app1" . into( ) )
170214 ) ;
171215
172- let auth = Authentication :: try_from ( vec ! [ "app1:key1" . to_string( ) , "app2:key1" . to_string( ) ] ) ;
216+ let auth =
217+ Authentication :: try_from ( vec ! [ "app1:key1:10" . to_string( ) , "app2:key1:10" . to_string( ) ] ) ;
173218 assert ! ( auth. is_err( ) ) ;
174219 assert_eq ! ( auth. unwrap_err( ) , DuplicateAPIKeyArgument ( "app2" . into( ) ) ) ;
175220 }
0 commit comments