Instead of having to clean an array in a contract using a
`before_validation` block, for example, we can now pass `compact_blank:
true` to the attribute, like this:
```ruby
attribute :ids, :array, compact_blank: true
```
1. Update `register_preloaded_category_custom_fields` API to be
reload-safe
2. Update post-voting to use this in all cases, and remove the
`respond_to?` checks since this plugin is now bundled with core
If, for some reasons, you were to try to "unsuspend" a moderator, you
wouldn't be able to because the "can_suspend" was checking for
"user.regular?".
Added a "can_unsuspend?" to support this use-case.
Ref - https://meta.discourse.org/t/-/385786
When Chrome isn't installed, running "bin/rails qunit:test" would fail
because it wouldn't be able to detect that Chromium was installed.
This fixed that and also pass the detected browser to testem
Our current implementation of lightbox uses Magnific Popup, which is now
deprecated and will only receive critical/security bug fixes. Magnific
also relies on jQuery, which we would like to remove where possible
throughout our codebase.
After looking at various options, the general consensus was that
PhotoSwipe was a close match to what we need.
Regular image types that are supported with our current lightbox (jpg,
png etc) will work with their existing cooked markup (no need to rebake
posts). This PR also adds support for SVG images and markup from various
theme components (ie. Discourse Mermaid).
---------
Co-authored-by: Martin Brennan <martin@discourse.org>
This task was failing to load rspec-core because `lib/tasks` are loaded
in full in prod environments and this was meant to be run only in
dev/test environments (the task it is overwriting is defined in a gem
that's only loaded in those environments).
If we add more tasks like this, we can create a new subfolder in `tasks`
to segregate such tasks in a clearer manner.
This creates an overriding `rswag:specs:swaggerize` rake task that also
adds plugin paths, and updates spec helpers to handle plugin paths.
Also adds the spec files for the discourse-calendar events index
endpoint.
### Testing
Running `rake rswag:specs:swaggerize` now generates the same
`openapi/openapi.yaml` file, with `/discourse-post-event/events.ics` and
`/discourse-post-event/events.json` GET documentation.
When a user is auto-silenced because they receive enough spam flag, we notify moderators (given the notify_mods_when_user_silenced is enabled).
However, when a user is auto-silenced for other reasons, e.g. typing too fast, we don't send this notification.
This commit:
- Lifts the notification logic into a new UserSilencer#auto_silence method, which delegates 99% of its work to UserSilencer#silence.
- Uses this new method in places where users are auto-silenced.
Faraday [updated their authentication/authorization middleware in version 2](https://github.com/lostisland/faraday/pull/1306), which was a breaking change for the Twitter auth health check.
The relevant test was manually mocking and stubbing the individual Faraday objects, so the relevant code path wasn't exercised by our tests.
This commit:
- Updates the test to use `stub_request` instead. (This correctly catches
the deprecated method error.)
- Updates the health check to use the new middleware.
Chat::MessageProcessor includes CookedProcessorMixin but only sets
@model, leaving @post as nil. The process_hotlinked_image method was
attempting to access @post.post_hotlinked_media, causing undefined
method errors when processing chat messages with images.
The "watching first post" notification level is not a topic notification
level but a category/tag notification level.
This fixes both the "topics_filter.rb" and "topic_query.rb" to account
for this and allow the filter to work.
Ref - meta/t/385316
When `enable_staged_users` is disabled and a category has
`email_in_allow_strangers` enabled, fallback to using the system user
instead of raising UserNotFoundError. This allows email-in functionality
to work in categories that explicitly allow anonymous email submissions
even when staged users are globally disabled.
This splits the Login and Authentication admin page into multiple
sections: Settings, social logins, DiscourseConnect, OAuth2.0, OIDC.
Internal ticket `t/161648`
This PR also adds a new extension point for plugins that want to extend
this area of the app.
```
register_site_setting_area("oauth2")
register_admin_config_login_route("oauth2")
```
Adding this to a plugin allows it to extend both the setting areas
(existing functionality) and add a tab to this admin settings screen via
`register_admin_config_login_route`.
Adds `locale` as a new filter on /filter for topics.
- locale:en -- single locale filtering
- locale:ja,es -- comma-separated OR logic
- locale:ja locale:es -- space-separated OR logic
- -locale:en -- exclusion of single locale
- -locale:en,ja -- exclusion of multiple locales
- locale:en status:closed -- combination with other filters
Description
When trying to fix migration issues for wrongly ordered posts by running
rake posts:reorder_posts, you may encounter errors like:
```
PG::UniqueViolation: ERROR: duplicate key value violates unique constraint "post_timings_unique"
```
This happens if there are PostTiming records without a corresponding
Post. Currently, the code does not handle these records, and when
updating records to the new order, some values may collide, causing the
error.
This patch introduces a new step to the Ruby Service Framework.
`only_if` will execute its block (other steps) only if the provided
condition evaluates to `true`. As for the other steps, the name provided
is the name of the method that will be executed.
```ruby
only_if(:can_update) do
model :user
step :update_user
step :notify
end
private
def can_update(guardian:)
…
end
```
This step cannot fail and the whole block will be skipped if the method
evaluates to a falsy value.
This is rendered by the steps inspector:
```
[ 1/13] [options] default ✅
[ 2/13] [model] model ✅
[ 3/13] [policy] policy ✅
[ 4/13] [params] default ✅
[ 5/13] [lock] parameter:other_param ✅
[ 6/13] [transaction]
[ 7/13] [step] in_transaction_step_1 ✅
[ 8/13] [step] in_transaction_step_2 ✅
[ 9/13] [try]
[10/13] [step] might_raise ✅
[11/13] [only_if] condition ⏭️ (condition was not met)
[12/13] [step] optional_step
[13/13] [step] final_step ✅
```
The inspector also renders text with colors now.
<img width="419" height="336" alt="Copie d'écran_20251008_162920"
src="https://github.com/user-attachments/assets/add4fd16-076e-4f30-ae1a-3e933494967e"
/>
This change ensures that oneboxes, lightboxes are correctly generated
for localized posts.
The `PostLocalizer` was using `PrettyText.cook` directly, which does not
perform all the necessary post-processing steps, such as onebox
generation.
This commit introduces a new `LocalizedCookedPostProcessor` class that
is responsible for post-processing the cooked HTML of translated posts.
This new class reuses the `CookedProcessorMixin` to gain access to the
`post_process_oneboxes` method. The `PostLocalizer` is updated to use
this new processor, ensuring that oneboxes are correctly generated in
the translated content.
---------
Co-authored-by: Nat <natalie.tay@discourse.org>
A new webpack entrypoint is created for media-optimization, so that
webpack can take care of bundling up the dependencies. The main Worker
is still hosted in `public/javascripts`, since Workers must be
same-origin.
The `discourse_owned?` method in `lib/plugin/instance.rb` was calling
`.split` on `parsed_commit_url.path` without checking if the path could
be nil. This caused a 500 error on `/admin/plugins` when any plugin had
a commit URL that parsed successfully but returned a nil path (e.g.,
plugins without a git remote configured).
Added a nil check for `parsed_commit_url.path` to gracefully handle this
edge case and prevent the crash. Also added a test case to verify the
method returns false when the parsed URL has a nil path.
This commit splits the `moderators_manage_categories_and_groups` setting
into 2 separate settings to allow for more precise control over
categories and groups management by moderators.
Internal topic: t/141392.
c.f. https://github.com/discourse/discourse/pull/34945
This commit updates `PostRevisor` to bump a topic if the
edited post is a wiki post and it is also the first post in
the topic (OP).
In this case, people want to know about a
change to the OP, because it may need to be reviewed (in the case of a
wiki) or it should be “promoted” so that others can see what’s changed
(in the case of general documentation).
A related change in this commit is to add a `should_bump_topic`
plugin modifier, so plugins like Discourse Doc Categories
(see https://meta.discourse.org/t/discourse-doc-categories/322376)
can enforce bumping in certain cases.
We can't enable `Rails/WhereNot` lint/autofix, because it would break
code that uses mini_sql instead of AR (which rubocop, and tbh also we,
can't easily differentiate)
Those are safe because they either:
* are executed in AR model scope definitions
* are clearly chained starting from a AR model
* are less-clearly chained, but still can be traced to a AR model/scope
---------
Co-authored-by: Loïc Guitaut <loic@discourse.org>
This commit adds a new setting `moderators_change_trust_levels` to
control whether moderators are allowed to change trust level of users.
Moderators are currently allowed to change trust levels, so this new
setting is enabled by default to avoid sudden changes in behavior for
existing sites.
When the setting is disabled and moderators are not allowed to change
trust levels, they see the trust levels dropdown disabled.
Internal topic: t/141392.
---------
Co-authored-by: Alan Guo Xiang Tan <gxtan1990@gmail.com>
**Description**
Add an option to ignore orphaned posts since these can cause errors when
running the task like:
```
ERROR:
duplicate key value violates unique
PG:: UniqueViolation:
DETAIL: Key (topic_i, post_number, user_id)=(212064, 1, 33887) already exists.
```
This PR uses MessagePack instead of JSON for serializing our cookies.
MessagePack is almost as fast as Marshal but without the security
issues. It’s also able to serialize more objects than JSON (like Time,
Symbol, etc.). As it’s a binary format, it takes less space than JSON,
sometimes half less. Finally, MessagePack isn’t Ruby-specific and
implementations exist in every existing language.
Regarding the cookies Discourse is using, we can see a small improvement
on the `_forum_session` one when it’s almost empty (around 2%), but the
more things are put into it, the more we’ll see savings. For the `_t`
cookie, we’re saving around 20% for free.
Followup 2a65bf4522
With the above change, we inadvertently made it so that
when you edited the topic title or category, we bumped
the topic.
This fix makes it so we do not bump topics when only title, category,
or tags are changed, to restore the previous behaviour.
In addition, we are making it so the following settings no longer
influence topic bump behaviour, keeping only their intended notification
behaviour around. The site setting description never mentioned anything
about topic bumps:
* disable_category_edit_notifications
* disable_tag_edit_notifications
Reverts discourse/discourse#34639
We understood the main culprit for cookie overflows was storing
`destination_url` in the session, so we don’t really need that debug
code anymore.
Before this change, impersonating a user would result in that user's
`last_seen_at` being updated. This PR fixes that for the new
impersonation feature gated behind the `experimental_impersonation` site
setting.
The old impersonation feature that logs in as the impersonated user has
a completely separate code path. If we decide to backport this change it
will be in a separate PR.
This moves the logic for creating the convert_video job to the upload
after_create hook so that we ensure there is an upload_id. When this
logic
was in the s3 store and direct to s3 uploads was enabled the convert
video job
would never fire because we didn't have an upload_id.
1. Use relative paths instead of absolute. This will make the commands
portable to other machines, and matches the out-the-box behavior of the
regular rspec command
2. Strip out some 'infrastructure' ENV and params from the
rerun_command, so that it's easier to copy/paste and run locally