Skip to content
This repository has been archived by the owner on May 2, 2022. It is now read-only.

Enhance rate limit handling, add email config param #483

Merged
merged 12 commits into from
Apr 2, 2020

Conversation

sbocinec
Copy link
Contributor

@sbocinec sbocinec commented Mar 29, 2020

Changes

  • Add rate limit count as a config parameter: RATE_LIMIT_COUNT
  • Add rate limit window length as a config parameter: RATE_LIMIT_WINDOW
  • Add email as a config parameter: EMAIL
  • Add limit route & page view
  • Add contact partial
  • Update 404 & 500 views to use the contact partial
  • Update SK translations

Details

Rate limit enhancements

The original express-rate-limit code returns default generic message on exceeding the configured rate limit: Too many requests, please try again later. (English only). What's worse, administrators don't have any clue this is happening.

Users often share their IPv4 IP address as operators are using IPv6 and provide a shared IPv4 IP for hundreds of users. I've already experienced this on the SK deployment when users were affected unable to submit their reports until one user notified me having no clue what's going on.

This PR tries to address this situation and brings new /limit route, that can provide more localized info for users and also give us (admins) information, the rate limit has been reached (seeing /limit route in the analytics).

Email as a config param

Twitter handler was the only configurable contact available on the site. There are countries where twitter is not very popular or used, or some people don't have twitter account unable to contact us.

@@ -95,9 +96,12 @@ const extractTestResult = (req: Request): TestResult | undefined => {
};

const createReportRateLimit = rateLimit({
max: 20, // allowed requests per window
max: config.RATE_LIMIT, // allowed requests per window
windowMs: 24 * 60 * 60 * 1000, // 24 hour window,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we should add windowMs to the config as well? Makes sense as RATE_LIMIT option by itself doesn't really indicate how strict it is.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@michaelmcmillan perfect idea! I've added it in the latest commit, now we have:
RATE_LIMIT_COUNT and RATE_LIMIT_WINDOW new params - feel free to suggest better names :-)

I might later add config params README as the number of params starts to grow 😅

@michaelmcmillan michaelmcmillan self-requested a review March 29, 2020 22:05
@sbocinec sbocinec force-pushed the rate-limit-tweaks branch 2 times, most recently from b7a8a14 to bf69942 Compare March 30, 2020 17:27
@sbocinec sbocinec changed the title Enhance rate limit handling Enhance rate limit handling, add optional email config param Mar 30, 2020
@sbocinec sbocinec marked this pull request as ready for review March 30, 2020 18:40
windowMs: config.RATE_LIMIT_WINDOW, // window length in miliseconds
keyGenerator: req => determineRemoteAddress(req),
onLimitReached(req, res) {
return res.redirect(`${res.locals.urls.limit}`);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice, you don't really need the template literals here, return res.redirect(res.locals.urls.limit); will do

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice catch, thank you, fixing

@@ -22,6 +22,10 @@ router.get(`${urls.contributors}`, (req, res) => {
return res.render('pages/contributors');
});

router.get(`${urls.limit}`, (req, res) => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
router.get(`${urls.limit}`, (req, res) => {
router.get(urls.limit, (req, res) => {

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@fossecode i see also all other router.get above are using the same notation, why to change it specifically for this route?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably just a copy/paste error. Would have made sense to use template literals if we were to have a variable in the route, e.g.
router.get(`/${countryCode}/privacy-statement`, (req, res) => {

Copy link
Member

@fossecode fossecode Mar 30, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess it has been copied from
router.get(`${urls.profile}/:passcode`, async (req, res) => {

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah, okay, thanks for explanation :-) I can change & fix all

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fix commited

app/config.ts Outdated
@@ -26,6 +26,7 @@ const fallbackConfig: Config = {
MAP_CENTER: process.env.MAP_CENTER || '10.7522, 63.9139',
MAP_ZOOM: parseInt(process.env.MAP_ZOOM || '4', 10),
MAP_MAX_ZOOM: parseInt(process.env.MAP_MAX_ZOOM || '13', 10),
EMAIL: process.env.EMAIL,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know about the rest of you, but I feel we have been a bit inconsistent on what we put in the config vs what we put in the translations. We discussed this at one point, and I think we decided to put URLs, emails etc in the translation file. I also believe that is easier to maintain than the config (although both is hard 😓). In my opinion, we could at least move EMAIL, TWITTER (and possibly ZIP_PLACEHOLDER) to the translations. If we e.g. use __(`[email protected]`) when rendering the email, it would automatically fallback to [email protected] if it is not overriden. Thoughts on this?

Copy link
Contributor Author

@sbocinec sbocinec Mar 30, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would support the idea, but- AFAIK minority of the domains have email system configured for the domain. That's why I made it optional and only enable when explicitely enabled in the config. In this case I don't think it's good to move it to the translation files as most of those will use [email protected] what can be a bit misleading.

I tried to create the contact partial dynamic and only display email when it's set.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I get the point. But do you think that it is better to don't display a contact email at all if it is not set? We have gotten a few questions and comments from different countries on our email, so it could be nice to have a fallback?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, I didn't realize that, it makes sense to have the fallback email 👍
So, should I move it to the translations then?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah or you could also do EMAIL: process.env.EMAIL || '[email protected]'. I think I would prefer translations, but you can use the config if it is easier :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay. According to these info, I will use the default value here and:

  1. Keep EMAIL in the config to have it next to the TWITTER
  2. Move both EMAIL and TWITTER in another PR to the translations (I guess moving the TW would require much more effort due to the testing of all other parts where TW is actually used)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

change commited

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if it's worth to add the option to config.example.json yet, not to confuse people if it's gonna move out soon.

@sbocinec sbocinec changed the title Enhance rate limit handling, add optional email config param Enhance rate limit handling, add email config param Mar 30, 2020
@fossecode
Copy link
Member

Since this a page that is not part of the ordinary flow, I guess it is ok to merge it without getting translations for all languages first. In the rare case where people hit the rate limit, it should be ok that it is in english.

@fossecode
Copy link
Member

Could you fix the conflicts, and then we'll merge!

@fossecode
Copy link
Member

Is this one ready to be merged?

@sbocinec
Copy link
Contributor Author

sbocinec commented Apr 2, 2020

Is this one ready to be merged?

Going to rebase and will be ready soon :-)

app/server.ts Outdated
@@ -82,6 +83,8 @@ app.use((req, res, next) => {
res.locals.localeToFlag = localeToFlag;
res.locals.currentLocale = req.getLocale();
res.locals.formatNumber = createNumberFormatter(config.THOUSAND_SEPARATOR);
res.locals.rateLimitCount = config.RATE_LIMIT_COUNT;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This and the next line can be removed

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks, removed!

@fossecode fossecode merged commit 3fee78d into BustByte:master Apr 2, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants