Commit Graph

2277 Commits

Author SHA1 Message Date
evazion
c1b865b160 searchable: add more enum attribute search options.
Add `<enum>_not` and `<enum>_id_<op>` search options:

* https://danbooru.donmai.us/mod_actions?search[category_not]=post_regenerate,post_regenerate_iqdb
* https://danbooru.donmai.us/mod_actions?search[category_not]=48,49
* https://danbooru.donmai.us/mod_actions?search[category_id]=40..50
* https://danbooru.donmai.us/mod_actions?search[category_id_not]=40..50
* https://danbooru.donmai.us/mod_actions?search[category_id_gt]=40&search[category_id_lt]=50
2021-01-11 19:13:35 -06:00
evazion
e7b454686e searchable: refactor where_operator method.
Refactor the `where_operator` method so we can use it to avoid raw SQL
in more places.
2021-01-11 19:13:29 -06:00
evazion
6d2eeb6f28 searchable: fix being unable to use multiple operators on same attribute.
Fix searches like this not working:

* https://danbooru.donmai.us/tags?search[id]=1..100&search[id_not]=50

Before one of these params would override the other.
2021-01-11 14:59:04 -06:00
evazion
1e7a5ba49d Fix ruby warnings about deprecated keyword arguments. 2021-01-11 05:12:09 -06:00
evazion
be1251b6be autocomplete: optimize various types of bogus input.
Optimize autocomplete to ignore various types of bogus input that will
never match anything. It turns out it's not uncommon for people to do
things like paste random URLs into autocomplete, or hold down keys, or
enter long strings of gibberish text (sometimes in other languages).
Some things, like autocorrect and slash abbreviations, become
pathologically slow when fed certain types of bad input.

Autocomplete will abort and return nothing in the following situations:

* Searching for URLs (tags that start with http:// or https://).
* Overly long tags (strings longer than the 170 char tag name limit).
* Slash abbreviations longer than 10 chars (e.g. typing `/qwoijqoiqogirqewgoi`).
* Slash abbreviations that aren't alphanumeric (e.g. typing `/////////`).
* Autocorrect input that contains too much punctuation and not enough actual letters.
2021-01-11 05:12:09 -06:00
evazion
fc5db679e4 autocomplete: optimize searching by artist/wiki page other names.
Optimize searches for non-English phrases in autocomplete. These
searches were pretty slow, and could sometimes cause sitewide lag spikes
when users typed long strings of non-English text into the search box
and caused an unintentional DoS.

The trick is to use an `array_to_tsvector(other_names) USING gin` index
on other_names. This supports fast string prefix matching against all
elements of the array. The downside is that it doesn't allow infix or
suffix matches, so we can't support wildcards in general. Wildcards
didn't quite work anyway, since artist and wiki other names can contain
literal '*' characters.
2021-01-10 03:35:12 -06:00
evazion
0899194f6b Fix conflict between normalize and array_attribute macros.
Fix the `normalize` and `array_attribute` macros conflicting with each
other on the WikiPage model. This meant code like
`wiki_page.other_names = "foo bar"` didn't work. Both macros defined a
`other_names=` method, but one method overrode the other.

The fix is to use anonymous modules and prepend so we can chain method
calls with super.
2021-01-10 02:03:12 -06:00
evazion
9759701071 search: add way to search array attributes by regex.
Add a `where_any_in_array_matches_regex` method and expose it to the API:

 * https://danbooru.donmai.us/artists?search[any_other_name_matches_regex]=^blah
 * https://danbooru.donmai.us/wiki_pages?search[any_other_name_matches_regex]=^blah
 * https://danbooru.donmai.us/saved_searches?search[any_label_matches_regex]=^blah

In SQL, this does `WHERE '^blah' ~<< ANY(other_names)`, where `~<<` is a
custom operator based on the `~` regex match operator, but with the
arguments reversed. This allows it to be used with the ANY(array) operator.

See also:

* https://stackoverflow.com/a/22101172
* https://www.postgresql.org/docs/current/sql-createfunction.html
* https://www.postgresql.org/docs/current/sql-createoperator.html
* https://www.postgresql.org/docs/current/functions-comparisons.html
2021-01-10 02:03:02 -06:00
evazion
65adcd09c2 users: track logins, signups, and other user events.
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.
2021-01-08 22:34:37 -06:00
evazion
94e125709c users: add Restricted user level.
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.
2021-01-07 17:10:29 -06:00
evazion
da3e8e4726 searchable: fix bug with searching multiple association attributes.
Fix a bug with searches like the following not working correctly:

* https://danbooru.donmai.us/comments.json?search[creator][level]=20&search[creator_id]=1234
* https://danbooru.donmai.us/comments.json?search[creator][level]=20&search[creator_name]=abcd
* https://danbooru.donmai.us/comments.json?search[post][rating]=s&search[post_tags_match]=touhou

It wasn't possible to search for both `creator` and `creator_id` at the
same time (or `post` and `post_tags_match`, etc). Only the `creator_id`
param would be recognized.

Also refactor some internals:

* `search_includes` was renamed to `search_associated_attribute`.
* `search_attribute` was split up into `search_basic_attribute` and
  `search_associated_attribute`.
2021-01-07 17:10:29 -06:00
BrokenEagle
db5f9ce243 Support multiple excludes for enum types
It's not possible to pass it off to search_numeric_attribute directly
since the column "category" does not match the prefix "category_id".
2021-01-06 20:21:56 +00:00
BrokenEagle
57de81686b Support using all numeric searches for includes 2021-01-06 20:21:56 +00:00
BrokenEagle
4a439d72d6 Support multiple exclusions
Since it does a not of numeric_attribute_matches which uses the
post query builder, it now also support reverse ranges and reverse
greater/less than.
2021-01-06 20:21:55 +00:00
evazion
65be2c99b0 Fix #4657: Hentai-Foundry: Document tree depth limit exceeded. 2021-01-06 03:05:36 -06:00
BrokenEagle
16d6f3bbd5 Add post regenerations 2021-01-04 18:35:50 -06:00
evazion
1909d6e062 Merge pull request #4636 from nonamethanks/fix_replacements
Uploads preprocessing: get rid of same-source existence check
2021-01-04 01:38:03 -06:00
evazion
3542c401d4 Merge pull request #4654 from nonamethanks/fix_gelbooru_normalization
Fix gelbooru source normalization
2021-01-04 01:31:17 -06:00
evazion
50e799e959 Merge branch 'master' into minor_fix 2021-01-04 01:30:28 -06:00
evazion
5612413546 Merge pull request #4641 from nonamethanks/weibo_previews
Weibo: use proxy for upload previews
2021-01-04 01:20:50 -06:00
evazion
ed7e7b1d30 Merge pull request #4639 from nonamethanks/fix_pixiv_en_links
Update artist finder blacklist
2021-01-04 01:15:15 -06:00
evazion
9008e836e4 BURs: raise limit on Builder artist tag moves from 100 to 200 posts. 2021-01-04 01:10:26 -06:00
evazion
257fa3d9c1 Fix #4645: Builders can alias empty non-artist tags 2021-01-04 01:02:39 -06:00
evazion
69cfa1696a html: disable browser spellcheck on all non-DText inputs.
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.
2021-01-04 00:25:54 -06:00
evazion
98ee6c31c1 favorites: refactor fav:/ordfav: searches to not use fav_string.
Refactor fav:<name> and ordfav:<name> searches to use the favorites
table instead of the posts.fav_string.

This may be slower for fav:<name> searches. The fav_string effectively
treats favorites like secret tags on the post, so fav:<name> searches
were effectively the same as tag searches. Now they do a subquery on the
favorites table, which may not perform as well for things like multiple
fav:<name> metatags or negated fav:<name> metatags.

For ordfav:<name> searches, this may be faster. ordfav: searches had a
tag match clause (`tag_index @@ 'fav:123'`) in addition to a join on the
favs table. This was redundant, and in some cases it inhibited the query
planner from choosing a more optimal plan.

Partially addresses #4652 by eliminating another place where we depended
on the fav_string.
2021-01-03 19:18:31 -06:00
nonamethanks
b3f92dd2c7 Fix gelbooru source normalization 2021-01-03 20:12:40 +01:00
evazion
dbe2eeb00d emails: remove "Valid?" search option.
No longer necessary after running previous commit because all invalid
email addresses have been purged.
2021-01-02 04:09:43 -06:00
evazion
36f95891bd search: let wildcard searches match up to 100 tags.
Let searching for things like *_legwear match up to 100 tags. Previously
the limit was 25.
2021-01-02 04:09:43 -06:00
evazion
5b7894a8b2 autocomplete: fix exception when type param is missing. 2021-01-01 04:06:38 -06:00
evazion
430ba5dced users: fix exception during signup for IPv6 addresses.
`ip_address.private?` failed on IPv6 addresses.
2021-01-01 03:57:17 -06:00
evazion
ae5c0d1034 newrelic: log request path. 2020-12-31 06:50:10 -06:00
evazion
9e9ac8f4bf sessions: store geolocated country in CurrentUser. 2020-12-31 04:54:00 -06:00
evazion
7fc5845e72 /emails: add more search options.
Add options to search for invalid emails and emails from restricted
domains.
2020-12-28 19:31:40 -06:00
evazion
6a52216631 newrelic: log additional request headers.
Log the Referer header, as well as the Sec-Fetch-* headers. These are
only sent by recent versions of Chrome; see https://www.w3.org/TR/fetch-metadata.
2020-12-28 01:53:22 -06:00
evazion
805bbc8a33 users: add config option to disable verification of new accounts.
Fixes #4618.
2020-12-28 00:01:35 -06:00
evazion
9dc788c0ce users: improve sockpuppet detection on signup.
Require new accounts to verify their email address if any of the
following conditions are true:

* Their IP is a proxy.
* Their IP is under a partial IP ban.
* They're creating a new account while logged in to another account.
* Somebody recently created an account from the same IP in the last week.

Changes from before:

* Allow logged in users to view the signup page and create new accounts.
  Creating a new account while logged in to your old account is now
  allowed, but it requires email verification. This is a honeypot.
* Creating multiple accounts from the same IP is now allowed, but they
  require email verification. Previously the same IP check was only for
  the last day (now it's the last week), and only for an exact IP match
  (now it's a subnet match, /24 for IPv4 or /64 for IPv6).
* New account verification is disabled for private IPs (e.g. 127.0.0.1,
  192.168.0.1), to make development or running personal boorus easier
  (fixes #4618).
2020-12-27 23:41:07 -06:00
evazion
7e8f859b24 tags: eliminate Tag.category_for method.
Tag.category_for looked up a tag's category in the Redis cache. This was
only used in a few places (in related tags, and on the popular/missed
search pages). Get rid of this method so we can work towards getting rid
of caching tag categories in Redis.
2020-12-27 21:03:26 -06:00
evazion
7f1b798b05 searchable: refactor search_boolean_attribute. 2020-12-27 05:26:21 -06:00
evazion
058d71aa30 user upgrades: send dmail to purchaser for gifted upgrades.
* Refactor to move upgrade logic from UserPromotion to UserUpgrade.
* Send the recipient and the purchaser of a gifted upgrade separate
  dmail notifications.
2020-12-25 00:43:58 -06:00
evazion
74ed2a8b96 user upgrades: add UserUpgrade model.
Add a model to store the status of user upgrades.

* Store the upgrade purchaser and the upgrade receiver (these are
  different for a gifted upgrade, the same for a self upgrade).
* Store the upgrade type: gold, platinum, or gold-to-platinum upgrades.
* Store the upgrade status:
** pending: User is still on the Stripe checkout page, no payment
   received yet.
** processing: User has completed checkout, but the checkout status in
   Stripe is still 'unpaid'.
** complete: We've received notification from Stripe that the payment
   has gone through and the user has been upgraded.
* Store the Stripe checkout ID, to cross-reference the upgrade record on
  Danbooru with the checkout record on Stripe.

This is the upgrade flow:

* When the user clicks the upgrade button on the upgrade page, we call
  POST /user_upgrades and create a pending UserUpgrade.
* We redirect the user to the checkout page on Stripe.
* When the user completes checkout on Stripe, Stripe sends us a webhook
  notification at POST /webhooks/receive.
* When we receive the webhook, we check the payment status, and if it's
  paid we mark the UserUpgrade as complete and upgrade the user.
* After Stripe sees that we have successfully processed the webhook,
  they redirect the user to the /user_upgrades/:id page, where we show
  the user their upgrade receipt.
2020-12-24 21:15:04 -06:00
evazion
7762489d7d user upgrades: upgrade to new Stripe checkout system.
This upgrades from the legacy version of Stripe's checkout system to the
new version:

> The legacy version of Checkout presented customers with a modal dialog
> that collected card information, and returned a token or a source to
> your website. In contrast, the new version of Checkout is a smart
> payment page hosted by Stripe that creates payments or subscriptions. It
> supports Apple Pay, Dynamic 3D Secure, and many other features.

Basic overview of the new system:

* We send the user to a checkout page on Stripe.
* Stripe collects payment and sends us a webhook notification when the
  order is complete.
* We receive the webhook notification and upgrade the user.

Docs:

* https://stripe.com/docs/payments/checkout
* https://stripe.com/docs/payments/checkout/migration#client-products
* https://stripe.com/docs/payments/handling-payment-events
* https://stripe.com/docs/payments/checkout/fulfill-orders
2020-12-24 19:58:29 -06:00
evazion
dbb66ace90 routes: replace hardcoded routes in models with route helpers.
Add a Routes module that gives models access to route helpers outside of
views, and use it to replace various hardcoded routes.
2020-12-24 00:17:19 -06:00
evazion
3c4781f6d8 users: update last_logged_in_at hourly.
Update last_logged_in_at on an hourly basis instead of a weekly basis.
2020-12-21 22:42:50 -06:00
evazion
6ac9882711 newrelic: log country of each request in newrelic.
Log the country of each HTTP request in NewRelic. Uses the CF-IPCountry
header set by Cloudflare.
2020-12-21 20:47:58 -06:00
evazion
efb836ac02 wikis: normalize Unicode characters in wiki bodies.
* Introduce an abstraction for normalizing attributes. Very loosely
  modeled after https://github.com/fnando/normalize_attributes.
* Normalize wiki bodies to Unicode NFC form.
* Normalize Unicode space characters in wiki bodies (strip zero width
  spaces, normalize line endings to CRLF, normalize Unicode spaces to
  ASCII spaces).
* Trim spaces from the start and end of wiki page bodies. This may cause
  wiki page diffs to show spaces being removed even when the user didn't
  explicitly remove the spaces themselves.
2020-12-21 20:47:50 -06:00
nonamethanks
2423c8a447 Weibo: use proxy for upload previews 2020-12-21 15:28:28 +01:00
evazion
3ad4beac02 autocomplete: fix exception when completing unsupported metatags. 2020-12-20 01:27:48 -06:00
evazion
28926c2332 autocomplete: remove old autocomplete endpoints.
Remove /tag/autocomplete.json and /saved_searches/labels.json.
2020-12-20 00:51:29 -06:00
evazion
9de7a07af7 /status: fix blank distro version field.
The `source` command is a bash-ism and doesn't work in a strictly POSIX
shell like dash, which is the /bin/sh on Debian/Ubuntu. Use `.` instead.

https://en.wikipedia.org/wiki/Dot_(command)
2020-12-20 00:51:29 -06:00
evazion
09e3146819 artist finder: add blog.livedoor.jp to blacklist. 2020-12-19 00:51:34 -06:00