Commit Graph

24 Commits

Author SHA1 Message Date
evazion
a160a3acce users: add stricter username rules.
Add stricter username rules:

* Only allow usernames to contain basic letters, numbers, CJK characters, underscores, dashes and periods.
* Don't allow names to start or end with punctuation.
* Don't allow names to have multiple underscores in a row.
* Don't allow active users to have names that look like deleted users (e.g. "user_1234").
* Don't allow emoji or any other Unicode characters except for Chinese, Japanese, and Korean
  characters. CJK characters are currently grandfathered in but will be disallowed in the future.

Users with an invalid name will be shown a permanent sitewide banner until they change their name.
2022-03-05 01:08:53 -06:00
evazion
7bed81812d Don't show error messages that could contain private information.
Fix a potential exploit where private information could be leaked if
it was contained in the error message of an unexpected exception.

For example, NoMethodError contains a raw dump of the object in the
error message, which could leak private user data if you could force a
User object to raise a NoMethodError.

Fix the error page to only show known-safe error messages from expected
exceptions, not unknown error messages from unexpected exceptions.

API changes:

* JSON errors now have a `message` param. The message will be blank for unknown exceptions.
* XML errors have a new format. This is a breaking change. They now look like this:

    <result>
      <success type="boolean">false</success>
      <error>PaginationExtension::PaginationError</error>
      <message>You cannot go beyond page 5000.</message>
      <backtrace type="array">
        <backtrace>app/logical/pagination_extension.rb:54:in `paginate'</backtrace>
        <backtrace>app/models/application_record.rb:17:in `paginate'</backtrace>
        <backtrace>app/logical/post_query_builder.rb:529:in `paginated_posts'</backtrace>
        <backtrace>app/logical/post_sets/post.rb:95:in `posts'</backtrace>
        <backtrace>app/controllers/posts_controller.rb:22:in `index'</backtrace>
      </backtrace>
    </result>

  instead of like this:

    <result success="false">You cannot go beyond page 5000.</result>
2022-02-06 18:09:54 -06:00
evazion
450594b803 tests: fix broken tests. 2022-01-07 14:44:24 -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
d99985160a api keys: add API key usage tracking.
Track when an API key was last used, which IP address last used it, and
how many times it's been used overall.

This is so you can tell when an API key was last used, so you know if
the key is safe to delete, and so you can tell if an unrecognized IP has
used your key.
2021-02-14 21:02:07 -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
a6707fbfa2 api keys: allow users to have multiple API keys.
This is useful if you have multiple programs and want to give them
different API keys, or if you want to rotate keys for a single program.
2021-02-14 04:09:47 -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
e9b33dbd48 api: remove legacy password_hash login method.
Remove the ability to authenticate to the API with the `login` and
`password_hash` url parameters. This is a legacy authentication method
from Danbooru 1. How to actually generate the password_hash for this
method hasn't been fully documented for many years now. It required
taking the SHA1 hash of your password combined with an undocumented salt
value (i.e., password_hash = sha1("choujin-steiner--#{password}")).

This authentication method was also slow because it required checking
the password on every API call. Checking passwords is deliberately slow
because passwords are hashed with BCrypt. BCrypt takes about ~200ms per
request, so using this method effectively limited you to ~5 requests per
second in a single thread.
2020-03-25 18:48:43 -05:00
evazion
4d49bf053f tests: fix only param test. 2020-03-20 17:53:59 -05:00
evazion
cd47987b05 tests: fixup tests for cc4e39b88. 2019-10-07 23:29:31 -05:00
evazion
19f2cc1e74 api: refactor only param. 2019-09-08 23:28:02 -05:00
evazion
24202d51f0 api: support the expires_in param on all GET requests.
`expires_in` is an alternative to `expiry` that supports durations other
than days:

* https://danbooru.donmai.us/posts.json?expires_in=30s
* https://danbooru.donmai.us/posts.json?expires_in=5min
* https://danbooru.donmai.us/posts.json?expires_in=1hour
* https://danbooru.donmai.us/posts.json?expires_in=1week
* https://danbooru.donmai.us/posts.json?expires_in=1month
2019-09-08 15:32:31 -05:00
evazion
22fd90eee9 api: support the expiry param on all GET requests. 2019-09-08 15:32:31 -05:00
evazion
3f7e05316d api: refactor default options for xml responses.
In xml responses, if the result is an empty array we want the response
to look like this:

   <posts type="array"/>

not like this (the default):

   <nil-classes type="array"/>

This refactors controllers so that this is done automatically instead of
having to manually call `@things.to_xml(root: "things")` everywhere. We
do this by overriding the behavior of `respond_with` in `ApplicationResponder`
to set the `root` option by default in xml responses.
2019-09-08 15:32:31 -05:00
evazion
3e85ce8110 Fix searching models by id/created_at/updated_at attributes. 2019-09-02 13:38:00 -05:00
evazion
7e2eb7e5a7 Fix Rails 6 content_type deprecation warning.
DEPRECATION WARNING: Rails 6.1 will return Content-Type header without
    modification. If you want just the MIME type, please use `#media_type`
    instead.
2019-08-31 12:55:07 -05:00
evazion
8e39985d66 app controller: fix api responses on access denied errors.
Bug: A .json/.xml/.js request that resulted in an access denied error
returned a html response instead of a .json/.xml/.js response.
2019-08-25 20:29:32 -05:00
evazion
c7f8fbbec2 app controller: standardize access denied error handling.
Refactor to use `render_error_page` to handle User::PrivilegeError
exceptions. This way these exceptions are logged to New Relic.

Changes:

* Anonymous users aren't automatically redirected to the login page.
  Instead they're taken to the access denied page, which links to the
  login/signup pages.

* JSON/XML error responses return `message` instead of `reason`.
2019-08-24 23:10:22 -05:00
evazion
2d34e69737 api: disable csrf protection for api requests.
Fixes POST/PUT API requests failing with InvalidAuthenticityToken errors
due to missing CSRF tokens.

CSRF protection is only necessary for cookie-based authentication. For
non-cookie-based authentication we can safely disable it. That is, if
the user is already passing their login + api_key, then we don't need
to additionally verify the request with a CSRF token.

ref: 2e407fa476 (comments)
2019-08-24 22:55:35 -05:00
evazion
9c79f006f8 tests: move authentication tests out of post tests. 2019-08-24 22:55:35 -05:00
evazion
d657624a80 Revert "application controller: fix errors in normalize_search."
This reverts commit 28a88cfa85.
2019-08-14 01:46:43 -05:00
evazion
28a88cfa85 application controller: fix errors in normalize_search.
Fix exceptions in `normalize_search` on e.g. `https://danbooru.donmai.us/users?search=blah`.
Caused when the `search` param is not a hash.
2019-08-13 21:30:20 -05:00
evazion
35dfc704bc application controller: fix bad file extension errors.
Fix requests with bad file extensions not always returning errors correctly:

* https://danbooru.donmai.us/posts.jpg
* https://danbooru.donmai.us/posts.blah
* https://danbooru.donmai.us/posts/bad.jpg
* https://danbooru.donmai.us/posts/bad.blah
2019-08-08 22:16:39 -05:00