Commit Graph

6445 Commits

Author SHA1 Message Date
Alan Guo Xiang Tan f562da3150
PERF: Reduce ActiveRecord allocations in `CategoryList#find_relevant_topics` (#25950)
Why this change?

Prior to this change, the `CategoryList#find_relevant_topics` method was
loading and allocating all `CategoryFeaturedTopic` records in the
database to eventually only just use its `category_id` and `topic_id`
column. On a site with many `CategoryFeaturedTopic` records, the loading
of the ActiveRecord objects is a source of bottleneck.

The other problem with the `CategoryList#find_relevant_topics` method is
that it is unconditionally loading all records from the database even if
the user does not have access to the category. This again is wasteful.

What does this change do?

This commit makes it such that `CategoryList#find_relevant_topics` is
called only after `CategoryList#find_categories` in the `CategoryList#initialize`
method so that we can filter featured topics against categories that the
user has access to.

The second change is that Instead of loading `CategoryFeaturedTopic` records, we make an
inner join agains the `topics` table instead and skip any allocation of
`CatgoryFeaturedTopic` ActiveRecord objects.
2024-02-29 12:19:04 +08:00
Natalie Tay a8a39d86b4
UX: Improve invite error message when a user uses an email that has already redeemed (#25695)
Improve invite error message when a user uses an email that has already redeemed
2024-02-27 18:24:20 +08:00
Ted Johansson 1bcb521fbf
DEV: Add DB backed problem checks to support perform_every config (#25834)
As part of problem checks refactoring, we're moving some data to be DB backed. In this PR it's the tracking of problem check execution. When was it last run, when was the last problem, when should it run next, how many consecutive checks had problems, etc.

This allows us to implement the perform_every feature in scheduled problem checks for checks that don't need to be run every 10 minutes.
2024-02-27 11:17:39 +08:00
Andrei Prigorshnev b3a1199493
FEATURE: Hide user status when user is hiding public profile and presence (#24300)
Users can hide their public profile and presence information by checking 
“Hide my public profile and presence features” on the 
`u/{username}/preferences/interface` page. In that case, we also don't 
want to return user status from the server.

This work has been started in https://github.com/discourse/discourse/pull/23946. 
The current PR fixes all the remaining places in Core.

Note that the actual fix is quite simple – a5802f484d. 
But we had a fair amount of duplication in the code responsible for 
the user status serialization, so I had to dry that up first. The refactoring 
as well as adding some additional tests is the main part of this PR.
2024-02-26 17:40:48 +04:00
David Taylor 542cb22fd4 DEV: Drop Ember 3 feature flag 2024-02-26 12:22:05 +00:00
Isaac Janzen 21f23cc032
DEV: Convert header to glimmer (#25214)
Here is a breakdown of the changes that will be implemented in this PR.

# Widgets -> Glimmer

Obviously, the intention of the todo here is to convert the header from widgets to glimmer. This PR splits the respective widgets as so:

### widgets/site-header.js
```mermaid height=200
flowchart TB
    A[widgets/site-header.js] 
    A-->B[components/glimmer-site-header.gjs]
```

### widgets/header.js and children
```mermaid height=200
flowchart TB
    A[widgets/header.js] 
    A-->B[components/glimmer-header.gjs]
    B-->C[glimmer-header/contents.gjs]
    C-->D[./auth-buttons.gjs]
    C-->E[./icons.gjs]
    C-->F[./user-menu-wrapper.gjs]
    C-->G[./hamburger-dropdown-wrapper.gjs]
    C-->H[./user-menu-wrapper.gjs]
    C-->I[./sidebar-toggle.gjs]
    C-->J[./topic/info.gjs]
```

There are additional components rendered within the `glimmer-header/*` components, but I will leave those out for now. From this view you can see that we split apart the logic of `widgets/header.js` into 10+ components. Breaking apart these mega files has many benefits (readability, etc).

# Services

I have introduced a [header](cdb42caa04/app/assets/javascripts/discourse/app/services/header.js) service. This simplifies how we pass around data in the header, as well as fixes a bug we have with "swiping" menu panels.


# Modifiers
Added a [close-on-click-outside](cdb42caa04/app/assets/javascripts/discourse/app/modifiers/close-on-click-outside.js) modifier that is built upon the [close-on-click-outside modifier](https://github.com/discourse/discourse/blob/main/app/assets/javascripts/float-kit/addon/modifiers/close-on-click-outside.js) that @jjaffeux built for float-kit. I think we could replace float-kit's implementation with mine and have it in a centralized location as they are extremely similar.

# Tests
Rewrote the existing header tests ([1](https://github.com/discourse/discourse/blob/main/app/assets/javascripts/discourse/tests/integration/components/widgets/header-test.js), [2](https://github.com/discourse/discourse/blob/main/app/assets/javascripts/discourse/tests/integration/components/site-header-test.js)) as system tests. 

# Other
- Converted `widgets/user-status-bubble.js` to a gjs component
- Converted `widgets/sidebar-toggle.js` to a gjs component
- Converted `topicFeaturedLinkNode()` to a gjs component
- Deprecated the [docking mixin](https://github.com/discourse/discourse/blob/main/app/assets/javascripts/discourse/app/mixins/docking.js)
2024-02-23 11:08:15 -07:00
Vinoth Kannan b3238bfc34
FEATURE: call hub API to update Discourse discover enrollment. (#25634)
Now forums can enroll their sites to be showcased in the Discourse [Discover](https://discourse.org/discover) directory. Once they enable the site setting `include_in_discourse_discover` to enroll their forum the `CallDiscourseHub` job will ping the `api.discourse.org/api/discover/enroll` endpoint. Then the Discourse Hub will fetch the basic details from the forum and add it to the review queue. If the site is approved then the forum details will be displayed in the `/discover` page.
2024-02-23 11:42:28 +05:30
Sam 207cb2052f
FIX: muted tags breaking hot page when filtered to tags (#25824)
Also, remove experimental setting and simply use top_menu for feature detection

This means that when people eventually enable the hot top menu, there will
be topics in it


Co-authored-by: Alan Guo Xiang Tan <gxtan1990@gmail.com>
2024-02-23 17:11:39 +11:00
Ted Johansson a72dc2f420
DEV: Introduce a problem checks API (#25783)
Previously, problem checks were all added as either class methods or blocks in AdminDashboardData. Another set of class methods were used to add and run problem checks.

As of this PR, problem checks are promoted to first-class citizens. Each problem check receives their own class. This class of course contains the implementation for running the check, but also configuration items like retry strategies (for scheduled checks.)

In addition, the parent class ProblemCheck also serves as a registry for checks. For example we can get a list of all existing check classes through ProblemCheck.checks, or just the ones running on a schedule through ProblemCheck.scheduled.

After this refactor, the task of adding a new check is significantly simplified. You add a class that inherits ProblemCheck, you implement it, add a test, and you're good to go.
2024-02-23 11:20:32 +08:00
Daniel Waterworth 13291dc5ef
FIX: Cache keys should be strings (#25791)
* FIX: Cache keys should be strings

Otherwise, there are subtle bugs that don't show up with a single
process.
2024-02-21 10:55:48 -06:00
Alan Guo Xiang Tan 3e331b1725
DEV: Set a bytesize limit for `ThemeSetting#json_value` (#25761)
Why this change?

Firstly, note that this is not a security commit because this feature is
still in development and should not be used anywhere.

The reason we want to set a limit here is to greatly reduce the
possibility of a DoS attack in the future via `ThemeSetting` where
someone would set an arbituary large json string in
`ThemeSetting#json_value` and causing the server to run out of resources
trying to serialize/deserialize the value.

What does this change do?

Adds an ActiveRecord validation to ensure that the bytesize of the json
string being stored is smaller than or equal to 0.5mb. We believe 0.5mb
is a decent limit for now but we can review the limit in the future if
we believe it is too small.
2024-02-21 08:09:37 +08:00
Alan Guo Xiang Tan 6ca2396b12
DEV: Centralise logic for validating a theme setting value (#25764)
Why this change?

The logic for validating a theme setting's value and default value was
not consistent as each part of the code would implement its own logic.
This is not ideal as the default value may be validated differently than
when we are setting a new value. Therefore, this commit seeks to
refactor all the validation logic for a theme setting's value into a
single service class.

What does this change do?

Introduce the `ThemeSettingsValidator` service class which holds all the
necessary helper methods required to validate a theme setting's value
2024-02-21 08:08:26 +08:00
Daniel Waterworth 13083d03ae
DEV: Async category search for sidebar modal (#25686) 2024-02-20 11:24:30 -06:00
Bianca Nenciu a24d110258
FIX: Preload parent categories for sidebar (#25726)
When "lazy load categories" is enabled, only the categories present in
the sidebar are preloaded. This is insufficient because the parent
categories are necessary too for the sidebar to be rendered properly.
2024-02-16 16:39:18 +02:00
David Taylor b1f74ab59e
FEATURE: Add experimental option for strict-dynamic CSP (#25664)
The strict-dynamic CSP directive is supported in all our target browsers, and makes for a much simpler configuration. Instead of allowlisting paths, we use a per-request nonce to authorize `<script>` tags, and then those scripts are allowed to load additional scripts (or add additional inline scripts) without restriction.

This becomes especially useful when admins want to add external scripts like Google Tag Manager, or advertising scripts, which then go on to load a ton of other scripts.

All script tags introduced via themes will automatically have the nonce attribute applied, so it should be zero-effort for theme developers. Plugins *may* need some changes if they are inserting their own script tags.

This commit introduces a strict-dynamic-based CSP behind an experimental `content_security_policy_strict_dynamic` site setting.
2024-02-16 11:16:54 +00:00
Martin Brennan 5935148bd8
FIX: Respect homepage prefs on admin sidebar Back to Forum link (#25642) 2024-02-16 14:31:42 +10:00
Martin Brennan ae24e04a5e
DEV: Add a plugin modifier for user_action_stream_builder (#25691)
Reactions needs this to be able to filter out likes received
actions, where there is also an associated reaction, since
now most reactions also count as a like.
2024-02-16 10:24:39 +10:00
Alan Guo Xiang Tan cc9480b24a
PERF: Use `-ping` option to ImageMagick `identify` command (#25713)
Why this change?

This adds the `-ping` option to the spots we missed in
cfdb461e9a.
2024-02-16 07:39:49 +08:00
Osama Sayegh cfdb461e9a
PERF: Pass the `-ping` option to the `identify` ImageMagick command to speed it up (#25697)
The `-ping` option significantly speeds up the ImageMagick `identify` command per our testing and the [documentation](https://imagemagick.org/script/command-line-options.php#ping):

> -ping
Efficiently determine these image characteristics: image number, the file name, the width and height of the image, whether the image is colormapped or not, the number of colors in the image, the number of bytes in the image, the format of the image (JPEG, PNM, etc.). Use +ping to ensure accurate image properties.

We already pass the `-ping` option in other places where the `identify` command is used, so it makes sense to use the option everywhere.

Internal topic: t/121431.
2024-02-15 18:55:39 +03:00
Sam 4346abe260
FEATURE: apply pinning to hot topic lists (#25690)
pinned topics should be pinned even on hot lists so it can be used as a
home page
2024-02-15 18:27:54 +11:00
Penar Musaraj c1577019c8
DEV: Add post_id parameter to reset_bump_date route (#25372)
This would allow a theme component (or an API call) to reset the bump
date of a topic to a given post's created_at date.

I picked `post_id` as the parameter here because it provides a bit of
extra protection against accidentally resetting the bump date to a date
that doesn't make sense.
2024-02-15 16:42:42 +11:00
Blake Erickson bb261094cf
FEATURE: Auto generate and display video preview image (#25633)
This change will allow auto generated video thumbnails to be used
instead of the black video thumbnail that overlays videos.

Follow up to: 2443446e62
2024-02-14 13:43:53 -07:00
Bianca Nenciu 9a6406d4bb
FIX: Preload user-specific category fields (#25663)
This is used when lazy_load_categories is enabled to fetch more info
about the category.
2024-02-13 20:00:44 +02:00
Martin Brennan 6b596151ff
DEV: Change Group.trusted_group_ids to use const (#25639)
We have AUTO_GROUPS, we can use this instead of the
hardcoded 10..19 (not even sure why it goes up to 19,
trust levels previously only went to 5 max).
2024-02-12 12:36:00 +10:00
Daniel Waterworth 6311a80724
FIX: Preload associations on subcategories when lazy loading categories (#25630) 2024-02-09 11:48:26 -06:00
Sam c8410537c1
FIX: hot not adding recently bumped topics (#25619)
When we insert into the hot set we add things with a score of 0
This means that if hot has more than batch size items in it with a score, then the 0s don't get an initial score

This corrects the situation by always ensuring we re-score:

1. batch size high scoring topics
2. (new) batch size recently bumped topics

* Update spec/models/topic_hot_scores_spec.rb

Co-authored-by: Isaac Janzen <50783505+janzenisaac@users.noreply.github.com>

---------

Co-authored-by: Isaac Janzen <50783505+janzenisaac@users.noreply.github.com>
2024-02-09 07:45:47 +11:00
Penar Musaraj 6bd26e81c1
FIX: Respect date range in top traffic sources report (#25599)
See https://meta.discourse.org/t/reports-top-traffic-sources-topics-stat-issue/179850
2024-02-08 11:17:59 -05:00
Martin Brennan 7ce76143ac
FIX: Always trust admin and moderators with post edits (#25602)
Removes duplication from LimitedEdit to see who can edit
posts, and also removes the old trust level setting check
since it's no longer necessary.

Also make it so staff can always edit since can_edit_post?
already has a staff escape hatch.
2024-02-08 13:10:26 +10:00
Alan Guo Xiang Tan 9f884cdaab
DEV: Introduce experimental `type: objects` theme setting (#25538)
Why this change?

This commit introduces an experimental `type: objects` theme setting
which will allow theme developers to store a collection of objects as
JSON in the database. Currently, the feature is still in development and
this commit is simply setting up the ground work for us to introduce the
feature in smaller pieces.

What does this change do?

1. Adds a `json_value` column as `jsonb` data type to the `theme_settings` table.
2. Adds a `experimental_objects_type_for_theme_settings` site setting to
   determine whether `ThemeSetting` records of with the `objects` data
   type can be created.
3. Updates `ThemeSettingsManager` to support read/write access from the
   `ThemeSettings#json_value` column.
2024-02-08 10:20:59 +08:00
Martin Brennan adb4eee153
DEV: Make more group-based settings client: false (#25585)
Affects the following settings:

* whispers_allowed_groups
* anonymous_posting_allowed_groups
* personal_message_enabled_groups
* shared_drafts_allowed_groups
* here_mention_allowed_groups
* uploaded_avatars_allowed_groups
* ignore_allowed_groups

This turns off `client: true` for these group-based settings,
because there is no guarantee that the current user gets all
their group memberships serialized to the client. Better to check
server-side first.
2024-02-08 09:43:34 +10:00
Ted Johansson 95a2d285d3
FEATURE: Add new 'illegal' flag reason (#25498)
To comply with Digital Services Act we need a way for users to flag a post as potentially illegal. This PR adds that functionality.
2024-02-07 10:12:22 +08:00
Gerhard Schlager dd5ca6cc4c
FEATURE: Permalinks for users (#25552) 2024-02-05 17:31:31 +01:00
Alan Guo Xiang Tan d460229ed8
FIX: Update themes javascript cache after running themes migrations (#25562)
Why this change?

This is caused by a regression in
59839e428f, where we stopped saving the
`Theme` object because it was unnecessary. However, it resulted in the
`after_save` callback not being called and hence
`Theme#update_javascript_cache!` not being called. As a result, some
sites were reporting that after runing a theme migration, the defaults
for the theme settings were used instead of the settings overrides
stored in the database.

What does this change do?

Add a call to `Theme#update_javascript_cache!` after running theme
migrations.
2024-02-05 14:35:11 +08:00
Bianca Nenciu 1d160702ad
FIX: Preload sidebar categories when lazy loading categories (#25332)
This fixes a bug where the sidebar categories would not be loaded when
the categories were lazy loaded because the sidebar uses the preloaded
category list, which was empty.
2024-02-02 10:35:15 +02:00
Ted Johansson e071b74a79
DEV: Drop deprecated Badge#image column (#25536)
We just completed the 3.2 release, which marks a good time to drop some previously deprecated columns.

Since the column has been marked in ignored_columns, it has been inaccessible to application code since then. There's a tiny risk that this might break a Data Explorer query, but given the nature of the column, the years of disuse, and the fact that such a breakage wouldn't be critical, we accept it.
2024-02-02 14:09:55 +08:00
Sam 140b2118af
FEATURE: improvements to hot feature (#25533)
1. Don't show visited line for hot filter, it is in random order
2. Don't count likes on non regular posts (eg: whispers / small actions)
3. Don't count participants in non regular posts
2024-02-02 10:53:27 +11:00
Sam 690ff4499c
DEV: adjustments to hot algorithm (#25517)
1. Serial likers will just like a bunch of posts on the same topic, this will
heavily inflate hot score. To avoid artificial "heat" generated by one user only count
the first like on the topic within the recent_cutoff range per topic

2. When looking at recent topics prefer "unique likers", defer to total likes on
older topics cause we do not have an easy count for unique likers

3. Stop taking 1 off like_count, it is not needed - platforms like reddit
allow you to like own post so they need to remove it.
2024-02-01 17:11:40 +11:00
Alan Guo Xiang Tan 44f8418093
DEV: Refactor `Theme#settings` to return a hash instead of array (#25516)
Why this change?

Returning an array makes it hard to immediately retrieve a setting by
name and makes the retrieval an O(N) operation. By returning an array,
we make it easier for us to lookup a setting by name and retrieval is
O(1) as well.
2024-02-01 10:26:56 +08:00
chapoi a695d85cbd
UX: Update selected colour var (#25500) 2024-01-31 09:32:38 +01:00
David Taylor 88305e3d96
DEV: Remove version-number-based logic (#25482)
The `deprecate_column` helper would change its behavior based on the current `Discourse::VERSION`. This means that 'finalizing' a stable release introduces a previously untested behavior change.

Much better to keep it as a deprecation until manual action is taken to introduce the breaking change.
2024-01-30 17:34:10 +00:00
Sam 27301ae5c7
FEATURE: support silent internal links (#25472)
Internal links always notify and add internal connections in topics.

This adds a special feature that lets you append `?silent=true` to a link
to have it excluded from:

1. Notifications - users will not be notified for these links
2. Post links below posts in the UI

This is specifically useful for large reports where adding all these connections
just results in noise.
2024-01-30 17:03:58 +11:00
marstall 5a00d1964f
DEV: add site setting to disable watched word checking in user fields (#25411)
adding a hidden sitesetting, `disable_watched_word_checking_in_user_fields` - false by default. if set to true, you can use any word at all in user profile fields.

meta: https://meta.discourse.org/t/watched-words-scope/282699/20
2024-01-29 12:44:32 -05:00
David Taylor 63f6bd5efe
DEV: Add admin warning for sites on Ember 3 (#25459)
Running Discourse 3.2 stable under Ember 3 will technically be possible, but is only intended as a short-term migration point. This commit adds an admin warning for sites which are using this configuration, to make it clear that themes and plugins are unlikely to support the configuration.

https://meta.discourse.org/t/287211
2024-01-29 14:09:07 +00:00
Ted Johansson 6ad34a0152
DEV: Exclude system users when calculating group user count (#25400)
We want to exclude the system user from group user counts, since intuitively admins wouldn't include them.

Originally this was accomplished by booting said system user from the groups, but this is causing problems, because the system user needs TL group membership to perform certain tasks.

After this PR, system user is still in the TL groups, but excluded when refreshing the user count.
2024-01-25 08:13:58 +08:00
Ted Johansson 32e2a1fd4a
DEV: Add delegated Group#human_users scope (#25398)
Some preparatory refactoring as we're working on TL groups for the system user. On User we have a scope #human_users to exclude the system user, DiscoBot, etc. This PR adds the same scope (delegated to User) on Group.
2024-01-24 13:33:05 +08:00
Penar Musaraj 4f901cae8f
PERF: Better query performance for user avatar consistency check. (#25342) 2024-01-22 18:33:39 +01:00
Roman Rizzi 57915d9edc
FIX: Radar chart not widely available. (#25368)
We added support for radar type charts in #24274. However, radar charts work with three variables, meaning we can't display any report that way.

Unfortunately, by adding `:radar` to the `Report#modes` variable, I made them widely available.

Related bug report: https://meta.discourse.org/t/report-radar-graph-uncaught-typeerror/292360
2024-01-22 11:21:28 -03:00
Martin Brennan b3904eab45
FIX: User group check should return true for system user for auto groups (#25357)
This is a temporary fix to address an issue where the
system user is losing its automatic groups when the server
is running. If any auto groups are provided, and the user is
a system user, then we return true. The system user is admin,
moderator, and TL4, so they usually have all auto groups.

We can remove this when we get to the bottom of why the auto
groups are being deleted.
2024-01-22 14:40:29 +10:00
Blake Erickson 561851b104
FEATURE: Add hot as a homepage option (#25325) 2024-01-18 16:36:18 -07:00
Bianca Nenciu 6a205ea0a5
DEV: Replace lazy_load_categories site setting (#25302)
The site setting has been removed in a previous commit abad38c, but it
was merged at the same time with 4cfc0e2 which added it back.
2024-01-17 21:44:48 +02:00
Bianca Nenciu abad38c2e7
DEV: Make lazy_load_categories setting use groups (#25282)
This allows certain users to test the new feature and avoid disruptions
in other's workflows.
2024-01-17 20:26:51 +02:00
Bianca Nenciu 4cfc0e231a
DEV: Change categories#index loading strategy (#25232)
The old strategy used to load 25 categories at a time, including the
subcategories. The new strategy loads 20 parent categories and at most
5 subcategories for each parent category, for a maximum of 120
categories in total.
2024-01-17 17:18:01 +02:00
Sam df8bb947b2
FEATURE: improvements to hot algorithm (#25295)
- Decrease gravity, we come in too hot prioritizing too many new topics
- Remove all muted topics / categories and tags from the hot list
- Punish topics with zero likes in algorithm
2024-01-17 16:12:03 +11:00
Sam ebd3971533
FEATURE: experiment with hot sort order (#25274)
This introduces a new experimental hot sort ordering. 

It attempts to float top conversations by first prioritizing a  topics with lots of recent activity (likes and users responding) 

The schedule that updates hot topics is disabled unless the hidden site setting: `experimental_hot_topics` is enabled. 

You can control "decay" with `hot_topic_gravity` and `recency` with `hot_topics_recent_days` 

Data is stored in the new `topic_hot_scores` table and you can check it out on the `/hot` route once 
enabled. 
---------

Co-authored-by: Penar Musaraj <pmusaraj@gmail.com>
2024-01-17 13:01:04 +11:00
Gerhard Schlager 241bf48497 DEV: Allow rebakes to generate optimized images at the same time
Previously only Sidekiq was allowed to generate more than one optimized image at the same time per machine. This adds an easy mechanism to allow the same in rake tasks and other tools.
2024-01-16 14:33:16 +01:00
Gerhard Schlager bcb8b3fab9 REFACTOR: Reuse `Discourse.store` instance
Calling `Discourse.store` creates a new instance of a store each time.
2024-01-16 14:33:16 +01:00
Alan Guo Xiang Tan 22614ca85b
DEV: Compile theme migrations javascript files when running theme qunit (#25219)
Why this change?

Currently, is it hard to iteratively write a theme settings migrations
because our theme migrations system does not rollback. Therefore, we
want to allow theme developers to be able to write QUnit tests for their
theme migrations files enabling them to iteratively write their theme
migrations.

What does this change do?

1. Update `Theme#baked_js_tests_with_digest` to include all `ThemeField`
records of `ThemeField#target` equal to `migrations`. Note that we do
not include the `settings` and `themePrefix` variables for migration files.

2. Don't minify JavaScript test files becasue it makes debugging in
   development hard.
2024-01-16 09:50:44 +08:00
Alan Guo Xiang Tan c76ca876a6
DEV: Add more debugging information to AR query logs on GitHub actions (#25237)
Why this change?

We have been chasing a problem with our flaky system test where the user
is logged out when it should never be.

What does this change do?

1. Logs the request path when lookup a user auth token.
2. Logs the request path and also the current thread's object id in
   ActiveRecord query logs.
2024-01-12 13:06:29 +08:00
Renato Atilio f5f3742166
FIX: respect creation date when paginating group activity posts (#24993)
* FIX: respect creation date when paginating group activity posts

There are scenarios where the chronological order of posts doesn't match the order of their IDs. For instance, when moving the first post from one topic or PM to another, a new post (with a higher ID) will be created, but it will retain the original creation time.

This PR changes the group activity page and endpoint to paginate posts using created_at instead of relying on ID ordering.
2024-01-11 13:37:27 -03:00
Alan Guo Xiang Tan 59839e428f
DEV: Add `skip_migrations` param when importing remote theme (#25218)
Why this change?

Importing theme with the `bundle` params is used mainly by
`discourse_theme` CLI in the development environment. However, we do not
want migrations to automatically run in the development environment
and instead want the developer to be intentional about running theme
migrations. As such, this commit adds support for a
`skip_migrations` param when importing a theme with the `bundle` params.

This commit also adds a `migrated` attribute for migrations theme fields
to indicate whether a migrations theme field has been migrated or not.
2024-01-11 14:04:02 +08:00
Bianca Nenciu be46acce8f
PERF: Prefer subquery instead of two queries (#25167)
The query that is now a subquery could return a long list of category
IDs, which slowed down the query considerably. This improvement reduces
the execution time from over 2 seconds down to about 100ms.
2024-01-09 08:19:37 +08:00
Daniel Waterworth 75c645453d
SECURITY: Store custom field values according to their registered type 2024-01-08 08:02:17 -07:00
Daniel Waterworth 4494d62531
SECURITY: Run custom field validations with save_custom_fields 2024-01-08 08:02:16 -07:00
Rafael dos Santos Silva 13735f35fb
FEATURE: Cache embed contents in the database (#25133)
* FEATURE: Cache embed contents in the database

This will be useful for features that rely on the semantic content of topics, like the many AI features



Co-authored-by: Roman Rizzi <rizziromanalejandro@gmail.com>
2024-01-05 10:09:31 -03:00
Isaac Janzen 1f94da349b
DEV: Make the Glimmer Search Menu the new default (#25092)
- Convert group based `experimental_search_menu_groups_enabled` site setting to be a _hidden_ boolean `experimental_search_menu` setting.
- Make default `true`
- Remove widget search menu tests

Discourse Encrypt Test Failure Fix - https://github.com/discourse/discourse-encrypt/pull/301
2024-01-03 09:07:27 -07:00
Martin Brennan 4e6d4193ea
DEV: Fix spec for post menu (#25100)
Followup to b92993fcee
I ran out of time to get this working for that fix,
also here I am making the post.url method have parity
with post.shareUrl in JS, which omits the post number
for the first post.
2024-01-03 16:55:08 +10:00
Natalie Tay b4f36507e0
FIX: Allow the flags to be cleaned up (#25085)
Currently, the reviewable queue includes ReviewableFlaggedPost with posts that have already been hidden. This allows for such hidden posts to be cleared up by the auto-tool.
2024-01-02 18:32:50 +08:00
Bianca Nenciu 14269232ba
DEV: No longer preload categories (#24950)
Categories will no longer be preloaded when `lazy_load_categories` is
enabled through PreloadStore.

Instead, the list of site categories will continue to be populated
by `Site.updateCategory` as more and more categories are being loaded
from different sources (topic lists, category selectors, etc).
2023-12-28 14:36:33 +02:00
Martin Brennan 89705be722
DEV: Add auto map from TL -> group site settings in DeprecatedSettings (#24959)
When setting an old TL based site setting in the console e.g.:

SiteSetting.min_trust_level_to_allow_ignore = TrustLevel[3]

We will silently convert this to the corresponding Group::AUTO_GROUP. And vice-versa, when we read the value on the old setting, we will automatically get the lowest trust level corresponding to the lowest auto group for the new setting in the database.
2023-12-26 14:39:18 +08:00
Ted Johansson 25ccf6fab1
FIX: Update position on model when re-positioning record (#24997)
When updating the position of a category, the server correctly updates the position in the database, but the response sent back to the client still contains the old position, causing it to "flip back" in the UI when saving. Only reloading the page will reveal the new, correct value.

The Positionable concern correctly positions the record and updates the database, but we don't assign the new position to the already instantiated model.

This change just assigns self.position after the database update. 😎
2023-12-21 10:15:10 +08:00
Blake Erickson 3380d283c9
FEATURE: Add API scope for /logs route (#24956)
Adds an API scope for accessing Logster's routes. This one is a bit
different than routes from core because it is mounted like

```
mount Logster::Web => "/logs"
```

and doesn't have all the route info a traditional rails app/engine does.
2023-12-18 19:45:04 -07:00
Blake Erickson a08691a599
FIX: Ensure file size restriction types are ints (#24947)
Settings that are using the new `file_size_restriction` types like the
`max_image_size_kb` setting need to have their values saved as integers.
This was a recent regression in 00209f03e6
that caused these values to be saved as strings.

This change also removes negatives from the validation regex because
file sizes can't be negative anyways.

Bug report: https://meta.discourse.org/t/289037
2023-12-18 09:22:50 -07:00
Bianca Nenciu 680cf443f4
FIX: Better infinite scrolling on categories page (#24831)
This commit refactor CategoryList to remove usage of EmberObject,
hopefully make the code more readable and fixes various edge cases with
lazy loaded categories (third level subcategories not being visible,
subcategories not being visible on category page, requesting for more
pages even if the last one did not return any results, etc).

The problems have always been here, but were not visible because a lot
of the processing was handled by the server and then the result was
serialized. With more of these being moved to the client side for the
lazy category loading, the problems became more obvious.
2023-12-18 16:46:09 +02:00
Martin Brennan 6de00f89c2
FEATURE: Initial admin sidebar navigation (#24789)
This is v0 of admin sidebar navigation, which moves
all of the top-level admin nav from the top of the page
into a sidebar. This is hidden behind a enable_admin_sidebar_navigation
site setting, and is opt-in for now.

This sidebar is dynamically shown whenever the user enters an
admin route in the UI, and is hidden and replaced with either
the:

* Main forum sidebar
* Chat sidebar

Depending on where they navigate to. For now, custom sections
are not supported in the admin sidebar.

This commit removes the experimental admin sidebar generation rake
task but keeps the experimental sidebar UI for now for further
testing; it just uses the real nav as the default now.
2023-12-18 11:48:25 +10:00
Kelv 2477bcc32e
DEV: lint against Layout/EmptyLineBetweenDefs (#24914) 2023-12-15 23:46:04 +08:00
Daniel Waterworth d7a09fb08d
DEV: Add true_fields method for CustomFields (#24876)
This is useful for plugins that might otherwise rely on the
CUSTOM_FIELD_TRUE constant.
2023-12-14 11:06:21 -06:00
Daniel Waterworth f7aefffea7
DEV: Concerns can use class_methods (#24875) 2023-12-13 14:12:03 -06:00
Ted Johansson 36057638ca
DEV: Convert min_trust_to_edit_post to groups (#24840)
We're changing the implementation of trust levels to use groups. Part of this is to have site settings that reference trust levels use groups instead. It converts the min_trust_to_edit_post site setting to edit_post_allowed_groups.

The old implementation will co-exist for a short period while I update any references in plugins and themes.
2023-12-13 13:25:13 +08:00
Jarek Radosz 8355664c82
FIX: Don't use `:true`/`:false` symbols (#24861)
on line 252 `has_children` is set to true/false (actual booleans) which means `has_children?` was in some cases returning incorrect value…
2023-12-13 00:27:14 +01:00
Angus McLeod 95c61b88dc
Apply embed unlisted setting consistently (#24294)
Applies the embed_unlisted site setting consistently across topic embeds, including those created via the WP Discourse plugin. Relatedly, adds a embed exception to can_create_unlisted_topic? check. Users creating embedded topics are not always staff.
2023-12-12 09:35:26 -05:00
Bianca Nenciu 81b0420614
FEATURE: Add pagination to categories page (#23976)
When `lazy_load_categories` is enabled, the categories are no longer
preloaded in the `Site` object, but instead they are being requested
on a need basis.

The categories page still loaded all categories at once, which was not
ideal for sites with many categories because ti would take a lot of
time to build and parse the response.

This commit adds pagination to the categories page using the LoadMore
helper. As the user scrolls through the categories page, more categories
are requested from the server and appended to the page.

<!-- NOTE: All pull requests should have tests (rspec in Ruby, qunit in JavaScript). If your code does not include test coverage, please include an explanation of why it was omitted. -->
2023-12-11 17:58:45 +02:00
Gerhard Schlager d725b3ca9e DEV: Add script for preprocessing uploads as part of a migration
This script preprocesses all uploads within a intermediate DB (output of converters) and uploads those files to S3. It does the same for optimized images. This speeds up migrations when you have to run them multiple times, because you only have to preprocess and upload the files once.

This script is very hacky and mostly undocumented for now. That will change in the future.
2023-12-11 16:23:07 +01:00
Bianca Nenciu dcd81d56c0
FIX: category selectors for lazy loaded categories (#24533)
A lot of work has been put in the select kits used for selecting
categories: CategorySelector, CategoryChooser, CategoryDrop, however
they still do not work as expected when these selectors already have
values set, because the category were still looked up in the list of
categories stored on the client-side Categrories.list().

This PR fixes that by looking up the categories when the selector is
initialized. This required altering the /categories/find.json endpoint
to accept a list of IDs that need to be looked up. The API is called
using Category.asyncFindByIds on the client-side.

CategorySelector was also updated to receive a list of category IDs as
attribute, instead of the list of categories, because the list of
categories may have not been loaded.

During this development, I noticed that SiteCategorySerializer did not
serializer all fields (such as permission and notification_level)
which are not a property of category, but a property of the relationship
between users and categories. To make this more efficient, the
preload_user_fields! method was implemented that can be used to
preload these attributes for a user and a list of categories.
2023-12-08 12:01:08 +02:00
Martin Brennan d9a422cf61
FIX: Do not attempt S3 ACL call if secure status did not change (#24785)
When rebaking and in various other places for posts, we
run through the uploads and call `update_secure_status` on
each of them.

However, if the secure status didn't change, we were still
calling S3 to change the ACL, which would have been a noop
in many cases and takes ~1 second per call, slowing things
down a lot.

Also, we didn't account for the s3_acls_enabled site setting
being false here, and in the specs doing an assertion
that `Discourse.store.update_ACL` is not called doesn't
work; `Discourse.store` isn't a singleton, it re-initializes
`FileStore::S3Store.new` every single time.
2023-12-08 12:58:45 +10:00
Daniel Waterworth 611acaa6bc
FIX: Validate each value in an array custom field separately (#24659) 2023-12-07 14:24:04 -06:00
Mark VanLandingham ee05f57e2d
FEATURE: Site setting to display user avatars in user menu (#24514) 2023-12-07 11:30:44 -06:00
Martin Brennan 7afb5fc481
DEV: Use Discourse::SYSTEM_USER_ID in fixtures/009_users (#24743)
I couldn't find where we created the system user and
this is why -- everywhere else in the app we reference
SYSTEM_USER_ID but here.
2023-12-07 09:04:45 +10:00
Jarek Radosz 694b5f108b
DEV: Fix various rubocop lints (#24749)
These (21 + 3 from previous PRs) are soon to be enabled in rubocop-discourse:

Capybara/VisibilityMatcher
Lint/DeprecatedOpenSSLConstant
Lint/DisjunctiveAssignmentInConstructor
Lint/EmptyConditionalBody
Lint/EmptyEnsure
Lint/LiteralInInterpolation
Lint/NonLocalExitFromIterator
Lint/ParenthesesAsGroupedExpression
Lint/RedundantCopDisableDirective
Lint/RedundantRequireStatement
Lint/RedundantSafeNavigation
Lint/RedundantStringCoercion
Lint/RedundantWithIndex
Lint/RedundantWithObject
Lint/SafeNavigationChain
Lint/SafeNavigationConsistency
Lint/SelfAssignment
Lint/UnreachableCode
Lint/UselessMethodDefinition
Lint/Void

Previous PRs:
Lint/ShadowedArgument
Lint/DuplicateMethods
Lint/BooleanSymbol
RSpec/SpecFilePathSuffix
2023-12-06 23:25:00 +01:00
Jarek Radosz 6a66dc1cfb
DEV: Fix Lint/BooleanSymbol (#24747) 2023-12-06 13:19:09 +01:00
Jarek Radosz 138bf486d3
DEV: Fix Lint/DuplicateMethods (#24746) 2023-12-06 13:18:34 +01:00
Daniel Waterworth 434ae5bbe7
FIX: Allow setting an array custom field to a singleton value (#24636)
Also, validation happens per item in an array field.
2023-11-29 14:18:47 -06:00
Daniel Waterworth eef93ac926
DEV: Allow setting max_length for field types using the plugin API (#24635) 2023-11-29 14:17:12 -06:00
Sam b09422428d
DEV: update syntax tree to latest (#24623)
update format to latest syntax tree
2023-11-29 16:38:07 +11:00
Bianca Nenciu e85a81f33c
FIX: Make category-drop work with lazy_load_categories (#24187)
The category drop was rerendered after every category async change
because it updated the categories list. This is not necessary and
categories can be referenced indirectly by ID instead.
2023-11-28 17:58:47 +02:00
David Taylor 5783f231f8
DEV: Introduce `DISCOURSE_ASSET_URL_SALT` (#24596)
This value is included when generating static asset URLs. Updating the value will allow site operators to invalidate all asset urls to recover from configuration issues which may have been cached by CDNs/browsers.
2023-11-28 11:28:40 +00:00
Martin Brennan 1fc0ce1ac2
FIX: with_secure_uploads? could return nil in some cases (#24592)
When we check upload security, one of the checks is to
run `access_control_post.with_secure_uploads?`. The problem
here is that the `topic` for the post could be deleted,
which would make the check return `nil` sometimes instead
of false because of safe navigation. We just need to be
more explicit.
2023-11-28 13:12:28 +10:00
Krzysztof Kotlarek 5551a71c55
FEATURE: increase tag description limit to 1000 (#24561)
Admin can add tag description up to 1000 characters.

Full description is displayed on tag page, however on topic list it is truncated to 80 characters.
2023-11-28 08:45:40 +11:00
Martin Brennan 91232847e3
FIX: Video placeholders not auto-linking post uploads (#24559)
Followup to 2443446e62

We introduced video placeholders which prevent preloading
metadata for videos in posts. The structure looks like this
in HTML when the post is cooked:

```
<div class="video-placeholder-container" data-video-src="http://some-url.com/video.mp4" dir="ltr" style="cursor: pointer;">
  <div class="video-placeholder-wrapper">
    <div class="video-placeholder-overlay">
      <svg class="fa d-icon d-icon-play svg-icon svg-string" xmlns="http://www.w3.org/2000/svg">
        <use href="#play"></use>
      </svg>
    </div>
  </div>
</div>
```

However, we did not update the code that links post uploads
to the post via UploadReference, so any videos uploaded since
this change are essentially dangling and liable to be deleted.
This also causes some uploads to be marked secure when they
shouldn't be, because they are not picked up and analysed in the
CookedPostProcessor flow.
2023-11-27 12:38:52 +10:00
Bianca Nenciu 012541b045
FIX: Serialize parent categories first (#24530)
The parent category needs to be serialized before the child category
because they are parsed in order. Otherwise the client will not build
the parent-child relationship correctly.
2023-11-23 19:03:05 +02:00
Daniel Waterworth 6aa69bdaea
DEV: Allow setting different custom field length limits by key (#24505) 2023-11-22 12:00:42 -06:00
Daniel Waterworth 0059e6807c
DEV: Refactor save_custom_fields methods (#24495)
Operate a key at a time, to make it clearer what's going on.

This also fixes a bug where array integer fields would get re-written
even when there wasn't a change.
2023-11-21 12:40:15 -06:00
Daniel Waterworth ced21fa5c1
DEV: Deprecate array custom fields (#24492)
Array custom fields use separate rows for each value, but whenever we
update an array, we have always destroy the existing rows and create new
ones. Therefore, there's no benefit over using the json type.
2023-11-21 11:05:49 -06:00
Daniel Waterworth b3c67a78b8
FIX: Preserve custom field array order (#24491) 2023-11-21 10:55:22 -06:00
Jarek Radosz 8968887e24
DEV: Fix various typos (#24461)
November 2023 edition
2023-11-20 16:49:49 +01:00
Martin Brennan 146da75fd7
FEATURE: Add setting & preference for search sort default order (#24428)
This commit adds a new `search_default_sort_order` site setting,
set to "relevance" by default, that controls the default sort order
for the full page /search route.

If the user changes the order in the dropdown on that page, we remember
their preference automatically, and it takes precedence over the site
setting as a default from then on. This way people who prefer e.g.
Latest Post as their default can make it so.
2023-11-20 10:43:58 +10:00
Martin Brennan 186e415e38
DEV: Housekeeping for CleanUpUploads job (#24361)
Followup to 9db8f00b3d, we
don't need this dead code any more. Also made some minor
improvements and comments.
2023-11-20 09:50:09 +10:00
David Taylor 04a58a6e64
PERF: Only invalidate other translations when en changes (#24443)
en is the only fallback locale we use, so there's no need to invalidate everything when other languages change. Limiting this also helps to prevent circular dependent_field relations which could cause issues in some situations.

Followup to eda79186ee
2023-11-18 12:36:25 +00:00
Daniel Waterworth 0c712eaa3a
DEV: Don't define methods in an included block (#24433) 2023-11-17 12:22:32 -06:00
Alan Guo Xiang Tan e0ef88abca
DEV: Run QUnit tests for official Discourse themes (#24405)
Why this change?

As the number of themes which the Discourse team supports officially
grows, we want to ensure that changes made to Discourse core do not
break the plugins. As such, we are adding a step to our Github actions
test job to run the QUnit tests for all official themes.

What does this change do?

This change adds a new job to our tests Github actions workflow to run the QUnit
tests for all official plugins. This is achieved with the following
changes:

1. Update `testem.js` to rely on the `THEME_TEST_PAGES` env variable to set the
   `test_page` option when running theme QUnit tests with testem. The
   `test_page` option [allows an array to be specified](https://github.com/testem/testem#multiple-test-pages) such that tests for
   multiple pages can be run at the same time. We are relying on a ENV variable
   because  the `testem` CLI does not support passing a list of pages
   to the `--test_page` option.

2. Support a `/testem-theme-qunit/:testem_id/theme-qunit` Rails route in the development environment. This
   is done because testem prefixes the path with a unique ID to the configured `test_page` URL.
   This is problematic for us because we proxy all testem requests to the
   Rails server and testem's proxy configuration option does not allow us
   to easily rewrite the URL to remove the prefix. Therefore, we configure a proxy in testem to prefix `theme-qunit` requests with
  `/testem-theme-qunit` which can then be easily identified by the Rails server and routed accordingly. 

3. Update `qunit:test` to support a `THEME_IDS` environment variable
   which will allow it to run QUnit tests for multiple themes at the
   same time.

4. Support `bin/rake themes:qunit[ids,"<theme_id>|<theme_id>"]` to run
   the QUnit tests for multiple themes at the same time.

5. Adds a `themes:qunit_all_official` Rake task which runs the QUnit
   tests for all the official themes.
2023-11-17 07:17:32 +08:00
Daniel Waterworth 46e2523177
DEV: Remove custom field regexes (#24390)
As far as I can tell, this isn't used
2023-11-16 11:37:10 -06:00
David Taylor eda79186ee
FIX: Recompile theme translations when fallback data changes (#24371)
Previously we would only recompile a theme locale when its own data changes. However, the output also includes fallback data from other locales, so we need to invalidate all locales when fallback locale data is changed. Building a list of dependent locales is tricky, so let's just invalidate them all.
2023-11-14 19:53:27 +00:00
Kris 797da5870b
FEATURE: remove category badge style options, set bullet style as default (#24198) 2023-11-13 10:46:15 -05:00
David Battersby 4b78254065
FIX: Post moved small action links should respect subfolder installs (#24336)
This change fixes an issue with small action links (when post is moved) to add the subfolder path to the url.
2023-11-13 11:06:25 +08:00
Martin Brennan 731dffdf92
DEV: Align S3 transfer acceleration global settings (#24302)
Followup to fe05fdae24

For consistency with other S3 settings, make the global setting
the same name as the site setting and use SiteSetting.Upload
too so it reads from the correct place.
2023-11-10 09:50:23 +10:00
Andrei Prigorshnev d91456fd53
DEV: Ability to collect stats without exposing them via API (#23933)
This adds the ability to collect stats without exposing them 
among other stats via API.

The most important thing I wanted to achieve is to provide 
an API where stats are not exposed by default, and a developer 
has to explicitly specify that they should be 
exposed (`expose_via_api: true`). Implementing an opposite 
solution would be simpler, but that's less safe in terms of 
potential security issues. 

When working on this, I had to refactor the current solution. 
I would go even further with the refactoring, but the next steps 
seem to be going too far in changing the solution we have, 
and that would also take more time. Two things that can be 
improved in the future:
1. Data structures for holding stats can be further improved
2. Core stats are hard-coded in the About template (it's hard 
to fix it without correcting data structures first, see point 1):
    63a0700d45/app/views/about/index.html.erb (L61-L101)

The most significant refactorings are:
1. Introducing the `Stat` model
2. Aligning the way the core and the plugin stats' are registered
2023-11-10 00:44:05 +04:00
Bianca Nenciu bdb81b5346
DEV: Use a single registry for preloaded category custom fields (#24272)
There was a registry for preloaded site categories and a new one has
been introduced recently for categories serialized through a
CategoryList.

Having two registries created a lot of friction for developers and this
commit merges them into a single one, providing a unified API.
2023-11-09 18:23:24 +02:00
Martin Brennan 3c5fb871c0 SECURITY: Filter unread bookmark reminders the user cannot see
There is an edge case where the following occurs:

1. The user sets a bookmark reminder on a post/topic
2. The post/topic is changed to a PM before or after the reminder
   fires, and the notification remains unread by the user
3. The user opens their bookmark reminder notification list
   and they can still see the notification even though they cannot
   access the topic anymore

There is a very low chance for information leaking here, since
the only thing that could be exposed is the topic title if it
changes to something sensitive.

This commit filters the bookmark unread notifications by using
the bookmarkable can_see? methods and also prevents sending
reminder notifications for bookmarks the user can no longer see.
2023-11-09 13:39:16 +11:00
Krzysztof Kotlarek 5f20748e40 SECURITY: SSRF vulnerability in TopicEmbed
Block redirects when making the final request in TopicEmbed to prevent Server Side Request Forgery (SSRF)
2023-11-09 13:39:08 +11:00
Andrei Prigorshnev be2eb3df44
FIX: user got notified about a mention inside a chat message quote (#24229)
When quoting a chat message in a post, if that message contains a mention, 
that mention should be ignored. But we've been detecting them and sending 
notifications to users. This PR fixes the problem. Since this fix is for 
the chat plugin, I had to introduce a new API for plugins:

    # We strip posts before detecting mentions, oneboxes, attachments etc. 
    # We strip those elements that shouldn't be detected. For example, 
    # a mention inside a quote should be ignored, so we strip it off. 
    # Using this API plugins can register their own post strippers. 
    def register_post_stripper(&block) 
    end
2023-11-08 23:13:25 +04:00
Roman Rizzi 3c29a84d98
DEV: Add support for radar charts when displaying reports. (#24274)
Reports can have the radar type, which will get rendered by the `admin-report-radar` component.
2023-11-08 10:48:12 -03:00
Ted Johansson c3708c4276
DEV: Add support for custom retries for scheduled admin checks (#24224)
We updated scheduled admin checks to run concurrently in their own jobs. The main reason for this was so that we can implement re-check functionality for especially flaky checks (e.g. group e-mail credentials check.)

This works in the following way:

1. The check declares its retry policy using class methods.
2. A block can be yielded to if there are problems, but before they are committed to Redis.
3. The job uses this block to either a) schedule a retry if there are any remaining or b) do nothing and let the check commit.
2023-11-06 08:57:02 +08:00
Ted Johansson 47e58357b6
DEV: Parallel scheduled admin checks (#24190)
This PR does some preparatory refactoring of scheduled admin checks in order for us to be able to do custom retry strategies for some of them.

Instead of running all checks in sequence inside a single, scheduled job, the scheduled job spawns one new job per check.

In order to be concurrency-safe, we need to change the existing Redis data structure from a string (of serialized JSON) to a list of strings (of serialized JSON).
2023-11-03 09:05:29 +08:00
Osama Sayegh 3cadd6769e
FEATURE: Theme settings migrations (#24071)
This commit introduces a new feature that allows theme developers to manage the transformation of theme settings over time. Similar to Rails migrations, the theme settings migration system enables developers to write and execute migrations for theme settings, ensuring a smooth transition when changes are required in the format or structure of setting values.

Example use cases for the theme settings migration system:

1. Renaming a theme setting.

2. Changing the data type of a theme setting (e.g., transforming a string setting containing comma-separated values into a proper list setting).

3. Altering the format of data stored in a theme setting.

All of these use cases and more are now possible while preserving theme setting values for sites that have already modified their theme settings.

Usage:

1. Create a top-level directory called `migrations` in your theme/component, and then within the `migrations` directory create another directory called `settings`.

2. Inside the `migrations/settings` directory, create a JavaScript file using the format `XXXX-some-name.js`, where `XXXX` is a unique 4-digit number, and `some-name` is a descriptor of your choice that describes the migration.

3. Within the JavaScript file, define and export (as the default) a function called `migrate`. This function will receive a `Map` object and must also return a `Map` object (it's acceptable to return the same `Map` object that the function received).

4. The `Map` object received by the `migrate` function will include settings that have been overridden or changed by site administrators. Settings that have never been changed from the default will not be included.

5. The keys and values contained in the `Map` object that the `migrate` function returns will replace all the currently changed settings of the theme.

6. Migrations are executed in numerical order based on the XXXX segment in the migration filenames. For instance, `0001-some-migration.js` will be executed before `0002-another-migration.js`.

Here's a complete example migration script that renames a setting from `setting_with_old_name` to `setting_with_new_name`:

```js
// File name: 0001-rename-setting.js

export default function migrate(settings) {
  if (settings.has("setting_with_old_name")) {
    settings.set("setting_with_new_name", settings.get("setting_with_old_name"));
  }
  return settings;
}
```

Internal topic: t/109980
2023-11-02 08:10:15 +03:00
Bianca Nenciu fd07c943ad
DEV: Refactor watched words (#24163)
- Ignore only invalid words, not all words if one of them is invalid

- The naming scheme for methods was inconsistent

- Optimize regular expressions
2023-11-01 16:41:10 +02:00
Ted Johansson 3f3d2ee2c0
DEV: Deprecate defunct User#flag_level column (#24134)
The User#flag_level column has not been in use for a very long time. The "new" reviewable system dynamically calculates flag scores based on past performance of the user.

This PR removes flag_level from the admin user serializer (since it isn't displayed anywhere in admin user lists) and marks the column as deprecated and targeted for removal in the next minor version.
2023-10-27 17:27:04 +08:00
Ted Johansson f9f9cf0bf4
DEV: Remove unreachable IP address validation message (#24131)
The message: :signup_not_allowed option to the IP address validator does nothing, because the AllowedIpAddressValidator chooses one of either:

- ip_address.blocked or
- ip_address.max_new_accounts_per_registration_ip

internally. This means that the translation for this was also never used.

This PR removes the ineffectual option and the unused translation. It also moves the translated error messages for blocked and max_new_accounts_per_registration_ip into the correct location so we can pass a symbol to ActiveModel::Errors#add.

There is no actual change in behaviour.
2023-10-27 15:22:38 +08:00
Martin Brennan 219b071994
FIX: Revise and reject post breaks on new topics queued (#24109)
Followup to 9762e65758. This
original commit did not take into account the fact that
new topics can end up in the approval queue as a
ReviewableQueuedPost, and so there was a 500 error raised
when accessing `self.topic` when sending a PM to the user.
2023-10-27 13:05:41 +10:00
Ted Johansson d0915027a8
DEV: Remove deprecated queue_jobs site setting (#24127)
Using SiteSetting.queue_jobs= to configure job asynchronicity was deprecated here four years ago and marked for removal in version 2.9.0. This PR removes the fallback method we kept since then. The method was there because it was still being used in a bunch of plugin tests (now fixed.)
2023-10-27 11:05:02 +08:00
Ted Johansson 3ad8e1fbde
DEV: Remove deprecated PostAction.remove_act method (#24126)
The PostAction.remove_act class method has been deprecated and replaced by PostActionDestroyer. It was marked for removal in version 2.9.0. This PR removes the method.
2023-10-27 10:02:14 +08:00
Angus McLeod 2a75656ff2
DEV: Add category custom field preloading to CategoryList (#23969)
This commit also introduced a plugin API for preloading category custom
fields.
2023-10-26 16:34:23 +03:00
Alan Guo Xiang Tan f2a90afa4c
DEV: Introduce `Theme#get_setting` (#24032)
Why this change?

Currently, we do not have a method to easily retrieve a theme setting's
value on the server side. Such a method can be useful in the test
environment where we need to retrieve the theme's setting and use its
value in assertions.

What does this change do?

This change introduces the `Theme#get_setting` instance method.
2023-10-23 07:41:40 +08:00
Sérgio Saquetim 0cfc42e0e6
FEATURE: Add dark mode option for category backgrounds (#24003)
Adds a new upload field for a dark mode category background that will be used as an alternative when Discourse is using a dark mode theme.
2023-10-20 12:48:06 +00:00
Bianca Nenciu e7afd18155
DEV: Fix lazy_load_categories for uncategorized topic lists (#24028) 2023-10-20 13:31:20 +03:00
David Battersby 75441e063a
DEV: create new_post_moved event trigger when moving posts (#24005)
This change adds a new event trigger (new_post_moved) when the first post in a topic is moved to a new topic.

Plugins that listen for the new_post_moved event now have an easy way to update old data based on the post id.
2023-10-20 17:56:50 +08:00
Régis Hanol 33715ccc57
FEATURE: Add all user update API scopes (#24016)
There are a few PUT requests that users can do in their preferences tab that aren't going through the standard `user#update` action.

This commit adds all the "trivial" ones (aka. except the security-related one, username and email changes) so you can now change the badge title, the avatar or featured topic of a user via the API.
2023-10-19 15:37:25 +02:00
Martin Brennan 9ef3a18ce4
DEV: Add new experimental admin UI route and sidebar (#23952)
This commit adds a new admin UI under the route `/admin-revamp`, which is
only accessible if the user is in a group defined by the new `enable_experimental_admin_ui_groups` site setting. It
also adds a special `admin` sidebar panel that is shown instead of the `main`
forum one when the admin is in this area.

![image](https://github.com/discourse/discourse/assets/920448/fa0f25e1-e178-4d94-aa5f-472fd3efd787)

We also add an "Admin Revamp" sidebar link to the community section, which
will only appear if the user is in the setting group:

![image](https://github.com/discourse/discourse/assets/920448/ec05ca8b-5a54-442b-ba89-6af35695c104)

Within this there are subroutes defined like `/admin-revamp/config/:area`,
these areas could contain any UI imaginable, this is just laying down an
initial idea of the structure and how the sidebar will work. Sidebar links are
currently hardcoded.

Some other changes:

* Changed the `main` and `chat` panels sidebar panel keys to use exported const values for reuse
* Allowed custom sidebar sections to hide their headers with the `hideSectionHeader` option
* Add a `groupSettingArray` setting on `this.siteSettings` in JS, which accepts a group site setting name
  and splits it by `|` then converts the items in the array to integers, similar to the `_map` magic for ruby
  group site settings
* Adds a `hidden` option for sidebar panels which prevents them from showing in separated mode and prevents
  the switch button from being shown

---------

Co-authored-by: Krzysztof Kotlarek <kotlarek.krzysztof@gmail.com>
2023-10-19 14:23:41 +10:00
Martin Brennan 5dc45b5dcf
FIX: Secure upload post processing race condition (#23968)
* FIX: Secure upload post processing race condition

This commit fixes a couple of issues.

A little background -- when uploads are created in the composer
for posts, regardless of whether the upload will eventually be
marked secure or not, if secure_uploads is enabled we always mark
the upload secure at first. This is so the upload is by default
protected, regardless of post type (regular or PM) or category.

This was causing issues in some rare occasions though because
of the order of operations of our post creation and processing
pipeline. When creating a post, we enqueue a sidekiq job to
post-process the post which does various things including
converting images to lightboxes. We were also enqueuing a job
to update the secure status for all uploads in that post.

Sometimes the secure status job would run before the post process
job, marking uploads as _not secure_ in the background and changing
their ACL before the post processor ran, which meant the users
would see a broken image in their posts. This commit fixes that issue
by always running the upload security changes inline _within_ the
cooked_post_processor job.

The other issue was that the lightbox wrapper link for images in
the post would end up with a URL like this:

```
href="/secure-uploads/original/2X/4/4e1f00a40b6c952198bbdacae383ba77932fc542.jpeg"
```

Since we weren't actually using the `upload.url` to pass to
`UrlHelper.cook_url` here, we weren't converting this href to the CDN
URL if the post was not in a secure context (the UrlHelper does not
know how to convert a secure-uploads URL to a CDN one). Now we
always end up with the correct lightbox href. This was less of an issue
than the other one, since the secure-uploads URL works even when the
upload has become non-secure, but it was a good inconsistency to fix
anyway.
2023-10-18 23:48:01 +00:00
Martin Brennan e91d8feab3
Revert "FEATURE: Count only approved flagged posts in user pages (#22799)" (#23962)
This reverts commit 5f0bc4557f.

Through extensive internal discussion we have decided to revert
this change, as it significantly impacted moderation flow for
some Discourse site moderators, especially around "something else"
flags. We need to re-approach how flags are counted holistically,
so to that end this change is being reverted.
2023-10-18 11:38:17 +10:00
Bianca Nenciu bf97899029
DEV: Limit preloaded categories (#23958)
Site data is preloaded on the first page load, which includes categories
data. For sites with many categories, site data takes a long time to
serialize and to transfer.

In the future, preloaded category data will be completely removed.
2023-10-17 22:04:56 +03:00
Blake Erickson 60ae69027c
DEV: Add category style deprecation check warning (#23951)
The category style site setting is being deprecated. This commit will
show a warning on the admin dashboard if a site isn't using the default
category style (bullet).
2023-10-17 10:40:31 -06:00
Bianca Nenciu c95ffb98ef
DEV: Serialize categories in topic lists (#23597)
At this moment, this feature is under a site setting named
lazy_load_categories.

In the future, categories will no longer be preloaded through site data.
This commit add information about categories in topic list and ensures
that data is used to display topic list items.

Parent categories are serialized too because they are necessary to
render {{category-link}}.
2023-10-17 19:06:01 +03:00
Martin Brennan 61c87fb59f
FIX: Properly attach secure images to email for non-secure uploads (#23865)
There are cases where a user can copy image markdown from a public
post (such as via the discourse-templates plugin) into a PM which
is then sent via an email. Since a PM is a secure context (via the
.with_secure_uploads? check on Post), the image will get a secure
URL in the PM post even though the backing upload is not secure.

This fixes the bug in that case where the image would be stripped
from the email (since it had a /secure-uploads/ URL) but not re-attached
further down the line using the secure_uploads_allow_embed_images_in_emails
setting because the upload itself was not secure.

The flow in Email::Sender for doing this is still not ideal, but
there are chicken and egg problems around when to strip the images,
how to fit in with other attachments and email size limits, and
when to apply the images inline via Email::Styles. It's convoluted,
but at least this fixes the Template use case for now.
2023-10-17 14:08:21 +10:00
Krzysztof Kotlarek 09eca87c76
FIX: synonym tags are not considered as unused (#23950)
Currently, `Tag.unused` scope is used to delete unused tags on `/tags` and by CleanUpTags job. Synonym tags, should not be included and treated as unused. Synonyms are only deleted when main tag is deleted:

https://github.com/discourse/discourse/blob/main/app/models/tag.rb#L57
2023-10-16 23:53:02 +00:00
Alan Guo Xiang Tan 4cb7472376
SECURITY: Prevent arbitrary topic custom fields from being set
Why this change?

The `PostsController#create` action allows arbitrary topic custom fields
to be set by any user that can create a topic. Without any restrictions,
this opens us up to potential security issues where plugins may be using
topic custom fields in security sensitive areas.

What does this change do?

1. This change introduces the `register_editable_topic_custom_field` plugin
API which allows plugins to register topic custom fields that are
editable either by staff users only or all users. The registered
editable topic custom fields are stored in `DiscoursePluginRegistry` and
is called by a new method `Topic#editable_custom_fields` which is then
used in the `PostsController#create` controller action. When an unpermitted custom fields is present in the `meta_data` params,
a 400 response code is returned.

2. Removes all reference to `meta_data` on a topic as it is confusing
   since we actually mean topic custom fields instead.
2023-10-16 10:34:35 -04:00
Martin Brennan 9762e65758
FEATURE: Add Revise... option for queued post reviewable (#23454)
This commit adds a new Revise... action that can be taken
for queued post reviewables. This will open a modal where
the user can select a Reason from a preconfigured list
(or by choosing Other..., a custom reason) and provide feedback
to the user about their post.

The post will be rejected still, but a PM will also be sent to
the user so they have an opportunity to improve their post when
they resubmit it.
2023-10-13 11:28:31 +10:00
David Taylor 525cfcbe0e
FIX: Ensure nested ember components can be used with mustache syntax (#23912)
We run the ember-this-fallback transformation on plugin and theme code so that they can continue omitting `this.` in `.hbs` templates. A bug in the implementation meant that it was incorrectly transforming things like `{{dir/some-component}}` into `<DirSomeComponent />` (rather than `<Dir::SomeComponent />`).

This commit uses patch-package to apply the fix from https://github.com/tildeio/ember-this-fallback/pull/56
2023-10-12 11:08:57 +01:00
Martin Brennan 542f77181a
FIX: Update upload security on post rebake from UI (#23861)
When a user creates or edits a post, we already were updating
the security of uploads in the post based on site settings and
their access control post, which is important since these uploads
may be switched from secure/not secure based on configuration.
The `with_secure_uploads?` method on a post is used to determine
whether to use the secure-uploads URL for all uploads in the post,
regardless of their individual security, so if this is false and
some of the posts are still secure when rebaking, we end up with
broken URLs.

This commit just makes it so rebaking via the UI also re-evaluates
upload security so that when the post is loaded again after processing,
all of the uploads have the correct security.
2023-10-10 11:15:51 +10:00
Krzysztof Kotlarek c468110929
FEATURE: granular webhooks (#23070)
Before this change, webhooks could be only configured for specific groups like for example, all topic events.

We would like to have more granular control like for example topic_created or topic_destroyed.

Test are failing because plugins changed has to be merged as well:
discourse/discourse-assign#498
discourse/discourse-solved#248
discourse/discourse-topic-voting#159
2023-10-09 03:35:31 +00:00
Alan Guo Xiang Tan 832b3b9e60
FEATURE: Remove support for legacy navigation menu (#23752)
Why this change?

Back in May 17 2023 along with the release of Discourse 3.1, we announced
on meta that the legacy hamburger dropdown navigation menu is
deprecated and will be dropped in Discourse 3.2. This is the link to the announcement
on meta: https://meta.discourse.org/t/removing-the-legacy-hamburger-navigation-menu-option/265274

## What does this change do?

This change removes the `legacy` option from the `navigation_menu` site
setting and migrates existing sites on the `legacy` option to the
`header dropdown` option.

All references to the `legacy` option in code and tests have been
removed as well.
2023-10-09 07:24:10 +08:00
Sam f21a4a6cb3
Revert "FIX: Allow category moderators to move topics to their categories" (#23810)
This reverts commit 70be873b9c.
2023-10-06 09:00:22 +08:00
Penar Musaraj 0af6c5efdc
DEV: Refactor webauthn to support passkeys (1/3) (#23586)
This is part 1 of 3, split up of PR #23529. This PR refactors the
webauthn code to support passkey authentication/registration.

Passkeys aren't used yet, that is coming in PRs 2 and 3.

Co-authored-by: Alan Guo Xiang Tan <gxtan1990@gmail.com>
2023-10-03 14:59:28 -04:00
Natalie Tay 70be873b9c
FIX: Allow category moderators to move topics to their categories (#20896) 2023-10-03 17:59:16 +08:00
KThompson-Lane-Unity 607f700c8c
FEATURE: Add API key scopes for tag_groups (#23634) 2023-10-03 16:20:17 +08:00
Jarek Radosz 5a904949b2
DEV: Add gjs support for themes (#23473) 2023-10-02 12:36:06 +02:00
Ella E b860c6ec17
A11Y: Improve contrast on the WCAG color schemes (#23692)
A11Y: Improve contrast on WCAG color palette

---------

Co-authored-by: Penar Musaraj <pmusaraj@gmail.com>
2023-09-29 10:03:08 -06:00
David Taylor fc2e92d423
DEV: Drop post_uploads table (#23673)
The post_uploads table has not been used since 9db8f00b3d
2023-09-27 12:43:19 +01:00
Arpit Jalan 3669723a86
FEATURE: allow filtering posts report by multiple categories (#23669) 2023-09-26 21:56:47 +05:30
Bianca Nenciu 3700514819
DEV: Prefer nested queries (#23464)
Some sites have a large number of categories and fetching the category
IDs or category topic IDs just to build another query can take a long
time or resources (i.e. memory).
2023-09-25 19:38:54 +03:00
Ted Johansson 950357391a
DEV: Remove deprecated PostAction.act method (#23641)
The PostAction.act class method was deprecated four years ago and marked for removal in 2.9.0. This PR removes it.
2023-09-24 08:16:32 +01:00
Osama Sayegh 83621ccbe7
FIX: Parse the digest_suppress_tags setting correctly (#23623)
Meta topic: https://meta.discourse.org/t/suppress-these-tags-from-summary-emails-settings-is-not-working-in-preview-digest-email/279196?u=osama

Follow-up to 477a5dd371

The `digest_suppress_tags` setting is designed to be a list of pipe-delimited tag names, but the tag-based topic suppression logic assumes (incorrectly) that the setting contains pipe-delimited tag IDs. This mismatch in expectations led to the setting not working as expected.

This PR adds a step that converts the list of tag names in the setting to their corresponding IDs, which is then used to suppress topics tagged with those specific tags.
2023-09-18 10:45:43 +03:00
Renato Atilio d93c2cb3d2
FEATURE: site settings to revoke api keys older than a number of days (#23595)
* FEATURE: site settings to revoke api keys older than a number of days
2023-09-15 16:31:29 -03:00
Sérgio Saquetim e03dd76dc6
FEATURE: add outgoing web hooks for Chat messages 2023-09-13 17:31:42 -03:00
tshenry c163634ff9
DEV: Bump theme compiler version for max svg sprite size change (#23567)
This should have been included in f6326d0
2023-09-13 10:02:08 -07:00
Bianca Nenciu 6f782d8e45
SECURITY: Add limits for themes and theme assets
This commit adds limits to themes and theme components on the:

- file size of about.json and .discourse-compatibility
- file size of theme assets
- number of files in a theme
2023-09-12 15:31:31 -03:00
Daniel Waterworth 290306a932
SECURITY: Reduce maximum size of SVG sprite cache to prevent DoS
Co-authored-by: Penar Musaraj <pmusaraj@gmail.com>
2023-09-12 15:31:28 -03:00
Gerhard Schlager e3a2446874
SECURITY: Limit number of drafts per user and length of `draft_key`
The hidden site setting max_drafts_per_user defaults to 10_000 drafts per user.
The longest key should be "topic_<MAX_BIG_INT>" which is 25 characters.
2023-09-12 15:31:26 -03:00
OsamaSayegh c1b5faa5fd
SECURITY: Limit name field length of TOTP authenticators and security keys 2023-09-12 15:31:17 -03:00
Ted Johansson f08c6d2756
DEV: Switch over category settings to new table - Part 3 (#20657)
In #20135 we prevented invalid inputs from being accepted in category setting form fields on the front-end. We didn't do anything on the back-end at that time, because we were still discussing which path we wanted to take. Eventually we decided we want to move this to a new CategorySetting model.

This PR moves the require_topic_approval and require_reply_approval from custom fields to the new CategorySetting model.

This PR is nearly identical to #20580, which migrated num_auto_bump_daily, but since these are slightly more sensitive, they are moved after the previous one is verified.
2023-09-12 09:51:49 +08:00
Alan Guo Xiang Tan d2e4b32c87
DEV: Add support for uploading a theme from a directory in system tests (#23402)
Why this change?

Currently, we do not have an easy way to test themes and theme components
using Rails system tests. While we support QUnit acceptance tests for
themes and theme components, QUnit acceptance tests stubs out the server
and setting up the fixtures for server responses is difficult and can lead to a
frustrating experience. System tests on the other hand allow authors to
set up the test fixtures using our fabricator system which is much
easier to use.

What does this change do?

In order for us to allow authors to run system tests with their themes
installed, we are adding a `upload_theme` helper that is made available
when writing system tests. The `upload_theme` helper requires a single
`directory` parameter where `directory` is the directory of the theme
locally and returns a `Theme` record.
2023-09-12 07:38:47 +08:00
Bianca Nenciu 4db5310135
DEV: Remove unused topic_create_allowed_category_ids (#23463) 2023-09-08 12:03:22 +03:00
Martin Brennan c532f6eb3d
FEATURE: Secure uploads in PMs only (#23398)
This adds a new secure_uploads_pm_only site setting. When secure_uploads
is true with this setting, only uploads created in PMs will be marked
secure; no uploads in secure categories will be marked as secure, and
the login_required site setting has no bearing on upload security
either.

This is meant to be a stopgap solution to prevent secure uploads
in a single place (private messages) for sensitive admin data exports.
Ideally we would want a more comprehensive way of saying that certain
upload types get secured which is a hybrid/mixed mode secure uploads,
but for now this will do the trick.
2023-09-06 09:39:09 +10:00
Arpit Jalan e5f3c26d20
FEATURE: add group filter for admin reports (#23381)
FEATURE: add group filter for admin reports

DEV: add plugin outlet for admin dashboard tabs
2023-09-05 11:17:18 +05:30
Joffrey JAFFEUX f1d8cd529e
Revert "Revert "PERF: Cache each theme field value once (#23192)" (#23354)" (#23356)
This reverts commit 9821ca9413.
2023-08-31 14:12:03 -05:00
Joffrey JAFFEUX 9821ca9413
Revert "PERF: Cache each theme field value once (#23192)" (#23354)
This reverts commit 82a56334a3.
2023-08-31 19:04:43 +02:00
Daniel Waterworth 82a56334a3
PERF: Cache each theme field value once (#23192)
Previously, theme fields from components would be cached for each of
their parent themes.
2023-08-31 11:24:02 -05:00
Penar Musaraj 006a5166e5
DEV: Refactor rp_id and rp_name (#23339)
They're both constant per-instance values, there is no need to store them
in the session. This also makes the code a bit more readable by moving
the `session_challenge_key` method up to the `DiscourseWebauthn` module.
2023-08-31 09:11:23 -04:00
Renato Atilio 58b49bce41
FEATURE: support to initial values for form templates through /new-topic (#23313)
* FEATURE: adds support for initial values through /new-topic to form templates
2023-08-29 18:41:33 -03:00
Ted Johansson 4b52269827
DEV: Move option to delete user under reviewable reject menu (#23257)
Follow-up to #23199 in which we moved the "delete user" options under the relevant action menu for flagged post. This change does the same, but to queued posts.
2023-08-27 10:05:05 +08:00
Ted Johansson 12cdd7db1a
DEV: Move option to delete user under reviewable agree menu (#23199)
As per discussion, we want to move the options to delete the user under the "Yes" menu of the review queue, since these options are often the most recommended, but also frequently missed because they are tucked away under their own menu.

In addition to the move, I removed the title case of the options so that it matches the other options in the "Yes" menu.
2023-08-25 10:53:56 +08:00
Jarek Radosz 70f1cc5552
DEV: Use esbuild to make DiscourseJsProcessor (#23223)
Reverts e2705df and re-lands #23187 and #23219.

The issue was incorrect order of execution of Rails' `assets:precompile` task in our own precompilation stack.

Co-authored-by: David Taylor <david@taylorhq.com>
2023-08-24 16:36:22 +02:00
David Taylor e2705df0f4
Revert "DEV: Use esbuild to make DiscourseJsProcessor (#23187)" (#23221)
This reverts commit 4dfe25d062 and 4fdeb6281e. We are investigating an issue related to asset compilation and S3 assets
2023-08-24 13:25:44 +01:00
Jarek Radosz 4dfe25d062
DEV: Use esbuild to make DiscourseJsProcessor (#23187)
Co-authored-by: David Taylor <david@taylorhq.com>
2023-08-24 12:43:59 +02:00
Mark VanLandingham 730f652255
DEV: Add plugin modifier locations for user search locations (#23169) 2023-08-21 12:23:42 -05:00
Juan David Martínez Cubillos 477a5dd371
FEATURE: Digest suppression by tags (#23089)
* FEATURE: Digest suppression by tags

* fixed stree issues

* fixed code so untagged topics are not suppressed when suppressing certain tags
2023-08-18 14:28:20 -05:00
Joffrey JAFFEUX b2b84cc957
FEATURE: implements user based sidebar mode (#23078) 2023-08-18 20:33:07 +02:00
David Taylor 82b16f4f47
DEV: Do not manipulate theme module paths at build-time (#23148)
Manipulating theme module paths means that the paths you author are not the ones used at runtime. This can lead to some very unexpected behavior and potential module name clashes. It also meant that the refactor in 16c6ab8661 was unable to correctly match up theme connector js/templates.

While this could technically be a breaking change, I think it is reasonably safe because:

1. Themes are already forced to use relative paths when referencing their own modules (since they're namespaced based on the site-specific id). The only time this might be problematic is when theme tests reference modules in the theme's main `javascripts` directory

2. For things like components/services/controllers/etc. our custom Ember resolver works backwards from the end of the path, so adding `discourse/` in the middle will not affect resolution.
2023-08-18 18:15:23 +01:00
marstall 0dd1ee2e09
FIX: correct bulk invite expire time for DST (#23073)
This is a bug that happens only when the current date is less than 90 days from a date on which the time zone transitions into or out of Daylight Savings Time.

In these conditions, bulk invites show the time of day of their expiration as being 1 hour later than the current time.

Whereas it should match the time of day the invite was generated.

This is because the server has not been using the user's timezone in calculating the expiration time of day. This PR fixes issue by considering the user's timezone when doing the date math.

https://meta.discourse.org/t/bulk-invite-logic-to-generate-expire-date-bug/274689
2023-08-18 12:33:40 -04:00
Daniel Waterworth 91f560a521
DEV: Make every DistributedCache lazily instantiated (#23147) 2023-08-18 10:59:11 -05:00
Selase Krakani 87ebbec9b2
FIX: Pending post deletion by creator (#23130)
`ReviewableQueuedPost` got refactored a while back to use the more
appropriate `target_created_by` for the user of the post being queued
instead of `created_by`. The change was not extended to the `DELETE
/review/:id` endpoint leading to error responses for a user attempting
to deleting their own queued post.

This fix extends the `Reviewable` lookup implementation in
`ReviewablesController#destroy` and Guardian implementation to account
for this change.
2023-08-18 15:30:59 +00:00
Penar Musaraj 10c6b2a0c2
WIP: Rename Webauthn to DiscourseWebauthn (#23077) 2023-08-18 08:39:10 -04:00
David Taylor 16c6ab8661
DEV: Allow plugin outlets to be defined using gjs (#23142)
Previously we were discovering plugin outlets by checking first for dedicated template files, and then looking for classes to match them. This doesn't work for components which are entirely defined in JS (e.g. those authored with gjs, or those which are re-exports of a colocated component).

This commit refactors our detection logic to look for both class and template modules in a single pass. It also refactors things so that the modules themselves are required lazily when needd, rather than all being loaded during app boot.
2023-08-18 12:07:10 +01:00
Ted Johansson 79e3d4e2bd
FIX: Don't run post validations when hiding post (#23139)
When hiding a post (essentially updating hidden, hidden_at, and hidden_reason_id) our callbacks are running the whole battery of post validations. This can cause the hiding to fail in a number of edge cases. The issue is similar to the one fixed in #11680, but applies to all post validations, none of which should apply when hiding a post.

After some code reading and discussion, none of the validations in PostValidator seem to be relevant when hiding posts, so instead of just skipping unique check, we skip all post validator checks.
2023-08-18 10:55:17 +08:00
Daniel Waterworth 80a0d88e4c
FIX: Ensure javascript caches are unique per theme/theme_field (#23126)
We were assuming that this was the case before, but not enforcing it.
2023-08-17 13:57:04 -05:00
Krzysztof Kotlarek f8cd1da92a
FIX: increase sidebar URL limit to 1000 (#23120)
Before this change, sidebar URL had a limit of 200 characters. In some cases it is not enough, therefore it was increased to 1000.
2023-08-17 14:46:24 +10:00
Andreas Klöckner 9e568df316
FIX: reference to non-existent `groups#remove_members` in API key scope (#23042) 2023-08-17 07:20:55 +10:00
marstall 77626c088e
UX: support links in tag descriptions (#22994)
* scrub non-a html tags from tag descriptions on create, strips all tags from tag description when displayed in tag hover

* test for tag description links

* UX: basic render-tag test

* UX: fix linting

* UX: fix linting

* fix broken tests

* Update spec/models/tag_spec.rb

Co-authored-by: Penar Musaraj <pmusaraj@gmail.com>

* UX: use has_sanitizable_fields instead of has_scrubbable_fields to ensafen tag.description

---------

Co-authored-by: Penar Musaraj <pmusaraj@gmail.com>
2023-08-16 11:43:54 -04:00
Renato Atilio 840bea3c51
FEATURE: add topic voting webhook event type (#23072)
* FEATURE: add topic upvote webhook event type

* DEV: use a generic event type name for other actions in the same plugin
2023-08-11 13:42:28 -03:00
Ted Johansson 8053cb0c21
DEV: Add a HasDeprecatedColumns concern for better deprecation messages (#22930)
Currently when we decide we're going to drop a column in the future we just mark it with a TODO comment and add it to ignored_columns. This makes it instantly unavailable, and we mostly forget about the TODO in the end. 😬

This change adds a HasDeprecatedColumns concern which offers a little bit more flexibility. We can still simulate the old behaviour by setting drop_from to the current version, but we can also set it to a future version, causing it to raise a deprecation warning until then if used.
2023-08-11 15:25:44 +08:00
Jarek Radosz 94649565ce
DEV: Correct `Style/RedundantReturn` rubocop issues (#23052) 2023-08-10 02:03:38 +02:00
Gerhard Schlager b2fee68b3f DEV: Add rake task for generating avatars from SSO 2023-08-09 20:56:14 +02:00
Martin Brennan 09223e5ae7
DEV: Remove enable_experimental_hashtag_autocomplete logic (#22820)
This commit removes any logic in the app and in specs around
enable_experimental_hashtag_autocomplete and deletes some
old category hashtag code that is no longer necessary.

It also adds a `slug_ref` category instance method, which
will generate a reference like `parent:child` for a category,
with an optional depth, which hashtags use. Also refactors
PostRevisor which was using CategoryHashtagDataSource directly
which is a no-no.

Deletes the old hashtag markdown rule as well.
2023-08-08 11:18:55 +10:00
David Taylor e76e0ad592
DEV: In development, refresh client when theme changes are made (#22978)
This brings the theme development experience (via the discourse_theme cli) closer to the experience of making javascript changes in Discourse core/plugins via Ember CLI. Whenever a change is made to a non-css theme field, all clients will be instructed to immediately refresh via message-bus.
2023-08-04 11:02:26 +01:00
Ted Johansson 1f7e5e8e75
DEV: Switch over category settings to new table - Part 2 (#20580)
In #20135 we prevented invalid inputs from being accepted in category setting form fields on the front-end. We didn't do anything on the back-end at that time, because we were still discussing which path we wanted to take. Eventually we decided we want to move this to a new CategorySetting model.

This PR moves the num_auto_bump_daily from custom fields to the new CategorySetting model.

In addition it sets the default value to 0, which exhibits the same behaviour as when the value is NULL.
2023-08-04 10:53:22 +08:00
Renato Atilio 701ae8764e
FIX: keep first post edit history when moving/merging (#22966) 2023-08-03 22:04:35 -03:00
TheJammiestDodger e680437030
FIX: Add 'Ignored' flags to Moderator Activity report (#22041)
* FIX Add 'Ignored' flags to Moderator Activity report

The Moderator Activity query didn’t include the number of deferred flags in the Flags Reviewed totals. As this number is designed to reflect how many flags a moderator has seen, reviewed, and made a judgement on, the Ignored ones should also be included.

* Apply suggestions from code review

---------

Co-authored-by: Jarek Radosz <jradosz@gmail.com>
2023-08-02 12:27:31 +01:00
Daniel Waterworth 50d527b80c
DEV: Remove db_timeout setting (#22912)
It doesn't actually do anything.
2023-08-01 14:17:43 -05:00
Martin Brennan 6286e790b2
DEV: Remove unread_private_messages and deprecation (#22893)
This was added all the way back in 2020 in b79ea986ac,
enough time has passed, we can delete this now.
2023-08-01 14:44:39 +10:00
Kelv 5f0bc4557f
FEATURE: Count only approved flagged posts in user pages (#22799)
FEATURE: Only approved flags for post counters

* Why was this change necessary?
The counters for flagged posts in the user's profile and user index from
the admin view include flags that were rejected, ignored or pending
review. This introduces unnecessary noise. Also the flagged posts
counter in the user's profile includes custom flags which add further
noise to this signal.

* How does it address the problem?

* Modifying User#flags_received_count to return posts with only approved
  standard flags
* Refactoring User#number_of_flagged_posts to alias to
  User#flags_received_count
* Updating the flagged post staff counter hyperlink to navigate to a
  filtered view of that user's approved flagged posts to maintain
  consistency with the counter
* Adding system tests for the profile page to cover the flagged posts
  staff counter
2023-07-31 13:33:10 +08:00
Alan Guo Xiang Tan 2f5e66b6f8
PERF: Optimise `TopicTrackingState.report` query to speed up query (#22871)
In the query generated by `TopicTrackingState.report`, there are two
subqueies being executed. The first subquery fetches all the topics
that are new for a given user while the second subquery fetches all the topics with
unread posts for a given user. For the second subquery, there is a
filter `topics.updated_at >= user_stats.first_unread_at` which is used
as a performance optimisation to reduce the number of rows that PG has
to scan through the `topics` table.

However, we started to notice in production that the PG planner doesn't
always execute the filter first to reduce the number of rows that it has
to scan through. Running the following query in one of our production
instance,

```
EXPLAIN ANALYZE
SELECT
           DISTINCT topics.id as topic_id,
           u.id as user_id,
           topics.created_at,
           topics.updated_at,
           topics.highest_staff_post_number AS highest_post_number,
           last_read_post_number,
           c.id as category_id,
           c.topic_id AS category_topic_id,
           tu.notification_level,
           us.first_unread_at,
           GREATEST(
              CASE
              WHEN COALESCE(uo.new_topic_duration_minutes, 2880) = -1 THEN u.created_at
              WHEN COALESCE(uo.new_topic_duration_minutes, 2880) = -2 THEN COALESCE(
                u.previous_visit_at,u.created_at
              )
              ELSE ('2023-07-31 03:29:45.737630'::timestamp - INTERVAL '1 MINUTE' * COALESCE(uo.new_topic_duration_minutes, 2880))
              END, u.created_at, '2023-07-25 15:06:44'
           ) AS treat_as_new_topic_start_date
FROM topics
JOIN users u on u.id = 13455
JOIN user_stats AS us ON us.user_id = u.id
JOIN user_options AS uo ON uo.user_id = u.id
JOIN categories c ON c.id = topics.category_id
LEFT JOIN topic_users tu ON tu.topic_id = topics.id AND tu.user_id = u.id

WHERE u.id = 13455 AND
       topics.updated_at >= us.first_unread_at AND
      topics.archetype <> 'private_message' AND
      (("topics"."deleted_at" IS NULL AND (tu.last_read_post_number < topics.highest_staff_post_number) AND (COALESCE(tu.notification_level, 1) >= 2)) OR (1=0)) AND

      NOT (
  COALESCE((select array_agg(tag_id) from topic_tags where topic_tags.topic_id = topics.id), ARRAY[]::int[]) && ARRAY[451,452,453]
) AND

      topics.deleted_at IS NULL AND

      NOT (
        last_read_post_number IS NULL AND
        (
          topics.category_id IN (SELECT "categories"."id" FROM "categories" LEFT JOIN categories categories2 ON categories2.id = categories.parent_category_id LEFT JOIN category_users ON category_users.category_id = categories.id AND category_users.user_id = 13455 LEFT JOIN category_users category_users2 ON category_users2.category_id = categories2.id AND category_users2.user_id = 13455 WHERE ((category_users.id IS NULL AND COALESCE(category_users2.notification_level, 1) = 0) OR COALESCE(category_users.notification_level, 1) = 0))
          AND tu.notification_level <= 1
        )
      )
```

we get the following

```
                                                                                                                                                                                                                                                                                                                          QUERY PLAN
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 Unique  (cost=201606.06..201608.15 rows=76 width=60) (actual time=91.279..91.294 rows=14 loops=1)
   ->  Sort  (cost=201606.06..201606.25 rows=76 width=60) (actual time=91.278..91.284 rows=14 loops=1)
         Sort Key: topics.id, topics.created_at, topics.updated_at, topics.highest_staff_post_number, tu.last_read_post_number, c.id, c.topic_id, tu.notification_level, us.first_unread_at, (GREATEST(CASE WHEN (COALESCE(uo.new_topic_duration_minutes, 2880) = '-1'::integer) THEN u.created_at WHEN (COALESCE(uo.new_topic_duration_minutes, 2880) = '-2'::integer) THEN COALESCE(u.previous_visit_at, u.created_at) ELSE ('2023-07-31 03:29:45.73763'::timestamp without time zone - ('00:01:00'::interval * (COALESCE(uo.new_topic_duration_minutes, 2880))::double precision)) END, u.created_at, '2023-07-25 15:06:44'::timestamp without time zone))
         Sort Method: quicksort  Memory: 26kB
         ->  Hash Join  (cost=97519.51..201603.69 rows=76 width=60) (actual time=87.662..91.268 rows=14 loops=1)
               Hash Cond: (topics.id = tu.topic_id)
               Join Filter: ((tu.last_read_post_number < topics.highest_staff_post_number) AND ((tu.last_read_post_number IS NOT NULL) OR (NOT (hashed SubPlan 2)) OR (tu.notification_level > 1)))
               Rows Removed by Join Filter: 10
               ->  Nested Loop  (cost=1.54..104075.36 rows=3511 width=68) (actual time=0.055..3.609 rows=548 loops=1)
                     ->  Nested Loop  (cost=1.13..25.20 rows=1 width=32) (actual time=0.027..0.033 rows=1 loops=1)
                           ->  Nested Loop  (cost=0.71..16.76 rows=1 width=28) (actual time=0.020..0.023 rows=1 loops=1)
                                 ->  Index Scan using users_pkey on users u  (cost=0.42..8.44 rows=1 width=20) (actual time=0.010..0.012 rows=1 loops=1)
                                       Index Cond: (id = 13455)
                                 ->  Index Scan using user_stats_pkey on user_stats us  (cost=0.29..8.31 rows=1 width=12) (actual time=0.008..0.010 rows=1 loops=1)
                                       Index Cond: (user_id = 13455)
                           ->  Index Scan using index_user_options_on_user_id_and_default_calendar on user_options uo  (cost=0.42..8.44 rows=1 width=8) (actual time=0.007..0.008 rows=1 loops=1)
                                 Index Cond: (user_id = 13455)
                     ->  Nested Loop  (cost=0.41..104015.12 rows=3504 width=36) (actual time=0.026..3.503 rows=548 loops=1)
                           ->  Seq Scan on categories c  (cost=0.00..13.73 rows=73 width=8) (actual time=0.003..0.039 rows=73 loops=1)
                           ->  Index Only Scan using index_topics_on_updated_at_public on topics  (cost=0.41..1424.20 rows=48 width=28) (actual time=0.012..0.046 rows=8 loops=73)
                                 Index Cond: ((updated_at >= us.first_unread_at) AND (category_id = c.id))
                                 Filter: (NOT (COALESCE((SubPlan 1), '{}'::integer[]) && '{451,452,453}'::integer[]))
                                 Heap Fetches: 553
                                 SubPlan 1
                                   ->  Aggregate  (cost=4.31..4.32 rows=1 width=32) (actual time=0.002..0.002 rows=1 loops=548)
                                         ->  Index Only Scan using index_topic_tags_on_topic_id_and_tag_id on topic_tags  (cost=0.29..4.31 rows=1 width=4) (actual time=0.002..0.002 rows=1 loops=548)
                                               Index Cond: (topic_id = topics.id)
                                               Heap Fetches: 178
               ->  Hash  (cost=97222.14..97222.14 rows=19914 width=16) (actual time=87.545..87.546 rows=42884 loops=1)
                     Buckets: 65536 (originally 32768)  Batches: 1 (originally 1)  Memory Usage: 2387kB
                     ->  Bitmap Heap Scan on topic_users tu  (cost=1217.47..97222.14 rows=19914 width=16) (actual time=14.419..78.286 rows=42884 loops=1)
                           Recheck Cond: (user_id = 13455)
                           Filter: (COALESCE(notification_level, 1) >= 2)
                           Rows Removed by Filter: 15839
                           Heap Blocks: exact=45285
                           ->  Bitmap Index Scan on index_topic_users_on_user_id_and_topic_id  (cost=0.00..1212.49 rows=59741 width=0) (actual time=6.448..6.448 rows=58723 loops=1)
                                 Index Cond: (user_id = 13455)
               SubPlan 2
                 ->  Nested Loop Left Join  (cost=0.74..46.90 rows=1 width=4) (never executed)
                       Join Filter: (category_users2.category_id = categories2.id)
                       Filter: (((category_users.id IS NULL) AND (COALESCE(category_users2.notification_level, 1) = 0)) OR (COALESCE(category_users.notification_level, 1) = 0))
                       ->  Nested Loop Left Join  (cost=0.45..32.31 rows=73 width=16) (never executed)
                             Join Filter: (category_users.category_id = categories.id)
                             ->  Nested Loop Left Join  (cost=0.15..18.45 rows=73 width=8) (never executed)
                                   ->  Seq Scan on categories  (cost=0.00..13.73 rows=73 width=8) (never executed)
                                   ->  Memoize  (cost=0.15..0.28 rows=1 width=4) (never executed)
                                         Cache Key: categories.parent_category_id
                                         Cache Mode: logical
                                         ->  Index Only Scan using categories_pkey on categories categories2  (cost=0.14..0.27 rows=1 width=4) (never executed)
                                               Index Cond: (id = categories.parent_category_id)
                                               Heap Fetches: 0
                             ->  Materialize  (cost=0.29..11.69 rows=2 width=12) (never executed)
                                   ->  Index Scan using idx_category_users_user_id_category_id on category_users  (cost=0.29..11.68 rows=2 width=12) (never executed)
                                         Index Cond: (user_id = 13455)
                       ->  Materialize  (cost=0.29..11.69 rows=2 width=8) (never executed)
                             ->  Index Scan using idx_category_users_user_id_category_id on category_users category_users2  (cost=0.29..11.68 rows=2 width=8) (never executed)
                                   Index Cond: (user_id = 13455)
 Planning Time: 1.740 ms
 Execution Time: 91.414 ms
(59 rows)
```

From the execution plan, we can see the most of the time is spent
joining about 42888 rows in the `topics` table to the `topic_users` table.
However, we know that we only have to scan through a
subset of the `topics` table because the user's last unread at is '2023-07-20 11:33:05'.
If we filter the `topics` table with `topics.updated_at >= '2023-07-20 11:33:05'`, this would only
return about 1500 rows.

From our testing in production, the PG planner is able to execute a
better query plan when we avoid the unnecessary joins on `user_stats` just to be
able to get the user's `UserStat#first_unread_at`. Instead, we can just
pass the value of `UserStat#first_unread_at` directly as a query
parameter.

```
EXPLAIN ANALYZE
SELECT
           DISTINCT topics.id as topic_id,
           u.id as user_id,
           topics.created_at,
           topics.updated_at,
           topics.highest_staff_post_number AS highest_post_number,
           last_read_post_number,
           c.id as category_id,
           c.topic_id AS category_topic_id,
           tu.notification_level,
           GREATEST(
              CASE
              WHEN COALESCE(uo.new_topic_duration_minutes, 2880) = -1 THEN u.created_at
              WHEN COALESCE(uo.new_topic_duration_minutes, 2880) = -2 THEN COALESCE(
                u.previous_visit_at,u.created_at
              )
              ELSE ('2023-07-31 03:29:45.737630'::timestamp - INTERVAL '1 MINUTE' * COALESCE(uo.new_topic_duration_minutes, 2880))
              END, u.created_at, '2023-07-25 15:06:44'
           ) AS treat_as_new_topic_start_date
FROM topics
JOIN users u on u.id = 13455
JOIN user_options AS uo ON uo.user_id = u.id
JOIN categories c ON c.id = topics.category_id
LEFT JOIN topic_users tu ON tu.topic_id = topics.id AND tu.user_id = u.id

WHERE u.id = 13455 AND
       topics.updated_at >= '2023-07-20 11:33:05' AND
      topics.archetype <> 'private_message' AND
      (("topics"."deleted_at" IS NULL AND (tu.last_read_post_number < topics.highest_staff_post_number) AND (COALESCE(tu.notification_level, 1) >= 2)) OR (1=0)) AND

      NOT (
  COALESCE((select array_agg(tag_id) from topic_tags where topic_tags.topic_id = topics.id), ARRAY[]::int[]) && ARRAY[451,452,453]
) AND

      topics.deleted_at IS NULL AND

      NOT (
        last_read_post_number IS NULL AND
        (
          topics.category_id IN (SELECT "categories"."id" FROM "categories" LEFT JOIN categories categories2 ON categories2.id = categories.parent_category_id LEFT JOIN category_users ON category_users.category_id = categories.id AND category_users.user_id = 13455 LEFT JOIN category_users category_users2 ON category_users2.category_id = categories2.id AND category_users2.user_id = 13455 WHERE ((category_users.id IS NULL AND COALESCE(category_users2.notification_level, 1) = 0) OR COALESCE(category_users.notification_level, 1) = 0))
          AND tu.notification_level <= 1
        )
      );
```

Note how the filter is now `topics.updated_at >= '2023-07-20 11:33:05'`
instead of `topics.updated_at >= us.first_unread_at`. The modified query
above generates the following execution plan.

```
                                                                                                                                                                                                                                                                                                                QUERY PLAN
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 Unique  (cost=5189.86..5189.88 rows=1 width=52) (actual time=4.991..5.002 rows=14 loops=1)
   ->  Sort  (cost=5189.86..5189.86 rows=1 width=52) (actual time=4.990..4.994 rows=14 loops=1)
         Sort Key: topics.id, topics.created_at, topics.updated_at, topics.highest_staff_post_number, tu.last_read_post_number, c.id, c.topic_id, tu.notification_level, (GREATEST(CASE WHEN (COALESCE(uo.new_topic_duration_minutes, 2880) = '-1'::integer) THEN u.created_at WHEN (COALESCE(uo.new_topic_duration_minutes, 2880) = '-2'::integer) THEN COALESCE(u.previous_visit_at, u.created_at) ELSE ('2023-07-31 03:29:45.73763'::timestamp without time zone - ('00:01:00'::interval * (COALESCE(uo.new_topic_duration_minutes, 2880))::double precision)) END, u.created_at, '2023-07-25 15:06:44'::timestamp without time zone))
         Sort Method: quicksort  Memory: 26kB
         ->  Nested Loop  (cost=52.11..5189.85 rows=1 width=52) (actual time=0.093..4.974 rows=14 loops=1)
               ->  Nested Loop  (cost=51.70..5181.39 rows=1 width=60) (actual time=0.084..4.931 rows=14 loops=1)
                     ->  Nested Loop  (cost=51.28..5172.94 rows=1 width=44) (actual time=0.076..4.887 rows=14 loops=1)
                           ->  Nested Loop  (cost=0.41..1698.46 rows=59 width=36) (actual time=0.029..3.537 rows=548 loops=1)
                                 ->  Seq Scan on categories c  (cost=0.00..13.73 rows=73 width=8) (actual time=0.005..0.039 rows=73 loops=1)
                                 ->  Index Only Scan using index_topics_on_updated_at_public on topics  (cost=0.41..23.07 rows=1 width=28) (actual time=0.012..0.047 rows=8 loops=73)
                                       Index Cond: ((updated_at >= '2023-07-20 11:33:05'::timestamp without time zone) AND (category_id = c.id))
                                       Filter: (NOT (COALESCE((SubPlan 1), '{}'::integer[]) && '{451,452,453}'::integer[]))
                                       Heap Fetches: 552
                                       SubPlan 1
                                         ->  Aggregate  (cost=4.31..4.32 rows=1 width=32) (actual time=0.002..0.002 rows=1 loops=548)
                                               ->  Index Only Scan using index_topic_tags_on_topic_id_and_tag_id on topic_tags  (cost=0.29..4.31 rows=1 width=4) (actual time=0.002..0.002 rows=1 loops=548)
                                                     Index Cond: (topic_id = topics.id)
                                                     Heap Fetches: 178
                           ->  Index Scan using index_topic_users_on_user_id_and_topic_id on topic_users tu  (cost=50.86..58.88 rows=1 width=16) (actual time=0.002..0.002 rows=0 loops=548)
                                 Index Cond: ((user_id = 13455) AND (topic_id = topics.id))
                                 Filter: ((COALESCE(notification_level, 1) >= 2) AND (last_read_post_number < topics.highest_staff_post_number) AND ((last_read_post_number IS NOT NULL) OR (NOT (hashed SubPlan 2)) OR (notification_level > 1)))
                                 Rows Removed by Filter: 0
                                 SubPlan 2
                                   ->  Nested Loop Left Join  (cost=0.74..50.43 rows=1 width=4) (never executed)
                                         Join Filter: (category_users2.category_id = categories2.id)
                                         Filter: (((category_users.id IS NULL) AND (COALESCE(category_users2.notification_level, 1) = 0)) OR (COALESCE(category_users.notification_level, 1) = 0))
                                         ->  Nested Loop Left Join  (cost=0.45..35.84 rows=73 width=16) (never executed)
                                               Join Filter: (category_users.category_id = categories.id)
                                               ->  Nested Loop Left Join  (cost=0.15..21.97 rows=73 width=8) (never executed)
                                                     ->  Seq Scan on categories  (cost=0.00..13.73 rows=73 width=8) (never executed)
                                                     ->  Memoize  (cost=0.15..0.61 rows=1 width=4) (never executed)
                                                           Cache Key: categories.parent_category_id
                                                           Cache Mode: logical
                                                           ->  Index Only Scan using categories_pkey on categories categories2  (cost=0.14..0.60 rows=1 width=4) (never executed)
                                                                 Index Cond: (id = categories.parent_category_id)
                                                                 Heap Fetches: 0
                                               ->  Materialize  (cost=0.29..11.69 rows=2 width=12) (never executed)
                                                     ->  Index Scan using idx_category_users_user_id_category_id on category_users  (cost=0.29..11.68 rows=2 width=12) (never executed)
                                                           Index Cond: (user_id = 13455)
                                         ->  Materialize  (cost=0.29..11.69 rows=2 width=8) (never executed)
                                               ->  Index Scan using idx_category_users_user_id_category_id on category_users category_users2  (cost=0.29..11.68 rows=2 width=8) (never executed)
                                                     Index Cond: (user_id = 13455)
                     ->  Index Scan using users_pkey on users u  (cost=0.42..8.44 rows=1 width=20) (actual time=0.003..0.003 rows=1 loops=14)
                           Index Cond: (id = 13455)
               ->  Index Scan using index_user_options_on_user_id_and_default_calendar on user_options uo  (cost=0.42..8.44 rows=1 width=8) (actual time=0.002..0.002 rows=1 loops=14)
                     Index Cond: (user_id = 13455)
 Planning Time: 1.281 ms
 Execution Time: 5.092 ms
(48 rows)
```

With the new query, PG first does an index scan using the `index_topics_on_updated_at_public` index to filter away most of the topics making the subsequent joins much cheaper. Total query time has been reduced from ~90ms to ~5ms.

This optimisation will mostly affect users with very few/recent unread topics since a large `UserStat#firsts_unread_at` value will still mean scanning through a large portion of the `topics` table.
2023-07-31 12:21:41 +08:00
Ted Johansson c4d0bbce62
DEV: Delete upload references upon deleting draft (#22851)
We currently are accumulating orphaned upload references whenever drafts are deleted.

This change deals with future cases by adding a dependent strategy of delete_all on the Draft#upload_references association. (We don't really need destroy strategy here, since UploadReference is a simple data bag and there are no validations or callbacks on the model.)

It deals with existing cases through a migration that deletes all existing, orphaned draft upload references.
2023-07-31 10:16:23 +08:00
Selase Krakani 81cf481b16
FIX: Missing pending queued posts from topic view (#22838)
A previous change updated `ReviewableQueuedPost`'s `created_by`
to be consistent with other reviewable types. It assigns
the the creator of the post being queued to `target_created_by` and sets
the `created_by` to the creator of the reviewable itself.

This fix updates some of the `created_by` references missed during the
intial fix.
2023-07-28 16:16:23 +00:00
Bianca Nenciu 0736611423
SECURITY: Hide restricted tags in noscript view
The hidden tags are usually filtered out by the serializer, but the
noscript view uses the topic objects instead of the serialized objects.
2023-07-28 12:53:50 +01:00
Penar Musaraj dcc825bda5
SECURITY: Limit length of edit reason column 2023-07-28 12:53:49 +01:00
Blake Erickson 62a609ea2d
SECURITY: Handle concurrent invite accepts
Raise an error on concurrent invite accept attempts.
2023-07-28 12:53:48 +01:00
Alan Guo Xiang Tan bfc3132bb2
SECURITY: Impose a upper bound on limit params in various controllers
What is the problem here?

In multiple controllers, we are accepting a `limit` params but do not
impose any upper bound on the values being accepted. Without an upper
bound, we may be allowing arbituary users from generating DB queries
which may end up exhausing the resources on the server.

What is the fix here?

A new `fetch_limit_from_params` helper method is introduced in
`ApplicationController` that can be used by controller actions to safely
get the limit from the params as a default limit and maximum limit has
to be set. When an invalid limit params is encountered, the server will
respond with the 400 response code.
2023-07-28 12:53:46 +01:00
Natalie Tay 173de8afe6
DEV: Add logging and rescue when user already exists and connecting via DiscourseConnect (#22833)
This is happening because despite the user already existing in the forum, the `SingleSignOnRecord` doesn't exist and "require_activation" is set on the provider, causing us to skip looking for the email, and resulting in us creating a new User then seeing Validation failed: Primary email has already been taken when DiscourseConnect is attempting to make a new account.
2023-07-28 02:53:33 +08:00
Joffrey JAFFEUX db0aef1192
DEV: removes unused group_manager model (#22827)
The associated table has been removed in 2015: 6dd4bc7d57 (diff-53b8234c51c429b92eb91d0212e15bbab16fcd5d1cbd3db64509977c9e1a060d)
2023-07-27 17:10:58 +02:00
Alan Guo Xiang Tan fe5cd479eb
PERF: Add index on topic_id and created_at to posts table (#22818)
Why this change?

In `PostDestroyer#make_previous_post_the_last_one` and
`Topic.reset_highest`, we have a query that looks something like this:

```
SELECT user_id FROM posts
WHERE topic_id = :topic_id AND
      deleted_at IS NULL AND
      post_type <> 4
      #{post_type}
ORDER BY created_at desc
LIMIT 1
```

However, we currently don't have an index that caters directly to this
query. As a result, we have seen this query performing poorly on large
sites if the PG planner ends up using an index that is suboptimal for
the query.

This commit adds an index to the `posts` table on `topic_id` and then
`created_at`. For the query above, PG will be able to do a backwards
index scan efficiently.
2023-07-27 10:55:10 +08:00
Alan Guo Xiang Tan 0a56274596
FIX: Seed all categories and tags configured as defaults for nav menu (#22793)
Context of this change:

There are two site settings which an admin can configured to set the
default categories and tags that are shown for a new user. `default_navigation_menu_categories`
is used to determine the default categories while
`default_navigation_menu_tags` is used to determine the default tags.

Prior to this change when seeding the defaults, we will filter out the
categories/tags that the user do not have permission to see. However,
this means that when the user does eventually gain permission down the
line, the default categories and tags do not appear.

What does this change do?

With this commit, we have changed it such that all the categories and tags
configured in the `default_navigation_menu_categories` and
`default_navigation_menu_tags` site settings are seeded regardless of
whether the user's visibility of the categories or tags. During
serialization, we will then filter out the categories and tags which the
user does not have visibility of.
2023-07-27 10:52:33 +08:00
Ted Johansson 4ef8129bff
DEV: Remove deprecated whitelist methods (#22731)
These methods were deprecated and marked for removal in 2.6. This change deletes them.

These deprecations use raise_error: true, so the fallbacks are at this point unreachable and can't be used anyway.
2023-07-21 11:32:21 +08:00
Roman Rizzi 238d71bcad
FEATURE: Regenerate outdated summaries. (#22718)
Users unable to generate new summaries won't be able to regenerate them. They'll only see the warning saying it's outdated.
2023-07-20 15:25:46 -03:00
Ted Johansson 341acacba8
DEV: Add endpoint for dismissing outdated translations (#22509)
Recently we started giving admins a notice in the advice panel when their translations have become outdated due to changes in core. However, we didn't include any additional information.

This PR adds more information about the outdated translation inside the site text edit page, together with an option to dismiss the warning.
2023-07-19 23:06:13 +08:00
Selase Krakani 3d554aa10e
FIX: Keep ReviewableQueuedPosts even with user delete reviewable actions (#22501)
Performing a `Delete User`/`Delete and Block User` reviewable actions for a
queued post reviewable from the `review.show` route results in an error
popup even if the action completes successfully.

This happens because unlike other reviewable types, a user delete action
on a queued post reviewable results in the deletion of the reviewable
itself. A subsequent attempt to reload the reviewable record results in
404. The deletion happens as part of the call to `UserDestroyer` which
includes a step for destroying reviewables created by the user being
destroyed. At the root of this is the creator of the queued post
being set as the creator of the reviewable as instead of the system
user.

This change assigns the creator of the reviewable to the system user and
uses the more approapriate `target_created_by` column for the creator of the
post being queued.
2023-07-18 11:50:31 +00:00
Ted Johansson 72ea73988c
DEV: Add missing report filter type in bookmarks report (#22616)
Adding a filter without a type parameter has been deprecated for the last three years, and was marked for removal in 2.9.0.

During this time we have had a few deprecation warnings in logs coming from Reports::Bookmarks.

The fallback was to set the type to the name of the filter. This change just passes the type (same as name) explicitly instead, and removes the deprecation fallback.
2023-07-18 11:07:01 +08:00
Ted Johansson 7c0534c292
DEV: Replace raw comments with deprecation warnings (#22617)
We have a number of raw comments indicating that certain methods and classes are deprecated and marked for removal. This change turn those comments into deprecation warnings so that we can 1) see them in the logs of our own hosting and 2) give some warning to self hosters.
2023-07-18 10:13:40 +08:00
Alan Guo Xiang Tan 3da6759860
FEATURE: Add admin dashboard warning for `legacy` navigation menu (#22655)
Why this change?

The `legacy` navigation menu option for the `navigation_menu` site
setting will be removed shortly after the release of Discourse 3.1 in
the first beta release of Discourse 3.2. Therefore, we're adding an
admin dashboard warning to give sites on the `legacy` navigation menu a
heads up.
2023-07-18 09:41:38 +08:00
Martin Brennan 6459922993
DEV: Move Bookmark modal/component to use d-modal (#22532)
c.f. https://meta.discourse.org/t/converting-modals-from-legacy-controllers-to-new-dmodal-component-api/268057

This also converts the Bookmark component to a Glimmer
component.
2023-07-17 10:14:17 +10:00
Ted Johansson 7a53fb65da
FIX: Don't show admin warnings about deleted translation overrides (#22614)
We recently introduced this advice to admins when some translation overrides are outdated or using unknown interpolation keys:

However we missed the case where the original translation key has been renamed or altogether removed. When this happens they are no longer visible in the admin interface, leading to the confusing situation where we say there are outdated translations, but none are shown.

Because we don't explicitly handle this case, some deleted translations were incorrectly marked as having unknown interpolation keys. (This is because I18n.t will return a string like "Translation missing: foo", which obviously has no interpolation keys inside.)

This change adds an additional status, deprecated for TranslationOverride, and the job that checks them will check for this status first, taking precedence over invalid_interpolation_keys. Since the advice only checks for the outdated and invalid_interpolation_keys statuses, this fixes the problem.
2023-07-14 16:52:39 +08:00
Jamie Dunstan 56e792df9b
FEATURE: Extend the topics:read API scope to allow read by external_id (#22536)
Allow an API key created with `topics:read` API scope to get a topic by `external_id`
2023-07-13 09:02:32 -06:00
Ted Johansson 110393e438
DEV: Remove deprecated Reviewable#post_options method (#22595)
The attribute Reviewable#post_options was deprecated (and replaced by #payload) four years ago, and marked for deletion in 2.9.0. This commit removes it.
2023-07-13 22:29:40 +08:00
Alan Guo Xiang Tan 48c8ed49d6
FIX: Dismissing unread posts did not publish changes to other clients (#22584)
Why this change?

Prior to this change, dismissing unreads posts did not publish the
changes across clients for the same user. As a result, users can end up
seeing an unread count being present but saw no topics being loaded when
visiting the `/unread` route.
2023-07-13 18:05:56 +08:00
Ted Johansson 6abec9335f
DEV: Remove deprecated Category#url_with_id method (#22582)
This method has been deprecated (replaced by Category#url) and marked for removal in 2.9.0. This PR removes it.
2023-07-13 11:21:47 +08:00
Krzysztof Kotlarek bdecd697b9
FIX: more performance improvement for PostAlert job (#22487)
Simplified query based on SiteSettings to join only relevant user_options rows.
In addition, index was added to 'watched_precedence_over_muted` column in `user_options` table to speed up query
2023-07-13 09:02:23 +10:00
Daniel Waterworth b7404373cf
FIX: Always clear caches after committing the current transaction (#22550)
Instead of having to remember every time, just always wait until the
current transaction (if it exists) has committed before clearing any
DistributedCache.

The only exception to this is caches that aren't caching things from
postgres.

This means we have to do the test setup after setting the test
transaction, because doing the test setup involves clearing caches.

Reapplying this - it now doesn't use after_commit if skip_db is set
2023-07-12 09:49:28 -05:00
Blake Erickson 52b003d915
SECURITY: limit amount of links in custom sidebar section (#22543)
Custom sidebar section can have maximum of 50 links

Co-authored-by: Krzysztof Kotlarek <kotlarek.krzysztof@gmail.com>
2023-07-11 15:25:01 -06:00
Blake Erickson 0718289574
SECURITY: ensure topic is valid before updating category (#22545)
Co-authored-by: David Battersby <info@davidbattersby.com>
2023-07-11 15:24:13 -06:00
Bianca Nenciu 0b16fc8172
FEATURE: Show tooltip for bootstrap mode (#22257)
Improve user tips UX and make them smoother.
2023-07-10 20:42:09 +03:00
Ted Johansson 9915236e42
FEATURE: Warn about outdated translation overrides in admin dashboard (#22384)
This PR adds a feature to help admins stay up-to-date with their translations. We already have protections preventing admins from problems when they update their overrides. This change adds some protection in the other direction (where translations change in core due to an upgrade) by creating a notice for admins when defaults have changed.

Terms:

- In the case where Discourse core changes the default translation, the translation override is considered "outdated".
- In the case above where interpolation keys were changed from the ones the override is using, it is considered "invalid".
- If none of the above applies, the override is considered "up to date".

How does it work?

There are a few pieces that makes this work:

- When an admin creates or updates a translation override, we store the original translation at the time of write. (This is used to detect changes later on.)
- There is a background job that runs once every day and checks for outdated and invalid overrides, and marks them as such.
- When there are any outdated or invalid overrides, a notice is shown in admin dashboard with a link to the text customization page.

Known limitations

The link from the dashboard links to the default locale text customization page. Given there might be invalid overrides in multiple languages, I'm not sure what we could do here. Consideration for future improvement.
2023-07-10 10:06:40 +08:00
Daniel Waterworth cb794275a7
Revert "FIX: Always clear caches after committing the current transaction" (#22493)
This reverts commit 8310c7842c.

This was breaking precompilation.
2023-07-07 18:05:38 -05:00
Daniel Waterworth 9dd01ca2ef
FIX: Always clear caches after committing the current transaction (#22491)
Instead of having to remember every time, just always wait until the
current transaction (if it exists) has committed before clearing any
DistributedCache.

The only exception to this is caches that aren't caching things from
postgres.

This means we have to do the test setup after setting the test
transaction, because doing the test setup involves clearing caches.
2023-07-07 14:24:56 -05:00
Osama Sayegh d2d6d727de
FEATURE: Add default site settings to control the defaults of navigation menu preferences (#22485)
Follow-up to b27e12445d

This commit adds 2 new site settings `default_sidebar_link_to_filtered_list` and `default_sidebar_show_count_of_new_items` to control the default values for the navigation menu preferences that were added in the linked commit (`sidebar_link_to_filtered_list` and `sidebar_show_count_of_new_items` respectively).
2023-07-07 04:52:10 +03:00
Sérgio Saquetim 4f2299949a
FIX: Prevent field name conflicts when using the `groups_for_users_search` modifier (#22446) 2023-07-05 19:58:21 -03:00
Krzysztof Kotlarek 134dcdd63a
FEATURE: allow user to override watched_precedence_over_muted setting (#22340)
Recently, site setting watched_precedence_over_muted was introduced - https://github.com/discourse/discourse/pull/22252

In this PR, we are allowing users to override it. The option is only displayed when the user has watched categories and muted tags, or vice versa.
2023-07-04 15:08:29 +10:00
Krzysztof Kotlarek de2febcc0c
FIX: error when CategoryList tried to find relevant topics (#22339)
Recently, we added the option for watched tag/categories to take precedence over muted tag/categories. Therefore, `remove_muted_tags` is using `category_users` to check if categories are not watched. There was missing join in CategoryList which was causing an error.
2023-06-29 11:25:58 +10:00
Keegan George c0707897ef
DEV: Make max length of template and name admin configurable (#22332) 2023-06-28 12:49:19 -07:00
Ted Johansson 6fc62586a2
FEATURE: Show available interpolation keys when overriding translations (#22220)
This is the first of a number of PRs aimed at helping admins manage their translation overrides. It simply adds a list of available interpolation keys below the input field when editing an override.

It also includes custom interpolation key.
2023-06-28 19:03:04 +08:00
Alan Guo Xiang Tan aef7c2fe8f
UX: Use modals to edit categories and tags that appear in sidebar (#22295)
Why this change?

We are currently not fully satisfied with the current way to edit the
categories and tags that appears in the sidebar where the user is
redirected to the tracking preferences tab in the user's profile causing
the user to lose context of the current page. In addition, the dropdown
to select categories or tags limits the amount of information we can
display.

Since editing or adding a custom categories section is already using a
modal, we have decided to switch editing the categories and tags that
appear in the sidebar to use a modal as well.

This commit removes the `new_edit_sidebar_categories_tags_interface_groups` site setting and
make the modals the default for all users.
2023-06-28 07:20:31 +08:00
Roman Rizzi f4e7a80600
DEV: Cache summarization strategy results. (#22230)
Updates the interface for implementing summarization strategies and adds a cache layer to summarize topics once.

The cache stores the final summary and each chunk used to build it, which will be useful when we have to extend or rebuild it.
2023-06-27 11:44:34 -03:00
Bianca Nenciu d888a8b692
FEATURE: Show first notification tip to all users (#22258)
It used to show only to users with trust level 0 or 1 and users who
signed up in the past week.
2023-06-26 18:39:29 +03:00
Alessio Cosenza 56718504ac
FEATURE: Add hooks for email poller plugins (#21384)
While we are unable to support OAUTH2 with pop3 (due to upstream dependency ruby/net-pop#16), we are adding the support for mail pollers plugin. Doing so, it would be possible to write a plugin which then uses other ways (microsoft graph sdk for example) to poll emails from a mailbox.

The idea is that a plugin would define a class which inherits from Email::Poller and defines a poll_mailbox static method which returns an array of strings. Then the plugin could call register_mail_poller(<class_name>) to have it registered. All the configuration (oauth2 tokens, email, etc) could be managed by sitesettings defined in the plugin.
2023-06-26 13:16:03 +08:00
Ted Johansson a183f14d09
DEV: Update display name in new quote format - Part 2 (#22104)
This change adds support retroactively updating display names in the new quote format when the user's name is changed. It happens through a background job that is triggered by a callback when a user is saved with a new name.
2023-06-26 11:01:59 +08:00
Daniel Waterworth 6f8056572e
DEV: Refactor updating parent/child relationships between themes (#22244)
The prior add_relative_themes! method was confusing and cleared the
cache repeatedly instead of once for the whole operation.
2023-06-22 13:57:39 -05:00
Osama Sayegh b27e12445d
FEATURE: Split navigation preference for count and behavior of sidebar links (#22203)
This PR splits up the preference that controls the count vs dot and destination of sidebar links, which is really hard to understand, into 2 simpler checkboxes:

The new preferences/checkboxes are off by default, but there are database migrations to switch the old preference to the new ones so that existing users don't have to update their preferences to keep their preferred behavior of sidebar links when this changed is rolled out.

Internal topic: t/103529.
2023-06-22 19:04:13 +03:00
Penar Musaraj 47ab7eb49a
FIX: Staged user creation loses user custom field data (#22206)
Don't cache user_fields on users separately from custom_fields, since they can get out of sync.

---------

Co-authored-by: Daniel Waterworth <me@danielwaterworth.com>
2023-06-21 12:35:24 -05:00
Sam 9e241e82e9
DEV: use HTML5 version of loofah (#21522)
https://meta.discourse.org/t/markdown-preview-and-result-differ/263878

The result of this markdown had different results in the composer preview and the post. This is solved by updating Loofah to the latest version and using html5 fragments like our user had reported. While the change was only needed in cooked_post_processor.rb for this fix, other areas also had to be updated due to various side effects.
2023-06-20 09:49:22 +08:00
Isaac Janzen a2b038ffe7
DEV: Upgrade search-menu to glimmer (#20482)
# Top level view
This PR is the first version of converting the search menu and its logic from (deprecated) widgets to glimmer components. The changes are hidden behind a group based feature flag. This will give us the ability to test the new implementation in a production setting before fully committing to the new search menu.

# What has changed
The majority of the logic from the widget implementation has been updated to fit within the context of a glimmer component, but it has not fundamentally changed. Instead of having a single widget - [search-menu.js](https://github.com/discourse/discourse/blob/main/app/assets/javascripts/discourse/app/widgets/search-menu.js) - that built the bulk of the search menu logic, we split the logic into (20+) bite size components. This greatly increases the readability and makes extending a component in the search menu much more straightforward.

That being said, certain pieces needed to be rewritten from scratch as they did not translate from widget -> glimmer, or there was a general code upgraded needed. There are a few of these changes worth noting:

### Search Service
**Search Term** -> In the widget implementation we had a overly complex way of managing the current search term. We tracked the search term across multiple different states (`term`, `opts.term`, `searchData.term`) causing headaches. This PR introduces a single source of truth: 
```js
this.search.activeGlobalSearchTerm
```
This tracked value is available anywhere the `search` service is injected. In the case the search term should be needs to be updated you can call 
```js
this.search.activeGlobalSearchTerm = "foo"
```
 
**event listeners** -> In the widget implementation we defined event listeners **only** on the search input to handle things such as 
- keyboard navigation / shortcuts
- closing the search menu
- performing a search with "enter"

Having this in one place caused a lot of bloat in our logic as we had to handle multiple different cases in one location. Do _x_ if it is this element, but do _y_ if it is another. This PR updates the event listeners to be attached to individual components, allowing for a more fine tuned set of actions per element. To not duplicate logic across multiple components, we have condensed shared logic to actions on the search service to be reused. For example - `this.search.handleArrowUpOrDown` - to handle keyboard navigation.

### Search Context
We have unique logic based on the current search context (topic / tag / category / user / etc). This context is set within a models route file. We have updated the search service with a tracked value `searchContext` that can be utilized and updated from any component where the search service is injected.

```js
# before
this.searchService.set("searchContext", user.searchContext);

# after
this.searchService.searchContext = user.searchContext;
```

# Views
<img width="434" alt="Screenshot 2023-06-15 at 11 01 01 AM" src="https://github.com/discourse/discourse/assets/50783505/ef57e8e6-4e7b-4ba0-a770-8f2ed6310569">

<img width="418" alt="Screenshot 2023-06-15 at 11 04 11 AM" src="https://github.com/discourse/discourse/assets/50783505/2c1e0b38-d12c-4339-a1d5-04f0c1932b08">

<img width="413" alt="Screenshot 2023-06-15 at 11 04 34 AM" src="https://github.com/discourse/discourse/assets/50783505/b871d164-88cb-405e-9b78-d326a6f63686">

<img width="419" alt="Screenshot 2023-06-15 at 11 07 51 AM" src="https://github.com/discourse/discourse/assets/50783505/c7309a19-f541-47f4-94ef-10fa65658d8c">

<img width="424" alt="Screenshot 2023-06-15 at 11 04 48 AM" src="https://github.com/discourse/discourse/assets/50783505/f3dba06e-b029-431c-b3d0-36727b9e6dce">

<img width="415" alt="Screenshot 2023-06-15 at 11 08 57 AM" src="https://github.com/discourse/discourse/assets/50783505/ad4e7250-040c-4d06-bf06-99652f4c7b7c">
2023-06-16 09:24:07 -05:00
Ted Johansson d548231475
DEV: Remove old deprecation warnings where constants already removed (#22140)
We renamed these constants 3 years ago. This PR just removes the old deprecation notices.
2023-06-16 11:26:26 +08:00
Krzysztof Kotlarek 959c50001d
FIX: rename everything link to topics (#22076)
Rename everything link in community sidebar section to topics, which is
a bit more descriptive.
2023-06-15 11:36:38 +10:00
Krzysztof Kotlarek 2effcaa0f9
FIX: Update sidebar to be navigation menu (#22101)
Communities can use sidebar or header dropdown, therefore navigation menu is a better name settings in 2 places:

- Old user sidebar preferences;
- Site setting about default tags and categories.
2023-06-15 09:31:28 +10:00
Ella E b5d60da191
A11Y: Adjust contrast for the Dark and Solarized Dark tertiary color schemes (#22102) 2023-06-14 10:14:53 -06:00
Selase Krakani 2652354da3
FIX: Moderator(non-admin staff user) group visibility scope queries (#22109)
Currently, groups owned by moderators are not visible to them on the
groups page. This happens because, the group visibility queries don't
account for non-admin staff user group ownership.

This change updates the group visibility scope queries to account for a
moderator(non-admin staff user) group ownership.
2023-06-14 15:25:45 +00:00
Roman Rizzi 8938ecabc2
FEATURE: Custom content summarization strategies. (#21813)
* FEATURE: Content custom summarization strategies.

This PR establishes a pattern for plugins to register alternative ways of summarizing content by extending a class that defines an interface.

Core controls which strategy we'll use and who has access to it through the `summarization_strategy` and `custom_summarization_allowed_groups`. It also defines the UI for summarizing topics.

Other plugins can access this summarization mechanism and implement their features, removing cross-plugin customizations, as it currently happens between chat and the discourse-ai plugin.

* Group membership validation and rate limiting

* Work with objects instead of classes

* Port summarization feature from discourse-ai to chat

* Rename available summaries to 'Top Replies' and 'Summary'
2023-06-13 14:21:46 -03:00
Blake Erickson 644dded000
SECURITY: Use canonical url for topic embeddings (#22085)
This prevents duplicate topics from being created when using embed_urls
that only differ on query params.
2023-06-13 11:08:08 -06:00
Blake Erickson 56b74e6042
SECURITY: Limit ThemeField value length to prevent DoS (#22087)
Co-authored-by: Daniel Waterworth <me@danielwaterworth.com>
2023-06-13 12:07:47 -05:00
Loïc Guitaut 5257c80064 DEV: Set limits on custom fields
This patch sets some limits on custom fields:
- an entity can’t have more than 100 custom fields defined on it
- a custom field can’t hold a value greater than 10,000,000 characters

The current implementation of custom fields is relatively complex and
does an upsert in SQL at some point, thus preventing to simply add an
`ActiveRecord` validation on the custom field model without having to
rewrite a part of the existing logic.
That’s one of the reasons this patch is implementing validations in the
`HasCustomField` module adding them to the model including the module.
2023-06-13 11:47:21 +02:00
Daniel Waterworth 3d3e8c8fbd
FIX: json_schemer no longer allows nil keys (#22015) 2023-06-08 15:12:47 -05:00
Juan David Martínez Cubillos 5fdd3bd28a
DEV: Implement staff logs for user columns edits (#21774)
* DEV: Implement staff logs for user columns edits

* deleted extra space in staff logger detail string, deleted string when no changes are made, added basic test coverage for EditDirectoryColumnsController

* fixed change made to #self.staff_actions un UserHistory

* implemented a method that builds the details, previous_values and new_values in a dynamic way

* removed details of changes

* refactored small merge
2023-06-07 17:19:58 -05:00
Alan Guo Xiang Tan fc296b9a81
UX: First pass at edit categories navigation modal for sidebar (#21963)
What this change?

We are currently not fully satisfied with the current way to edit the
categories and tags that appears in the sidebar where the user is
redirected to the tracking preferences tab in the user's profile causing
the user to lose context of the current page. In addition, the dropdown
to select categories or tags limits the amount of information we can
display.

Since editing or adding a custom categories section is already using a
modal, we have decided to switch editing the categories and tags that
appear in the sidebar to use a modal as well.

This commit ships a first pass of the edit categories modal such that we
can keep the commit small and reviewable. The incomplete nature of the
feature is also reflected in the fact that the feature is hidden behind
a new `new_edit_sidebar_categories_tags_interface_groups` site setting.
2023-06-07 12:09:30 +08:00
Blake Erickson 704a792f18
FEATURE: Add API Scope for latest posts (#21913)
Adds api scopes for

- `/posts.json`
- `/posts.rss`
- `/private-posts.json`
- `/private-posts.rss`
2023-06-05 09:04:34 -06:00
Blake Erickson 56ee46bf63
FEATURE: API Scope for latest.rss feed (#21906)
Adds an API scope for the `/latest.rss` route.

https://meta.discourse.org/t/188480
2023-06-02 08:28:14 -06:00
Sam c2332d7505
FEATURE: reduce avatar sizes to 6 from 20 (#21319)
* FEATURE: reduce avatar sizes to 6 from 20

This PR introduces 3 changes:

1. SiteSetting.avatar_sizes, now does what is says on the tin.
previously it would introduce a large number of extra sizes, to allow for
various DPIs. Instead we now trust the admin with the size list.

2. When `avatar_sizes` changes, we ensure consistency and remove resized
avatars that are not longer allowed per site setting. This happens on the
12 hourly job and limited out of the box to 20k cleanups per cycle, given
this may reach out to AWS 20k times to remove things.

3.Our default avatar sizes are now "24|48|72|96|144|288" these sizes were
very specifically picked to limit amount of bluriness introduced by webkit.
Our avatars are already blurry due to 1px border, so this corrects old blur.

This change heavily reduces storage required by forums which simplifies
site moves and more.

Co-authored-by: David Taylor <david@taylorhq.com>
2023-06-01 10:00:01 +10:00
Vinoth Kannan d4bfd441ba
FEATURE: display PM participant group names in the topics list. (#21677)
After this change, we can view all participant group names on the topic list page.

Co-authored-by: Régis Hanol <regis@hanol.fr>
2023-05-31 19:32:06 +05:30
Sérgio Saquetim 908117e270
DEV: Added modifier hooks to allow plugins to tweak how categories and groups are fetched (#21837)
This commit adds modifiers that allow plugins to change how categories and groups are prefetched into the application and listed in the respective controllers.

Possible use cases:

- prevent some categories/groups from being prefetched when the application loads for performance reasons.
- prevent some categories/groups from being listed in their respective index pages.
2023-05-30 18:41:50 -03:00
Renato Atilio c539f749f1
FEATURE: support for chronologically merging posts into existing topic (#21374)
When a user chooses to move a topic/message to an existing topic/message, they can now opt to merge the posts chronologically (using a checkbox in the UI).
2023-05-25 14:38:34 -04:00
Alan Guo Xiang Tan 5cfe323445
PERF: Strict loading for SidebarSection queries (#21717)
What is this change required?

I noticed that actions in `SidebarSectionsController` resulted in
lots of N+1 queries problem and I wanted a solution to
prevent such problems without having to write N+1 queries tests. I have
also used strict loading for `SidebarSection` queries in performance
sensitive spots.

Note that in this commit, I have also set `config.active_record.action_on_strict_loading_violation = :log`
for the production environment so that we have more visibility of
potential N+1 queries problem in the logs. In development and test
environment, we're sticking with the default of raising an error.
2023-05-25 09:10:32 +08:00
Alan Guo Xiang Tan 916495e0a1
DEV: Avoid leaking new site setting states in test environment (#21713)
What is the problem?

In the test environement, we were calling `SiteSetting.setting` directly
to introduce new site settings. However, this leads to changes in state of the SiteSettings
hash that is stored in memory as test runs. Changing or leaking states
when running tests is one of the major contributors of test flakiness.

An example of how this resulted in test flakiness is our `spec/integrity/i18n_spec.rb` spec file which
had a test case that would fail because a new "plugin_setting" site
setting was registered in another test case but the site setting did not
have translations for the site setting set.

What is the fix?

There are a couple of changes being introduced in this commit:

1. Make `SiteSetting.setting` a private method as it is not safe to be
   exposed as a public method of the `SiteSetting` class

2. Change test cases to use existing site settings in Discourse instead
   of creating custom site settings. Existing site settings are not
   removed often so we don't really need to dynamically add new site
   settings in test cases. Even if the site settings being used in test
   cases are removed, updating the test cases to rely on other site
   settings is a very easy change.

3. Set up a plugin instance in the test environment as a "fixture"
   instead of having each test create its own plugin instance.
2023-05-25 07:53:57 +08:00
Rafael dos Santos Silva baa5389a23
FEATURE: Add support for AVIF images (#21680) 2023-05-24 16:13:36 -03:00
Loïc Guitaut 37b71c5903 FIX: Don’t run validations when invalidating invites
This patch is a followup of
https://github.com/discourse/discourse/pull/21504 where limits on custom
message for an invite were introduced.

This had a side effect of making some existing invites invalid and with
the current code, they can’t be invalidated anymore.

This patch takes the approach of skipping the validations when invites
are invalidated since the important thing here is to mark the invite as
invalidated regardless of its actual state in the DB. (no other
attributes are updated at the same time anyway)
2023-05-24 15:51:33 +02:00
Loïc Guitaut 4ea396e67c DEV: Bump the limits on group request text fields
Users submitting requests to join groups were not receiving errors when
the character limit for the request was exceeded. This also affects the
UX when admin-created group request templates are inserted into the
request.

This patch bumps the limits.

- https://meta.discourse.org/t/group-membership-requests-suddenly-limited-to-274-characters/265127
- https://github.com/discourse/discourse/pull/19993
2023-05-24 09:57:46 +02:00
Krzysztof Kotlarek 2aa5fc927e
FIX: allow published pages to be added to sidebar (#21687)
Custom sidebar sections should accept publish pages with URL `/pub/*`. Similarly to `/my/activity` links.
2023-05-24 08:59:19 +10:00
Blake Erickson b637249169
FIX: Video thumbnails can have duplicates (#21681)
* FIX: Video thumbnails can have duplicates

It's possible that a duplicate video or even a very similar video could
generate the same video thumbnail. Because video thumbnails are mapped
to their corresponding video by using the video sha1 in the thumbnail
filename we need to allow for duplicate thumbnails otherwise even when a
thumbnail has been generated for a topic it will not be mapped
correctly.

This will also allow you to re-upload a video on the same topic to
regenerate the thumbnail.

* fix typo
2023-05-23 09:00:09 -06:00
Krzysztof Kotlarek 7ead8de232
DEV: endpoint to reset community community-section (#21664)
In upcoming PRs, admins will be able to edit the Community section. We need an endpoint which allows resetting it to the default state.
2023-05-23 09:53:32 +10:00
Bianca Nenciu 5654aedd75
UX: Remove welcome topic admin tip and tweak copy (#21593)
The welcome topic user tip was for admins only, but in general, user
tips should be used for guiding new users through the features that
Discourse offers. For this reason, we decided to remove the user tip.

This commit also includes a few more copy tweaks to the welcome topic.
2023-05-18 16:38:04 +03:00
Bianca Nenciu f0ec1fad8c
FIX: Update category tag stats with new or deleted (#21531)
The old method updated only existing records, without considering that
new tags might have been created or some tags might not exist anymore.
This was usually not a problem because the stats were also updated by
other code paths.

However, the ensure consistency job should be more solid and help when
other code paths fail or after importing data.

Also, update category tag stats too should happen when updating other
category stats as well.
2023-05-18 12:46:44 +03:00
Keegan George 082821c754
DEV: Remove legacy user menu (#21308) 2023-05-17 09:16:42 -07:00
Ted Johansson 445196399d
FIX: Remove obsolete references to lounge category (#21607)
### What is this change?

The lounge category was replaced with the general category in https://github.com/discourse/discourse/pull/18097.

However, there are still a few references to the lounge category in code. In particular, `Category#seeded?` is erroring out in production looking for `SiteSetting.lounge_category_id`.
2023-05-17 16:34:14 +08:00
Ted Johansson a2bc24456f
DEV: Update call sites using BaseStore#download but expecting exceptions (#21551)
In #21498, we split `BaseStore#download` into a "safe" version which returns nil on errors, and an "unsafe" version which raises an exception, which was the old behaviour of `#download`.

This change updates call sites that used the old `#download`, which raised exceptions, to use the new `#download!` to preserve behaviour (and silence deprecation warnings.)

It also silences the deprecation warning in tests.
2023-05-17 16:03:33 +08:00
Loïc Guitaut d63ce56252 DEV: Set limit for Invite#custom_message 2023-05-15 09:55:28 +02:00
Loïc Guitaut b81c13280a DEV: Set limits for text fields on BadgeGrouping 2023-05-15 09:54:54 +02:00
Loïc Guitaut 9f283eb836
DEV: Set a limit for ApiKey#description (#21502) 2023-05-15 14:12:25 +10:00
Bianca Nenciu b73a9a1faa
UX: Various improvements to welcome topic CTA (#21010)
- Update welcome topic copy
- Edit the welcome topic automatically when the title or description changes
- Remove “Create your Welcome Topic” banner/CTA
- Add "edit welcome topic" user tip
2023-05-12 17:09:40 +03:00
Ted Johansson 59867cc091
DEV: Gracefully handle user avatar download SSRF errors (#21523)
### Background

When SSRF detection fails, the exception bubbles all the way up, causing a log alert. This isn't actionable, and should instead be ignored. The existing `rescue` does already ignore network errors, but fails to account for SSRF exceptions coming from `FinalDestination`.

### What is this change?

This PR does two things.

---

Firstly, it introduces a common root exception class, `FinalDestination::SSRFError` for SSRF errors. This serves two functions: 1) it makes it easier to rescue both errors at once, which is generally what one wants to do and 2) prevents having to dig deep into the class hierarchy for the constant.

This change is fully backwards compatible thanks to how inheritance and exception handling works.

---

Secondly, it rescues this new exception in `UserAvatar.import_url_for_user`, which is causing sporadic errors to be logged in production. After this SSRF errors are handled the same as network errors.
2023-05-12 15:32:02 +08:00
Blake Erickson bd6e487df0
FIX: Allow integer group_ids for create invite api (#21494)
This fixes a bug in the create invite API where if you passed in an
integer for the group_ids field it would fail to add the user to the
specified group.
2023-05-11 11:39:33 -06:00
Ted Johansson b837459e1d
DEV: Add both safe and unsafe Discourse.store.download methods (#21498)
* DEV: Add both safe and unsafe Discourse.store.download methods

* DEV: Update call sites that can use the safe store download method
2023-05-11 17:27:27 +08:00
Martin Brennan 7a1d60c60e
FIX: Likes received count in digest email (#21458)
This commit fixes an issue where the Likes Received notification
count in the user digest email was not affected by the
since/last_seen date for the user, which meant that no matter
how long it had been since the user visited the count was
always constant.

Now instead for the Likes Received count, we only count the
unread notifications of that type since the user was last
seen.
2023-05-09 19:19:26 +02:00
Loïc Guitaut ae369b1100 FIX: Change the limit on badges description
The current limit (250 characters) is too low, as we have some
translations used for our badge descriptions that result in a
description length of 264 characters.

To be on the safe side, the limit is now set to 500 characters.
2023-05-09 11:41:40 +02:00
Alan Guo Xiang Tan 0c8d3f8542
DEV: Fix `category:` filter only supported alphabets and numbers (#21427)
A category's slug can be encoded when
`SiteSetting.slug_generation_method` has been set to "encoded". As a
result, we have to support non ASCII characters as well.
2023-05-09 08:10:08 +08:00
Sam ac0673d29e
DEV: In test, if flush is called and there is no thread, flush inline (#21426) 2023-05-08 13:25:00 +10:00
Sam 608bde734b
FEATURE: allow for longer membership domains (#21428) 2023-05-08 10:40:37 +08:00
Sam 83f1a13374
DEV: stop leaking data into tables during test (#21403)
This amends it so our cached counting reliant specs run in synchronize mode

When running async there are situations where data is left over in the table
after a transactional test. This means that repeat runs of the test suite
fail.
2023-05-06 07:15:33 +10:00
David Taylor 05cd39d4d9
FIX: Do not log 'personal message view' when sending webhook (#21375)
Similar to the issue resolved by 3b55de90e5
2023-05-04 10:15:31 +01:00
Penar Musaraj d4a2e9a740
UX: Use fixed colors for admin stacked chart reports (#21371)
* UX: Use fixed colors for admin stacked chart reports

* Fix specs
2023-05-04 08:35:19 +02:00
Krzysztof Kotlarek 709fa24558
DEV: move sidebar community section to database (#21166)
* DEV: move sidebar community section to database

Before, community section was hard-coded. In the future, we are planning to allow admins to edit it. Therefore, it has to be moved to database to `custom_sections` table.

Few steps and simplifications has to be made:
- custom section was hidden behind `enable_custom_sidebar_sections` feature flag. It has to be deleted so all forums, see community section;
- migration to add `section_type` column to sidebar section to show it is a special type;
- migration to add `segment` column to sidebar links to determine if link should be displayed in primary section or in more section;
- simplify more section to have one level only (secondary section links are merged);
- ensure that links like `everything` are correctly tracking state;
- make user an anonymous links position consistence. For example, from now on `faq` link for user and anonymous is visible in more tab;
- delete old community-section template.
2023-05-04 12:14:09 +10:00
Bianca Nenciu cc18a99105
FEATURE: Add new notification for admin problems (#21287)
Add new notification for admin problems to replace old PM-based flow.
2023-05-03 19:35:22 +03:00
Loïc Guitaut 783c935dcb DEV: Set limits for text fields in reviewables 2023-05-03 09:54:54 +02:00
Joffrey JAFFEUX 6c90747dea
FIX: correctly use types for reviewables type (#21333)
Before this fix if the underlying model of a reviewable was changed, the filter wouldn't work anymore as it was expecting a 1:1 relation between filter type and model name.

This commit also relies on the `Reviewable.types` array to check against valid types instead of a regex not checking much.

Finally this commit adds a spec to ensure chat reviewables are listable from the review index page.
2023-05-02 14:21:14 +02:00
Gerhard Schlager 01dc461cc2
FIX: Disallow invisible Unicode characters in usernames (#21331)
The list of excluded characters is based on https://invisible-characters.com/ and the list of invisible characters used by Visual Studio Code (https://github.com/hediet/vscode-unicode-data)
2023-05-02 17:34:53 +10:00
Blake Erickson e2fbf4865a
DEV: Check if video thumbnails site setting is enabled (#21306) 2023-04-28 14:08:20 -06:00
Daniel Waterworth ae63d9ea09
PERF: Remove unnecessary queries from Theme#set_field (#21281) 2023-04-27 13:04:58 -05:00
Loïc Guitaut c4c2da83b4 DEV: Set limits for text fields in badges 2023-04-27 17:22:32 +02:00
Selase Krakani 552697e194
DEV: Add deprecation warning for user_badge_removed event (#21255)
`user_badge_removed` event has been replaced with `user_badge_revoked`
2023-04-27 13:07:02 +00:00
Loïc Guitaut a89b3c27aa DEV: set limits for text fields on groups 2023-04-27 13:58:46 +02:00
Sam 2ccc5fc66e
FEATURE: add support for figure and figcaption tags in embeddings (#21276)
Many blog posts use these to illustrate and images were previously omitted

Additionally strip superfluous HTML and BODY tags from embed HTML.

This was incorrectly returned from server.
2023-04-27 19:57:06 +10:00
Selase Krakani 37cc056c1b
FIX: Ensure group-filtered group user event webhooks fire (#21254)
Group user event webhooks filtered by group fail silently
because the `group_ids` job arg wasn't being passed into the job.

This change add's `group_ids` to the `EmitWebHookEvent` jobs queued for
`user_added_to_group` and `user_removed_from_group` events.
2023-04-26 22:38:28 +00:00
Isaac Janzen 366ff0e76b
FIX: Don't display destroy reviewable button on client (#21226)
# Context

https://meta.discourse.org/t/missing-translate-in-review-page/262604

![image](https://user-images.githubusercontent.com/50783505/234089049-72332040-e7d5-4081-824a-b0b36e37187a.png)

An additional button was added as a result of dd495a0e19 which was intended to grant access to deleting reviewable from the API. 

We were being too flexible by only checking if the user was an admin

012aaf0ba3/lib/guardian.rb (L237)

where it should instead by scoped to check if the request was an API call.

# Fix

https://github.com/discourse/discourse/pull/21226/files#diff-0a2548be4b18bd4ef2dffb3ef8e44984d2fef7f037b53e98f67abea52ef75aa2R237

# Additions

Added a new guard of `is_api?`

https://github.com/discourse/discourse/pull/21226/files#diff-0a2548be4b18bd4ef2dffb3ef8e44984d2fef7f037b53e98f67abea52ef75aa2R657-R660

In `app/models/reviewable.rb` we check if the user has the permissions to the destroy action via the `Guardian`. To do this we were instantiating a new `Guardian` class which then caused us to lose the context of the request. The request is a necessary component in the guard of `is_api?` so we needed to pass the already defined Guardian from the `app/controllers/reviewables_controller.rb` to the `#perform` method to ensure the request is present.
2023-04-24 20:22:37 -05:00
Selase Krakani cdf1589a85
FEATURE: Add support for user badge revocation webhook events (#21204)
Currently, only user badge grants emit webhook events. This change
extends the `user_badge` webhook to emit user badge revocation events.

A new `user_badge_revoked` event has been introduced instead of relying
on the existing `user_badge_removed` event. `user_badge_removed` emitted
just the `badge_id` and `user_id` which aren't helpful for generating a
meaningful webhook payload for revoked(deleted) user badges.

The new event emits  the user badge object.
2023-04-24 20:36:40 +00:00
Isaac Janzen 599979902e
FIX: Error when trying to bump a topic with no category (#21207)
When revising a post, if the topic that post belonged to did not have a category attached it would error with 

> NoMethodError (undefined method `read_restricted' for nil:NilClass)
2023-04-24 09:28:10 -05:00
Blake Erickson 6ae0c42c01
FIX: Do not overwrite existing thumbnails (#21199)
* FIX: Do not overwrite existing thumbnails

When auto generating video thumbnails they should not overwrite any
existing topic thumbnails.

This also addresses an issue with capitalized file extensions like .MOV
that were being excluded.

* Update app/models/post.rb

Remove comment

Co-authored-by: Penar Musaraj <pmusaraj@gmail.com>

---------

Co-authored-by: Penar Musaraj <pmusaraj@gmail.com>
2023-04-21 13:33:33 -06:00
Ted Johansson e002a24eca
FEATURE: Add new don't feed the trolls feature (#21001)
Responding to negative behaviour tends to solicit more of the same. Common wisdom states: "don't feed the trolls".

This change codifies that advice by introducing a new nudge when hitting the reply button on a flagged post. It will be shown if either the current user, or two other users (configurable via a site setting) have flagged the post.
2023-04-20 15:49:35 +08:00
Isaac Janzen a3693fec58
FEATURE: Allow drafts to be deleted via the API (#21148)
This PR adds the ability to destroy drafts for a passed user via the API. This was not possible before as this action was reserved for only your personal drafts.

If a user is an admin and calls the `#destroy` action from the API they are able to destroy a draft for a passed user. A user can be targeted by passed either their:
- username
- external_id (for SSO) 

to the request.

In the case you attempt to destroy a non-personal draft and
- You are not an admin
- You do not access the `#destroy` action via the API

you will raise a `Discourse::InvalidAccess` (403) and will not succeed in destroying the draft.
2023-04-19 14:41:45 -05:00
Ted Johansson f3f30d6865
SECURITY: Encode embed url (#21133)
The embed_url in "This is a companion discussion..." could be used for
XSS.

Co-authored-by: Blake Erickson <o.blakeerickson@gmail.com>
2023-04-18 15:05:29 +08:00
Loïc Guitaut a5235f7d16
DEV: Refactor STI/polymorphic associations in chat (#20789) 2023-04-17 15:41:56 +02:00
David Battersby 967010e545
FEATURE: Add an emoji deny list site setting (#20929)
This feature will allow sites to define which emoji are not allowed. Emoji in this list should be excluded from the set we show in the core emoji picker used in the composer for posts when emoji are enabled. And they should not be allowed to be chosen to be added to messages or as reactions in chat.

This feature prevents denied emoji from appearing in the following scenarios:
- topic title and page title
- private messages (topic title and body)
- inserting emojis into a chat
- reacting to chat messages
- using the emoji picker (composer, user status etc)
- using search within emoji picker

It also takes into account the various ways that emojis can be accessed, such as:
- emoji autocomplete suggestions
- emoji favourites (auto populates when adding to emoji deny list for example)
- emoji inline translations
- emoji skintones (ie. for certain hand gestures)
2023-04-13 15:38:54 +08:00
David Taylor 9238767f7e
FEATURE: Persist password hashing algorithm/params in database (#20980)
Previously, Discourse's password hashing was hard-coded to a specific algorithm and parameters. Any changes to the algorithm or parameters would essentially invalidate all existing user passwords.

This commit introduces a new `password_algorithm` column on the `users` table. This persists the algorithm/parameters which were use to generate the hash for a given user. All existing rows in the users table are assumed to be using Discourse's current algorithm/parameters. With this data stored per-user in the database, we'll be able to keep existing passwords working while adjusting the algorithm/parameters for newly hashed passwords.

Passwords which were hashed with an old algorithm will be automatically re-hashed with the new algorithm when the user next logs in.

Values in the `password_algorithm` column are based on the PHC string format (https://github.com/P-H-C/phc-string-format/blob/master/phc-sf-spec.md). Discourse's existing algorithm is described by the string `$pbkdf2-sha256$i=64000,l=32$`

To introduce a new algorithm and start using it, make sure it's implemented in the `PasswordHasher` library, then update `User::TARGET_PASSWORD_ALGORITHM`.
2023-04-11 10:16:28 +01:00
Krzysztof Kotlarek 63a0466548
FIX: improve performance of UserStat.ensure_consistency (#21044)
Optimize `UserStatpost_read_count` calculation.

In addition, tests were updated to fail when code is not evaluated. Creation of PostTiming was updating `post_read_count`. Count it has to be reset to ensure that ensure_consitency correctly calculates result.

Extracting users seen in the last hour to separate Common Table Expression reduces the amount of processed rows.

Before
```
Update on user_stats  (cost=267492.07..270822.95 rows=2900 width=174) (actual time=12606.121..12606.127 rows=0 loops=1)
  ->  Hash Join  (cost=267492.07..270822.95 rows=2900 width=174) (actual time=12561.814..12603.689 rows=10 loops=1)
        Hash Cond: (user_stats.user_id = x.user_id)
        Join Filter: (x.c <> user_stats.posts_read_count)
        Rows Removed by Join Filter: 67
        ->  Seq Scan on user_stats  (cost=0.00..3125.34 rows=75534 width=134) (actual time=0.014..39.173 rows=75534 loops=1)
        ->  Hash  (cost=267455.80..267455.80 rows=2901 width=48) (actual time=12558.613..12558.617 rows=77 loops=1)
              Buckets: 4096  Batches: 1  Memory Usage: 39kB
              ->  Subquery Scan on x  (cost=267376.03..267455.80 rows=2901 width=48) (actual time=12168.601..12558.572 rows=77 loops=1)
                    ->  GroupAggregate  (cost=267376.03..267426.79 rows=2901 width=12) (actual time=12168.595..12558.525 rows=77 loops=1)
                          Group Key: pt.user_id
                          ->  Sort  (cost=267376.03..267383.28 rows=2901 width=4) (actual time=12100.490..12352.106 rows=2072830 loops=1)
                                Sort Key: pt.user_id
                                Sort Method: external merge  Disk: 28488kB
                                ->  Nested Loop  (cost=1.28..267209.18 rows=2901 width=4) (actual time=0.040..11528.680 rows=2072830 loops=1)
                                      ->  Nested Loop  (cost=0.86..261390.02 rows=13159 width=8) (actual time=0.030..3492.887 rows=3581648 loops=1)
                                            ->  Index Scan using index_users_on_last_seen_at on users u  (cost=0.42..89.71 rows=28 width=4) (actual time=0.010..0.201 rows=78 loops=1)
                                                  Index Cond: (last_seen_at > '2023-04-11 00:22:49.555537'::timestamp without time zone)
                                            ->  Index Scan using index_post_timings_on_user_id on post_timings pt  (cost=0.44..9287.60 rows=4455 width=8) (actual time=0.081..38.542 rows=45919 loops=78)
                                                  Index Cond: (user_id = u.id)
                                      ->  Index Scan using forum_threads_pkey on topics t  (cost=0.42..0.44 rows=1 width=4) (actual time=0.002..0.002 rows=1 loops=3581648)
                                            Index Cond: (id = pt.topic_id)
                                            Filter: ((deleted_at IS NULL) AND ((archetype)::text = 'regular'::text))
                                            Rows Removed by Filter: 0
Planning Time: 0.692 ms
Execution Time: 12612.587 ms
```
After
```
Update on user_stats  (cost=9473.60..12804.30 rows=2828 width=174) (actual time=677.724..677.729 rows=0 loops=1)
  ->  Hash Join  (cost=9473.60..12804.30 rows=2828 width=174) (actual time=672.536..677.706 rows=1 loops=1)
        Hash Cond: (user_stats.user_id = x.user_id)
        Join Filter: (x.c <> user_stats.posts_read_count)
        Rows Removed by Join Filter: 54
        ->  Seq Scan on user_stats  (cost=0.00..3125.34 rows=75534 width=134) (actual time=0.012..23.977 rows=75534 loops=1)
        ->  Hash  (cost=9438.24..9438.24 rows=2829 width=48) (actual time=647.818..647.822 rows=55 loops=1)
              Buckets: 4096  Batches: 1  Memory Usage: 37kB
              ->  Subquery Scan on x  (cost=9381.66..9438.24 rows=2829 width=48) (actual time=647.409..647.805 rows=55 loops=1)
                    ->  HashAggregate  (cost=9381.66..9409.95 rows=2829 width=12) (actual time=647.403..647.786 rows=55 loops=1)
                          Group Key: pt.user_id
                          Batches: 1  Memory Usage: 121kB
                          ->  Nested Loop  (cost=1.86..9367.51 rows=2829 width=4) (actual time=0.056..625.245 rows=120022 loops=1)
                                ->  Nested Loop  (cost=1.44..3692.96 rows=12832 width=8) (actual time=0.047..171.754 rows=217440 loops=1)
                                      ->  Nested Loop  (cost=1.00..254.63 rows=25 width=12) (actual time=0.030..1.407 rows=56 loops=1)
                                            Join Filter: (u.id = user_stats_1.user_id)
                                            ->  Nested Loop  (cost=0.71..243.08 rows=25 width=8) (actual time=0.018..1.207 rows=87 loops=1)
                                                  ->  Index Scan using index_users_on_last_seen_at on users u  (cost=0.42..86.71 rows=27 width=4) (actual time=0.009..0.156 rows=87 loops=1)
                                                        Index Cond: (last_seen_at > '2023-04-11 00:47:07.437568'::timestamp without time zone)
                                                  ->  Index Only Scan using user_stats_pkey on user_stats us  (cost=0.29..5.79 rows=1 width=4) (actual time=0.011..0.011 rows=1 loops=87)
                                                        Index Cond: (user_id = u.id)
                                                        Heap Fetches: 87
                                            ->  Index Scan using user_stats_pkey on user_stats user_stats_1  (cost=0.29..0.45 rows=1 width=4) (actual time=0.002..0.002 rows=1 loops=87)
                                                  Index Cond: (user_id = us.user_id)
                                                  Filter: (posts_read_count < 10000)
                                                  Rows Removed by Filter: 0
                                      ->  Index Scan using index_post_timings_on_user_id on post_timings pt  (cost=0.44..92.98 rows=4455 width=8) (actual time=0.036..2.492 rows=3883 loops=56)
                                            Index Cond: (user_id = user_stats_1.user_id)
                                ->  Index Scan using forum_threads_pkey on topics t  (cost=0.42..0.44 rows=1 width=4) (actual time=0.002..0.002 rows=1 loops=217440)
                                      Index Cond: (id = pt.topic_id)
                                      Filter: ((deleted_at IS NULL) AND ((archetype)::text = 'regular'::text))
                                      Rows Removed by Filter: 0
Planning Time: 1.406 ms
Execution Time: 677.817 ms
```
2023-04-11 12:28:08 +10:00
Daniel Waterworth fcc73b441d
FIX: Make emoji cache store marshalled objects (#21029)
We only marshal arrays, hashes and sets, which meant that the emojis
here were just getting `to_s`ed.

This is a hack.
2023-04-10 10:44:11 -05:00
Krzysztof Kotlarek e586f6052f
FEATURE: public custom sidebar sections visible to anonymous (#20931)
Previously, public custom sections were only visible to logged-in users. In this PR, we are making them visible to anonymous as well.

The reason is that Community Section will be moved into custom section model to be easily editable by admins.
2023-04-06 08:55:47 +10:00
Krzysztof Kotlarek b72282123b
FIX: public sidebar sections belong to system user (#20972)
Before, public sidebar sections were belonging to admin. However, a better choice is system user.
2023-04-05 10:52:18 +10:00
David Taylor 2386ad12f2
Update default ga_version to v4 and add warning message for v3 (#20936)
Sites which are already using ga3 will stay on that version, and will be shown a warning in the admin panel until they update.

https://meta.discourse.org/t/upgrade-to-google-analytics-4-before-july-2023/260498
2023-04-04 13:14:20 +01:00
Alan Guo Xiang Tan e54359c135
DEV: Drop plugin related index from core (#20930)
The migration of the index has since been moved into the
discourse-akismet plugin where it should have always been.
2023-04-04 07:31:09 +08:00
Alan Guo Xiang Tan fd34032db2
DEV: Support filter for topics in specific subcategories on /filter (#20927)
This commit adds support for filtering for topics in specific
subcategories via the categories filter query language.

For example: `category:documentation:admins` will filter for topics and
subcategory topics in
the category with slug "admins" whose parent category has the slug
"documentation".

The `=` prefix can also be used such that
`=category:documentation:admins` will exclude subcategory topics of the
category with slug "admins" whose parent category has the slug
"documentation".
2023-04-03 18:36:59 +08:00
Krzysztof Kotlarek c86d772277
FIX: Drop internal URL validation for paths in sidebar (#20891)
`Rails.application.routes.recognize_path(value)` was not working for /admin paths because StaffConstraint.new requires user to check permission.

This validation is not bringing much value, and the easiest way is to drop it. In the worse case scenario, a user will have an incorrect link in their sidebar.

Bug reported: https://meta.discourse.org/t/custom-sidebar-sections-being-tested-on-meta/255303/66
2023-03-31 13:26:56 +08:00
Mark VanLandingham 9518e47204
FEATURE: ability to bulk_remove users from a group (#20876) 2023-03-30 08:06:36 -05:00
Martin Brennan 84ff96bd07
FIX: Do not validate email in TL promotion (#20892)
There is no need to validate the user's emails when
promoting/demoting their trust level, this can cause
issues in things like Jobs::Tl3Promotions, we don't
need to fail in that case when all we are doing is changing
trust level.
2023-03-30 13:52:10 +10:00
Blake Erickson aa09a78d14
DEV: Remove diffhtml_preview for video thumbnails (#20865)
Video thumbnail generation is no longer dependent on
`enable_diffhtml_preview` being enabled.
2023-03-28 12:38:50 -06:00
Vinoth Kannan 08ff6eebad
FIX: skip category preference update if already set by group. (#20823)
`default_categories_*` site settings will update the category preferences on user creation. But it shouldn't update the user's category preference if a group's setting already updated it for that user.
2023-03-28 19:43:01 +05:30
Sam 7038540af6
PERF: ensure sidebar section link index is correctly ordered (#20854)
We perform lookups on sidebar section links based on sidebar_section_id
totally ignoring user. This ensures we have an index to work with.

This removes the previous index `links_user_id_section_id_position` which
partially doubled up `idx_unique_sidebar_section_links`
2023-03-28 15:13:44 +11:00
Daniel Waterworth d563b73202
DEV: Make category topic_ids cache work like other caches (#20814) 2023-03-27 09:23:29 -05:00
Daniel Waterworth 3e80ab3143
DEV: Make category subcategory_ids cache work like other caches (#20815) 2023-03-27 09:23:23 -05:00
Daniel Waterworth b2554e1490
DEV: Make hex cache work like other caches (#20816) 2023-03-27 09:22:53 -05:00
Daniel Waterworth 0f4bb19524
DEV: make developer cache work like other caches (#20817) 2023-03-27 09:22:33 -05:00
Krzysztof Kotlarek 4047073292
FIX: display validation under custom sidebar fields (#20772)
Before, incorrectly filled fields were marked with red border. Now, additional information under the field is displayed to notify the user what is incorrect.

/t/93696
2023-03-27 13:03:16 +11:00
Daniel Waterworth 0728fa055b
DEV: Make theme cache work like other caches (#20813) 2023-03-24 12:37:16 -05:00
Mark VanLandingham ebada4a6b0
DEV: More specific API to including extra associations in CategoryList (#20790) 2023-03-23 12:39:38 -05:00
Mark VanLandingham 32aa821f12
DEV: Add preload API to CategoryList (#20778) 2023-03-22 15:12:08 -05:00
Martin Brennan 520d4f504b
FEATURE: Auto-remove users without permission from channel (#20344)
There are many situations that may cause users to lose permission to
send messages in a chat channel. Until now we have relied on security
checks in `Chat::ChatChannelFetcher` to remove channels which the
user may have a `UserChatChannelMembership` record for but which
they do not have access to.

This commit takes a more proactive approach. Now any of these following
`DiscourseEvent` triggers may cause `UserChatChannelMembership`
records to be deleted:

* `category_updated` - Permissions of the category changed
   (i.e. CategoryGroup records changed)
* `user_removed_from_group` - Means the user may not be able to access the
   channel based on `GroupUser` or also `chat_allowed_groups`
* `site_setting_changed` - The `chat_allowed_groups` was updated, some
   users may no longer be in groups that can access chat.
* `group_destroyed` - Means the user may not be able to access the
   channel based on `GroupUser` or also `chat_allowed_groups`

All of these are handled in a distinct service run in a background
job. Users removed are logged via `StaffActionLog` and then we
publish messages on a per-channel basis to users who had their
memberships deleted.

When the user has a channel they are kicked from open, we show
a dialog saying "You no longer have access to this channel".

When they click OK we redirect them either:

* To their first other public channel, if they have any followed
* The chat browse page if they don't

This is to save on tons of requests from kicked out users getting messages
from other channels.

When the user does not have the kicked channel open, we can just
silently yoink it out of their sidebar and turn off subscriptions.
2023-03-22 10:19:59 +10:00
Daniel Waterworth 7b01576c8d
DEV: Remove emoji cache dead code (#20764)
The cache is already not shared between app servers that have different
app_versions, so this check was redundant.
2023-03-21 12:33:12 -05:00
Daniel Waterworth a0a6f6d71b
FIX: Fix the emoji toned regexes (#20763) 2023-03-21 11:48:55 -05:00
Régis Hanol 37609897e8
FEATURE: log manual bounce reset (#20758)
DEV: rename the route "/admin/users/:id/reset_bounce_score" to use dashes instead of underscores
2023-03-21 15:26:26 +01:00
Krzysztof Kotlarek 1859025228
FIX: my links in sidebar section (#20754)
Links like `/my/preferences` were invalid in custom section. The reason is that `/my` links are just redirects from backend, and they are not recognized as valid Ember paths.

https://github.com/discourse/discourse/blob/main/config/routes.rb#L433

Therefore, regex match allowlist was added - similar to backend check:

https://github.com/discourse/discourse/blob/main/app/controllers/users_controller.rb#L471

/safe-mode is same case
2023-03-21 15:58:42 +11:00