This change is mainly a refactor of the desktop notifications service to improve readability and have standardised values for tracking state for current user in regards to the Notification API and Push API.
Also improves readability when handling push notification jobs, especially in scenarios where the push_notification_time_window_mins site setting is set to 0, which will allow sending push notifications instantly.
To achieve this, a new notifications service is set up with an `isInDoNotDisturb` tracked property. While a user is in do-not-disturb mode, it runs a regular timer until do-not-disturb is over.
We were writing theme-transpiler JS files to the filesystem on a per-process basis, and then immediately reading them back in. Plus, there was no cleanup mechanism, so the tmp directory would grow indefinitely.
This commit refactors things so that the `build.js` script outputs the theme-transpiler source to stdout. That way, we can read it directly into the process, and then into mini-racer, without needing to go via the filesystem. No cleanup required!
In production, the theme-transpiler is still cached in a file during `assets:precompile`
In the formkit conversion in 2ca06ba236
we missed setting a type for the UppyImageUploader for badges. Also,
we were not passing down the `image_url` as form data, so when we used
`data.image` for that field the badge was not updating in the UI after
page loads and the image URL was not loading for preview.
Co-authored-by: Joffrey JAFFEUX <j.jaffeux@gmail.com>
This commit introduces the `behaviorTransformer` API to safely override behaviors defined in Discourse.
Two new plugin APIs are introduced:
- `addBehaviorTransformerName` which allows plugins and theme-components to add a new valid transformer name if they want to provide overridable behaviors;
- `registerBehaviorTransformer` to register a transformer to override behaviors.
It also introduces the function `applyBehaviorTransformer` which can be imported from `discourse/lib/transformer`. This is used to mark a callback containing the desired behavior as overridable and applies the transformer logic.
How does it work?
## Marking a behavior as overridable:
To mark a behavior as overridable, in Discourse core, first the transformer name must be added to `app/assets/javascripts/discourse/app/lib/transformer/registry.js`. For plugins and theme-components, use the plugin API `addBehaviorTransformerName` instead.
Then, in your component or class, use the function `applyBehaviorTransformer` to mark the Behavior as overridable and handle the logic:
- example:
```js
...
@action
loadMore() {
applyBehaviorTransformer(
"discovery-topic-list-load-more",
() => {
this.documentTitle.updateContextCount(0);
return this.model
.loadMore()
.then(({ moreTopicsUrl, newTopics } = {}) => {
if (
newTopics &&
newTopics.length &&
this.bulkSelectHelper?.bulkSelectEnabled
) {
this.bulkSelectHelper.addTopics(newTopics);
}
if (moreTopicsUrl && $(window).height() >= $(document).height()) {
this.send("loadMore");
}
});
},
{ model: this.model }
);
},
...
```
## Overriding a behavior in plugins or themes
To override a behavior in plugins, themes, or TCs use the plugin API `registerBehaviorTransformer`:
- Example:
```js
withPluginApi("1.35.0", (api) => {
api.registerBehaviorTransformer("example-transformer", ({ context, next }) => {
console.log('we can introduce new behavior here instead', context);
next(); // call next to execute the expected behavior
});
});
```
Ember's legacy mixin system does not support native-class syntax, so we have to use the non-decorator syntaxes for `action()` and `computed()`.
Eventually, we will need to refactor things to remove these mixins... but today is not that day.
When creating a shared draft, we're recording topic view stats on the draft and then pass those on when the draft is published, conflating the actual view count.
This fixes that by not registering topic views if the topic is a shared draft.
When `SiteSetting.review_every_post` is true and the category `require_topic_approval` system creates two reviewable items.
1. Firstly, because the category needs approval, the `ReviewableQueuePost` record` is created - at this stage, no topic is created.
2. Admin is approving the review. The topic and first post are created.
3. Because `review_every_post` is true `queue_for_review_if_possible` callback is evaluated and `ReviewablePost` is created.
4. Then `ReviewableQueuePost` is linked to the newly generated topic and post.
At the beginning, we were thinking about hooking to those guards:
```
def self.queue_for_review_if_possible(post, created_or_edited_by)
return unless SiteSetting.review_every_post
return if post.post_type != Post.types[:regular] || post.topic.private_message?
return if Reviewable.pending.where(target: post).exists?
...
```
And add something like
```
return if Reviewable.approved.where(target: post).exists?
```
However, because the callback happens in point 3. before the `ReviewableQueuePost` is linked to the `Topic`, it was not possible.
Therefore, when `ReviewableQueuePost` is creating a `Topic`, a new option called `:reviewed_queued_post` is passed to `PostCreator` to avoid creating a second `Reviewable`.
Currently, descriptions for flag types aren’t interpolated, returning
`%{base_path}` in their string, for example. This breaks the navigation
on the sites.
The behavior changed probably because of an upgrade of Ruby, as two
hashes were passed to `I18n.t` (`vars` and `default`) without using the
splat operator.
Similar to https://github.com/discourse/discourse/pull/28061, merging topics with many posts can exceed the 30 seconds timeout that Unicorn workers are limited to, so we should move the operation into a background thread to get around this limit.
Internal topic: t/133710.
* SECURITY: Update default allowed iframes list
Change the default iframe url list to all include 3 slashes.
* SECURITY: limit group tag's name length
Limit the size of a group tag's name to 100 characters.
Internal ref - t/130059
* SECURITY: Improve sanitization of SVGs in Onebox
---------
Co-authored-by: Blake Erickson <o.blakeerickson@gmail.com>
Co-authored-by: Régis Hanol <regis@hanol.fr>
Co-authored-by: David Taylor <david@taylorhq.com>
Followup 4aea12fdcb
In certain config areas (like About) we want to be able
to fetch specific site settings by name. In this case,
sometimes we need to be able to fetch hidden settings,
in cases where a config area is still experimental.
Splitting out a different endpoint for this purpose
allows us to be stricter with what we return for config
areas without affecting the main site settings UI, revealing
hidden settings before they are ready.
`addCommunitySectionLink` API function accepts secondary argument to determine if the link should be added to the primary or secondary (more) section. There was a bug and all links were mounted in the secondary section.
We have a dedicated admin page (`/admin/customize/email_templates`) that lets admins customize all emails that Discourse sends to users. The way this page works is that it lists all translations strings that are used for emails, and the list of translation strings is currently hardcoded and hasn't been updated in years. We've had a number of new emails that Discourse sends, so we should add those templates to the list to let admins easily customize those templates.
Meta topic: https://meta.discourse.org/t/3-2-x-still-ignores-some-custom-email-templates/308203.
In this case, there is no 'nearPost' param in the URL. Instead, the server preloads a post-stream with whichever page of posts is requested. We can check for that situation using `postStream.firstPostPresent`.
Also updates the widget-header version to fetch a value from the service on initial render, instead of relying on the observer triggering.
Followup to bdec564d14
Currently, if MF definitions are missing (typically because there’s a
compilation error), `I18n.messageFormat` will try to access
`I18n._mfMessages.hasMessage` resulting in a crash that will in turn
crash Ember.
This patch addresses the issue by using the optional chaining operator
making the `I18n.messageFormat` method return a "Missing Key" message.
MF strings won’t be rendered properly, but the site will stay usable.
* FIX: Ensure JsLocaleHelper to obly outputs up-to-date translations
The old implementation forgot to filter out deprecated
translations, causing these translations to incorrectly override the new
locale in the frontend.
This commit fills in the forgotten where clause, filtering only the
up-to-date part.
Related meta topic: https://meta.discourse.org/t/outdated-translation-replacement-causing-missing-translation/314352
By default, the swc minifier seems to unwrap 'unneeded' IIFE. That means it was undoing the 'bugfix' transformation we have for class fields in Safari 15. Disabling the 'inline' and 'reduce_funcs' options seems to stop this behavior.
Currently, when adding translation overrides, values aren’t validated
for MF strings. This results in being able to add invalid plural keys or
even strings containing invalid syntax.
This patch addresses this issue by compiling the string when saving an
override if the key is detected as an MF one.
If there’s an error from the compiler, it’s added to the model errors,
which in turn is displayed to the user in the admin UI, helping them to
understand what went wrong.
When we show user tips, we immediately send an AJAX request to mark the
tiup as seen. This is done in the background. However, when system tests
are run, sometimes that request is not completed before the test ends.
This causes the test to be flakey.
One way to fix this is to force the system test run to wait for the AJAX
request to complete. However, this is not ideal because it makes the
test suite slower on each run.
Instead, this commit removes the flakey assertion and adds an alternative
assertion in the frontend tests that ensures the background request is
sent when the user tip is shown.
Form Kit is our new form library/framework for unifying the way forms look across Discourse. The admin config area for the /about page is a new form that isn't currently used, so it makes sense for it to be one of the first forms to be migrated to Form Kit to test the library.
Co-authored-by: Joffrey JAFFEUX <j.jaffeux@gmail.com>
* `@ember/owner` instead of `@ember/application`
* `discourse-i18n` instead of `I18n`
* `{ service } from "@ember/service"` instead of `inject as service`
In an attempt to improve build performance, 9db5eafb mistakenly removed minimization for some of our JS assets, leading to a significant increase in the size of some files.
This commit restores minimization to those files. To avoid regressing on the build time improvements, this commit switches to using the `webpack-terser-plugin`'s "swcMinify" option. On an entry-level 1CPU/1GB-ram/2GB-swap DO droplet, this commit increases build time from ~16 minutes to ~18 minutes.
Co-authored-by: Alan Guo Xiang Tan <gxtan1990@gmail.com>
Performing a bulk action on many topics can exceed the 30 seconds timeout that Unicorn workers have which results in the request failing and the operation getting aborted. To get around this 30 seconds timeout, we can push the operation into a background thread using the rack `hijack` API.
Internal topic: t/133779.
In development, classes are lazy loaded so `Jobs::Onceoff.onceoff_job_klasses`
may not have been set. This is not a problem in production cause stuff
is eager loaded.
Follow-up to f4d06f195d
* FIX: Add post id to the anchor to prevent two identical anchors
We generate anchors for headings in posts. This works fine if there is
only one post in a topic with anchors. The problem comes when you have
two or more posts with the same heading. PrettyText generates anchors
based on the heading text using the raw context of each post, so it is
entirely possible to generate the same anchor for two posts in the same
topic, especially for topics with template replies
Post1:
# heading
context
Post2:
# heading
context
When both posts are on the page at the same time, the anchor will only
work for the first post, according to the [HTML specification](https://html.spec.whatwg.org/multipage/browsing-the-web.html#scroll-to-the-fragment-identifier).
> If there is an a element in the document tree whose root is document
> that has a name attribute whose value is equal to fragment, then
> return the *first* such element in tree order.
This bug is particularly serious in forums with non-Latin languages,
such as Chinese. We do not generate slugs for Chinese, which results in
the heading anchors being completely dependent on their order.
```ruby
[2] pry(main)> PrettyText.cook("# 中文")
=> "<h1><a name=\"h-1\" class=\"anchor\" href=\"#h-1\"></a>中文</h1>"
```
Therefore, the anchors in the two posts must be in exactly the same by
order, causing almost all of the anchors in the second post to be
invalid.
This commit solves this problem by adding the `post_id` to the anchor.
The new anchor generation method will add `p-{post_id}` as a prefix when
post_id is available:
```ruby
[3] pry(main)> PrettyText.cook("# 中文", post_id: 1234)
=> "<h1><a name=\"p-1234-h-1\" class=\"anchor\" href=\"#p-1234-h-1\"></a>中文</h1>"
```
This way we can ensure that each anchor name only appears once on the
same topic. Using post id also prevents the potential possibility of the
same anchor name when splitting/merging topics.
We are investigating a memory leak in Sidekiq and saw the following line
when comparing heap dumps over time.
`Allocated IMEMO 14775 objects of size 591000/7389528 (in bytes) at:
/var/www/discourse/app/jobs/onceoff/onceoff.rb:36`
That line in question was doing a `.select { |klass| klass < self }` on
`ObjectSpace.each_object(Class)`. This for some reason is allocating a
whole bunch of `IMEMO` objects which are instruction sequence objects.
Instead of diving deeper into why this might be leaking, we can just
save our time by switching to an implementation that is more efficient
and does not require looping through a ton of objects.
Disabling webpack minimize is a bug we are working to resolve but we
have to consider self-hosters that deploy on low cost hardware
and reenabling this for them drastically increases the build time.
For now, add a `DISCOURSE_WEBPACK_MINIMIZE` env to allow sites to opt
back in.
Previously in these 2 PRs, we introduced a new site setting `SiteSetting.enforce_second_factor_on_external_auth`.
https://github.com/discourse/discourse/pull/27547https://github.com/discourse/discourse/pull/27674
When disabled, it should enforce 2FA for local login with username and password and skip the requirement when authenticating with oauth2.
We stored information about the login method in a secure session but it is not reliable. Therefore, information about the login method is moved to the database.
This commit also attempts to promote more declarative patterns. The route history logic has been replaced by using the history-store service.
---------
Co-authored-by: Jarek Radosz <jarek@cvx.dev>
Co-authored-by: David Taylor <david@taylorhq.com>
This commit changes the group SMTP settings form (at
`/g/:name/manage/email`) to use
FormKit, our magical new form component system ✨
---------
Co-authored-by: Joffrey JAFFEUX <j.jaffeux@gmail.com>
- Ensure main title is set as 'not visible' when removed from DOM
- `deactivate` -> `willTransition` to ensure proper behavior when navigating between multiple topics
Followup to bdec564d14
- Move topic-title on-screen detection to intersection-observer (via new modifier), and add a boolean to header service which indicates whether it's on-screen
- Move scroll-direction from Mixin to dedicated service. Teach it to pause scroll monitoring while transitions are in progress, to avoid reporting false changes in scroll direction. Also resets to a 'neutral' state after each navigation, which indicates the the user has not yet scrolled
- When entering a topic view, notify the header service which post is being targeted. It can then make an educated guess about whether the topic title is likely to be in-view
- Update header service `topicInfoVisible` to be a declarative getter, based on the three refactored sources of truth mentioned above
- Update legacy widget header to use the header service for topic info
All of these changes mean that the header no longer 'flickers' when navigating into topics on mobile. As well as the improved UX, this should also improve our Cumulative Layout Shift (CLS) web vital metrics.
Fixed using next instead. It was causing this kind of errors:
```
Job exception: unexpected return
/var/www/discourse/app/controllers/topics_controller.rb:1304:in `block in defer_topic_view'
/var/www/discourse/lib/scheduler/defer.rb:115:in `block in do_work'
rails_multisite-6.0.0/lib/rails_multisite/connection_management/null_instance.rb:49:in `with_connection'
rails_multisite-6.0.0/lib/rails_multisite/connection_management.rb:21:in `with_connection'
/var/www/discourse/lib/scheduler/defer.rb:109:in `do_work'
/var/www/discourse/lib/scheduler/defer.rb:97:in `block (2 levels) in start_thread'
```
* FEATURE: Clean up previously logged information after permanently deleting posts
When soft deleteing a topic or post, we will log some details in the
staff log, including the raw content of the post. Before this commit, we
will not clear the information in these records. Therefore, after
permanently deleting the post, `UserHistory` still retains copy of the
permanently deleted post. This is an unexpected behaviour and may raise
some potential legal issues.
This commit adds a behavior that when a post is permanently deleted, the
details column of the `UserHistory` associated with the post will be
overwritten to "(permanently deleted)". At the same time, for permanent
deletion, a new `action_id` is introduced to distinguish it from soft
deletion.
Related meta topic: https://meta.discourse.org/t/introduce-a-way-to-also-permanently-delete-the-sensitive-info-from-the-staff-logs/292546
Followup dd30463276
We missed the explicit `return` when we changed to
async/await, so the model ends up being null on admin
backups.
This means we also have no tests for the backup UI, that
will be fixed in a subsequent PR.
There is a bug with chat type flags - "An error occurred: Applies to is not included in the list"
Flag.valid_applies_to_types is a set of core types and types registered by plugins `Set.new(DEFAULT_VALID_APPLIES_TO | DiscoursePluginRegistry.flag_applies_to_types)`
Using lamba should ensure that valid values are calculated dynamically.
This commit promotes the new topic bulk action
menu introduced in 89883b2f51
to the main method of bulk selecting and performing
actions on topics. The site setting flag gating this
feature is deleted, and the old bulk select code is
deleted as well.
The new modal shows a loading spinner while operations
are taking place, allows selecting the action from a dropdown
instead of having a 2-step modal flow,
and also supports additional options for some operations, e.g.
allowing Close silently.
Replaces the existing topic map with the experimental-topic-map made by @awesomerobot.
---------
Co-authored-by: awesomerobot <kris.aubuchon@discourse.org>
This commit introduces the foundation for a new design for the /about page that we're currently working on. The current version will remain available and still be the default until we finish the new version and are ready to roll out. To opt into the new version right now, add one or more group to the `experimental_redesigned_about_page_groups` site setting and members in those groups will get the new version.
Internal topic: t/128545.
* FEATURE: Add logging for CustomEmoji
We didn't provide any logs for CustomEmoji before, nor did we record the
person who added any emoji in the database. As a result, the staff had
no way to trace back who added a certain emoji.
This commit adds a new column `user_id` to `custom_emojis` to record the
creator of an emoji. At the same time, a log is added for staff logs to
record who added or deleted a custom emoji.
If a user has a required action, e.g. adding a 2FA method or filling in new required fields, we disable client-side routing except to allowed pages.
This led to a situation where a user might navigate away from e.g. the profile page to look at the new ToS, and then being "stuck" due to not knowing how to get back to accept the new terms.
This PR makes it so that if you click any restricted link, instead of doing nothing we transition the user back to the page where they can take the required action.
User actions can trigger functions that render changes to the screen within the same cycle (e.g. pressing the reply button will cause the login modal to pop up), potentially impacting performance and causing some jank on slower devices.
This change inserts runAfterFramePaint where certain actions are triggered. Below are some screenshots indicating an improved INP for some of the buttons affected on controls with the highest INPs. The two places where this is added help with several actions, e.g. user + group cards, generic button action usage.
Usage:
```
@validation="integer"
```
This commit also adds a default for rules. By default a rule will now be `ruleName: {}`, this avoids all the boilerplate in validation-parser.js.
We'd implemented the deprecation by overriding `get parentView`, and storing the real value on `_parentView`. Unfortunately that meant people could access `_parentView` directly, thereby bypassing the deprecation message.
This commit moves the internal storage to a private field, which cannot be accessed from outside the class. A deprecated getter for `_parentView` is introduced to avoid immediate breakage for any code using this workaround.
This is a convenience for when you have multiple properties to set in form kit.
```
// before
set("foo", 1);
set("bar", 2);
//after
setProperties({foo: 1, bar: 2});
```
Before migration is run flags code is evaluated. It is causing error:
```
NoMethodError: undefined method `require_message' for an instance of Flag (NoMethodError)
Did you mean? require_dependency
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activemodel-7.1.3.4/lib/active_model/attribute_methods.rb:489:in `method_missing'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activerecord-7.1.3.4/lib/active_record/relation/delegation.rb💯in `each'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activerecord-7.1.3.4/lib/active_record/relation/delegation.rb💯in `each'
/var/www/discourse/app/models/post_action_type.rb:64:in `reject'
```
The solution is to temporarily fall back to old column name - custom_type
Our old group SMTP SSL option was a checkbox,
but this was not ideal because there are actually
3 different ways SSL can be used when sending
SMTP:
* None
* SSL/TLS
* STARTTLS
We got around this before with specific overrides
for Gmail, but it's not flexible enough and now people
want to use other providers. It's best to be clear,
though it is a technical detail. We provide a way
to test the SMTP settings before saving them so there
should be little chance of messing this up.
This commit also converts GroupEmailSettings to a glimmer
component.
Allow admin to create custom flag which requires an additional message.
I decided to rename the old `custom_flag` into `require_message` as it is more descriptive.
- removes unused css code
- improves password control sizing
- adds more spacing between collection items
- correct a typo in collection class
---------
Co-authored-by: chapoi <101828855+chapoi@users.noreply.github.com>
This PR introduces FormKit, a component-based form library designed to simplify form creation and management. This library provides a single `Form` component, various field components, controls, validation mechanisms, and customization options. Additionally, it includes helpers to facilitate testing and writing specifications for forms.
1. **Form Component**:
- The main component that encapsulates form logic and structure.
- Yields various utilities like `Field`, `Submit`, `Alert`, etc.
**Example Usage**:
```gjs
import Form from "discourse/form";
<template>
<Form as |form|>
<form.Field
@name="username"
@title="Username"
@validation="required"
as |field|
>
<field.Input />
</form.Field>
<form.Field @name="age" @title="Age" as |field|>
<field.Input @type="number" />
</form.Field>
<form.Submit />
</Form>
</template>
```
2. **Validation**:
- Built-in validation rules such as `required`, `number`, `length`, and `url`.
- Custom validation callbacks for more complex validation logic.
**Example Usage**:
```javascript
validateUsername(name, value, data, { addError }) {
if (data.bar / 2 === value) {
addError(name, "That's not how maths work.");
}
}
```
```hbs
<form.Field @name="username" @validate={{this.validateUsername}} />
```
3. **Customization**:
- Plugin outlets for extending form functionality.
- Styling capabilities through propagated attributes.
- Custom controls with properties provided by `form` and `field`.
**Example Usage**:
```hbs
<Form class="my-form" as |form|>
<form.Field class="my-field" as |field|>
<MyCustomControl id={{field.id}} @onChange={{field.set}} />
</form.Field>
</Form>
```
4. **Helpers for Testing**:
- Test assertions for form and field validation.
**Example usage**:
```javascript
assert.form().hasErrors("the form shows errors");
assert.form().field("foo").hasValue("bar", "user has set the value");
```
- Helper for interacting with he form
**Example usage**:
```javascript
await formKit().field("foo").fillIn("bar");
```
5. **Page Object for System Specs**:
- Page objects for interacting with forms in system specs.
- Methods for submitting forms, checking alerts, and interacting with fields.
**Example Usage**:
```ruby
form = PageObjects::Components::FormKit.new(".my-form")
form.submit
expect(form).to have_an_alert("message")
```
**Field Interactions**:
```ruby
field = form.field("foo")
expect(field).to have_value("bar")
field.fill_in("bar")
```
6. **Collections handling**:
- A specific component to handle array of objects
**Example Usage**:
```gjs
<Form @data={{hash foo=(array (hash bar=1) (hash bar=2))}} as |form|>
<form.Collection @name="foo" as |collection|>
<collection.Field @name="bar" @title="Bar" as |field|>
<field.Input />
</collection.Field>
</form.Collection>
</Form>
```
Previously, we did not log any topic slow mode changes. This allowed
some malicious (or just careless) TL4 users to delete slow modes created
by moderators at will. Administrators could not see who changed the slow
mode unless they had SQL knowledge and used Data Explorer.
This commit enables logging who turns slow mode on, off, or changes it.
Related meta topic: https://meta.discourse.org/t/why-is-there-no-record-of-who-added-or-removed-slow-mode/316354
Followup 7b627dc14b
In this other commit, I changed the email settings validator
to always use the `login` authentication method for
office365 and outlook, but I didn't change the actual
group SMTP mailer to do this.
This commit fixes that issue and does some minor refactoring.
Originally in 964da21817
we hid the SMTPAuthenticationError message except in
very specific cases. However this message often contains
helpful information from the mail provider, for example
here is a response from Office365:
> 535 5.7.139 Authentication unsuccessful, user is locked by your
organization's security defaults policy. Contact your administrator.
So, we will show the error message in the modal UI instead
of supressing it with a generic message to be more helpful.
The watch words controller creation function, create_or_update_word(), doesn’t validate the size of the replacement parameter, unlike the word parameter, when creating a replace watched word. So anyone with moderator privileges can create watched words with almost unlimited characters.
`after_commit` should be used before refreshing processes to be sure that the database is already updated.
Also, MessageBus is used instead of events as MessageBus works correctly with many processes;
In order to facilitate discourse-tag-icons and discourse-category-icons to render icons for post content, we need to provide an additional slug parameter here
The OutOfDateThemes problem check is using an old method of setting the message, by overriding #message. It should instead use #translation_keys. (By chance I noticed the same thing applies to UnreachableThemes.
This commit updates `StaticController#enter` to not redirect to invalid
paths when the `redirect` param is set. Instead it should redirect to `/` when the
`redirect` param is invalid.
Followup 560e8aff75
GitHub auth tokens cannot be made with permissions to
access multiple organisations. This is quite limiting.
This commit changes the site setting to be a "secret list"
type, which allows for a key/value mapping where the value
is treated like a password in the UI.
Now when a GitHub URL is requested for oneboxing, the
org name from the URL is used to determine which token
to use for the request.
Just in case anyone used the old site setting already,
there is a migration to create a `default` entry
with that token in the new list setting, and for
a period of time we will consider that token valid to
use for all GitHub oneboxes as well.
"Replies" in non-crawler view makes a request when clicked to get all replies, however this does not make sense in the crawler view where we load everything per post number.
So the solution here is to exclude the reply number so we can avoid having to nest all replies in a post.
### What is the problem?
We have recently added a new option to add user fields required for existing users. This is in contrast to requiring fields only on sign-up.
This revealed an existing problem. Consider the following:
1. User A signs up.
2. Admin adds a new user field required on sign-up. (Should not apply to User A since they already signed up.)
3. User A tries to update their profile.
**Expected behaviour:**
No problem.
**Actual behaviour:**
User A receives an error saying they didn't fill up all required fields.
### How does this fix it?
When updating profile, we only check that required fields that are "for all users" are filled. Additionally, we check that fields that were required on sign-up and have previously been filled are not blanked out.
Allow admin to create custom flag which requires an additional message.
I decided to rename the old `custom_flag` into `require_message` as it is more descriptive.
This tightens things up to reduce the number of initializers which need to be wrapped in an IIFE.
Mirrors the changes made in https://github.com/babel/babel/pull/16569
This needs to run before any component files are `import`'d. In traditional resolver-based tests, this was working previously because component files would only be loaded 'at runtime'. However, in gjs-based tests (e.g. those introduced in the formkit PR), component files are imported before the application is booted.
This reverts commit d05f8285e7 and 727acfee6a. This bump introduced a new deprecation message which is very noisy for us. We'll resolve it before merging again.
Followup db993cf8fd
Since in the above commit we converted integer site settings
to actual integers then set that as the new `buffered.value`,
the overridden indicator technically thinks the value has changed,
even if the user sets it back to the default:
```
overridden: propertyNotEqual("setting.default", "buffered.value"),
```
We can fix this by converting the parsed integer back to a string
before setting the buffered setting value.
- set in constructor so they're guaranteed to be present, even if async-import hasn't finished yet
- ensure they're all cleaned up properly
- combine two cleanup methods into one
Currently, when a plugin registers a new reviewable type or extends a
list method (through `register_reviewble_type` and `extend_list_method`
respectively), the new array is statically computed and always returns
the same value. It will continue to return the same value even if the
plugin is disabled (it can be a problem in a multisite env too).
To address this issue, this patch changes how `extend_list_method`
works. It’s now using `DiscoursePluginRegistry.define_filtered_register`
to create a register on the fly and store the extra values from various
plugins. It then combines the original values with the ones from the
registry. The registry is already aware of disabled plugins, so when a
plugin is disabled, its registered values won’t be returned.
Both office365 and outlook SMTP servers need LOGIN
SMTP authentication instead of PLAIN (which is what
we are using by default). This commit uses that
unconditionally for these servers, and also makes
sure to use STARTTLS for them too.
This patch upgrades the MessageFormat library to version 3.3.0 from
0.1.5.
Our `I18n.messageFormat` method signature is unchanged, and now uses the
new API under the hood.
We don’t need dedicated locale files for handling pluralization rules
anymore as everything is now included by the library itself.
The compilation of the messages now happens through our
`messageformat-wrapper` gem. It then outputs an ES module that includes
all its needed dependencies.
Most of the changes happen in `JsLocaleHelper` and in the `ExtraLocales`
controller.
A new method called `.output_MF` has been introduced in
`JsLocaleHelper`. It handles all the fetching, compiling and
transpiling to generate the proper MF messages in JS. Overrides and
fallbacks are also handled directly in this method.
The other main change is that now the MF translations are served through
the `ExtraLocales` controller instead of being statically compiled in a
JS file, then having to patch the messages using overrides and
fallbacks. Now the MF translations are just another bundle that is
created on the fly and cached by the client.
Drafts used to be deleted instead of being destroyed. The callbacks that
clean up the upload references were not being called. As a result, the
upload references were not cleaned up and uploads were not deleted
either. This has been partially fixed in 9655bf3e.
On the review page, once you select a category to filter by, while you can still change the category, you can not clear it.
After this commit, we pass the "clearable" select-kit option through.
Followup 0434112aa7,
we introduced HideApplicationHeaderButtons there
but didn't validate the buttons passed to it. With this
commit we do, and send an error to the browser console
if an invalid one is used.
When a user action is required and enforced, such as filling up newly added required fields or adding a 2FA method, we disable routing on the client-side. However, this could be bypassed by first loading an always allowed page, such as /faq and then client-side routing away from there.
This commit fixes that by 1) moving the logic for checking if routing is restricted and if a given path is allowed into a service and 2) hoisting the willTransition hook into the application router and use the newly created service to check whether to abort transitions or not.
Last week I disabled smart lists in Firefox in 2ab4913d13.
This week the same issue presented itself in Chrome. Turns out,
the list modification was still not firing at the right time
in the event chain. I investigated and it looks as though
`beforeinput` is a better fit, since:
> This allows web apps to override text edit behavior before the browser
modifies the DOM tree, and provides more control over input events to
improve performance.
c.f. https://developer.mozilla.org/en-US/docs/Web/API/Element/beforeinput_event
and https://webkit.org/blog/7358/enhanced-editing-with-input-events/
and https://www.w3.org/TR/uievents/#events-keyboard-event-order
The order of keyboard events is `keydown` -> `beforeinput` -> `input` -> `keyup`
I changed to detect the event type of `insertLineBreak` which is
not always consistently true in `input` events. If it's true when
`beforeinput` is fired then we go ahead with the smart list when
`input` fires.
Handles the cases where the sections titles are Unicode only strings, allowing them to be expanded separately if the Unicode string contains letters.
Also prevents a sidebar section with the header hidden to be displayed collapsed.
Followup 3ff7ce78e7
Basing this setting on referrer was too brittle --
the referrer header can easily be ommitted or changed.
Instead, for the small amount of use cases that this
site setting serves, we can use a group-based setting
instead, changing it to `cross_origin_opener_unsafe_none_groups`
instead.
- Delete vendored copy
- Create a JS entrypoint under `static/` which imports all the modes/themes/extensions we need
- Create an async `load-ace-editor` entrypoint
- Update `<AceEditor` component to use the new entrypoint
- De-jquery-ify `<AceEditor`
- Bump `v1.4.13` -> `v1.35.2`
When a crawler visits a topic that has a deleted author, it would error because the `show.html.erb` view was expecting a user to be always present.
This ensure we don't render the "author" meta data when the author of the topic has been deleted.
Internal ref t/132508
This change eliminates a couple of instances where subfolder urls are badly formatted, in most cases we can use Discourse.base_url_no_prefix to prevent adding the subfolder to the base url.
Adds a report to show the top 100 most viewed topics in a date range,
combining logged in and anonymous views. Can be filtered by category.
This is a followup to 527f02e99f
and d1191b7f5f. We are also going to
be able to see this data in a new topic map, but this admin report
helps to see an overview across the forum for a date range.
Background:
In order to redrive failed webhook events, an operator has to go through and click on each. This PR is adding a mechanism to retry all failed events to help resolve issues quickly once the underlying failure has been resolved.
What is the change?:
Previously, we had to redeliver each webhook event. This merge is adding a 'Redeliver Failed' button next to the webhook event filter to redeliver all failed events. If there is no failed webhook events to redeliver, 'Redeliver Failed' gets disabled. If you click it, a window pops up to confirm the operator. Failed webhook events will be added to the queue and webhook event list will show the redelivering progress. Every minute, a job will be ran to go through 20 events to redeliver. Every hour, a job will cleanup the redelivering events which have been stored more than 8 hours.
Example:
```hbs
<DBreadcrumbItem
@path="/admin/plugins/{{@plugin.name}}"
@label={{@plugin.nameTitleized}}
/>
```
Using `@path` instead of `@route`+`@model` combo makes it impossible to pass temporarily unresolvable routes.
This fixes a bug with navigating from a model-based route to a parent route.
Followup to 527f02e99f,
I had to introduce defer_track_visit_v2 because discourse-docs
relied on defer_track_visit. Now that discourse-docs
is using the new method as of
discourse/discourse-docs@0d9365571b,
we can rename it in core. Then we will need one more PR
in both core and docs to remove usage of the "v2" method.
This is a follow up to 005f623c42 where
we want to truncate the user agent string instead of nulling out the
column when the user agent string is too low. By truncating, we still
get to retain information that can still be useful.
Adds experimental_flags_admin_page_enabled_groups (default "")
to remove the Moderation Flags link from the admin sidebar for now,
there are still a few bugfixes that need to be done before we
are comfortable with turning this on more widely. This is
a _temporary_ flag, we will be removing this once the feature
is more stable.
Add a new column - `user_agent` - to the `SearchLog` table.
This column can be null as we are only allowing a the user-agent string to have a max length of 2000 characters. In the case the user-agent string surpasses the max characters allowed, we simply nullify the value, and save/write the log as normal.
The user serializer groups method previously relied on the members_visible_groups to determine groups that the user should be able to see, however this setting was intended for visibility of group members (which is entirely different).
The result of this could be seen when choosing a primary group from user preferences -> account, due to the serializer the group name was not visible when members_visible_groups was set to owners.
The featured topics have not been rendered correctly since 2190c9b and
it has been fixed for desktop recently in commit d2a52c3. This commit
implements similar changes that initialize Category and Topic object
instances from the serialized data.
The AdminPlugin JS model uses a similar pattern to chat models,
where it is a plain JS class manually converting provided
snake_case attributes from the serializer to JS camelCase.
However this doesn't work when it comes to using `add_to_serializer`
in plugins since core does not know about these new attributes.
Instead, we can use a JS function to convert snake_case to camelCase
and use that when initializing AdminPlugin. This commit also moves
similar functions to a new case-converter.js file in
discourse-common/lib.