Skip to main content

reinhardt_admin/server/
limits.rs

1//! Resource limits for admin panel operations
2//!
3//! This module defines configurable limits to prevent DoS attacks
4//! through resource exhaustion (memory, CPU, database).
5
6/// Maximum number of records that can be exported in a single request
7///
8/// This prevents memory exhaustion when exporting large tables.
9/// Default: 10,000 records
10pub const MAX_EXPORT_RECORDS: u64 = 10_000;
11
12/// Maximum import file size in bytes
13///
14/// This prevents memory exhaustion from large file uploads.
15/// Default: 10 MB
16pub const MAX_IMPORT_FILE_SIZE: usize = 10 * 1024 * 1024;
17
18/// Maximum number of records that can be imported in a single request
19///
20/// This prevents database overload from bulk inserts.
21/// Default: 1,000 records
22pub const MAX_IMPORT_RECORDS: usize = 1_000;
23
24/// Maximum number of IDs that can be deleted in a single bulk delete request
25///
26/// This prevents DoS attacks through extremely large ID lists
27/// that could exhaust database resources.
28/// Default: 1,000 IDs
29pub const MAX_BULK_DELETE_IDS: usize = 1_000;
30
31/// Maximum page size for list views
32///
33/// This prevents memory exhaustion from large page requests.
34/// Default: 500 records per page
35pub const MAX_PAGE_SIZE: u64 = 500;
36
37/// Default page size when not specified
38pub const DEFAULT_PAGE_SIZE: u64 = 25;
39
40#[cfg(all(test, server))]
41mod tests {
42	use super::*;
43	use rstest::rstest;
44
45	#[rstest]
46	fn export_records_limit_is_within_reasonable_bounds() {
47		// Arrange
48		let min = 1_u64;
49		let max = 100_000_u64;
50
51		// Act & Assert
52		assert!(MAX_EXPORT_RECORDS >= min);
53		assert!(MAX_EXPORT_RECORDS <= max);
54	}
55
56	#[rstest]
57	fn import_file_size_limit_is_within_reasonable_bounds() {
58		// Arrange
59		let min = 1_usize;
60		let max = 100 * 1024 * 1024_usize; // 100 MB
61
62		// Act & Assert
63		assert!(MAX_IMPORT_FILE_SIZE >= min);
64		assert!(MAX_IMPORT_FILE_SIZE <= max);
65	}
66
67	#[rstest]
68	fn import_records_limit_is_within_reasonable_bounds() {
69		// Arrange
70		let min = 1_usize;
71		let max = 10_000_usize;
72
73		// Act & Assert
74		assert!(MAX_IMPORT_RECORDS >= min);
75		assert!(MAX_IMPORT_RECORDS <= max);
76	}
77
78	#[rstest]
79	fn page_size_limit_is_within_reasonable_bounds() {
80		// Arrange
81		let min = 1_u64;
82		let max = 1_000_u64;
83
84		// Act & Assert
85		assert!(MAX_PAGE_SIZE >= min);
86		assert!(MAX_PAGE_SIZE <= max);
87	}
88
89	#[rstest]
90	fn default_page_size_does_not_exceed_max() {
91		// Act & Assert
92		assert!(DEFAULT_PAGE_SIZE > 0);
93		assert!(DEFAULT_PAGE_SIZE <= MAX_PAGE_SIZE);
94	}
95
96	#[rstest]
97	fn export_limit_is_expected_value() {
98		// Assert
99		assert_eq!(MAX_EXPORT_RECORDS, 10_000);
100	}
101
102	#[rstest]
103	fn import_file_size_limit_is_10mb() {
104		// Assert
105		assert_eq!(MAX_IMPORT_FILE_SIZE, 10 * 1024 * 1024);
106	}
107
108	#[rstest]
109	fn import_records_limit_is_expected_value() {
110		// Assert
111		assert_eq!(MAX_IMPORT_RECORDS, 1_000);
112	}
113
114	#[rstest]
115	fn page_size_limit_is_expected_value() {
116		// Assert
117		assert_eq!(MAX_PAGE_SIZE, 500);
118	}
119
120	#[rstest]
121	fn default_page_size_is_expected_value() {
122		// Assert
123		assert_eq!(DEFAULT_PAGE_SIZE, 25);
124	}
125
126	#[rstest]
127	fn bulk_delete_ids_limit_is_within_reasonable_bounds() {
128		// Arrange
129		let min = 1_usize;
130		let max = 10_000_usize;
131
132		// Act & Assert
133		assert!(MAX_BULK_DELETE_IDS >= min);
134		assert!(MAX_BULK_DELETE_IDS <= max);
135	}
136
137	#[rstest]
138	fn bulk_delete_ids_limit_is_expected_value() {
139		// Assert
140		assert_eq!(MAX_BULK_DELETE_IDS, 1_000);
141	}
142}