* Tie rate limits to both the user's ID and their IP address.
* Make each endpoint have separate rate limits. This means that, for
example, your post edit rate limit is separate from your post vote
rate limit. Before all write actions had a shared rate limit.
* Make all write endpoints have rate limits. Before some endpoints, such
as voting, favoriting, commenting, or forum posting, weren't subject
to rate limits.
* Add stricter rate limits for some endpoints:
** 1 per 5 minutes for creating new accounts.
** 1 per minute for login attempts, changing your email address, or
for creating mod reports.
** 1 per minute for sending dmails, creating comments, creating forum
posts, or creating forum topics.
** 1 per second for voting, favoriting, or disapproving posts.
** These rate limits all have burst factors high enough that they
shouldn't affect normal, non-automated users.
* Raise the default write rate limit for Gold users from 2 per second to
4 per second, for all other actions not listed above.
* Raise the default burst factor to 200 for all other actions not listed
above. Before it was 10 for Members, 30 for Gold, and 60 for Platinum.
Rework the rate limit implementation to make it more flexible:
* Allow setting different rate limits for different actions. Before we
had a single rate limit for all write actions. Now different
controller endpoints can have different limits.
* Allow actions to be rate limited by user ID, by IP address, or both.
Before actions were only limited by user ID, which meant non-logged-in
actions like creating new accounts or attempting to login couldn't be rate
limited. Also, because actions were limited by user ID only, you could
use multiple accounts with the same IP to get around limits.
Other changes:
* Remove the API Limit field from user profile pages.
* Remove the `remaining_api_limit` field from the `/profile.json` endpoint.
* Rename the `X-Api-Limit` header to `X-Rate-Limit` and change it from a
number to a JSON object containing all the rate limit info
(including the refill rate, the burst factor, the cost of the call,
and the current limits).
* Fix a potential race condition where, if you flooded requests fast
enough, you could exceed the rate limit. This was because we checked
and updated the rate limit in two separate steps, which was racy;
simultaneous requests could pass the check before the update happened.
The new code uses some tricky SQL to check and update multiple limits
in a single statement.
The search form uses a <button type="submit"> tag instead of a
<input type="submit"> tag. It uses a <button> because it contains an
icon and <input> tags can't contain nested tags.
Light mode:
* Change child post border from orange back to dark yellow (still darker
than previous yellow).
* Make flagged borders brighter red.
* Make admins brighter red.
* Make parent, child, and pending post notice bars brighter.
* Change copyright tags from purple to magenta (very close to copyright
tag color from before).
* Darken forum topic new/approved/rejected labels.
Dark mode:
* Make platinum users brighter grey.
Add site icons linking to all the artist's sites in the fetch source
data box.
Some artist entries have a large number of URLs. Various heuristics are
applied to try to present the most useful URLs first. Dead URLs and
redundant URLs (Pixiv stacc and Twitter intent URLs) are filtered out.
Remaining URLs are sorted first by site (to put sites like Pixiv and
Twitter first), then by URL (to break ties when an artist has multiple
accounts on the same site).
Some sites have shitty hard-to-read icons. It can't be helped. The icons
are the official favicons of each site.
This happens because toggling a related tag updates the tag box, which
triggers autocomplete, which can't find a tag because the cursor isn't
in the tag box, so it ends up making an autocomplete call for the empty
string.
Make related tags use a single-column layout on mobile.
Related tags layout is still broken inside the tag edit dialog box, when
the dialog box is too small for multiple columns.
* Use -webkit-text-stroke instead of bold to indicate selected tags.
Bold causes the tag to change width, which is jarring and can cause
the tag to wrap around to a new line. -webkit-text-stroke doesn't
change the tag's width. Despite the name, this property is widely
supported.
* Don't wrap the checkbox in a label. In combination with flexbox, this
made the hitbox for the tag too big. You could click on empty space
outside the tag and it would still toggle the tag.
Instead of changing the background color of the entire page when you
change modes in the post mode menu (which was ugly, and not obvious what
the colors meant), show a notice and make it so that hovering a post
gives it a blue outline. This indicates that clicking the post will do
something different.
Fix issues with note sizing caused by the switch to `box-sizing: border-box`
in 19aea560. Note boxes have a 1px black border, which is counted as
part of the note box width when using border-box. This threw off sizing
and position calculations.
Also go back to 1px borders instead of 2px borders for unsaved and
selected notes. This also messed up note sizing.
* Standardize dialog box and tooltip box shadows.
* Add shadows behind all other floating elements, namely the
autocomplete menu and translation notes (except for embedded notes,
which are usually meant to be seamless).
Remove some rules intended to highlight the currently selected tag in
the autocomplete menu. The selected tag was supposed to be shown with
the tag hover color, but this didn't actually work because of CSS
specificity issues, and it possibly never worked to begin with, so it's
not worth fixing.
Partial revert of b9ea9d2f5. Go back to using a semi-transparent
background to indicate the selected parent/child post, but add more
padding and adjust the transparency to make it more legible.
In the related tags list, use checkboxes and bold to indicate selected
tags, instead of highlighting selected tags with a blue background.
This is so that you can see the colors of selected tags in the related
tags list, and in particular so you can see the artist tag.
Change the new, approved, pending, and rejected labels in the forum to
use an outlined pill style (like user levels in user tooltips) instead
of a filled background style. This is less obtrusive and more readable
in dark mode.
Remove the follow properties:
* clear (wasn't used)
* list-style-* (wasn't used)
* outline (only used a few times; can be achieved with borders or
box-shadow).
* mask (not well-supported in browsers; only used a few times for
effects that could be achieved in other ways).
* text-decoration-* (use the shorthand property)
* text-transform (can be achieved in other ways)
* Fix it so that all edit forms show an error banner if the form
has validation errors. Previously forms had to manually call
`error_messages_for`, which not all forms did.
* Fix it so that the full validation error message is shown next to each
input attribute that had errors. Also update the styling of these
error messages to look better.
* On the post show page, in the parent/child box, change it so that
currently selected post is more visible. Use a light blue outline
around the current post instead of a dark semi-transparent border.
* Fix it so that there's less empty space around thumbnails in the
parent/child box.
Add a new color palette and rework all site colors (both light mode and dark mode) to
use the new palette.
This ensures that colors are used consistently, from a carefully designed color palette,
instead of being chosen at random.
Before, colors in light mode were chosen on an ad-hoc basis, which resulted in a lot of
random colors and inconsistent design.
The new palette has 7 hues: red, orange, yellow, green, blue, azure (a lighter blue), and
purple. There's also a greyscale. Each hue has 10 shades of brightness, which (including
grey) gives us 80 total colors.
Colors are named like this:
var(--red-0); /* very light red */
var(--red-2); /* light red */
var(--red-5); /* medium red */
var(--red-7); /* dark red */
var(--red-9); /* very dark red */
var(--green-7); /* dark green */
var(--blue-5); /* medium blue */
var(--purple-3); /* light purple */
/* etc */
The color palette is designed to meet the following criteria:
* To have close equivalents to the main colors used in the old color scheme,
especially tag colors, so that changes to major colors are minimized.
* To produce a set of colors that can be used as as main text colors, as background
colors, and as accent colors, both in light mode and dark mode.
* To ensure that colors at the same brightness level have the same perceived brightness.
Green-4, blue-4, red-4, purple-4, etc should all have the same brightness and contrast
ratios. This way colors look balanced. This is actually a difficult problem, because human
color perception is non-linear, so you can't just scale brightness values linearly.
There's a color palette test page at https://danbooru.donmai/static/colors
Notable changes to colors in light mode:
* Username colors are the same as tag colors.
* Copyright tags are a deeper purple.
* Builders are a deeper purple (fixes#4626).
* Moderators are green.
* Gold users are orange.
* Parent borders are a darker green.
* Child borders are a darker orange.
* Unsaved notes have a thicker red border.
* Selected notes have a thicker blue (not green) border.
* Render counts in the user profile tooltip the same way as tag counts.
* Render tag counts in the tags index page the same way as tag counts in
the tags list.
Bug: In Postgres 13, getting the count of a blank search underestimated
the page count by a large margin (~700,000 posts).
The query we were executing was this:
EXPLAIN (FORMAT JSON) SELECT * FROM posts ORDER BY id DESC
The `ORDER BY id DESC` clause triggered a parallel seq scan query plan
in Postgres 13, which for some reason causes Postgres to underestimate
the row count by large amount in each parallel branch.
Getting rid of the ORDER BY clause makes it do a regular seq scan, which
gives an accurate estimate.