Commit Graph

134 Commits

Author SHA1 Message Date
evazion
99846b7e3d users: allow mods to change the names of other users.
Allow moderators to forcibly change the username of other users. This is
so mods can change abusive or invalid usernames.

* A mod can only change the username of Builder-level users and below.
* The user can't change their own name again until one week has passed.
* A modaction is logged when a mod changes a user's name.
* A dmail is sent to the user notifying them of the change.
* The dmail does not send the user an email notification. This is so we
  don't spam users if their name is changed after they're banned, or if
  they haven't visited the site in a long time.

The rename button is on the user's profile page, and when you hover over
the user's name and open the "..." menu.
2022-10-02 01:32:10 -05:00
evazion
b94cb7d824 emails: include logging information in email headers.
Log the following information in email headers:

* X-Danbooru-User: the user's name and ID.
* X-Danbooru-IP: the user's IP.
* X-Danbooru-Session: the users' session ID.
* X-Danbooru-URL: the page that triggered the email.
* X-Danbooru-Job-Id: the ID of the background job that sent the email.
* X-Danbooru-Enqueued-At: when the email was queued as a background job.
* X-Danbooru-Dmail: for Dmail notifications, the link to the Dmail.
* X-Request-Id: the request ID of the HTTP request that triggered the email.

Also make it so we log an event in the APM when we send an email.
2022-09-29 04:36:11 -05:00
evazion
88ac91f5f3 search: refactor to pass in the current user explicitly. 2022-09-22 04:31:21 -05:00
evazion
3114ef3daf searchable: standardize the <field>_matches operator for text fields.
Standardize it so that all fields of type `text` are searchable with
`search[<field>_matches]`.

Before, the `<field>_matches` param was handled manually and some fields
were left out or handled inconsistently. Now it applies to all columns
of type `text`.

This does a full-text search on the field, so for example, searching
`/artist_commentaries?search[translated_description_matches]=smiling`
will match translated commentaries containing either the word "smiling",
"smiles", "smiled", or "smile".

Note that this only applies to columns defined as type `text`, not to
columns defined as `character varying`. The difference is that `text` is
used for fields containing free-form natural language, such as comments,
notes, forum posts, wiki pages, pool descriptions, etc, while `character
varying` is used for short strings not containing free-form language,
such as tag names, wiki page titles, urls, status fields, etc.

API changes:

* Add the `search[original_title_matches]`, `search[original_description_matches]`,
  `search[translated_title_matches]`, `search[translated_description_matches]` params
  to /artist_commentaries and /artist_commentary_versions.
* Remove the `search[name_matches]` and `search[group_name_matches]` params from /artist_versions.
* Remove the `search[title_matches]` param from /wiki_page_versions.
* Change the `search[name_matches]` param on /pools, /favorite_groups, and /pool_versions
  to do a full-text search instead of a substring match.
2022-09-22 01:52:13 -05:00
evazion
a229a6f5c4 models: remove ignored_columns declarations.
These columns have been removed from the underlying database.
2022-09-20 23:09:32 -05:00
evazion
d4da8499ce models: stop saving IP addresses in version tables.
Mark various `creator_ip_addr` and `updater_ip_addr` columns as ignored
and stop updating them in preparation for dropping them.
2022-09-18 03:49:17 -05:00
evazion
ee638f976f Add /user_actions page.
Add a /user_actions page. This page shows you a global timeline of
(almost) all activity on the site, including uploads, comments, votes,
edits, forum posts, and so on.

The main things it doesn't include are post edits, pool edits, and
favorites (posts and pools live in a separate database, and favorites
don't have the timestamps we need for ordering).

This page is useful for moderation purposes because it lets you see a
history of almost all of a user's activity on a single page.

Currently this page is mod-only. In the future it will be open to all
users, so you can view the history of your own site activity, or the
activity of others.
2022-09-16 05:39:25 -05:00
evazion
32613f9bb1 emails: fix sending emails to invalid addresses.
Fix mailers to not attempt deliveries to invalid or nonexistent email
addresses. This usually happened when someone changed their email, and
we tried to send a confirmation email to a nonexistent address.
2022-01-02 16:07:57 -06:00
evazion
a7dc05ce63 Enable frozen string literals.
Make all string literals immutable by default.
2021-12-14 21:33:27 -06:00
evazion
e3b836b506 Refactor full-text search to get rid of tsvector columns.
Refactor full-text search on several tables (comments, dmails,
forum_posts, forum_topics, notes, and wiki_pages) to use to_tsvector
expression indexes instead of dedicated tsvector columns. This way
full-text search works the same way across all tables.

API changes:

* Changed /wiki_pages.json?search[body_matches] to match against only
  the body. Before `body_matches` matched against both the title and the body.

* Added /wiki_pages.json?search[title_or_body_matches] to match against
  both the title and the body.

* Fixed /dmails.json?search[message_matches] to match against both the
  title and body when doing a wildcard search. Before a wildcard search
  only matched against the body.

* Added /dmails.json?search[body_matches] to match against only the dmail body.
2021-10-16 07:44:27 -05:00
evazion
79fdfa86ae Fix various rubocop warnings. 2021-09-27 00:46:13 -05:00
evazion
07e23204b6 rubocop: fix various Rubocop warnings. 2021-06-17 04:17:53 -05:00
evazion
5623cfb145 Add max lengths to comments, dmails, and forum posts.
* Max comment length: 15,000 characters.
* Max forum post length: 200,000 characters.
* Max forum topic title length: 200 characters.
* Max dmail length: 50,000 characters.
* Max dmail title length: 200 characters.
2021-03-08 18:46:49 -06:00
evazion
0cc1dae677 Fix #4725: Don't mark as spam DMails sent by an user to themselves. 2021-02-23 19:27:04 -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
ee4516f5fe searchable: refactor searchable_includes.
Pass searchable associations directly to search_attributes instead of
defining them separately in searchable_includes.
2020-12-16 23:57:07 -06:00
evazion
e771c0fca8 searchable: don't automatically include id, created_at, updated_at.
Don't make search methods on models call super in order to search
certain default attributes (id, created_at, updated_at). Simplifies some
magic.
2020-12-16 23:57:07 -06:00
evazion
8d87b1a0c0 models: fix deprecated errors[:base] << "message" calls.
Replace the idiom `errors[:base] << "message"` with
`errors.add(:base, "message")`. The former is deprecated in Rails 6.1.
2020-12-13 04:10:48 -06:00
evazion
cc64f8b7ee tests: fix broken source tests.
Fix various tests broken by source files changing or being deleted.
2020-11-10 14:52:54 -06:00
evazion
7bc7001b12 dmails: add dmail sending rate limits.
Don't allow regular users to send dmails to more than 10 different
users in one hour. This is an anti-spam measure.
2020-08-28 12:36:42 -05:00
evazion
5baeb3eecc dmails: update unread dmail count when dmail is hard deleted.
When a dmail is hard deleted, update the user's unread dmail count and
delete any associated mod reports.

Dmails aren't normally hard deleted, except when there's a large spam
wave that necessitates manual intervention.
2020-08-28 11:28:28 -05:00
BrokenEagle
c4009efccd Convert models to use new search includes mechanism 2020-07-27 19:29:18 +00:00
evazion
eacb4d4df3 models: factor out api_attributes to policies.
Refactor models so that we define attribute API permissions in policy
files instead of directly in models.

This is cleaner because a) permissions are better handled by policies
and b) which attributes are visible to the API is an API-level concern
that models shouldn't have to care about.

This fixes an issue with not being able to precompile CSS/JS assets
unless the database was up and running. This was a problem when building
Docker images because we don't have a database at build time. We needed
the database because `api_attributes` was a class-level macro in some
places, which meant it ran at boot time, but this triggered a database
call because api_attributes used database introspection to get the list
of allowed API attributes.
2020-06-08 18:38:02 -05:00
evazion
9242bf522b pundit: convert moderation reports to pundit. 2020-03-20 18:03:01 -05:00
evazion
480f39c34a pundit: convert dmails to pundit. 2020-03-20 18:03:01 -05:00
evazion
0f0e7cedf3 dmails: fixup exceptions when verifying dmail keys.
Fix show action throwing exceptions when viewing a dmail without a dmail key.
2020-03-14 21:09:25 -05:00
evazion
dc1742321d dmails: send email notifications in background job. 2020-03-14 21:06:29 -05:00
evazion
258f4a8b95 users: move emails to separate table.
* Move emails from users table to email_addresses table.
* Validate that addresses are formatted correctly and are unique across
  users. Existing invalid emails are grandfathered in.
* Add is_verified flag (the address has been confirmed by the user).
* Add is_deliverable flag (an undeliverable address is an address that bounces).
* Normalize addresses to prevent registering multiple accounts with the
  same email address (using tricks like Gmail's plus addressing).
2020-03-12 21:18:53 -05:00
evazion
5625458f69 users: refactor password reset flow.
The old password reset flow:

* User requests a password reset.
* Danbooru generates a password reset nonce.
* Danbooru emails user a password reset confirmation link.
* User follows link to password reset confirmation page.
* The link contains a nonce authenticating the user.
* User confirms password reset.
* Danbooru resets user's password to a random string.
* Danbooru emails user their new password in plaintext.

The new password reset flow:

* User requests a password reset.
* Danbooru emails user a password reset link.
* User follows link to password edit page.
* The link contains a signed_user_id param authenticating the user.
* User changes their own password.
2020-03-08 23:18:15 -05:00
evazion
5bc0ab446b models: add deletable concern. 2020-03-06 17:06:29 -06:00
evazion
3a018ee9f7 dmails: set sender name and ip address explicitly.
Set the sender name and IP addresses explicitly in the controller rather
than implicitly in the model.

Fixes cases where automated dmails from DanbooruBot had their IP
addresses set to the person who triggered the dmail, even though they
didn't actually send the dmail themselves.
2020-02-23 17:26:08 -06:00
evazion
0ad42d23c9 models: refactor search visibility methods.
Refactor how model visibility works in index actions:

* Call `visible` in the controller instead of in model `search`
  methods. This decouples model visibility from model searching.

* Explicitly pass CurrentUser when calling `visible`. This reduces
  hidden dependencies on the current user inside models.

* Standardize on calling the method `visible`. In some places it was
  called `permitted` instead.

* Add a `visible` base method to ApplicationModel.
2020-02-19 17:08:59 -06:00
evazion
207861fd40 api: remove available_includes dependent on current user.
This is to avoid specifying permissions in multiple disjoint places and
because most API users shouldn't need these fields.
2020-02-16 23:07:06 -06:00
BrokenEagle
63b3503bfc Add ability to use nested only parameter
- The only string works much the same as before with its comma separation
-- Nested includes are indicated with square brackets "[ ]"
-- The nested include is the value immediately preceding the square brackets
-- The only string is the comma separated string inside those brackets
- Default includes are split between format types when necessary
-- This prevents unnecessary includes from being added on page load
- Available includes are those items which are allowed to be accessible to the user
-- Some aren't because they are sensitive, such as the creator of a flag
-- Some aren't because the number of associated items is too large
- The amount of times the same model can be included to prevent recursions
-- One exception is the root model may include the same model once
--- e.g. the user model can include the inviter which is also the user model
-- Another exception is if the include is a has_many association
--- e.g. artist urls can include the artist, and then artist urls again
2020-02-12 23:58:53 +00:00
evazion
f87ec2509a modreports: fix reporting inaccessible dmails and forum posts.
* Fix it being possible to report dmails belonging to other users.
* Fix it being possible to report forum posts in mod-only threads.
2020-02-03 22:11:48 -06:00
evazion
a5ebbc04e8 dmails: fix shortlinks to include correct key. 2020-02-03 22:05:58 -06:00
evazion
24cb920608 mod reports: include reported user and message in forum post.
Also fix it so that reports against dmails include the key in the dmail
link so that mods can view the reported dmail.
2020-02-03 04:52:12 -06:00
evazion
bb2022abed mod reports: autoreport spam and autoban spammers.
* Automatically generate a mod report when a comment, forum post, or
  dmail is detected as spam.
* Automatically ban users that receive too many automatic spam reports
  within a short window of time.
* Automatically mark spam dmails as deleted.
* Change ban threshold from 10 spam reports in 24 hours to 10 reports in 1 hour.
* Change ban length from 3 days to forever.
2020-02-03 04:52:12 -06:00
evazion
170a0e8a48 dmails: remove ability to mark dmails as spam.
Instead of marking messages as spam, users can either report the message
or mark it as deleted.
2020-02-03 04:52:12 -06:00
evazion
73219f38ce dmails: fix security issues with dmail permalinks.
Fix a couple security issues related to dmail permalinks. Dmails have a
permalink that you can give to a Mod to let them read the dmail. This is
done with a key param that grants access when the dmail is opened by
another user. The key param had several problems:

* The key contained a full copy of the message's title and body encoded in
  base64. This meant that anyone given a dmail permalink could read the
  full dmail just by decoding the key in the link, without even having
  to open the link.

* The key was derived from the dmail's title and body. If you knew or
  could guess a dmail's title and body you could open the dmail. One
  case when this was possible was when sending dmails. You could send
  someone a dmail, take the permalink from your sent copy of the dmail,
  then increment the dmail id to open the receiver's copy of the dmail.
  Since the sent copy and the received copy both had the same title and
  body, they both had the same dmail key. This let you check whether a
  person had read your dmail, and what time they read it at.

* The key verification was done with an insecure string comparison
  rather than a secure constant-time comparison. This was potentially
  vulnerable to timing attacks.

* Opening a dmail belonging to another user would mark it as read for them.

The fix to all this is to use the dmail's id as the key instead of the
dmail's title and body. This means that old permalinks no longer work.
This is unavoidable given the issues above.

Other changes:

* The name of the 'Permalink' link is now 'Share'.
* Anyone with the 'Share' link can view the dmail, not just Mods.
2020-02-02 22:27:49 -06:00
evazion
6468df6d44 dmails: allow marking dmails as unread.
* Add ability to mark dmails as unread.
* Fix users.unread_dmail_count to not count deleted dmails.
* Fix show action so that API calls don't mark dmails as read.
* Don't show the unread dmail notice on the /dmails page itself.
* Stop using users.has_mail flag.
2020-02-01 15:49:33 -06:00
evazion
76630bbf73 dmails: remove search[read] param. 2020-01-31 16:25:06 -06:00
evazion
d8eba59cfa dmails: add unread folder, show only received messages by default.
* Add unread and deleted dmail folders.
* Remove dmail_folder cookie (wasn't used).
* Default to the received folder so that we don't show sent messages by default.
2020-01-31 16:24:53 -06:00
evazion
f8db577c25 dmails: replace hard deletions with soft deletions.
Turn deletions into soft deletions (set the is_deleted flag) instead of
hard deletions (remove from database). The is_deleted flag actually
already existed, but it was never used before.
2020-01-31 16:24:27 -06:00
evazion
af044c45db mod reports: enable reporting for members, add dmail reporting.
* Add ability to report dmails.
* Enable reports for comments, forum posts, and dmails.
* Allow Members to send reports.
* Don't allow users to report the same thing twice.
2020-01-27 17:12:39 -06:00
evazion
cae9a5d7e3 Drop dmail filters.
Few people used dmail filters (~900 users in 5 years) and even fewer
used them correctly. Most people used them to try to block dmail spam,
but usually they either blocked too much (by adding common words that
are present in nearly all dmails, causing all mails to them to be
filtered) or too little (blocking specific email addresses or urls,
which usually are never seen again after the spammer is banned).
Nowadays the spam detection system does a better job of filtering spam.
2020-01-21 00:10:20 -06:00
evazion
895199ecfc models: include all int/bool columns as html data attributes by default. 2020-01-05 22:57:47 -06:00
BrokenEagle
4b904dff5a Convert classes to use data attributes
- Remote resolved classes on post flags since they were unused
2020-01-04 22:02:45 +00:00
BrokenEagle
223a6df5d8 Add API data to show/index views 2020-01-04 22:02:44 +00:00
evazion
d0f060d8eb api: refactor api attribute declarations.
Replace the `method_attributes` and `hidden_attributes` methods with
`api_attributes`. `api_attributes` can be used as a class macro:

    # include only the given attributes.
    api_attributes :id, :created_at, :creator_name, ...

    # include all default attributes plus the `creator_name` method.
    api_attributes including: [:creator_name]

or as an instance method:

    def api_attributes
       [:id, :created_at, :creator_name, ...]
    end

By default, all attributes are included except for IP addresses and
tsvector columns.
2019-09-08 23:28:02 -05:00