This commit handles the edge case where a draft is lost with no warnings if the user edits the title (or category/tags) of a topic while they're replying.to the same topic. Repro steps are as follows:
1. Start replying to a topic and type enough to get a draft saved.
2. Scroll up to the topic title and click the pencil icon next to the topic title, change the title, category and/or tags, and then save the changes.
3. Reload the page and you'll see that the draft is gone.
This happens because we only allow 1 draft per topic per user and when you edit the title of a topic that you're replying to, from the server perspective it'll look like as if you've submitted your reply so it will advance the draft sequence for the topic and delete the draft.
The fix in this commit makes `PostRevisor` skip advancing the draft sequence when a topic's title is edited using the pencil button next to the title.
Internal ticket: t60854.
Co-authored-by: Robin Ward <robin.ward@gmail.com>
Meta topic: https://meta.discourse.org/t/rtl-direction-is-broken-in-quotes/217639?u=osama.
Posts in Discourse are by default always rendered in the same direction as the rest of site, for example if the site is RTL, a post in that site is always rendered RTL even if it's made of an LTR language entirely. However, this behavior can be changed by enabling the `support mixed text direction` site setting which makes our posts rendering engine consider each "paragraph" in the post and apply an appropriate direction (using the `dir` attribute) on it based on its content/language.
I put paragraph in quotes because technically we only loop through the immediate children of the HTML element that contains the post cooked HTML and do this direction check on them. Most of the time the immediate children are actually paragraphs, but not always. The direction of an element is determined by checking its `textContent` property against a regular expression that checks all characters are RTL characters and based on the regular expression result the `dir` attribute is set on the element.
This technique doesn't work so well on quotes because they may contain multiple paragraphs which may be in different languages/directions. For example: if a site's language is Arabic (RTL language) and the `support mixed text direction` setting is enabled, regular paragraphs outside quotes are rendered as expected with the right direction depending on the paragraph's language. However, paragraphs within a quote are all (incorrectly) rendered in a single direction, LTR or RTL, regardless of whether they're of different languages/directions or not.
The reason for this is that when we're determining the direction for the quote, it's considered as one element and the direction is set on the whole quote. But for complex quotes that contain mixed paragraphs, we need to be more surgical and apply direction on individual paragraphs/elements within the quote.
This commit adds special handling for quotes to ensure that:
* the quote top bar (the avatar plus the chevron and arrow) always match the site direction
* each immediate paragraph (`<p>` elements) under `<blockquote>` in the quote gets a direction based on its content.
For before/after screenshots, see PR #16004.
This option will make it so the [quote] bbcode will always
include the HTML link to the quoted post, even if a topic_id
is not provided in the PrettyText#cook options. This is so
[quote] bbcode can be used in other places, like chat messages,
that always need the link and do not have an "off-topic" ID
to use.
The 'new' tab doesn't exist for anonymous users. Every 'new' topic also publishes a message on the `/latest` channel, so the blue banner at the top of the topic-list will still be functional
* DEV: remove duplicate code in button component template
* DEV: refactor is-loading state of d-button component
Before this change on initialisation `forceDisabled` is set `false` and then might change to `undefined` - depending on the use of the button component. This change ensures a boolean value for `forceDisabled`.
The added test works with and without the new change. The test is added as it represents the default use case for most buttons.
Previously cached counting made redis calls in main thread and performed
the flush in main thread.
This could lead to pathological states in extreme heavy load.
This refactor reduces load and cleans up the interface
Previously we were publishing one messagebus message per user which was 'tracking' a topic. On large sites, this can easily be 1000+ messages. The important information in the message is common between all users, so we can manage with a single message on a shared channel, which will be much more efficient.
For user-specific values (notification_level and last_read_post_number), the JS app can infer values which are 'good enough'. Correct values will be loaded as soon as a topic-list containing the topic is visited.
aa1442fdc3 split theme stylesheets so that every component gets its own stylesheet. Therefore, there is now no need for parent themes to collate the settings/variables of its children during scss compilation.
Technically this is a breaking change for any themes which depend on the settings/variables of their child components. That was never a supported/recommended arrangement, so we don't expect this to cause issues.
If a theme is updated to introduce a new setting AND immediately make use of it in a stylesheet, then an error was being shown. This is because the stylesheet compilation was using the theme's cached settings, and the cache is only cleared **after** the theme has finished compiling.
This commit updates the SCSS compilation to use uncached values for settings. A similar fix was applied to other parts of theme compilation back in 2020: (a51b8d9c66)
The previous Discourse.cache usage was different to how other theme-related caching is handled, and also requires reaching out to redis every time. The common theme cache is held in memory (as a DistributedCache)
This will only work under Ember CLI, and a small hack is required to make the Resolver work in development mode. In future, when we move to a more recent version of the Ember Resolver, this hack will not be required.
The use of a `/g` regex was causing some surprising, seemingly random, behavior. (https://stackoverflow.com/a/1520853/5913559)
There was also a known issue which would cause inconsistent class behavior when running the 'loading slider' theme component.
This commit takes the opportunity to refactor the component to remove the use of observers and remove the regex-based class parsing.
This commit makes sure that the email log's bounce_error_code
conforms to the SMTP error code RFC on save, so that
it is always in the format X.X.X or XXX without any
additional string details. Also included is a migration
to fix this issue for past records.
Similar site settings exist for likes and edits and the new ones work
in a similar way.
By default, users below TL2 have a limit of 20, the limit is increased
by 1.5 for TL2 users up to 30, by 2 for TL3 users up to 40 and by 3 for
TL4 users up to 60.
We validate the *format* of email addresses in many places with a match against
a regex, often with very slightly different syntax.
Adding a separate EmailAddressValidator simplifies the code in a few spots and
feels cleaner.
Deprecated the old location in case someone is using it in a plugin.
No functionality change is in this commit.
Note: the regex used at the moment does not support using address literals, e.g.:
* localpart@[192.168.0.1]
* localpart@[2001:db8::1]
This commit moves _getMultilineContents and _applySurround into
TextareaTextManipulation, so other text area components using
that mixin can benefit from them (such as the chat composer).
It also creates a public function wrapper for many TextareaTextManipulation
functions that should not have underscore prefixes because they are
used outside the file. Will make follow-up PRs for each plugin/theme using
those functions then a final follow-up core PR to fix these up.
After leaving a group, it is trying to reload its member list. Previously, when the members_visibility_level attribute has a value of 2 or higher, it displayed an error popup since the can_see_members attribute was not updated.
2FA support in Discourse was added and grown gradually over the years: we first
added support for TOTP for logins, then we implemented backup codes, and last
but not least, security keys. 2FA usage was initially limited to logging in,
but it has been expanded and we now require 2FA for risky actions such as
adding a new admin to the site.
As a result of this gradual growth of the 2FA system, technical debt has
accumulated to the point where it has become difficult to require 2FA for more
actions. We now have 5 different 2FA UI implementations and each one has to
support all 3 2FA methods (TOTP, backup codes, and security keys) which makes
it difficult to maintain a consistent UX for these different implementations.
Moreover, there is a lot of repeated logic in the server-side code behind these
5 UI implementations which hinders maintainability even more.
This commit is the first step towards repaying the technical debt: it builds a
system that centralizes as much as possible of the 2FA server-side logic and
UI. The 2 main components of this system are:
1. A dedicated page for 2FA with support for all 3 methods.
2. A reusable server-side class that centralizes the 2FA logic (the
`SecondFactor::AuthManager` class).
From a top-level view, the 2FA flow in this new system looks like this:
1. User initiates an action that requires 2FA;
2. Server is aware that 2FA is required for this action, so it redirects the
user to the 2FA page if the user has a 2FA method, otherwise the action is
performed.
3. User submits the 2FA form on the page;
4. Server validates the 2FA and if it's successful, the action is performed and
the user is redirected to the previous page.
A more technically-detailed explanation/documentation of the new system is
available as a comment at the top of the `lib/second_factor/auth_manager.rb`
file. Please note that the details are not set in stone and will likely change
in the future, so please don't use the system in your plugins yet.
Since this is a new system that needs to be tested, we've decided to migrate
only the 2FA for adding a new admin to the new system at this time (in this
commit). Our plan is to gradually migrate the remaining 2FA implementations to
the new system.
For screenshots of the 2FA page, see PR #15377 on GitHub.
* FIX: Don't accept accents in slug if generation_method == 'ascii'
Fixes bug reported in:
- https://meta.discourse.org/t/404-when-trying-to-edit-category-with-accent-in-slug/214762
- https://meta.discourse.org/t/formatting-and-accents-in-urls/215734/5
Assuming `SiteSetting.slug_generation_method == 'ascii'.
If the user provides a slug containing non-ascii characters while
creating the category, the user will receive a 404 error just
after saving the category since the slug will be escaped anyway but
Category.find_by_slug_path won't escape the category slug
causing the Edit Page of the category to be inaccessible.
This commit checks the provided slug and raises an error if the
provided slugcontains non-ascii characters ensuring that the
provided value is consistent with the site settings.
It also changes Category.find_by_slug_path to always escape the slug,
since if present, it is escaped anyway in Category.ensure_slug to
prevent the 404 in the Edit Category Page in case the user already
have some category with a non-ascii slug.
* Removed trailing whitespace
When parent category or grandparent category is muted, then category should be muted as well.
Still, it can be overridden by setting individual subcategory notification level.
CategoryUser record is not created, mute for subcategories is purely virtual.
This can happen if the topic to which a user is invited is in a private
category and the user was not invited to one of the groups that can see
that specific category.
This used to be a warning and this commit makes it an error.
This was deprecated in Discourse 2.4, but no end version was put on the deprecation. Many plugins/themes are still using it. This commit restores it under ember-cli so that it does not block the Ember CLI rollout, and can be removed in a future commit.
This commit introduces two new APIs for handling unused uploads, one
can be used to exclude uploads in bulk when the data model allow and
the other one excludes uploads one by one.
We added this constraint in 5bd55acf83
but it is causing problems in hosted sites and is catching the
issue too far down the line. This commit removes the constraint
for now, and also fixes an issue found with PostDestroyer
which wasn't using the UserStatCountUpdater when updating post_count
and thus was causing negative numbers to occur.
Previously calls such as `Emoji["smile"]` would force a full dehydration of
objects from Redis.
This introduces a version safe site and global emoji cache so lookups are
cheap. It eliminates iterating through the list of emojis and pulling from
redis.
Distributed cache uses a normalized name as the key and stores an Array tuple
with version and Emoji. Successful hits always confirm version matches.
Interface to Emoji object remains unchanged.
We opted for 2 caches to improve reuse on multisites. misses though will be
stored in both caches. If there is a hit on the global cache we can avoid
looking up in site local cache and storing a miss there.