Commit Graph

2430 Commits

Author SHA1 Message Date
c8ccd4da31 DEV: Move setting deprecation check to SiteSetting::Update service (#31993)
This PR moves the logic that checks if a site setting we're trying to update has been deprecated from one of the controllers into a policy of the SiteSetting::Update service.

It also gives us the opportunity to shift the error message into a locale file.
2025-03-26 15:56:18 +08:00
d06c60ca7c FEATURE: add icons and emojis to category (#31795)
This feature allow admins to personalize their communities by
associating emojis or icons with their site categories.

There are now 3 style types for categories:
- Square (the default)
- Emoji
- Icon

### How it looks 🎨 

Adding an icon:

<img width="502" alt="Category with an icon"
src="https://github.com/user-attachments/assets/8f711340-166e-4781-a7b7-7267469dbabd"
/>

Adding an emoji:

<img width="651" alt="Category with an emoji"
src="https://github.com/user-attachments/assets/588c38ce-c719-4ed5-83f9-f1e1cb52c929"
/>

Sidebar:

<img width="248" alt="Sidebar with emojis"
src="https://github.com/user-attachments/assets/cd03d591-6170-4515-998c-0cec20118568"
/>

Category menus:

<img width="621" alt="Screenshot 2025-03-13 at 10 32 30 AM"
src="https://github.com/user-attachments/assets/7d89797a-f69f-45e5-bf64-a92d4cff8753"
/>

Within posts/topics:

<img width="382" alt="Screenshot 2025-03-13 at 10 33 41 AM"
src="https://github.com/user-attachments/assets/b7b1a951-44c6-4a4f-82ad-8ee31ddd6061"
/>

Chat messages:

<img width="392" alt="Screenshot 2025-03-13 at 10 30 20 AM"
src="https://github.com/user-attachments/assets/126f8076-0ea3-4f19-8452-1041fd2af29f"
/>

Autocomplete:

<img width="390" alt="Screenshot 2025-03-13 at 10 29 53 AM"
src="https://github.com/user-attachments/assets/cad75669-225f-4b8e-a7b5-ae5aa8f1bcad"
/>

---------

Co-authored-by: Martin Brennan <martin@discourse.org>
Co-authored-by: Joffrey JAFFEUX <j.jaffeux@gmail.com>
2025-03-26 09:46:17 +04:00
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
109fc428d8 DEV: Clear extra-locales cache between tests (#31488) 2025-02-24 22:10:43 +00:00
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
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
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
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
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
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
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
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
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
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
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
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
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
416ec83ae5 SECURITY: Limit /inline-onebox to 10 URLs at a time 2025-02-04 13:32:53 -03:00
d2de58e760 Don't allow loading tagged PMs in another user's inbox. 2025-02-04 13:32:46 -03:00
b89cf9b443 SECURITY: Disable access to "activate-account" route for existing users 2025-02-04 13:32:38 -03:00
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
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
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
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