Commit Graph

1568 Commits

Author SHA1 Message Date
evazion
4cc8dd41ec puma: add rack-timeout gem.
Unlike Unicorn, Puma doesn't have a builtin HTTP request timeout
mechanism, so we have to use Rack::Timeout instead.

See the caveats in the Rack::Timeout documentation [1]. In Unicorn, a
timeout would send a SIGKILL to the worker, immediately killing it. This
would result in a dropped connection and a Cloudflare 502 error to the
user. In Puma, it raises an exception, which we can catch and return a
better error to the user. On the other hand, raising an exception can
potentially corrupt application state if it's sent at the wrong time, or
be delayed indefinitely if the app is stuck in IO or C extension code.

The default request timeout is 65 seconds. 65 seconds is to give things
like HTTP requests on a 60 second timeout enough time to complete. Set
the RACK_REQUEST_TIMEOUT environment variable to change the timeout.

1: https://github.com/sharpstone/rack-timeout#further-documentation
2021-09-12 09:32:12 -05:00
evazion
3d660953d4 Add MediaMetadata model.
Add a model for storing image and video metadata for uploaded files.

Metadata is extracted using ExifTool. You will need to install ExifTool
after this commit. ExifTool 12.22 is the minimum required version
because we use the `--binary` option, which was added in this release.

The MediaMetadata model is separate from the MediaAsset model because
some files contain tons of metadata, and most of it is non-essential.
The MediaAsset model represents an uploaded file and contains essential
metadata, like the file's size and type, while the MediaMetadata model
represents all the other non-essential metadata associated with a file.

Metadata is stored as a JSON column in the database.

ExifTool returns all the file's metadata, not just the EXIF metadata.
EXIF is one of several types of image metadata, hence why we call
it MediaMetadata instead of EXIFMetadata.
2021-09-08 05:00:54 -05:00
evazion
4dcfd1d141 aliases/implications: log manual deletions by admins.
Log when an admin manually deletes an alias or implication outside of a
BUR. This is usually only necessary when a BUR is bugged.
2021-09-06 03:25:02 -05:00
evazion
b068c113a8 Add MediaAsset model.
A MediaAsset represents an image or video file uploaded to Danbooru. It
stores the metadata associated with the image or video. This is to work
on decoupling files from posts so that images can be uploaded separately
from posts.
2021-09-02 06:07:52 -05:00
evazion
c29539d44e /posts/random: fix reorder(nil).first deprecation warning
DEPRECATION WARNING: `.reorder(nil)` with `.first` / `.first!` no
    longer takes non-deterministic result in Rails 6.2. To continue
    taking non-deterministic result, use `.take` / `.take!` instead.
    (called from random at /home/user/src/danbooru/app/controllers/posts_controller.rb:91)
2021-09-02 04:09:03 -05:00
evazion
1bb383703d iqdb: allow searching images by iqdb hash.
Example:

    https://danbooru.donmai.us/iqdb_queries?search[hash]=iqdb_3fe4c0bd5a88fab53fbe5104efdc43ba3fa094416e6e039cf880f9f1fafafafffc80fd7bfd7dfd80fe72fe79fe80fefafefdfeffff75ff79ff7aff7dfff1fffb000100020003000400080082008a00940184018802000287028c028f030004000600078308001080ef80f800f8fdf900fafdfc00fc7dfcfafe00fe72fefdff7effdffff0fff8fffcfffd0007000f001f003e0080008f0106018d02800282038003810403040806800683070b078007870d800d830f801f00f800f96cfa76fb00fb7efbf4fc00fcfdfd00fd74fdfbfe78fe7efef5fef9fefbfefeff6cff76ff7efffcfffe00070080008300860087008b01030106018002820283028503800402040a0502058b0d80

The hash may be obtained from a regular IQDB search, or by calculating
it yourself (an exercise for the reader).
2021-09-02 03:37:36 -05:00
Lily
8d49d35ab1 make appeals editable 2021-06-29 14:43:27 -03:00
evazion
ad4c75eb1a docs add more docs to app/{jobs,logical}.
These were missed in the last commit.
2021-06-28 05:09:19 -05:00
evazion
0563ca3001 docs: document config/ and some directories in app/.
* Add README files to several directories in app/ giving a brief
  overview of some parts of Danbooru's architecture.
* Add documentation for files in config/.
2021-06-27 05:21:38 -05:00
evazion
07e23204b6 rubocop: fix various Rubocop warnings. 2021-06-17 04:17:53 -05:00
evazion
0f36bbf8d3 iqdb: update API client to use new version of IQDB.
Replace the old IQDB API client with a new client for the new forked
version of IQDB at https://github.com/danbooru/iqdb.

Changes:

* The /iqdb_queries endpoint now returns `hash` and `signature` fields.
  The `signature` is the full decoded Haar signature, while the `hash`
  is a encoded version of the signature.
* The /iqdb_queries endpoint no longer returns `width` and `height`
  fields in the response (these were always 128x128).
* We no longer need the IQDBs frontend server, now we talk to the IQDB
  instance directly.
* We no longer send add/remove image commands to IQDB through AWS SQS,
  now we send them to IQDB directly. They are sent in a delayed job so
  that if IQDB is down, uploading images is still possible, the add
  image commands will just get queued up.
* Fix a bug where regenerating an image's thumbnails didn't regenerate
  IQDB, because IQDB silently ignored add image commands when the image
  already existed in the database.
2021-06-16 05:36:24 -05:00
evazion
24ead500f0 users: use sudo mode when changing email addresses.
When a user tries to change their email, redirect them to the confirm
password page (like Github's sudo mode) instead of having them re-enter
their password on the change email page. This is the same thing we do
when a user updates their API keys. This way we have can use the same
confirm password authentication flow for everything that needs a
password.
2021-05-19 01:10:03 -05:00
evazion
e36fb6fee3 /status: show HTTP request headers and client IP.
Show the HTTP request headers and the client IP on the /status page.
This is for debugging request headers added by reverse proxies such as
Cloudflare and Nginx, and for making sure the client IP is correctly set
by the X-Forwarded-For header.
2021-05-06 00:32:24 -05:00
evazion
b3c1c753b3 comments: allow admins to remove comment votes (fix #4640)
Allow admins to remove comment votes by other users. This is done by
clicking the comment score to get to the comment vote list, then
clicking the Remove button on every vote.
2021-03-30 00:10:25 -05:00
evazion
6b91e55283 comments: allow votes to be soft deleted.
Make it so that when a user removes their own vote, the vote is soft
deleted (the is_deleted flag is set) instead of hard deleted.

Changes:

* Add is_deleted flag to comment votes.
* Relax uniqueness constraint so you can have multiple deleted votes on
  the same comment. You can still only have one active vote on the comment.
* Add `soft_delete` method to Deletable concern.
2021-03-30 00:10:22 -05:00
evazion
6a84d33409 Fix #4770: Allow flaggers to update flag reason. 2021-03-23 01:27:16 -05:00
evazion
0f90ae0fed storage manager: use canonical URL for image URLs.
Generate image URLs relative to the site's canonical URL instead of
relative to the domain of the current request.

This means that all subdomains of Danbooru - safebooru.donmai.us,
shima.donmai.us, saitou.donmai.us, and kagamihara.donmai.us - will use
image URLs from https://danbooru.donmai.us, instead of from the current
domain.

The main reason we did this before was so that we could generate either
http:// or https:// image URLs, depending on whether the current request
was HTTP or HTTPS, back when we tried to support both at the same time.
Now we support only HTTPS in production, so there's no need for this. It
was also pretty hacky, since it required storing the URL of the current
request in a per-request global variable in `CurrentUser`.

This also improves caching slightly, since users of safebooru.donmai.us
will receive cached images from danbooru.donmai.us.

Downstream boorus should make sure that the `canonical_url` and
`storage_manager` config options are set correctly. If you don't support
https:// in development, you should make sure to set the canonical_url
option to http:// instead of https://.
2021-03-16 23:30:29 -05:00
evazion
f93b1fe478 custom css: don't add !important to every line.
Fixes #4398.
2021-03-16 20:04:09 -05:00
evazion
28c0a48117 discord: fix tag search commands being limited to 2 tags. 2021-03-14 16:42:07 -05:00
evazion
698be2d0e4 discord: add /random command. 2021-03-11 21:23:20 -06:00
evazion
2c8c7ff80a discord: add initial slash command integration.
Add initial support for the `/count <tags>` and `/posts <tags>` slash commands.

Slash commands are basically like webhooks; we register a command, and
when anybody types that command in Discord, Discord sends us a HTTP
request that we respond to.

* https://discord.com/developers/docs/interactions/slash-commands
* https://support.discord.com/hc/en-us/articles/1500000368501-Slash-Commands-FAQ
2021-03-11 03:04:10 -06:00
evazion
81fe68d392 bans: change expires_at field to duration.
Changes:

* Change the `expires_at` field to `duration`.
* Make moderators choose from a fixed set of standard ban lengths,
  instead of allowing arbitrary ban lengths.
* List `duration` in seconds in the /bans.json API.
* Dump bans to BigQuery.

Note that some old bans have a negative duration. This is because their
expiration date was before their creation date, which is because in 2013
bans were migrated to Danbooru 2 and the original ban creation dates
were lost.
2021-03-11 02:59:58 -06:00
evazion
b169d60f64 Fix saved searces, news updates, ip bans being dumped to BigQuery.
Prevent saved searches, news updates, and ip bans from being publicly
dumped to BigQuery. They didn't override the `visible` method to
restrict their visibility for anonymous users.
2021-03-10 03:08:49 -06:00
evazion
fee7ed506b comments: put sticky option in popup menu instead of in edit form.
Put the option to sticky a comment in the "..." popup menu instead of
in the comment edit form. This makes it more consistent with deleting or
undeleting a comment.

Also fix a bug where the comment undelete icon didn't show up due to a
typo.
2021-03-07 20:13:38 -06:00
evazion
4b61a9c73c /robots.txt: enable HTTP caching.
Cache /robots.txt at the HTTP level because it rarely changes but it
gets requested by bots relatively frequently.
2021-03-07 18:35:37 -06:00
evazion
58e42ee8d3 rate limits: add /rate_limits endpoint.
Allow users to view their own rate limits with /rate_limits.json.

Note that rate limits are only updated after every API call, so this
page only shows the state of the limits after the last call, not the
current state.
2021-03-05 16:47:20 -06:00
evazion
413cd34c45 rate limits: adjust limits for various actions.
* 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.
2021-03-05 16:02:57 -06:00
evazion
4492610dfe rate limits: rework rate limit implementation.
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.
2021-03-05 16:00:54 -06:00
evazion
52adf87489 Fix #4666: Broken network link for some IPs. 2021-03-01 20:44:51 -06:00
evazion
1c1d784547 css: rework color scheme to use new color palette.
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.
2021-02-22 02:32:49 -06:00
evazion
3798a2d29e logins: don't return api_token field in API.
Remove the api_token field from the response to the login action (POST
/sessions). This doesn't make sense in the presence of multiple API
keys, and is also not generally useful; if you need an API key, create
one yourself and write it down.
2021-02-15 14:28:31 -06:00
evazion
3d01febcf7 api keys: require reauthentication when working with API keys.
Require the user to re-enter their password before they can view,
create, update, or delete their API keys.

This works by tracking the timestamp of the user's last password
re-entry in a `last_authenticated_at` session cookie, and redirecting
the user to a password confirmation page if they haven't re-entered
their password in the last hour.

This is modeled after Github's Sudo mode.
2021-02-15 00:17:31 -06:00
evazion
25fda1ecc2 api keys: add IP whitelist and API permission system.
Add the ability to restrict API keys so that they can only be used with
certain IP addresses or certain API endpoints.

Restricting your key is useful to limit damage in case it gets leaked or
stolen. For example, if your key is on a remote server and it gets
hacked, or if you accidentally check-in your key to Github.

Restricting your key's API permissions is useful if a third-party app or
script wants your key, but you don't want to give full access to your
account.

If you're an app or userscript developer, and your app needs an API key
from the user, you should only request a key with the minimum
permissions needed by your app.

If you have a privileged account, and you have scripts running under
your account, you are highly encouraged to restrict your key to limit
damage in case your key gets leaked or stolen.
2021-02-14 21:02:07 -06:00
evazion
37061f95a6 api keys: rework API key UI.
* Add an explanation of what an API key is and how to use it.
* Make it possible for the site owner to view all API keys.
* Remove the requirement to re-enter your password before you can view
  your API key (to be reworked).
* Move the API key controller from maintenance/user/api_keys_controller.rb
  to a top level controller.
2021-02-14 04:09:47 -06:00
evazion
e23f09235e artists: redact version histories of banned artists.
Fix names and urls of banned artists being visible in Google through
artist version pages.
2021-02-07 23:28:50 -06:00
evazion
327deb9cbb tests: fix regression in 6d867de20.
6d867de20 caused an exception in the ApiKeysController, which calls
respond_with with two arguments: `respond_with(CurrentUser.user, @api_key)`.
`options[0]` referred to the second argument, which was incorrect.
2021-02-05 03:33:07 -06:00
evazion
19db959894 Merge pull request #4674 from BrokenEagle/add-missing-associated-attributes
Add missing associated attributes
2021-02-04 00:37:32 -06:00
evazion
896e5cb763 Add BetterErrors gem. 2021-01-30 14:19:37 -06:00
evazion
d0c9f6e0b8 posts: allow toggling between upvotes and downvotes.
Like 9efb374ae, allow users to toggle between upvoting and downvoting a
post without raising an error or having to manually remove the vote
first. If you upvote a post, then downvote it, the upvote is
automatically removed and replaced by the downvote.

Other changes:

* Tagging a post with `upvote:self` or `downvote:self` is now silently
  ignored when the user doesn't have permission to vote, instead of
  raising an error.
* Undoing a vote that doesn't exist now does nothing instead of
  returning an error. This can happen if you open the same post in two
  tabs, undo the vote in tab 1, then try to undo the vote again in tab 2.

Changes to the /post_votes API:

* `POST /post_votes` and `DELETE /post_votes` now return a post vote
  instead of a post.
* The `score` param in `POST /post_votes` is now 1 or -1, not `up` or
  `down`.
2021-01-29 02:22:23 -06:00
BrokenEagle
5698847077 Add in missing available includes 2021-01-22 02:58:30 +00:00
BrokenEagle
6d867de20f Add way for controllers with different models to use the only parameter
The /emails endpoint was passing in the "Email" model because that's
how the emails controller classifies. This was to fix that, and to
allow any other such cases in the future.
2021-01-22 02:58:30 +00:00
evazion
168db63807 comments: raise limit to 20 posts per page on /comments index. 2021-01-21 07:58:50 -06:00
evazion
9efb374ae5 comments: allow swapping votes.
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.`
2021-01-21 07:58:50 -06:00
evazion
07bdc6eab0 comments: rework thresholded comments.
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).
2021-01-19 04:07:33 -06:00
evazion
054ac51d47 policies: remove current request from context.
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.
2021-01-17 00:57:59 -06:00
evazion
6671711784 dmails, emails: refactor to use Rails signed_id.
Refactor email verification links and Dmail share links to use the new
Rails signed_id mechanism, rather than our own handrolled mechanism.

For Dmail share links, we have to override some Rails internal methods
so that our old links still work. For email verification links, this
will invalidate existing links, but this isn't a huge deal since these
links are short-lived anyway.

https://api.rubyonrails.org/classes/ActiveRecord/SignedId.html
https://api.rubyonrails.org/classes/ActiveRecord/SignedId/ClassMethods.html
2021-01-17 00:24:02 -06:00
evazion
6ca007ee1f Fix #4670: Replace RequestStore with AS::CurrentAttributes.
This also requires replacing CurrentUser.name with CurrentUser.user.name
because the `name` method had a conflict with CurrentAttributes.
2021-01-16 12:43:20 -06:00
evazion
32dd14f461 Remove /admin/dashboard page.
This page was just a combination of the forum listing and the bulk
update requests listing. It got zero hits in the last week.
2021-01-16 03:32:11 -06:00
evazion
b4530183f4 Fix #4525: Show mod report notices next to reported content. 2021-01-16 01:02:42 -06:00
evazion
4719a5ed1c users: set default settings in ruby instead of in database.
Specify the default settings for new users inside the User model instead
of inside the database. This makes it easier to change defaults, and it
makes the code clearer.
2021-01-15 02:03:54 -06:00