@@ -9,6 +9,7 @@ use std::time::Duration;
9
9
crate :: pg_enum! {
10
10
pub enum LimitedAction {
11
11
PublishNew = 0 ,
12
+ PublishExisting = 1 ,
12
13
}
13
14
}
14
15
@@ -17,13 +18,15 @@ impl LimitedAction {
17
18
pub fn default_rate_seconds ( & self ) -> u64 {
18
19
match self {
19
20
LimitedAction :: PublishNew => 60 * 10 ,
21
+ LimitedAction :: PublishExisting => 60 ,
20
22
}
21
23
}
22
24
23
25
/// How many requests a user can make before the rate limit goes into effect.
24
26
pub fn default_burst ( & self ) -> i32 {
25
27
match self {
26
28
LimitedAction :: PublishNew => 5 ,
29
+ LimitedAction :: PublishExisting => 30 ,
27
30
}
28
31
}
29
32
@@ -32,13 +35,17 @@ impl LimitedAction {
32
35
LimitedAction :: PublishNew => {
33
36
"You have published too many new crates in a short period of time."
34
37
}
38
+ LimitedAction :: PublishExisting => {
39
+ "You have published too many versions of existing crates in a short period of time."
40
+ }
35
41
}
36
42
}
37
43
38
44
/// Key used to identify this action in environment variables. See `src/config.rs`.
39
45
pub fn env_var_key ( & self ) -> & ' static str {
40
46
match self {
41
47
LimitedAction :: PublishNew => "PUBLISH_NEW" ,
48
+ LimitedAction :: PublishExisting => "PUBLISH_EXISTING" ,
42
49
}
43
50
}
44
51
}
@@ -350,6 +357,49 @@ mod tests {
350
357
Ok ( ( ) )
351
358
}
352
359
360
+ #[ test]
361
+ fn two_actions_dont_interfere_with_each_other ( ) -> QueryResult < ( ) > {
362
+ let conn = pg_connection ( ) ;
363
+ let now = now ( ) ;
364
+ let user_id = new_user ( & conn, "user" ) ?;
365
+
366
+ let mut config = HashMap :: new ( ) ;
367
+ config. insert (
368
+ LimitedAction :: PublishNew ,
369
+ RateLimiterConfig {
370
+ rate : Duration :: from_secs ( 1 ) ,
371
+ burst : 10 ,
372
+ } ,
373
+ ) ;
374
+ config. insert (
375
+ LimitedAction :: PublishExisting ,
376
+ RateLimiterConfig {
377
+ rate : Duration :: from_secs ( 1 ) ,
378
+ burst : 20 ,
379
+ } ,
380
+ ) ;
381
+ let rate = RateLimiter :: new ( config) ;
382
+
383
+ let refill_time = now + chrono:: Duration :: seconds ( 4 ) ;
384
+ assert_eq ! (
385
+ 10 ,
386
+ rate. take_token( user_id, LimitedAction :: PublishNew , refill_time, & conn) ?
387
+ . tokens,
388
+ ) ;
389
+ assert_eq ! (
390
+ 9 ,
391
+ rate. take_token( user_id, LimitedAction :: PublishNew , refill_time, & conn) ?
392
+ . tokens,
393
+ ) ;
394
+ assert_eq ! (
395
+ 20 ,
396
+ rate. take_token( user_id, LimitedAction :: PublishExisting , refill_time, & conn) ?
397
+ . tokens,
398
+ ) ;
399
+
400
+ Ok ( ( ) )
401
+ }
402
+
353
403
#[ test]
354
404
fn override_is_used_instead_of_global_burst_if_present ( ) -> QueryResult < ( ) > {
355
405
let conn = pg_connection ( ) ;
@@ -375,6 +425,47 @@ mod tests {
375
425
Ok ( ( ) )
376
426
}
377
427
428
+ #[ test]
429
+ fn override_is_different_for_each_action ( ) -> QueryResult < ( ) > {
430
+ let conn = pg_connection ( ) ;
431
+ let now = now ( ) ;
432
+ let user_id = new_user ( & conn, "user" ) ?;
433
+
434
+ let mut config = HashMap :: new ( ) ;
435
+ for action in & [ LimitedAction :: PublishNew , LimitedAction :: PublishExisting ] {
436
+ config. insert (
437
+ * action,
438
+ RateLimiterConfig {
439
+ rate : Duration :: from_secs ( 1 ) ,
440
+ burst : 10 ,
441
+ } ,
442
+ ) ;
443
+ }
444
+ let rate = RateLimiter :: new ( config) ;
445
+
446
+ diesel:: insert_into ( publish_rate_overrides:: table)
447
+ . values ( (
448
+ publish_rate_overrides:: user_id. eq ( user_id) ,
449
+ publish_rate_overrides:: action. eq ( LimitedAction :: PublishNew ) ,
450
+ publish_rate_overrides:: burst. eq ( 20 ) ,
451
+ ) )
452
+ . execute ( & conn) ?;
453
+
454
+ let refill_time = now + chrono:: Duration :: seconds ( 4 ) ;
455
+ assert_eq ! (
456
+ 20 ,
457
+ rate. take_token( user_id, LimitedAction :: PublishNew , refill_time, & conn) ?
458
+ . tokens,
459
+ ) ;
460
+ assert_eq ! (
461
+ 10 ,
462
+ rate. take_token( user_id, LimitedAction :: PublishExisting , refill_time, & conn) ?
463
+ . tokens,
464
+ ) ;
465
+
466
+ Ok ( ( ) )
467
+ }
468
+
378
469
#[ test]
379
470
fn overrides_can_expire ( ) -> QueryResult < ( ) > {
380
471
let conn = pg_connection ( ) ;
0 commit comments