When an anonymous users tries to go to the new upload page, direct them
to the login page instead of showing them an "Access Denied" error.
Fixes complaints from SEO tools about linking to pages that return a 403
error.
Factor out FontAwesome icons into a set of helpers. This is so that it's
easier to keep track of which icons we're using and easier to change
icons globally.
Allow users to upvote a comment, then downvote it, without raising an
error or having to manually remove the upvote first. The upvote is
automatically removed and replaced by the downvote.
Changes to the /comment_votes API:
* `POST /comment_votes` and `DELETE /comment_votes` now return a comment
vote instead of a comment.
* The `score` param in `POST /comment_votes` is now 1 or -1, not
`up` or `down.`
* Add comment scores.
* Rework voting buttons so that you can click the upvote/downvote
buttons to toggle votes.
* Hide the edit, delete, undelete, and report buttons behind a popup menu.
* Show the upvote/downvote/reply buttons to logged out users. Redirect
them to the login page instead.
* Set the default comment threshold to -8. This means that comments are
hidden at -8 or lower and greyed out at -4 or lower.
* Reset the comment threshold to -8 for anyone with a threshold greater
than -8. For reference, only about ~3100 users had a non-default
threshold. About 1600 of those had their threshold reset to -8.
* Change the comment threshold to a less-than-or-equal comparison
instead of a less-than comparsion. This means that a threshold of 0
before is the same as a threshold of -1 now. Since everyone's
thresholds were reset, this only affects people whose thresholds were
already less than -8, which is so low that the difference shouldn't
matter much.
* Set the maximum comment threshold to 5. For reference, less than 1% of
comments have a score greater than 5.
* Set the minimum comment threshold to -100. For reference, the most
downvoted comment has a score of -60.
Let users see when a post has deleted comments. Show normal users a
'[deleted]' placeholder when a comment is deleted. Show the full comment
to moderators.
Also fix it so that the comment creator can't edit or undelete deleted
comments, and users can't vote on or report deleted comments.
Finally, hide the creator_id, updater_id, and body of deleted comments
in the API.
Previously thresholded comments were hidden completely. You had to click
the "Show X hidden comments" button to unhide all hidden comments in a
thread. Now it works like this:
* When a comment is below your threshold, the comment text is hidden and
replaced by a `[hidden]` link, which you can click to unhide the comment.
* When a comment is at half your threshold (for example, your threshold
is -8 but the comment is at -4), then the comment is greyed out.
This means that comments aren't completely hidden, they're just
collapsed, so you can see the commenter and the score without unhiding
the comment. It also means you don't have to scroll back up to unhide a
comment, and threads aren't disrupted by comments being secretly
hidden (which is confusing when people are replying to hidden comments,
which forces you to go back up and unhide to find).
This refactors Pundit policies to only rely on the current user, not on
the current user and the current HTTP request. In retrospect, it was a
bad idea to include the current request in the Pundit context. It bleeds
out everywhere and there are many contexts (in tests and models) where
we only have the current user, not the current request. The previous
commit got rid of the only two places where we used it.
This option was originally added in issue #1747. But only ~350 users
ever disabled autocomplete, only ~120 of these were seen in the last
year, and only 9 new users who signed up in the last year disabled it.
Users wishing to disable autocomplete can use this CSS:
.ui-autocomplete { display: none !important: }
or this Javascript:
$("[data-autocomplete]").autocomplete("disable");
Remove the enable_post_navigation option. This option was originally
added to disable the next/prev post navbar beneath posts. It was later
repurposed to disable keyboard shortcuts.
Users who don't want keyboard shortcuts are advised to not press random
buttons on the keyboard like a caveman.
Only ~1200 users disabled this option and only ~600 were seen in the
last year.
Remove the enable_sequential_post_navigation option. This option was
used to disable the next/previous post navbar below posts.
This option was originally added in issue #674 because of people
complaining about the navbar when it was originally added. Also there
were complaints about URLs being uglier because of search params in the
URL (e.g. /posts/1234?q=touhou). There were also various minor bugs with
it at the time, such as keyboard shortcuts not working correctly, or the
page not remembering your search after a tag edit.
These complaints are irrelevant nowadays because a) people are used to
the navbar by now (and more often complain about it *not* being there
for order:score searches), b) post URLs always contain the search now,
this option hasn't disabled that for years, and c) the initial bugs with
it were fixed years ago.
Only ~1000 users disabled this option and only ~600 were seen in the last year.
Users still wishing to hide the search navbar can use custom CSS instead.
Refactor the post preview html to use the ViewComponent framework. This
lets us encapsulate all the HTML, CSS, and helper methods for a UI
component in a single place.
See https://viewcomponent.org.
Refactor page limits to a) be explicitly listed in the User class (not
hidden away in the Danbooru config) and b) explicitly depend on the
CurrentUser (not implicitly by way of Danbooru.config.max_numbered_pages).
Add tracking of certain important user actions. These events include:
* Logins
* Logouts
* Failed login attempts
* Account creations
* Account deletions
* Password reset requests
* Password changes
* Email address changes
This is similar to the mod actions log, except for account activity
related to a single user.
The information tracked includes the user, the event type (login,
logout, etc), the timestamp, the user's IP address, IP geolocation
information, the user's browser user agent, and the user's session ID
from their session cookie. This information is visible to mods only.
This is done with three models. The UserEvent model tracks the event
type (login, logout, password change, etc) and the user. The UserEvent
is tied to a UserSession, which contains the user's IP address and
browser metadata. Finally, the IpGeolocation model contains the
geolocation information for IPs, including the city, country, ISP, and
whether the IP is a proxy.
This tracking will be used for a few purposes:
* Letting users view their account history, to detect things like logins
from unrecognized IPs, failed logins attempts, password changes, etc.
* Rate limiting failed login attempts.
* Detecting sockpuppet accounts using their login history.
* Detecting unauthorized account sharing.
Add a Restricted user level. Restricted users are level 10, below
Members. New users start out as Restricted if they sign up from a proxy
or an IP recently used by another user.
Restricted users can't update or edit any public content on the site
until they verify their email address, at which point they're promoted
to Member. Restricted users are only allowed to do personal actions
like keep favorites, keep favgroups and saved searches, mark dmails as
read or deleted, or mark forum posts as read.
The restricted state already existed before, the only change here is
that now it's an actual user level instead of a hidden state. Before it
was based on two hidden flags on the user, the `requires_verification`
flag (set when a user signs up from a proxy, etc), and the `is_verified`
flag (set after the user verifies their email). Making it a user level
means that now the Restricted status will be shown publicly.
Introducing a new level below Member means that we have to change every
`is_member?` check to `!is_anonymous` for every place where we used
`is_member?` to check that the current user is logged in.
In Danbooru 1, aliases (and implications) had a `reason` field where
either the admin or the alias requester gave a reason for the alias.
This field was removed from the code and the database schema, but it
still existed in the production database. This adds the field back, so
that the dev schema is consistent with the production schema, and so
that legacy reasons can be viewed on site again.
* Add back legacy tag_aliases.reason and tag_implications.reason field.
* Make /tag_aliases and /tag_implications show legacy reasons.
* Add the reason field to the search form.
Regenerate posts asynchronously using a delayed job.
Regenerating a post can be slow because it involves downloading the
original file, regenerating the thumbnails, and redistributing the new
thumbnails back to the image servers. It's better to run this in the
background, especially if a user is trying to regenerate posts in bulk.
The downside is there's no notification to the user when the regeneration
is complete. You have to check the modactions log to see when it's finished.
* Remove the PostRegeneration model. Instead just use a mod action
to log when a post is regenerated.
* Change it so that IQDB is also updated when the image samples are
regenerated. This is necessary because when the images samples are
regenerated, the thumbnail may change, which means IQDB needs to be
updated too. This can happen when regenerating old images with
transparent backgrounds where the transparency was flattened to black
instead of white in the thumbnail.
* Only display one "Regenerate image" option in the post sidebar, to
regenerate both the images and IQDB. Regenerating IQDB only can be
done through the API. Having two options in the sidebar is too much
clutter, and it's too confusing for Mods who don't know the difference
between an IQDB-only regeneration and a full image regeneration.
* Add a confirm prompt to the "Regenerate image" link.
Disable the browser's native spellchecking ability on all form inputs,
except for DText inputs. We do this by setting `spellcheck="false"` on
the <body> tag, and `spellcheck="true"` on DText <input> tags.
This fixes browsers displaying a red wavy underline beneath tags in the
tag search box, among other places. We disable spellchecking globally
because most form inputs, except for DText inputs, aren't meant for
natural English language.
* Remove the data-is-favorited attribute from post thumbnails.
* Remove the is_favorited attribute from the /posts.json API.
* Remove the fav_string attribute from the /posts.json API (only visible
to moderators).
* Change `Post#favorited_by?` to not use the fav_string.
Further addresses #4652 by eliminating the last places where fav_string
was used.
On the posts show page, in the favorites list, show favorites according
to the order they were added to the favorites table, rather than the
order they were added to the posts's fav_string.
On most posts these should be the same, but on old posts they may be
slightly different. The IDs of the first few hundred thousand favorites
don't appear to be in chronological order. Probably the original
favorite IDs were lost and recreated by a database move at some point in
Danbooru's history. The fav_string is also inconsistent with the
favorites table in some places (one contains favorites that aren't
contained by the other), which also throws off the order.
Partially addresses #4562 by eliminating one place where we depended on
the fav_string.
* Refactor various user limit methods to class methods from instance
methods so they can be used outside the context of a single user.
* Remove the Danbooru.config.base_tag_query_limit option.
Allow promo codes to be used during checkout if a secret promo=true url
param is passed. Allows promo codes to be offered without having the
promo code option always appear even when there aren't any active promos.
Add the following bank redirect payment methods:
* https://stripe.com/docs/payments/bancontact
* https://stripe.com/docs/payments/eps
* https://stripe.com/docs/payments/giropay
* https://stripe.com/docs/payments/ideal
* https://stripe.com/docs/payments/p24
These methods are used in Austria, Belgium, Germany, the Netherlands,
and Poland.
These methods require payments to be denominated in EUR, which means we
have to set prices in both USD and EUR, and we have to automatically
detect which currency to use based on the user's country. We also have
to automatically detect which payment methods to offer based on the
user's country. We do this by using Cloudflare's CF-IPCountry header to
geolocate the user's country.
This also switches to using prices and products defined in Stripe
instead of generated on-the-fly when creating the checkout.
Add links to the Stripe payment page and the Stripe receipt page on
completed user upgrades.
The Stripe payment link is a link to the payment details on the Stripe
dashboard and is only visible to the owner.