File tree Expand file tree Collapse file tree 5 files changed +648
-0
lines changed Expand file tree Collapse file tree 5 files changed +648
-0
lines changed Original file line number Diff line number Diff line change @@ -25,6 +25,7 @@ pub struct Server {
25
25
pub max_upload_size : u64 ,
26
26
pub max_unpack_size : u64 ,
27
27
pub publish_rate_limit : PublishRateLimit ,
28
+ pub new_version_rate_limit : Option < u32 > ,
28
29
pub blocked_traffic : Vec < ( String , Vec < String > ) > ,
29
30
pub max_allowed_page_offset : u32 ,
30
31
pub page_offset_ua_blocklist : Vec < String > ,
@@ -118,6 +119,7 @@ impl Default for Server {
118
119
max_upload_size : 10 * 1024 * 1024 , // 10 MB default file upload size limit
119
120
max_unpack_size : 512 * 1024 * 1024 , // 512 MB max when decompressed
120
121
publish_rate_limit : Default :: default ( ) ,
122
+ new_version_rate_limit : env_optional ( "MAX_NEW_VERSIONS_DAILY" ) ,
121
123
blocked_traffic : blocked_traffic ( ) ,
122
124
max_allowed_page_offset : env_optional ( "WEB_MAX_ALLOWED_PAGE_OFFSET" ) . unwrap_or ( 200 ) ,
123
125
page_offset_ua_blocklist,
Original file line number Diff line number Diff line change @@ -128,6 +128,15 @@ pub fn publish(req: &mut dyn RequestExt) -> EndpointResult {
128
128
) ) ) ;
129
129
}
130
130
131
+ if let Some ( daily_version_limit) = app. config . new_version_rate_limit {
132
+ let published_today = count_versions_published_today ( krate. id , & conn) ?;
133
+ if published_today >= daily_version_limit as i64 {
134
+ return Err ( cargo_err (
135
+ "You have published too many versions of this crate in the last 24 hours" ,
136
+ ) ) ;
137
+ }
138
+ }
139
+
131
140
// Length of the .crate tarball, which appears after the metadata in the request body.
132
141
// TODO: Not sure why we're using the total content length (metadata + .crate file length)
133
142
// to compare against the max upload size... investigate that and perhaps change to use
@@ -259,6 +268,19 @@ pub fn publish(req: &mut dyn RequestExt) -> EndpointResult {
259
268
} )
260
269
}
261
270
271
+ /// Counts the number of versions for `krate_id` that were published within
272
+ /// the last 24 hours.
273
+ fn count_versions_published_today ( krate_id : i32 , conn : & PgConnection ) -> QueryResult < i64 > {
274
+ use crate :: schema:: versions:: dsl:: * ;
275
+ use diesel:: dsl:: { now, IntervalDsl } ;
276
+
277
+ versions
278
+ . filter ( crate_id. eq ( krate_id) )
279
+ . filter ( created_at. gt ( now - 24 . hours ( ) ) )
280
+ . count ( )
281
+ . get_result ( conn)
282
+ }
283
+
262
284
/// Used by the `krate::new` function.
263
285
///
264
286
/// This function parses the JSON headers to interpret the data and validates
You can’t perform that action at this time.
0 commit comments