-
Notifications
You must be signed in to change notification settings - Fork 601
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement rate limiting for e-mail verifications #8419
base: main
Are you sure you want to change the base?
Conversation
This applies a burst of 3 and a refill time of 30 minutes by default per user. (Not that I can imagine a scenario where we'd ever override this for a user, but using the same machinery as other user actions is obviously much simpler.) I don't love that this ends up essentially prop-drilling the rate limiter into a bunch of new places, but I don't see an alternative other than prop-drilling the whole app struct through, which would be worse. This doesn't address (sorry) per-address rate limiting, but is at least a reasonable starting point.
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #8419 +/- ##
==========================================
+ Coverage 87.62% 87.63% +0.01%
==========================================
Files 272 272
Lines 26333 26426 +93
==========================================
+ Hits 23073 23158 +85
- Misses 3260 3268 +8 ☔ View full report in Codecov by Sentry. |
I think the root cause of this is that the model layer is currently sending emails, which IMHO is a bit questionable, especially because we're using this code path in a couple of places in the test suite too. It might be better to decouple these things first before introducing the rate limiting. |
Yeah, I went back and forth on this yesterday — decoupling the e-mail sending out of the model layer is better from an architectural perspective, but it means the The e-mail upsert code could be extracted into something that returns that state, but being in the same transaction as the user upsert is obviously a nice quality that would be bad to lose. I'm sorta wondering if we end up with something like this (treat names as placeholders): let new_user = NewUser::new(...);
let updater = new_user.create_or_update(&conn)?; // returns some intermediate type holding a transaction
let verification_required = updater.set_email(&email)?; // needs to be optional since not all updates might touch the e-mail?
updater.commit()?; // consumes updater
// Has to be after the commit;
if verification_required {
// send verification e-mail
} Another, simpler option would obviously be to return something else from Now I've typed this out, I probably have a slight preference for the second option (return something enclosing |
☔ The latest upstream changes (presumably 77d55e9) made this pull request unmergeable. Please resolve the merge conflicts. |
This applies a burst of 3 and a refill time of 30 minutes by default per user. (Not that I can imagine a scenario where we'd ever override this for a user, but using the same machinery as other user actions is obviously much simpler.)
I don't love that this ends up essentially prop-drilling the rate limiter into a bunch of new places, but I don't see an alternative other than prop-drilling the whole app struct through, which would be worse.
This doesn't address (sorry) per-address rate limiting, but is at least a reasonable starting point.