Testing this is kinda complicated ATM (especially mobile template with hbr) , this is a component we should definitely aim to test very extensively when we move away from hbr templates.
In the unlikely, but possible, scenario where a user has no email_tokens, and has an invite record for their email address, login would fail. This commit fixes the `Invite` `user_doesnt_already_exist` validation so that it only applies to new invites, or when changing the email address.
This regressed in d8fe0f4199 (based on `git bisect`)
The UI used to request a password reset by username when the user was
logged in. This did not work when hide_email_already_taken site setting
was enabled, which disables the lookup-by-username functionality.
This commit also introduces a check to ensure that the parameter is an
email when hide_email_already_taken is enabled as the single allowed
type is email (no usernames are allowed).
* FIX: Tag watching for everyone tag groups
Tags in tag groups that have permissions set to everyone were not able
to be saved correctly. A user on their preferences page would mark the
tags that they wanted to save, but the watched_tags in the response
would be empty. This did not apply to admins, just regular users. Even
though the watched tags were being saved in the db, the user serializer
response was filtering them out. When a user refreshed their preferences
pages it would show zero watched tags.
This appears to be a regression introduced by:
0f598ca51e
The issue that needed to be fixed is that we don't track the "everyone"
group (which has an id of 0) in the group_users table. This is because
everyone has access to it, so why fill a row for every single user, that
would be a lot. The fix was to update the query to include tag groups
that had permissions set to the "everyone" group (group_id 0).
I also added another check to the existing spec for updating
watched tags for tags that aren't in a tag group so that it checks the
response body. I then added a new spec which updates watched tags for
tags in a tag group which has permissions set to everyone.
* Resolve failing tests
Improve SQL query syntax for including the "everyone" group with the id
of 0.
This commit also fixes a few failing tests that were introduced. It
turns out that the Fabrication of the Tag Group Permissions was faulty.
What happens when creating the tag groups without any permissions is
that it sets the permission to "everyone". If we then follow up with
fabricating a tag group permission on the tag group instead of having a
single permission it will have 2 (everyone + the group specified)! We
don't want this. To fix it I removed the fabrication of tag group
permissions and just set the permissions directly when creating the tag
group.
* Use response.parsed_body instead of JSON.parse
* FIX: Mark invites flash messages as HTML safe.
This change should be safe as all user inputs included in the errors are sanitized before sending it back to the client.
Context: https://meta.discourse.org/t/html-tags-are-explicit-after-latest-update/214220
* If somebody adds a new error message that includes user input and doesn't sanitize it, using html-safe suddenly becomes unsafe again. As an extra layer of protection, we make the client sanitize the error message received from the backend.
* Escape user input instead of sanitizing
If themes/plugins introduce a sidebar on the left of the screen, the quote button would sometimes be positioned underneath. This commit ensures that the positioning logic keeps the floating buttons within the width of `.topic-area`
Some safari-specific logic was inadvertently removed during the refactoring in b2d45c59. This commit restores it. The logic requires some state, so the getRangeBoundaryRect helper has to be moved back into the Component class. The functional change in this commit is the three lines enclosed by `if (this.capabilities.isSafari) {`.
As part of /t/10298, try to remove the first flaky test in the list.
One finding is that the /t/280 topic has a very long post stream, so that may have caused some delay when rendering the topic. One way is to wait for the first expected element to load, but that doesn't scale well given how many waits we will need to add. So I chose to render a shorter topic instead.
Previously we were adding `/assets/discourse/tests/core_plugin_tests.js` to the test html all the time. This works in development mode, but fails silently when using testem via the `ember test` CLI, because there is no proxy running.
This commit makes a few changes to fix this, and make it more useful:
- Only renders the plugin `<script>` when in development mode, or when `LOAD_PLUGINS=1` (matching core's behavior)
- Only loads plugin translations based on the same logic
- When running via testem, and the above conditions are met, testem is configured to proxy `core_plugin_tests.js` through to a rails server. (port based on the `UNICORN_PORT` env variable)
- Adds a descriptive error if the plugin `<script>` fails to load. This can happen if the rails server hasn't been started
- Updates the logic for testem browsers. Ember CLI always launches testem in "CI" mode, and we don't really want 3 browsers opening by default. Our CI explicitly specifies the 3 browsers at runtime
This expands cbf99f48 to apply to all mobile devices. It removes the old mobile positioning logic entirely, refactors the new system a little for robustness and readability, and removes some JQuery.
On Andoid, we also need to avoid the start selection handle. Therefore the logic for locating selection boundaries is abstracted into a function for easier re-use.
* FEATURE: Export topics to markdown
The route `/raw/TOPIC_ID` will now export whole topics (paginated to 100
posts) in a markdown format.
See https://meta.discourse.org/t/-/152185/12
Previously the picker would attempt to avoid positioning itself hover textarea and could in limited width screen end up being out of screen.
This behavior would be even more probable on full screen mode where the textarea takes a lot of space.
We already set border-radius to 0 on all input elements, but we didn't do that for textarea, which resulted in some of those elements appearing rounded on some browsers (iOS Safari)
* The current evaluation of uppy promises is causing the entire suite to fail
if there's an exception. Instead of using `done` we use the simpler
pattern of returning the promise from the test to force Qunit to wait
until it's completed.
* In some browser conditions `/last.json` will be requested depending on the
particular scroll / performance. This causes the tests not to fail if
that is the case.
* Keyboard shortcuts were not being fully cleared between runs,
resulting in tests failures.
This commit adds a hover effect for drag and drop in
the admin emoji uploader. It also changes the "Add New
Emoji" button to open the file selector; previously it
was useless because it was disabled unless a name was
entered (which is not even a requirement for the emoji)
and also it didn't actually do anything on click even
if it wasn't disabled.
Now we have a way of adding files without having to drag
and drop them, which is nice.
Also in this PR, there was no indication before that the upload was
complete apart from the button becoming enabled again.
This commit adds the highlight class to the emoji list
and removes it once the highlight fade animation is done,
like we do for new posts.
Tapping within ~50px of the selection end handle on iOS doesn't trigger a click event. This commit ensures that our quote buttons are always at least 50px away from the end handle. It will try 4 positions in order of preference:
1. The original position
2. 50px to the left of the handle
3. 50px to the right of the handle
4. 50px below the handle, centered on the handle
Follow up to 48f70dcd5f. The group
_appeared_ to be saved in the UI until a refresh when it became
clear that the group wasn't actually sent to the DB. This is because
of the way the per-file data was being set with a computed property.
This commit fixes the computed property by changing it to a regular
function and also makes sure the name resetting after the first upload
in multiple uploads works too.
When uploading multiple emoji in Admin/Customize/Emojis
with an emoji Group selected, the group was cleared between
each file uploaded, making bulk uploading of emojis a chore
if anything but the default group was needed.
This commit fixes the issue, introduces tests for emoji-uploader,
and also adds `add-files` appEvents for uppy-upload mixin, same
as the composer-upload-uppy mixin, for interop with tests and so
we don't have to rely on a file upload element's change event.
This reverts commit 2c7906999a.
The changes break some things in local development (putting JS files
into minified files, not allowing debugger, and others)
This is a workaround a behavior change in Chromium v97.
The following text was sent to the blink-dev mailing list:
> This change broke a SingleSignOn login on the FOSS software Discourse. We have a flow like:
>
> 1. User visits forum.siteA.com, click login
> 2. Gets redirected to idp.siteB.com
> 3. Fills login details
> 4. Gets redirected to forum.siteA.com/session/sso_login?parameters
> 5. Gets redirected to forum.siteA.com/homepage
>
> On step 4, the response includes a `set-cookie` header, with proper `HttpOnly; SameSite=Lax; Secure `and set. But if there is an active service worker, the login will fail as that cookie will be rejected by Chromium due to SameSite rules now.
>
> t=2971 [st=258] COOKIE_INCLUSION_STATUS
> --> domain = "forum.siteA.com"
> --> name = "_t"
> --> operation = "store"
> --> path = "/"
> --> status = "EXCLUDE_SAMESITE_LAX, DO_NOT_WARN"
>
> The service worker is a vanilla WorkboxJS service worker that intercepts all GETs with the "Network First" strategy.
>
> Disabling the service worker or using Firefox results in a successful login. There is no warning in either DevTools network tab nor the console that the cookie was rejected.
>
> Chrome 96: login works
> Chrome 97: login does not work
> Chrome 98: login does not work
>
> Is this expected behavior? Even if the request `GET forum.siteA.com` was initiated because of a redirect from a different domain, is it expected that Chrome will silently drop same site cookies from forum.siteA.com?
Currently when pressing Shift key and hitting Reply button the user
stays on the post they are on and does not get navigated to newly
created topic/PM/reply. This is fine for replies but creates confusion
when composing a new topic/PM.
This commits makes it such that pressing Shift key and Reply button
(or ctrl-shift-enter / cmd-shift-enter) works only for replies and not
for new topic/PM. The user will always be navigated to new topic/PM.
This means that our DiscourseURL logic will work consistently in tests, where `window.location` doesn't get updated.
To make it work properly, our `replaceState` implementation needed to be updated so that it writes the new URL to Ember's router, rather than bypassing the router and going straight to the `location` API.
A couple of tests needed updating following this fix:
- the composer-test was asserting that the new reply should be missing from the DOM... when really it **should** be in the DOM, and this fix to the test environment makes it so
- the topic-test was making a fake topic fixture based on the data from a topic with a different id. This was causing the topic route to get confused, and 'fix' the currentURL. This commit updates it to use a fixture with consistent data.
This commit also removes the feature detection of `window.history`. It's feature-detected within `discourse-location`. Plus, we don't support any browsers without it.
Previously only `<div>one top element</div>` was allowed because we use `firstChild` instead of `children`.
We also want `<div>one</div><div>two</div>` to work with this method.
This reverts commit ea84a82f77.
This is causing problems with `/theme-qunit` on legacy, non-ember-cli production sites. Reverting while we work on a fix
This is quite complex as it means that in production we have to build
Ember CLI test files and allow them to be used by our Rails application.
There is a fair bit of glue we can remove in the future once we move to
Ember CLI completely.
The `plugin:pull_compatible_all` task is intended to take incompatible plugins and downgrade them to an earlier version. Problem is, when running the rake task in development/production environments, the plugins have already been activated. If an incompatible plugin raises an error in `plugin.rb` then the rake task will be unable to start.
This commit centralises our LOAD_PLUGINS detection, adds support for LOAD_PLUGINS=0 in dev/prod, and adds a warning to `plugin:pull_compatible_all` if it's run with plugins enabled.
- Update the TOPIC_URL_REGEXP in `lib/url` so that `navigatedToPost` doesn't attempt to handle slug-less URLs. Slugs must contain at least one non-numeric character, so we can use that fact to make the regex more specific. We want slug-less URLs to be routed as a normal Ember transition, so that `topic-by-slug-or-id` can catch them and re-write the URL to include the slug.
- Update the `topic-by-slug-or-id` afterModel to ensure that the Ember router is used to handle the redirect, rather than DiscourseURL. This guarantees that it will function as a redirect (DiscourseURL.routeTo sometimes bypasses the router). This solves the history problem which was worked-around in 27211ee7bb.
- Update routes/topic to recover from aborted transitions gracefully. This means that following an aborted transition, the browser URL continues to be updated with post numbers as the user scrolls down the page.
An admin could search for all screened ip addresses in a block by
using wildcards. 192.168.* returned all IPs in range 192.168.0.0/16.
This feature allows admins to search for a single IP address in all
screened IP blocks. 192.168.0.1 returns all IP blocks that match it,
for example 192.168.0.0/16.
* FEATURE: Remove roll up button for screened IPs
* FIX: Match more specific screened IP address first
The new warnings cover more cases and more accurate. Most of the
warnings will be visible only to staff members because otherwise they
would leak information about user's preferences.
This commit extends the options which can be passed to
`PrettyText.markdown` so that which Markdown-it rules and Discourse
Markdown plugins to be used when rendering a text can be customizable.
Currently, this extension is mainly used by plugins.
Having to load `ip_addr` is confusing especially when that file exists
to monkey patch Ruby's `IpAddr` class. Moving it to our freedom patches
folder which is automatically loaded on initialization.
…after you re-open the modal or select another emoji.
Reason:
Even the most used emoji would be knocked off the list after a while, if you use any emoji outside the recent. Consider the sequence:
✅, 😃, ✅ (from recent), 😀, ✅ (from recent), 😛, ✅ (from recent), 😎, ✅ (from recent), and so on
With the previous logic, the check mark emoji would leave the list, even though it used constantly and (and the time of removal) would the the second most recent used emoji.
---
It doesn't update the list when you use the recent list so that you can click an emoji repeatedly and it doesn't shift from under your mouse cursor.
The app's wrapper element ID is different in tests. `app.rootElement` allows us to consistently obtain the selector in the initializer, so it works correctly regardless of the app's configuration.
The test environment will wait for all timers to settle before continuing. These timers were causing all tests involving `/t/*` routes to spend 500ms doing nothing.
Fun fact: we load the topic route 214 times during the core test suite. That means that this commit saves a total of around 107s across the whole suite. On my machine, that's a 30% improvement in runtime.
Modern Ember only sets up a container when the ApplicationInstance is booted. We have legacy code which relies on having access to a container before boot (e.g. during pre-initializers).
In production we run with the default `autoboot` flag, which triggers Ember's internal `_globalsMode` flag, which sets up an ApplicationInstance immediately when an Application is initialized (via the `_buildDeprecatedInstance` method).
In tests, we worked around the problem by creating a fresh container, and placing a reference to it under `Discourse.__container__`.
HOWEVER, Ember was still creating a Container instance for each ApplicationInstance to use internally, and make available to EmberObjects via injection. The `Discourse.__container__` instance we created was barely used at all.
Having two different Container instances in play could cause some weird issues. For example, I noticed the problem because the `appEvents` instance held by DiscourseURL was different to the `appEvents` instance held by all the Ember components in our app. This meant that events triggered by DiscourseURL were not picked up by components in test mode.
This commit makes the hack more robust by ensuring that Ember re-uses the Container instance which we created pre-boot. This means we only have one Container instance in play, and makes `appEvents` work reliably across all parts of the app. It also adds detailed comments describing the hack, to help future travelers.
Hopefully in future we can remove this hack entirely, but it will require significant refactoring to our initialization process in Core and Plugins.
The mapping-router and map-routes initializer are updated to avoid the need for `container.lookup` during teardown. This isn't allowed under modern Ember, but was previously working for us because the pre-initializer was using the 'fake' container which was not ember-managed.
This is a partial revert of 099b679fc5.
`Bookmark#topic_id` and `Bookmark#reminder_type` was dropped in
b22450c7a8 so we need to continue ignoring
the dropped columns so as to ensure a seamless deploy. Otherwise,
ActiveRecord's schema cache will still contain references to
`Bookmark#topic_id` when the column is dropped in a post migration.
1. Hide the results element when empty (and set top-margin of section to 0, which fixes some custom themes)
2. Fixed the on-hover color of .trash-recent
Migrate deprecated decorateCooked to decorateCookedElement for audio cloak-prevention.
This might give a minimal performance boost: running audio cloak-prevention for 20 (non-audio) posts takes 1 ms and not 15 ms.
Co-authored-by: Jarek Radosz <jradosz@gmail.com>
Also:
* Remove an unused method (#fill_email)
* Replace a method that was used just once (#generate_username) with `SecureRandom.alphanumeric`
* Remove an obsolete dev puma `tmp/restart` file logic
It was impossible to select the 'all' filter for categories that have
the default list filter set to 'no subcategories'. This happens because
'/all' was not appended to the URL and in the absence of any list filter
('all' or 'none'), the default list filter ('none') was automatically
selected.
Before 6e0e6014, the flow looked something like:
1. `discovery/topics` controller (which extends `discovery` controller) `afterRefresh()` calls `.send("loadingComplete")`
2. Bubbles to [`discovery` route](554ff07786/app/assets/javascripts/discourse/app/routes/discovery.js (L58))
3. Discovery route calls `controllerFor('discovery').loadingComplete()`. `loading` is set false, and the spinner disappears
Now that `discovery/topics` defines `loadingComplete` as an action, the `discovery/topics` controller runs its own `loadingComplete` handler logic in step 1, and the action does not bubble any further.
This commit adds action overrides in `discovery/topics`, so that the new actions only apply to the main `discovery` controller. The need for this does suggest some more radical refactoring is required, but these are very critical routes, and we are very close to a major release.
It is too close to release of 2.8 for incomplete
feature shenanigans. Ignores and drops the columns and drops
the trigger/function introduced in
e21c640a3c.
Will pick this feature back up post-release.
This commit should be a no-op for all existing core outlets. Outlets which are introduced by themes/plugins may see a change in behavior, and should follow the steps below if they want to maintain their previous behavior.
`tagName="" connectorTagName=""` is almost always the correct choice for plugin outlets. 40eba8cd introduced a `noTags=true` shortcut which achieved this, and left a comment saying it should be the future default. This commit does exactly that. To avoid any breaking changes for plugins, all existing plugin outlets have been reviewed and adjusted by following this logic:
1) If `noTags=true`, remove the `noTags` parameter, and do not complete any further steps
2) If `tagName` is not specified, set `tagName="span"` (the previous default)
3) If `connectorTagName` is not specified, set `selectorTagName="div"` (the previous default)
4) If `tagName=""`, remove it
5) If `connectorTagName=""`, remove it
The updates were accomplished with the help of a ruby script:
```ruby
def removeAttr(tag, attribute)
tag = tag.sub /\s#{attribute}="?\w*"? /, " "
tag = tag.sub /\s#{attribute}="?\w*"?}}/, "}}"
tag = tag.sub /^\s*#{attribute}="?\w*"?\n/, ""
tag
end
files = Dir.glob("app/assets/javascripts/**/*.hbs")
puts "Checking #{files.count} files..."
files.each do |f|
content = File.read(f)
count = 0
edits = 0
content.gsub!(/{{\s*plugin-outlet.*?}}/m) do |match|
count += 1
result = match
noTags = result.include?("noTags=true")
tagName = result[/tagName="(\w*)"/, 1]
connectorTagName = result[/connectorTagName="(\w*)"/, 1]
if noTags
result = removeAttr(result, "noTags")
else
if connectorTagName == ""
result = removeAttr(result, "connectorTagName")
elsif connectorTagName.nil?
result = result.sub(/name="[\w-]+"/) { |m| "#{m} connectorTagName=\"div\"" }
end
if tagName == ""
result = removeAttr(result, "tagName")
elsif tagName.nil?
result = result.sub(/name="[\w-]+"/) { |m| "#{m} tagName=\"span\"" }
end
end
edits += 1 if match != result
result
end
puts "#{count} outlets, #{edits} edited -> #{f}"
File.write(f, content)
end
```
This workaround was introduced before we had the ability to render components with no wrapper element. Now we can pass `tagName=""` to `plugin-outlet`.
We are planning on attaching bookmarks to more and
more other models, so it makes sense to make a polymorphic
relationship to handle this. This commit adds the new
columns and backfills them in the bookmark table, and
makes sure that any new bookmark changes fill in the columns
via DB triggers.
This way we can gradually change the frontend and backend
to use these new columns, and eventually delete the
old post_id and for_topic columns in `bookmarks`.
da6edc1 introduced the `lookupView` method, which initialized a fresh resolver, and used it to directly look up raw-views (with no caching). This worked well, but was not a clean solution. It required initializing an entirely new resolver, and did not have any caching.
This commit updates the `helperContext` to include access to the registry, and uses it to perform raw-view lookups. As well as re-using the registry, this also means we're making use of the resolver's built-in cache.
I haven't been able to measure any noticeable performance impact from this change, but there is certainly less work being done, so it may be beneficial on older devices.
Co-authored-by: Ayke Halder <rr-it@users.noreply.github.com>
* File.exists? is deprecated and removed in Ruby 3.2 in favor of
File.exist?
* Dir.exists? is deprecated and removed in Ruby 3.2 in favor of
Dir.exist?
The rake task deleted here was added back in Feb 2020
when bookmarks were first converted from PostAction
records, it is no longer needed. The ignored columns
were removed in ed83d7573e.
If a theme/plugin raises an error while decorating post content, the decorator will be skipped, and the error reported on the console. Additionally, administrators will be shown a red warning at the top of the screen.
This commit refactors and re-uses some of the logic from the theme-initializer-error-reporting logic. In future, new error reports can be added by doing something like:
```
document.dispatchEvent(
new CustomEvent("discourse-error", {
detail: { messageKey: "some.translation.key", error },
})
);
```
- switches to a raster image QR code so it can be long-pressed (or right
clicked) and added to iCloud keychain
- adds `autocomplete="one-time-code"` to the 2FA input for better
discoverability
This commit adds a check that runs regularly as per
2d68e5d942 which tests the
credentials of groups with SMTP or IMAP enabled. If any issues
are found with those credentials a high priority problem is added to the
admin dashboard.
This commit also formats the admin dashboard differently if
there are high priority problems, bringing them to the top of
the list and highlighting them.
The problem will be cleared if the issue is fixed before the next
problem check, or if the group's settings are updated with a valid
credential.
Meta topic: https://meta.discourse.org/t/cant-pin-unpin-topic-from-the-title/213444?u=osama.
I know there is an inconsistency between the category of the linked topic (#bug) and the title prefix of this PR, but I really couldn't find anything in the code base that suggested this ever worked before, so I'm categorizing this PR as a feature.
Running in production mode is useful when doing performance-sensitive work.
- Set the `exportApplicationGlobal` flag, so we get the `Discourse` global in production mode. It defaults to only adding the global in development mode. Note that, when generating ember-cli assets via rails, we set this in `ApplicationHelper#discourse_config_environment`.
- Disable SRI - Ember CLI adds this to index.html when in production mode. We don't use SRI in production, so disable here to match.
- Refactor the `AssetRev` logic in `ember-cli-build.js`, so that our custom bundle hashes are find/replaced into index.html. Without this change, our custom bundles (e.g. `start-discourse.js`) remain without their hash in `index.html`, and do not function.
I have confirmed that the only diff in the `/dist` out following this change is to the `index.html` file. All other filenames and contents remain identical.
You can add callbacks that get called before updating an already consolidated notification or creating a consolidated one.
Instances of this rule can add callbacks to access the old notifications about to be destroyed or the consolidated one and add additional data inside the data hash versus having to execute extra queries when adding this logic inside the `set_mutations` block.
Centralizes calculations in a helper under the site header component.
This also reverts a small CSS change to the composer: since ac79c5ef,
the composer height was not including the grippie, which means that the
composer height was off by 11 pixels, and the topic progress widget was
sometimes being displayed cut off by 11 pixels.
I plan to use this in an upcoming discourse-reactions PR, where I want to like a post without notifying the user, so I can instead create a reaction notification.
Additionally, we decouple the a11y attributes from the icon itself, which will let us extend the widget's icon without losing them.
A follow-up to #15117 and #15141. Applies the previous changes to PM-specific fields, makes the preview area take the all the available height of the composer, and unifies more spacing between composer elements.
This PR moves the behavior from the PostAlerter. We delete an existing liked notification and set the `username2` attribute to the previous `display_username`. We repeat this process unless the last one is old enough or it's not in the most recent ones.
The new draft sequence is returned after the draft is saved and usually
it is the old draft sequence plus one and this way the new draft
sequence can be predicted.
Sometimes drafts are saved at odd times or the request is slower than
usual which can create a race condition. This prediction can fix this
problem.
This commit removes jQuery file uploader from Discourse,
completing the transition to Uppy. The image-uploader
and UploadMixin components are also removed in this commit
as they have already been replaced and are the only things
using jQuery file upload.
.-'~~~`-.
.' `.
| R I P |
| jquery |
| file |
| upload |
| |
\\| 2013-2021 |//
-----------------
The `fancy_title` column in the `topics` table currently has a constraint that limits the column to 400 characters. We need to remove that constraint because it causes some automatic topics/PMs from the system to fail when using Discourse in locales that need more than 400 characters to the translate the content of those automatic messages.
Internal ticket: t58030.