2428 Commits

Author SHA1 Message Date
Martin Brennan
e99ed81586
DEV: Serialize theme_id and colors for user selectable color palettes (#31972)
We currently have `user_color_schemes` serialized on the preloaded
`Site` object, but it's very lightweight, only having an ID and name.
It would be useful for some themes and also the user Interface
preferences tab to be able to access the colors for the color scheme,
as well as the theme it belongs to.

This commit expands the serializer to include these extra attributes.
This `user_color_schemes` key is already cached as a fragment, so this
shouldn't be too much extra burden to send to the client.
2025-03-25 16:31:28 +10:00
Régis Hanol
558c566ca8
FIX: avatar, profile & card backgrounds url in DiscourseConnect (#31956)
The URLs returned by DiscourseConnect for the user's avatar, profile and
card backgrounds were not always correctly handling CDN.

This make use of the `GlobalPath.full_cdn_url` helper method which has
been battle-tested.

Ref - https://meta.discourse.org/t/-/356599
2025-03-24 16:23:05 +01:00
Gary Pendergast
b77d0f7589
FEATURE: Sync Reviewable Status (#31901)
When multiple admins are working in the review queue, it's quite easy for two people to try and handle the same reviewable at the same time. This change addresses the two major situations where this can occur.

The `ReviewableClaimedTopic` model has been extended to allow the system to mark a reviewable as claimed as soon as the first moderator starts handling the reviewable, even when the `reviewable_claiming` setting is disabled. This ensures that reviewable actions with client-site activity (for example, `agree_and_suspend`) will lock the reviewable before another moderator starts working on it.

When someone handles handles a reviewable, we now use `MessageBus` to inform other moderators that it's changed. If any of the other moderator have that reviewable open (either individually, or on the list screen), it will automatically refresh that data.
2025-03-24 14:27:18 +11:00
Osama Sayegh
f7f7642ae0
UX: Improve naming for anonymous mode settings (#31832)
This PR renames a couple of settings related to anonymous mode:

1. `allow_anonymous_posting` → `allow_anonymous_mode`. This setting is
used as a switch for the entire anonymous mode feature, so it makes
sense to give it a generic name that better reflects what the setting
does.
2. `allow_anonymous_likes` → `allow_likes_in_anonymous_mode`. The new
name is clearer and will match a new setting that we'll add to allow
anonymous users to post in chat.

Internal topic: t/148088.
2025-03-21 04:54:06 +03:00
Alan Guo Xiang Tan
b3881d42d0
DEV: Disallow the use of Rails.logger= in RSpec tests (#31920)
Setting Rails.logger after the application has been initialized does not
seem to be safe anymore and can lead to flaky tests. This commit
disallows the reassignment of `Rails.logger` going forward and updates
the affected test.

### Reviewer notes

Reassigning `Rails.logger` from within RSpec tests is causing tests
which uses `Rails.logger.broadcast_to(FakeLogger.new)` to flake.
Example:
https://github.com/discourse/discourse/actions/runs/13951116847/job/39050616967

```
  1) invalid requests handles NotFound with invalid json body
     Failure/Error: expect(fake_logger.errors).to have_attributes(size: 1)
     
       expected [] to have attributes {:size => 1} but had attributes {:size => 0}
       Diff:
       @@ -1 +1 @@
       -:size => 1,
       +:size => 0,
       
     # ./spec/integration/invalid_request_spec.rb:18:in `block (2 levels) in <main>'
     # ./spec/rails_helper.rb:619:in `block (3 levels) in <top (required)>'
     # /var/www/discourse/vendor/bundle/ruby/3.3.0/gems/benchmark-0.4.0/lib/benchmark.rb:304:in `measure'
     # ./spec/rails_helper.rb:619:in `block (2 levels) in <top (required)>'
     # ./spec/rails_helper.rb:580:in `block (3 levels) in <top (required)>'
     # /var/www/discourse/vendor/bundle/ruby/3.3.0/gems/timeout-0.4.3/lib/timeout.rb:185:in `block in timeout'
     # /var/www/discourse/vendor/bundle/ruby/3.3.0/gems/timeout-0.4.3/lib/timeout.rb:192:in `timeout'
     # ./spec/rails_helper.rb:570:in `block (2 levels) in <top (required)>'
     # ./spec/rails_helper.rb:527:in `block (2 levels) in <top (required)>'
     # /var/www/discourse/vendor/bundle/ruby/3.3.0/gems/webmock-3.25.1/lib/webmock/rspec.rb:39:in `block (2 levels) in <top (required)>'
```
2025-03-21 08:48:38 +08:00
Ted Johansson
1a7303a35e
FIX: Amend broken group automatic member dialog (#31854)
When creating or editing a group, we are meant to show a dialog telling the admin how many members will be automatically added.
2025-03-18 19:37:37 +08:00
Penar Musaraj
ecbd3cc93a
DEV: Fix custom homepage crawler display and override (#31841)
Fixes the custom homepage crawler output to include links to the site's
top menu.

![CleanShot 2025-03-15 at 16 27
16@2x](https://github.com/user-attachments/assets/57f25b65-a218-4811-b7d4-211e3d60e586)

This also provides a way to override that content via a plugin. Example
usage in a `plugin.rb` file:

```
register_html_builder("server:custom-homepage-crawler-view") do |c|
  "<div>override</div>"
end
```
2025-03-17 13:06:09 -04:00
Alan Guo Xiang Tan
577c043487
FIX: Ensure ordering is enforced in PostsController#replies (#31826)
This was picked up by the `PostsController#replies supports pagination`
requests spec as it was flaky from time to time.
2025-03-14 17:56:26 +08:00
Penar Musaraj
ef006ec76b
DEV: Add support for .well-known/apple-app-site-association (#31798)
We already support `/apple-app-site-association` at the root. Apple also
accepts `.well-known/apple-app-site-association` as a valid path so this
adds that as well, just in case.
2025-03-13 10:49:47 -04:00
David Taylor
e8f4433872
DEV: Stop using sprockets to compile service-worker js (#31796)
The service worker isn't served via normal asset paths or the CDN.
Instead, the ERB was being compiled by sprockets, fished out of the
`public/` directory by the static_controller, and then the
sprockets-specific stuff like `sourceMappingUrl` was being removed.

Instead, we can put the ERB under `views/static/`, and have it evaluate
at runtime. There are only a couple of super-cheap interpolations, plus
the route is cached in nginx, so there is no performance concern.

This takes us one step closer to removing sprockets.
2025-03-13 12:49:33 +00:00
Martin Brennan
38920724a0
DEV: Refactor reports index into service (#31667)
This list of all reports is needed in the admin search
controller as well, so this commit refactors it into
a service, adds specs, and also updates the admin
search code to use this new service & avoid a second
AJAX call to the server.
2025-03-11 14:36:06 +10:00
Krzysztof Kotlarek
7da4fe82b6
FIX: redirect to parent tag when synonym page visited (#31688)
When a synonym page is visited, the user should be redirected to the
parent tag.
2025-03-10 09:45:38 +11:00
Gary Pendergast
e77e5bd3cc
FIX: If a tag has a description, use it for the meta description. (#31689)
When a tag has a description defined, we should use that in the `<meta
name="description"...` tag on the tagged topic list page. This matches
the behaviour on the equivalent category pages.
2025-03-07 12:53:54 +11:00
Kelv
305039b1c3
DEV: ensure Rails application default headers are present in responses (#31619)
Follow up from https://github.com/discourse/discourse/pull/31559.

We expect some standard headers to be added from
`Rails.application.config.action_dispatch.default_headers` for
responses, however these were found to be removed in some error paths. 
For more detail on this behaviour, refer to https://github.com/discourse/discourse/pull/31619#issuecomment-2699644232.

This PR adds those headers back if they aren't there, with the caveats
that we don't add headers that are irrelevant for non-HTML responses,
and neither do we add X-Frame-Options which is intentionally removed for
embeddables.
2025-03-05 13:19:09 +08:00
Krzysztof Kotlarek
702a2a9cbc
UX: display html tags in silence reason (#31598)
Allow HTML tags in silence reason. Tags must be stripped for title
attribute.

Before

![image](https://github.com/user-attachments/assets/05d9819a-9dbf-46b2-b9c5-88187ca9af5b)


After
<img width="1079" alt="Screenshot 2025-03-04 at 11 39 05 am"
src="https://github.com/user-attachments/assets/2bb41deb-227c-47a8-b840-b0316a764252"
/>
<img width="1096" alt="Screenshot 2025-03-04 at 11 39 22 am"
src="https://github.com/user-attachments/assets/02e27fc0-317e-43df-bce8-6b68e48ac40e"
/>
2025-03-05 12:43:03 +11:00
Guhyoun Nam
2ab00c5b37
DEV: Add apply_modifier on group's mentionable scope (#31565)
This PR adds DiscoursePluginRegistry.apply_modifier on group's
mentionable scope.
2025-03-04 15:36:55 -06:00
Joffrey JAFFEUX
80625f6c1c
DEV: explicit json for emojis/search-aliases (#31582)
Adds `.json` a suffix everywhere and makes it clear that's it's a json
route.

Also adds a missing spec for this endpoint and updates the underlying
discourse-emojis gem for better symlinking
2025-03-03 15:21:16 +01:00
Joffrey JAFFEUX
d38acc5df1
DEV: discourse-emojis gem (#31408)
This commit moves most of emoji logic into the discourse-emojis gem:
https://github.com/discourse/discourse-emojis/

Most notably:
- images are now symlinked from the gem
- the gem provides path to the json files

Search aliases have also been made asynchronous and memoized. When you
will search for an emoji we will now load the aliases and store the list
for future use.

---------

Co-authored-by: David Taylor <david@taylorhq.com>
2025-03-03 13:09:08 +01:00
Kelv
0d90f6e3c3
FIX: cross origin opener policy should apply to public error responses (#31559)
In some error paths, headers that were set earlier can get overwritten
(e.g. `Cross-Origin-Opener-Policy`) by middleware such as
ActionDispatch::ShowExceptions.

This PR sets the `Cross-Origin-Opener-Policy` header to the value of the
SiteSetting `cross_origin_opener_policy_header` if it's missing and if
the response is for HTML.

In future, this DefaultHeaders middleware can be used to set other
default headers that relate to security or other purposes.

### Testing
<img width="631" alt="test"
src="https://github.com/user-attachments/assets/05106a40-2bc7-435d-91a2-4dd2a098f349"
/>
2025-03-03 17:04:24 +08:00
Alan Guo Xiang Tan
66ecfc8996
DEV: Correct users create API docs (#31578)
The API docs is incorrect as the `active` param is only permitted when
an admin API key
is used. This has always been the case since
429f27ec96c090d9054c498263f0cb635b665d99
2025-03-03 16:42:46 +08:00
Gary Pendergast
8615fc6cbb
DEV: Add a user agent to all HTTP requests that Discourse makes. (#31555)
This change standardises the `User-Agent` header that Discourse will send when talking to other sites.

`Discourse.user_agent` is now the authority on what the user agent value should be. For Onebox requests, this changes the user agent from their existing value to match the new value (unless overridden).

For all other requests, `Net::HTTPHeader` is monkey-patched to add a default `User-Agent` header when one hasn't been provided.
2025-03-03 16:32:25 +11:00
Isaac Janzen
176ee0bf60
DEV: Add posts_controller_create_user modifier (#31562)
Add `posts_controller_create_user` modifier to modify which user is associated with the post creation.
2025-02-28 15:11:12 -06:00
Joffrey JAFFEUX
8c9a2d21ce
Revert "DEV: Prevent crawlers from loading search results. (#31535)" (#31540)
This reverts commit 38de3d7bd1f503743c5d0237bc8a8d9d89effb8e. This
changed seemed to be blocking our own AI helper as well if it has the
“Search” tool.
2025-02-27 10:34:18 +01:00
Gary Pendergast
38de3d7bd1
DEV: Prevent crawlers from loading search results. (#31535)
This change detects if a crawler is trying to load a search results page, and returns a simple response that should indicate to them that there's no content of interest available there.
2025-02-27 14:34:19 +11:00
Régis Hanol
26b0428837
FIX: exclude links from hidden posts in user summary (#31504)
Ref - https://meta.discourse.org/t/-/353878
2025-02-25 12:56:16 -05:00
Alan Guo Xiang Tan
209d289772
FIX: No method error in WebhooksController#sendgrid (#31495)
When an email is sent by sendgrid to an email address with an invalid
host, the webhook payload does not contain the "status" field:

```
[
  {
    "bounce_classification": "Unclassified",
    "email": "noemail@this.does.not.exist.tld",
    "event": "bounce",
    "reason": "unable to get mx info: failed to get IPs from PTR record: lookup <nil>: unrecognized address",
    "sg_event_id": "Ym91bmNlLTQtNTA0ODUxOTUtZXVvMmlLeGRTYXlQRjRZRTQtLUk3QS0w",
    "sg_message_id": "euo2iKxdSayPF4YE4--I7A.recvd-5f54b5d587-pczjm-1-67BADEEA-6.0",
    "smtp-id": "<870b3a2a-160c-4fc8-bc9a-bd0d5b943b81@forum.umbraco.com>",
    "timestamp": 1740300320,
    "tls": 0,
    "type": "blocked"
  }
]
```

When the `status` field is missing, it results in a `NoMethodError
(undefined method `[]' for nil:NilClass)`
error in the controller method. In this commit, we will specifically
handle the webhook event from sendgrid when the email address's domain
is invalid.

Co-Authored-By: @nul800sebastiaan
2025-02-25 13:08:59 +08:00
Krzysztof Kotlarek
f1a892a64e
FIX: include silence_reason when admin sees user (#31493)
Small regression created in this PR
https://github.com/discourse/discourse/pull/30635

The reason is included only when `include_silence_reason` option is
included.
2025-02-25 14:14:33 +11:00
David Taylor
109fc428d8
DEV: Clear extra-locales cache between tests (#31488) 2025-02-24 22:10:43 +00:00
Blake Erickson
db3db9fe41
DEV: Log site setting changes from the rails console (#31353)
When using the rails console to change site settings log them to the
staff actions logs so that there is a record.
2025-02-24 14:57:01 -07:00
David Taylor
1f5cce705c
FIX: Include locale in extra-locales URLs (#31480)
Previously the rendered locale was based on the current session's
locale. Now that we're routing requests via the CDN, we can't rely on
the user's session, and should instead include the locale name in the
URL. Also adds a `.js` suffix for parity with our other JS assets.
2025-02-24 17:20:46 +00:00
David Taylor
12291f745c
PERF: Move extra-locale digest from query-param to path (#31479)
CDNs are often configured to strip query params, which means that the
`?v=` parameter wasn't reaching the Rails app, and therefore the
cache-control header was not being set correctly. Having a 40 character
sha1 digest in the **path** is the approach we take for other similar
assets like stylesheets and theme-javascripts.

Also adds a spec for the fix in 573fbeef64f052decc47e740cbe01a3c298c20b5
2025-02-24 14:09:15 +00:00
Krzysztof Kotlarek
d50bba3bdc
DEV: Allow SiteSetting::Update service to bulk update (#31438)
Previously, the SiteSetting::Update service allowed to update of a
single site setting. In the About controller, we were using the loop
through all settings -
https://github.com/discourse/discourse/blob/main/app/controllers/admin/config/about_controller.rb#L39

It is suboptimal because if the 3 first settings are saved and the
fourth is invalid, we will end with partially updated data.

Changing SiteSetting::Update to accept hash means that we will check
upfront if none of the settings are hidden or invalid and update all or
none.

Custom policies are used to report which settings are failing.
2025-02-24 11:09:44 +11:00
David Taylor
1b5e4b6b0f
PERF: Cache all extra-locale bundles and use CDN (#31445)
Code/translations for the admin panel and wizard are not considered
sensitive, so there's no need for access control checks here. Once
they're removed, we can cache in NGINX and the CDN, and thereby improve
server and client-load performance.
2025-02-21 14:48:42 +00:00
David Taylor
00907363d4
DEV: Drop ember-cli-based SCSS and locale compilation (#31407)
This totally separate SCSS and i18n compilation pipelines only existed
so that we could run `ember exam` in CI without starting Rails.

Now that our CI has such heavy caching of Ruby dependencies and database
migrations, the speed benefit of this is not worth the cost of
maintaining these separate pipelines.

Therefore, this commit removes that system, and updates CI to use
`bin/rake qunit:test`. That will start up a Rails server and proxy
stylesheet/locale requests to it. This strategy was already used for our
theme and plugin qunit test runs.
2025-02-21 11:15:04 +00:00
Krzysztof Kotlarek
2763e1726e
FEATURE: display process information on flag modal (#31300)
Information about the process is displayed on top of the flag modal.

In addition `allow_tl0_and_anonymous_users_to_flag_illegal_content` site
setting was renamed to `allow_all_users_to_flag_illegal_content` as it
is more descriptive.

<img width="629" alt="Screenshot 2025-02-12 at 3 58 12 pm"
src="https://github.com/user-attachments/assets/67c74ebc-6771-490d-b2c4-cbec25db8128"
/>
<img width="642" alt="Screenshot 2025-02-12 at 3 58 04 pm"
src="https://github.com/user-attachments/assets/5e4b8c84-601a-40c2-812f-b73d2b88a549"
/>
2025-02-14 11:26:20 +11:00
Régis Hanol
2e10fe98a3
FIX: automatically redirect logged in users to topic when... (#31301)
...loading an invite link that points to a topic they already have
access to.

This "feature" was removed in 07ef1a80a1461123d602c57e366974aed265a91e
as part of the security fix.

Internal ref - t/145628
2025-02-12 17:48:59 +01:00
Osama Sayegh
4db3389f3d
FIX: Don't load all groups when rendering <GroupChooser /> (#31271)
In a few places throughout the app, when we render the `<GroupChooser
/>` component, we fetch the full groups list of the site from the
`/groups/search` endpoint. This is wasteful because the full groups list
is already included in the preloaded data that's sent to the client app
on the initial page load, so we can just use this preloaded list for
`<GroupChooser />` and we can avoid making an HTTP request.

Internal topic: t/147297.
2025-02-11 21:32:02 +03:00
David Taylor
6b6b31a97f
FEATURE: Allow admins to opt-in to seamless redirects on /auth/* (#31235)
By default, when multiple login providers are enabled, Discourse
requires user interaction before triggering an external auth flow. This
is defense-in-depth against "Login CSRF" attacks.

This commit introduces a setting to control this behavior, so that it
can be disabled when admins fully trust the downstream systems, and need
an interaction-free login flow on a site with multiple login providers.

Default behavior remains unchanged.
2025-02-07 11:43:39 +00:00
David Taylor
117027a40a
UX: Do not use generic username suggestions for invites (#31175)
6fd577d97d3923cec3d2458f45ebd2704703fd22 widened the scope of
`use_email_for_username_and_name_suggestions` (default false) to include
invites, which means that it fell back to a generic username like
`user1`.

This commit makes it bail out earlier in this situation, so that no
suggestion is attempted.
2025-02-07 10:52:41 +00:00
Osama Sayegh
284e708e67
FEATURE: Dark/light mode selector (#31086)
This commit makes the
[color-scheme-toggle](https://github.com/discourse/discourse-color-scheme-toggle)
theme component a core feature with improvements and bug fixes. The
theme component will be updated to become a no-op if the core feature is
enabled.

Noteworthy changes:

* the color mode selector has a new "Auto" option that makes the site
render in the same color mode as the user's system preference
* the splash screen respects the color mode selected by the user
* dark/light variants of category logos and background images are now
picked correctly based on the selected color mode
* a new `interface_color_selector` site setting to disable the selector
or choose its location between the sidebar footer or header

Internal topic: t/139465.

---------

Co-authored-by: Ella <ella.estigoy@gmail.com>
2025-02-07 03:28:34 +03:00
Krzysztof Kotlarek
5eb7d6d9c0
FEATURE: Gracefully handle unhandled reviewables (#31118)
Plugins like for example AI or Akismet create reviewable items. When the
plugin is disabled, then we cannot properly handle those items.

In that situation, we should display warnings about unhandled types.
Instruct admin to reenable plugins. In addition, we should allow the
admin to delete all pending reviews from disabled plugins.
2025-02-05 14:38:45 +11:00
OsamaSayegh
416ec83ae5
SECURITY: Limit /inline-onebox to 10 URLs at a time 2025-02-04 13:32:53 -03:00
Gary
d2de58e760
Don't allow loading tagged PMs in another user's inbox. 2025-02-04 13:32:46 -03:00
Penar Musaraj
b89cf9b443
SECURITY: Disable access to "activate-account" route for existing users 2025-02-04 13:32:38 -03:00
Alan Guo Xiang Tan
17e1bfe069
SECURITY: Preload data only when rendering application layout
This commit drops the `before_action :preload_json` callback in `ApplicationController` as it adds unnecessary complexity to `ApplicationController` as well as other controllers which has to skip this callback. The source of the complexity comes mainly from the following two conditionals in the `preload_json` method:

```
    # We don't preload JSON on xhr or JSON request
    return if request.xhr? || request.format.json?

    # if we are posting in makes no sense to preload
    return if request.method != "GET"
```

Basically, the conditionals solely exists for optimization purposes to ensure that we don't run the preloading code when the request is not a GET request and the response is not expected to be HTML. The key problem here is that the conditionals are trying to expect what the content type of the response will be and this has proven to be hard to get right. Instead, we can simplify this problem by running the preloading code in a more deterministic way which is to preload only when the `application` layout is being rendered and this is main change that this commit introduces.
2025-02-04 13:32:30 -03:00
Kelv
65324b6e5d
DEV: enable raise_error in test envs for deprecated icons in svg_sprite.rb (#30980)
This PR raises an error on any deprecated icon names being converted by
svg_sprite.rb, which will result in any deprecated icons being processed
by the ruby lib to fail tests.
2025-02-04 21:21:20 +08:00
Jean
ba1464a84e
FIX: Allow user directory searches to return more than 20 matching results (#31032)
This PR modifies the directory search logic so that searches by user
fields or name are no longer capped at 20 users
2025-01-29 11:02:42 -04:00
Penar Musaraj
dcac09ed32
DEV: Add proper error response when searching with an invalid page param (#31026)
Previously, for a search query with `page=11` or higher, we were quietly
returning the page 10 results. The frontend app isn't affected because
it sets its own limit to 10 pages, but still, this response from the
search endpoint does not make sense.

This change switches to returning a 400 error when the `page` parameter
is above the allowed limit (a max of 10).
2025-01-28 15:12:52 -05:00
Michael Brown
6bf5883fd7 FIX: always search email logs including the cc: addresses
It seems from the original commit notes that this was only included as a query
optimisation, but doing so leads to confusion: https://meta.discourse.org/t/348688

Searching for outbound mail to an address should find that address regardless
of whether or not the mail type to search for is explicitly `group_smtp`.
2025-01-27 21:57:24 -05:00
Krzysztof Kotlarek
cfcc60f847
FEATURE: new fast_typing_threshold site setting (#30865)
Rename `min_first_post_typing_time` to `fast_typing_threshold` and
provide admin 4 options:
- disabled
- low - 1 second
- standard - 3 seconds
- high - 5 seconds

Related PRs:
- https://github.com/discourse/discourse-zoom/pull/112
2025-01-28 09:53:03 +11:00