When secure uploads are enabled, we have to attach the images in the
digest so they can show up in the email.
However, we send attaching all the attachments, including "files" and
"media".
This ensures we only attach images when sending a digest.
Internal t/144542
The new site setting `allow_anonymous_and_tl0_to_flag_illegal` allows
tl0 users to flag illegal content. In addition, anonymous users are
instructed on how to flag illegal content by sending emails.
Also `email_address_to_report_illegal_content` setting is added. If not
provided, then the site contact email is used.
Followup 72c4709a5ab26f00e32b65d874b3a206d679181e
Previously we made a fix to allow skip validations when tagging
a topic via TopicCreator. However, this flow also skips a lot of
the more in-depth work on tags we do when creating a topic, like
processing tag synonyms. When approving reviewable queued posts,
we skip validations, so this would cause an issue where a topic
was approved and the tag synonyms weren't applied.
This commit changes the logic so we attempt the more complete
`DiscourseTagging.tag_topic_by_names` call first and if this fails
and skip validations is on, then we do
`DiscourseTagging.add_or_create_tags_by_name`.
This at least gives a chance for the full workflow to work first.
Related: https://github.com/discourse/discourse/pull/30535
In the PR above, the [content-disposition
header](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Disposition)
was removed for all non-svg files due to the "attachment" keyword added
to them, causing files to be downloaded instead of opening in a new tab
when requested. When removing that, it also removed the filename
attribute attached to s3 uploads.
After some testing, it turns out that `filename` is also respected when
next to `inline`, despite it not being obvious [in
docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Disposition#syntax).
This commit adds inline+filename so that users can still download files
and have filenames be respected instead of using the s3 hash.
```http
<!-- mdn docs -->
Content-Disposition: inline
Content-Disposition: attachment
Content-Disposition: attachment; filename="file name.jpg"
Content-Disposition: attachment; filename*=UTF-8''file%20name.jpg
<!-- this actually works too -->
Content-Disposition: inline; filename="file name.jpg"
```
The `key` provided in the S3 inventory file will esacpe any special
characters in the filename of the key so we need to unescape. Otherwise,
uploads with extensions that conatins special characters will fail to
match records which we insert into the temporary table based off the
s3 inventory file.
* Do not offer "categories with latest" option anymore, it does
not look good with our default Sidebar selection
* Display a sensible item in the dropdown if the admin has not
chosen hot, latest, or category_boxes as the homepage style,
before it was broken. Now we show Custom with a little blurb
about whether topics or categories are shown, and what the landing
page is
![image](https://github.com/user-attachments/assets/3e392583-d107-489e-9725-62d995a2d341)
Both heading_font and body_font should not allow
additional user-defined values, these are lists with
predefined choices. The UI already prevents this
because the font selector dropdown is unique, but
we want to make sure the setting definition reflects
this too.
This change allows controllers that construct TopicQuery parameters, to pass per_page into the TopicQuery constructor as an option. I can't see why this shouldn't be a public param, so long as we properly validate the value!
Internal discussion at t/145686.
This is a revert of 92793c5b73871ba84b024c2ce50055a0776f1ba6.
Following on from discussions after the previous commit, it became evident that it was only a small step towards solving the larger problem of finding site settings in a reliable fashion across multiple languages.
This is going to take more thought and discussion, and since the changes introduced in the previous commit are effectively non functional without additional work, I'm going to revert it for now.
`discourse-common` was created in the past to share logic between the
'wizard' app and the main 'discourse' app. Since then, the wizard has
been consolidated into the main app, so the separation of
`discourse-common` is no longer useful.
This commit moves `discourse-common/(lib|utils)/*` into
`discourse/lib/*`, adds shims for the imports, and updates existing
uses in core.
When we send an email notification to a user, we always include a link
that will allow them unsubscribe to these emails.
If the user reply to the email notification, the link to unsubscribe
might still be present in the final post (often in the elided part).
Since those links do not require authentication to unsubscribe a user
(this is a feature, not a bug), we would like to avoid showing them to
other users on Discourse.
(If such an email is forwarded elsewhere, then it's totally out of our
control.)
This commmit ensures we always strip those unsubscribe links from any
incoming email to avoid making it easier to unsubscribe another user.
Since the format we use for those links might be similar to the ones
used by other applications, the regular expression used to match those
links uses the absolute URL of the Discourse (aka.
`Discourse.base_url`).
This commit introduces a new rake task that can be used in situations where a community receives a large number of flags/reports and needs a quick way to handle all of those pending reports. Usage instructions are included in the rake task source code.
Internal topic: t/145475.
This removes some longstanding Safari iOS positioning hacks and refactors the mobile positioning strategy across Safari, Chrome and Firefox. See PR descriptions for more details.
Co-authored-by: Joffrey JAFFEUX <j.jaffeux@gmail.com>
Follow-up to 5a55c9062a
There are many scenarios that can result in creating a `ReviewableQueuedPost` record, however in the original commit we only added once scenario to the populate rake task. This commit adds the remaining scenarios to the rake task.
Previously we would enqueue sidekiq jobs like `PostProcessCooked` **before** triggering the `topic_created` and `post_created` DiscourseEvents. That means that, depending on the speed/availability of Sidekiq, PostProcessCooked might start running on another host before the DiscourseEvents have been executed.
This commit moves the event triggers before enqueue_jobs, so that ordering is guaranteed to be consistent, regardless of Sidekiq performance.
Following on from f369db5ae9a29a23299dff5f14768167230b0b79, we need to apply a similar fix to inline oneboxes, since they use a different code path to retrieve the onebox provider data.
This change ensures the Accept-Language header is sent by inline onebox requests, too.
Following on from f369db5ae9a29a23299dff5f14768167230b0b79, this change adds the ability to choose a custom locale to send to onebox providers.
If this setting is left blank, it will fall back to using default_locale.
Onebox embeds currently default to accepting any language response from the destination, which can have some surprising behaviour. For example the `curl` equivalent of what Onebox does:
```
% curl -si -H "Accept-Language: *" 'https://developer.android.com/studio' | grep location:
location: /studio?hl=hi
```
This PR uses the value of `SiteSetting.default_locale` to populate the `Accept-Language` header, falling back to English if that isn't available, then finally accepting whatever language the destination makes available.
The chat emoji picker is renamed emoji-picker, and the old emoji-picker is removed.
This commit doesn't attempt to fully rework a new emoji-picker but instead tries to migrate everything to one picker (the chat one) and add small changes.
Other notable changes:
- all the favorite emojis code has been mixed into one service which is able to store one state per context, favorites emojis will be stored for all topics, and for each chat channel. Meaning that if you always use a specific emoji in a channel, it will only show as favorite emoji in this channel.
- a lot of static code has been removed which should improve initial load perf of discourse. Initially this code was around to improve the performance of the emoji picker rendering.
- the emojis are now stored, once the full list has been loaded, if you close and reopen the picker it won't have to load them again.
List of components:
- `<EmojiPicker />` will render a button which will open a dropdown
- `<EmojiPickerContent />` represents the content of the dropdown alone, it's useful when you want to render a picker from an action which is not the default picker button
- `<EmojiPickerDetached />` just a simple wrapper over `<EmojiPickerContent />` to make it easier to use it with `this.menu.show(...)`
---------
Co-authored-by: Renato Atilio <renatoat@gmail.com>
This adds the Silence Reason column to silenced user lists.
This feature helps combat large spam attacks cause you can quickly see
why a user was silenced and then bulk act on all the silenced users
Nokogiri/libxml is now more strict in terms of params it receives.
It uses kwargs vs options object (I fixed an issue there in #30545) doesn't accept nil/blank html (fixed here) and most importantly handles encoding in a different way. It seems to require explicitly specifying UTF8.
* Build(deps): Bump nokogiri from 1.16.8 to 1.18.1
Bumps [nokogiri](https://github.com/sparklemotion/nokogiri) from 1.16.8 to 1.18.1.
- [Release notes](https://github.com/sparklemotion/nokogiri/releases)
- [Changelog](https://github.com/sparklemotion/nokogiri/blob/main/CHANGELOG.md)
- [Commits](https://github.com/sparklemotion/nokogiri/compare/v1.16.8...v1.18.1)
---
updated-dependencies:
- dependency-name: nokogiri
dependency-type: direct:production
update-type: version-update:semver-minor
...
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
* FIX: Wizard improvements post-merge part 1
Followup 3135f472e2c4221a9348aec27514d3e2947bc9ab
Fixes the following:
* On mobile, the Styling step was very narrow
* When clicking Next on the Styling step after previously
selecting Hot, we got an error
Also makes the following UX improvements for the preview:
* Use different topic titles for Latest and Hot
* Also make Hot view and reply numbers higher
This helps differentiate the two previews.
* DEV: Review fixes
Back then in 31e31ef, we added the Content-Disposition headers so that SVGs get downloaded instead of get run in the browser. Inadvertently, this also causes other attachments like pdfs and videos to be downloaded instead of heeding the "Open in new tab" option that users choose in the browser.
When the header is removed, the default value is "inline", this allows the browser to perform as requested. This also applies to other file types like pdfs, allowing users to "Open in new tab" and view them in the browser instead of always downloading them.
Existing tests (#10205) already do check that SVGs remain downloaded. Some existing tests written for PDFs have been modified to cater for SVGs instead, when there was a bug in defining the filenames per #10108
Experimental "What's new?" feature feed items previously calculated
a boolean for experimentEnabled on the client based on the siteSettings
service, and this would control the initial state of the experiment
toggle.
However this requires the person who creates the site setting for the
experiment to remember to set it to `client: true`. This commit removes
that manual step by calculating whether the experiment is enabled
server-side, where we have access to all the site settings.
Adds a new reviewables:populate rake task that works in a similar fashion to the existing *:populate rake tasks. The rake task creates pending reviewable of all core types, with possibility for plugins to extend the task to populate their own reviewable types.
Our bulk report endpoint uses `hijack`, which does not
use the current user's locale via the `with_resolved_locale`
method in `ApplicationController`. This is happening because
we are doing `around_action` to set the locale, then calling
the code in the block inside the action directly when we use
`hijack`.
We can fix this by capturing `I18n.locale` when starting the
hijack then using `I18n.with_locale` when evaluating the
block inside `hijack`, this way the translations will always
use the correct locale based on the current user.
This commit contains various quality improvements to
our site setup wizard, along with some rearrangement of
steps to improve the admin setup experience and encourage
admins to customize the site early to avoid "all sites look the
same" sentiment.
#### Step rearrangement
* “Your site is ready” from 3 → 4
* “Logos” from 4 → 5
* “Look and feel” from 5 → 3
#### Font selector improvements
Changes the wizard font selector dropdown to show
a preview of all fonts with a CSS class so you don't
have to choose the font to get a preview.
Also makes the fonts appear in alphabetical order.
#### Preview improvements
Placeholder text changed from lorem ipsum to actual topic titles,
category names, and post content. This makes it feel more "real".
Fixes "undefined" categories. Added a date to the topic timeline.
Fixes button rectangles and other UI elements not changing in
size when the font changed, leading to cut off text which looked super
messy. Also fixed some font color issues.
Fixed table header alignment for Latest topic list.
#### Homepage style selector improvements
Limited the big list of homepage styles to Latest, Hot, Categories with latest topics,
and Category boxes based on research into the most common options.
#### Preview header
Changed the preview header to move the hamburger to the left
and add a chat icon
#### And more!
Changed the background of the wizard to use our branded blob style.
When receiving emails sent with Exchange, we look for some markers to identify the body of the mail and the reply (aka. previous email).
For some reasons, those markers aren't 100% reliable and sometimes, only one of them is present.
The commit 20ba54d53630b57c25fa3f325b0f219581314936 introduced the bug because the `HTML_EXTRACTERS` regex for exchange looks for either `messageBodySection` or `messageReplySection` but we were only using the `reply` section. So if an email had only the `body` section, it would not be correctly extracted.
This commit handle the cases where either one of them is missing and use the other one as the actual "reply". When both are present, it correctly elides the "reply" section.
We were missing the "List-Unsubscribe-Post" header in emails we sent to allow Yahoo / GMail and others to automagically show a link to unsubscribe.
Internal ref - t/144713
The profile hiding feature is particularly problematic on sites that are
private (invite only or must approve users) so it is unconditionally disabled.
Also certain sites may prefer to disable the anti spam feature, they can
opt out using `hide_new_user_profiles`
Co-authored-by: Martin Brennan <martin@discourse.org>
This commit replaces the `full_name_required` setting with a new `full_name_requirement` setting to allow more flexibility with the name field in the signup form. The new setting has 2 options, "Required at signup" and "Optional at signup", which are equivalent to the true/false possibilities of the old setting, and a third option "Hidden at signup" that hides the name field from the signup form, making it effectively optional too.
New sites will have the "Hidden at signup" option as the default option, and existing site will continue to use the option that maps to their current configuration.
Internal topic: t/136746.
This commit adds the `add_request_rate_limiter` plugin API which allows plugins to add custom rate limiters on top of the default rate limiters which requests by a user's id or the request's IP address.
Example to add a rate limiter that rate limits all requests from Googlebot under the same rate limit bucket:
```
add_request_rate_limiter(
identifier: :country,
key: ->(request) { "country/#{DiscourseIpInfo.get(request.ip)[:country]}" },
activate_when: ->(request) { DiscourseIpInfo.get(request.ip)[:country].present? },
)
```
This PR involves cleaning up the codebase from my (@keegangeorge's) todos.
In particular:
- Remove Form Template related todos (these are no longer in the roadmap)
- Remove old left-over AI summarization related code after moving to AI (https://github.com/discourse/discourse-ai/pull/658)
- Update one form template related spec
* Split `shutdown` into two separate methods for better control:
- `shutdown` - signals threads to stop accepting new work
- `wait_for_termination` - waits for threads to finish (with optional timeout)
* Add tracking of busy threads via `@busy_threads` Set
* Make idle_time parameter optional with 30-second default
* Improve thread spawning logic:
- Spawn initial thread immediately when work is posted
- Spawn additional threads when all threads are busy and work is queued
* Fix race condition in work distribution
* Add busy thread count to stats output
* Add test coverage for zero min_threads configuration
This commit makes the ThreadPool more reliable, easier to use, and adds
better visibility into its internal state.
---------
Co-authored-by: Alan Guo Xiang Tan <gxtan1990@gmail.com>
This commit introduces a new ThreadPool class that provides efficient worker
thread management for background tasks. Key features include:
- Dynamic scaling from min to max threads based on workload
- Proper database connection management in multisite setup
- Graceful shutdown with task completion
- Robust error handling and logging
- FIFO task processing with a managed queue
- Configurable idle timeout for worker threads
The implementation is thoroughly tested, including stress tests, error
scenarios, and multisite compatibility.
There’s currently a bug when using a dedicated class as a policy in
services: if that class delegates its `#call` method (to an underlying
strategy object for example), then an error will be raised saying steps
aren’t allowed to provide default parameters.
This should not happen, and this patch fixes that issue.
This commit reimplements how we monitor Sidekiq processes that are
forked from the Unicorn master process. Prior to this change, we rely on
`Jobs::Heartbeat` to enqueue a `Jobs::RunHeartbeat` job every 3 minutes.
The `Jobs::RunHeartbeat` job then sets a Redis key with a timestamp. In
the Unicorn master process, we then fetch the timestamp that has been set
by the job from Redis every 30 minutes. If the timestamp has not been
updated for more than 30 minutes, we restart the Sidekiq process. The
fundamental flaw with this approach is that it fails to consider
deployments with multiple hosts and multiple Sidekiq processes. A
sidekiq process on a host may be in a bad state but the heartbeat check
will not restart the process because the `Jobs::RunHeartbeat` job is
still being executed by the working Sidekiq processes on other hosts.
In order to properly ensure that stuck Sidekiq processs are restarted,
we now rely on the [Sidekiq::ProcessSet](https://github.com/sidekiq/sidekiq/wiki/API#processes)
API that is supported by Sidekiq. The API provides us with "near real-time (updated every 5 sec)
info about the current set of Sidekiq processes running". The API
provides useful information like the hostname, pid and also when Sidekiq
last did its own heartbeat check. With that information, we can easily
determine if a Sidekiq process needs to be restarted from the Unicorn
master process.
`new_in_category` was using `first` instead of `limit`
This meant it gets an array and that means that you can not operate on it easily in a modifier.
This ensures we always give the modifier a relation, with the notable exception of suggested topics.
Previously, theme hbr files were compiled to an IIFE, which would be executed before the app is booted. That is causing silenced deprecations to be printed, because the deprecation-workflow isn't set up when the IIFE is run.
This commit updates the theme compiler so that it matches the ember-cli-based raw-hbs compiler. Templates are output to normal modules, which will then be loaded by the existing `eager-load-raw-templates` initializer. This runs after the app has started booting.