Add ConfigurePolicy and ClearRules to OperationRateLimiting
- Add ConfigurePolicy method to AbpOperationRateLimitingOptions for
partial modification of existing policies without full replacement
- Add ClearRules method to OperationRateLimitingPolicyBuilder for
clearing inherited rules before defining new ones
- Add FromPolicy factory method to reconstruct a builder from an
existing policy
- Change AddPolicy return type to AbpOperationRateLimitingOptions
for chaining consistency with ConfigurePolicy
- Add parameter validation to AddPolicy and FromPolicy
- Add documentation for overriding existing policies
- Add tests for ConfigurePolicy, ClearRules, chaining, and error cases
@ -114,6 +114,70 @@ The two counters are completely independent. If `alice` fails 5 times, her accou
When multiple rules are present, the module uses a two-phase approach: it checks all rules first, and only increments counters if every rule passes. This prevents a rule from consuming quota on a request that would have been rejected by another rule anyway.
## Customizing Policies from Reusable Modules
ABP modules (including your own) can ship with built-in rate limiting policies. For example, an Account module might define a `"Account.SendPasswordResetCode"` policy with conservative defaults that make sense for most applications. When you need different rules in your specific application, you have two options.
**Complete replacement with `AddPolicy`:** call `AddPolicy` with the same name and the second registration wins, replacing all rules from the module:
**Partial modification with `ConfigurePolicy`:** when you only want to tweak part of a policy — change the error code, add a secondary rule, or tighten the window — use `ConfigurePolicy`. The builder starts pre-populated with the module's existing rules, so you only express what changes.
For example, keep the module's default rules but assign your own localized error code:
If you want a clean slate, call `ClearRules()` first and then define entirely new rules — this gives you the same result as `AddPolicy` but makes the intent explicit:
> When multiple rules are present, the module uses a **two-phase check**: it first verifies all rules without incrementing counters, then increments only if all rules pass. This prevents wasted quota when one rule would block the request.
### Overriding an Existing Policy
If a reusable module (e.g., ABP's Account module) defines a policy with default rules, you have two ways to customize it in your own module's `ConfigureServices`.
**Option 1 — Full replacement with `AddPolicy`:**
Call `AddPolicy` with the same name. The last registration wins and completely replaces all rules:
````csharp
// In your application module — runs after the Account module
> `AddPolicy` stores policies in a dictionary keyed by name, so calling it again with the same name fully replaces the previous policy and all its rules.
**Option 2 — Partial modification with `ConfigurePolicy`:**
Use `ConfigurePolicy` to modify an existing policy without replacing it entirely. The builder is pre-populated with the existing rules, so you only need to express what changes:
`ConfigurePolicy` returns `AbpOperationRateLimitingOptions`, so you can chain multiple calls:
````csharp
options
.ConfigurePolicy("Account.SendPasswordResetCode", p => p.WithErrorCode("MyApp:SmsLimit"))
.ConfigurePolicy("Account.Login", p => p.WithErrorCode("MyApp:LoginLimit"));
````
> `ConfigurePolicy` throws `AbpException` if the policy name is not found. Use `AddPolicy` first (in the module that owns the policy), then `ConfigurePolicy` in downstream modules to customize it.
### Custom Error Code
By default, the exception uses the error code `Volo.Abp.OperationRateLimiting:010001`. You can override it per policy: