Currently, after creating an API key, there is no way in the UI to see what scope the key has. To do this we need to first store the selected scope mode when creating a new key.
In this PR we:
- Convert scope_mode from a transient attribute to a database backed enum.
- Ship the possible values through the javascript:update_constants rake task instead of hard coding in front-end.
In follow-up PRs we will:
- Backfill existing API keys based on their associated api_key_scopes records.
- Start showing the scope mode in the UI.
When a post is flagged due to matching watched words, it can be difficult to know what you're looking for, particularly if you have a lot of watched words built up over a long period of time.
This change stores the list of matched words, and later displays them in the review queue, listing which Watched Words were responsible for the flag. Because watched words can change, this is recorded at the time the post is flagged. For posts that were flagged prior to this feature landing, it tries to guess the relevant words based on the current Watched Words set.
Redesigned page to update site logos. `AdminBrandingLogoFormComponent`
is attached to the old logos page and the new branding page. In the next
steps, branding will replace the logos page.
A new `AdminConfigAreaCardSection` component was added hidden and less
frequently used settings.
An image placeholder was also needed because many additional logos have
a fallback to the site logo.
Finally, `twitter_summary_large_image` was renamed to
`x_summary_large_image`.
Desktop

Mobile

As we’re currently using a namespace for Sidekiq, in order to upgrade to
the latest version, we need to drop it as it’s not supported anymore.
The recommended way is to use a different Redis DB for Sidekiq.
This patch uses a different config for Sidekiq and also takes care of
migrating existing jobs (in queues and the retry and scheduled sets).
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>
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"
/>
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.
Followup e26a1175d7c33746bddbc858ad89e68cc14beefe
Adds extra functionality and tests for the admin search modal.
* Show third level plugin config pages in search, e.g. AI Usage
* Remember last used search filters
* Allow navigating search results with keyboard, using tab or up/down
and enter to go to result
* Add a placeholder beneath search input to tell the admin what to do
* Add a full page search at `/admin/search` which can be reached from
pressing Enter on the search input
* Add specs for modal and full page search
* Change admin sidebar filter "no results found" to point to full page
search
* Add keyboard shortcut help to modal for admin search
We have a native dependency, Rinku, that's used only to make links in one place. We can get rid of this and use PrettyText instead.
This is almost a one-for-one replacement, but PrettyText adds rel="noopener nofollow ugc" to external links, which I suspect is actually what we want. It also wraps the result in a <p> tag, which we strip out for parity with Rinku.
When secure uploads are enabled, we need to send images that are rendered in the digest e-mail as attachments. Before this change, we would indiscriminately attach all images in the relevant topic's first post, whether they were rendered the e-mail body or not.
This change fixes that by only attaching images that are referenced in the e-mail body.
As part of the theme/color palette overhaul project, we're redesigning
the UI for the editing color palettes. This commit introduces a new
`ColorPaletteEditor` component that encapsulates all the logic and
interface for editing color palettes in the redesigned admin interface.
This component isn't used anywhere at this moment, but it will be once
we start introducing the rest of the redesigned interface.
`PrettyText.cook` does two things: 1️⃣ convert raw to cooked, 2️⃣
partial sanitisation.
This commit splits the 2️⃣ up so that it can be applied to other cooked
content.
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.
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.
This change allows you to add a reaction to the most recent message, by sending a reaction message.
A reaction message can be formatted as `+{emoji}` (eg, `+❤️`), or as `+{emoji_code}` (eg, `+❤️`).
This feature allows admins to find what they are
looking for in the admin interface via a search modal.
This replaces the admin sidebar filter
as the focus of the Ctrl+/ command, but the sidebar
filter can also still be used. Perhaps at some point
we may remove it or change the shortcut.
The search modal presents the following data for filtering:
* A list of all admin pages, the same as the sidebar,
except also showing "third level" pages like
"Email > Skipped"
* All site settings
* Themes
* Components
* Reports
Admins can also filter which types of items are shown in the modal,
for example hiding Settings if they know they are looking for a Page.
In this PR, I also have the following fixes:
* Site setting filters now clear when moving between
filtered site setting pages, previously it was super
sticky from Ember
* Many translations were moved around, instead of being
in various namespaces for the sidebar links and the admin
page titles and descriptions, now everything is under
`admin.config` namespace, this makes it way easier to reuse
this text for pages, search, and sidebar, and if you change it
in one place then it is changed everywhere.
---------
Co-authored-by: Ella <ella.estigoy@gmail.com>
Followup to 087e8e4bdb53f71930ec5c930c463c37dd2bd58d
- Fixes the variable-prefixer so it doesn't explode when the input is
unparseable
- Add URL polyfills so that postcss can print its errors properly
- Catch postcss errors in the same way as sass errors
This is a follow up to a9eefd1b4849573452581c113cfcbdd4420fb3c2.
### Reviewer notes
This rake task is quite annoying to test so I don't think the time
trying to figure out how to test it is worth it. This does not sit in a
critical path anyway so I think the lack of tests here is OK.
This change adds a new `type_source` field to the `Reviewable` model, indicating whether the Reviewable type was registered by `core`, a plugin, or an `unknown` source.
When a plugin that registered a Reviewable type is disabled, this allows us to tell the user which plugin they need to re-enable to handle any orphan reviewable items.
This commit improves a few aspects regarding group name validation:
- `min_username_length` and `max_username_length` are validated with the
shortest and longest names of users and groups
- skip validation of the group name when the group is an automatic one
Both article images and section extraction were
not working for wikipedia oneboxes, this commit
fixes both and updates our spec fixture responses
to use the new HTML
Our language parser now incorrectly matches underscored locales:
```
[1] pry(main)> HttpLanguageParser.parse("zh-CN")
=> "zh_CN"
[2] pry(main)> HttpLanguageParser.parse("zh_CN")
=> "en_GB"
```
This commit makes sure the input can be agnostic of `-` or `_`
This makes the backtrace for a deprecated icon name error clearer in
terms of pointing out which plugin the icon is being registered from.
The error will only be raised in the test environment.
This PR also extracts out to a separate module the hashmaps & logic for
converting FA4 era icons to discourse FA6 compatible icons. This
isolates that logic for reuse in DiscoursePluginRegistry - otherwise
pulling in the whole SvgSprite resulted in errors.
This was intended to provide a better UX for interactive elements in the
composer preview. However, the morphing strategy has irreconcilable
conflicts with our `decorateCooked` API, and so we have been unable to
enable this by default.
Going forward, we're focussing efforts on the WYSIWYG composer to
provide this kind of smooth UX, so we're dropping the
`enable_diffhtml_preview` approach.
A previous refactor of the `Service::Base::Step` class introduced a
non thread-safe behavior. `#call` mutates instance variables at runtime,
and since a step instance is the same for any given service class, this
can sometimes lead to `context` being the wrong one for the running
service.
This patch makes use of `Concurrent::ThreadLocalVar` to fix the issue.
While it is possible derive a topic published event from category id
changes in a `post_edited` or `before_post_publish_changes` event, there
are use cases when a dedicated event is more apposite.
This repo was archived in March 2024 and is no longer supported.
Commit also fixes up the plugin-gem-symlinking logic to support removing
plugins from the list
[Security
patch](5558e72f22)
(for this [CVE](https://nvd.nist.gov/vuln/detail/CVE-2024-54133)) from
rails actionpack was backported from [Rails
8.0.0.1](https://github.com/rails/rails/blob/v8.0.1/actionpack/CHANGELOG.md#rails-8001-december-10-2024)
to previous stable versions including `7-1-stable` / `7-2-stable`.
Any previous version of Discourse upgrading to v3.4.0.beta3 and above
would have observed their sites crashing if they had invalid sources in
their CSP directive extensions.
This fix removes such invalid sources during our build of the CSP, and
logs these at a warning level so devs are able to find out why their CSP
sources were filtered out of the extendable directives.
This commit contains a couple of improvements for this
rake task.
* We no longer limit the uploads to only ones with Post
upload references, it doesn't matter what the secure uploads
are linked to, they should all be un-secured
* We now only get distinct uploads from the initial query,
multiple upload references on the same upload caused
double ups and confusing counts for the task
* We now also disable the secure_uploads_pm_only site
setting at the same time
This fixes an issue where the topic invitation rate limiter
for invites for the 1 minute period was incorrectly using
1 day as the length of time the limit should be applied over.
The default for `max_topic_invitations_per_minute` is 5,
so this would be very easy to exceed, then the user gets
a very confusing warning message saying they have to wait
23 hours to send more invites.
This commit also makes other `RateLimiter` period parameters
more consistent by always using the form `N.PERIOD` instead
of things like `86_400` hardcoded seconds per day.
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.
When `suppress_secured_categories_from_admin` SiteSetting is enabled, it
is expected that the admin will not be notified about PMs in which they
are not participating - even when they watch the attributed tag.
Before it was only checking if the admin had access to a secured
category assigned to a regular topic. PMs do not have categories so we
need to ensure that admin in participating in that conversation.
Followup 503f9b6f02ac5c4918d41611848c886b8755e5a0
This previous commit introduced an autogenerated
settings route for every plugin with more than one
setting defined. Plugins with only one setting
only have enabled_site_settings defined, which are
handled using the toggle in the admin plugin list,
so we don't need a dedicated setting page for them.
However in production this introduced a performance
issue, since we were looking through SiteSetting.all_settings
for every plugin, which could be quite slow in some
cases especially on our hosting.
Instead, we already have all the plugin settings cached
inside `SiteSetting.plugins`. We can instead use this to
count how many settings the plugin has, then if there is > 1
for a plugin we use the settings route. This is a much faster lookup
than
searching through SiteSetting.all_settings.