his is a new feature that lets admins dismiss notices from the dashboard. This helps with self-service in cases where a notice is "stuck", while we work on provisions to prevent "sticking" in the first place.
In TopicController, in addition to ensure_can_move_posts!, we also
checked if the topic is private message in this line:
```ruby
raise Discourse::InvalidAccess if params[:archetype] == "private_message" && !guardian.is_staff?
```
However, this was not present in `guardian.can_move_posts?`. As a result,
the frontend topic view got an incorrect serialized result, thinking
that TL4 could move the private message post. In fact, once they tried
to move it, they got the `InvalidAccess` error message.
This commit fixes that TL4 will no longer sees the "move to" option in
the "select post" panel for a private message.
Anonymous users are "shadow" users created when an existing real user desires to post anonymously. This feature is off by default, but it can be enabled via the `allow_anonymous_posting` site setting. Those shadow users shouldn't be included in the users directory (`/u`).
In 14cf8eacf1, we added the
`user_search_similar_results` site setting which when enabled will use
trigram matching for similarity search in `UserSearch`. However, we
noted that adding the `index_users_on_username_lower_trgm` index is
causing the PG planner to not use the `index_users_on_username_lower`
index when the `=` operator is used against the `username_lower` column.
Based on the PG mailing list discussion where support for the `=`
operator in gist_trgm_ops was being considered, it stated that "I also have checked that btree_gist is preferred over pg_trgm gist
index for equality search." This is however quite different from reality
on our own PG clusters where the btree index is not preferred leading to
significantly slower queries when the `=` operator is used.
Since the pg_trgm gist index is only used for queries when the `user_search_similar_results` site setting
is enabled, we decided to drop the feature instead as it is hidden and
disabled by default. As such, we can consider it experiemental and drop
it without deprecation.
PG mailing list discussiong: https://www.postgresql.org/message-id/CAPpHfducQ0U8noyb2L3VChsyBMsc5V2Ej2whmEuxmAgHa2jVXg%40mail.gmail.com
The user directory (`/u`) excludes inactive and silenced users from the list, so for the sake parity, it makes sense to also exclude those users from the /about page stats.
Internal topic: t/70928.
- fetch models inside services
- validate `user_id` in contracts
- use policy objects
- extract more logic to actions
- write specs for services and action
Adds support for `input-date` field when calling
`fill_in` on a FormKit field. Capybara supports passing
a Date object to `fill_in(with: value)` for date inputs,
so there is nothing fancy that needs to be done to support this.
Followup 0323b366f3
This was happening because another spec was adding a
report using the plugin API, but there was nothing
resetting that, so later in the reports controller
when we did Report.singleton_methods, we ended up
with another report with no translation, causing another
error.
The user option 'hide_profile_and_presence' is necessary to figure out
if the user status has to be displayed or not. In order to avoid N+1s
generated by `include_status?` method, both `user_status` and
`user_option` relations have to be included.
`track_sql_queries` only returned queries that were executed by
ActiveRecord. All queries executed through DB.exec, DB.query and others
were not returned.
Currently, when the custom flag has the same name as the system flag (which is disabled) then it is not displayed. To fix the problem, `custom_` prefix as `name_key` is used to distinguish between the system and the custom flag.
I considered writing a migration to fix existing custom flags name key. However, at the end of migration I would need to run rails code to reset cache `Flag.reset_flag_settings!`. I decided to skip that step as it is a very edge case. If someone has the same flag name as the system flag, then all they have to do is edit the flag and click save.
In addition, I made 2 small fixes:
- edit flag title was missing translation;
- flag form UI was not showing that description is the required field.
The Report model spec was directly adding methods
to the Report class, which was causing errors in the
admin reports controller because it would look for
a translation of the report name (e.g. report_timeout_test)
like so `I18n.t("reports.#{type}.title")`, then get an
error because the translation did not exist.
This is fixed by using `Report.stubs` instead, which is
cleaned up after every test.
This commit adds a new `about_page_hidden_groups` setting to exclude members of specific groups from the admin and moderator lists on the /about page.
Internal topic: t/137717.
### UI changes
All of the UI changes described are gated behind the `use_legacy_pageviews`
site setting.
This commit changes the admin dashboard pageviews report to
use the "Consolidated Pageviews with Browser Detection" report
introduced in 2f2da72747 with
the following changes:
* The report name is changed to "Site traffic"
* The pageview count on the dashboard is counting only using the new method
* The old "Consolidated Pageviews" report is renamed as "Consolidated Legacy Pageviews"
* By default "known crawlers" and "other" sources of pageviews are hidden on the report
When `use_legacy_pageviews` is `true`, we do not show or allow running
the "Site traffic" report for admins. When `use_legacy_pageviews` is `false`,
we do not show or allow running the following legacy reports:
* consolidated_page_views
* consolidated_page_views_browser_detection
* page_view_anon_reqs
* page_view_logged_in_reqs
### Historical data changes
Also part of this change is that, since we introduced our new "Consolidated
Pageviews with Browser Detection" report, some admins are confused at either:
* The lack of data before a certain date , which didn’t exist before
we started collecting it
* Comparing this and the current "Consolidated Pageviews" report data,
which rolls up "Other Pageviews" into "Anonymous Browser" and so it
appears inaccurate
All pageview data in the new report before the date where the _first_
anon or logged in browser pageview was recorded is now hidden.
This upgrade is designed to be fully backwards-compatible. Any icon names which have changed will be automatically remapped to the new name. For now, this will happen silently. In future, once core & official themes/plugins have been updated, we will start raising deprecation errors to help theme/plugin authors update their code.
Extracted from https://github.com/discourse/discourse/pull/28715
Announcement at https://meta.discourse.org/t/were-upgrading-our-icons-to-font-awesome-6/325349
Co-authored-by: awesomerobot <kris.aubuchon@discourse.org>
* FEATURE: Log tag group changes in staff action log
This commit records every change (add, change, delete) to a tag group in
the staff action log.
It uses a modal that was originally called ThemeChangeModal to display
changes, allowing staffs to see the specific changes clearly. The modal
is renamed to StaffActionLogChangeModal in this PR.
ref: https://meta.discourse.org/t/-/325011/14
Co-authored-by: Keegan George <kgeorge13@gmail.com>
This was added 10 years ago, but currently there's not a single use in our public and private plugins and no reference in third-party plugins on github
* FEATURE: Add user to topic_tags_changed event
Add user to topic_tags_changed event context
Update automation plugin with new arguments in event
Update tests for new arguments
relates to https://github.com/discourse/discourse-chat-integration/pull/214
* DEV: change variable name for better readability
changed `tags` to be payload and used `values_at` to get the values of the keys
This commit adds a link to the top of the new /about page, shown to admins only, to allow them to easily navigate to `/admin/config/about` where they can edit the /about page.
Internal topic: t/137546.
This patch removes the `with_service` helper from the code base.
Instead, we can pass a block with actions directly to the `.call` method
of a service.
This simplifies how to use services:
- use `.call` without a block to run the service and get its result
object.
- use `.call` with a block of actions to run the service and execute
arbitrary code depending on the service outcome.
It also means a service is now “self-contained” and can be used anywhere
without having to include a helper or whatever.
Currently, categories support designating only 1 group as a moderation group on the category. This commit removes the one group limitation and makes it possible to designate multiple groups as mods on a category.
Internal topic: t/124648.
This commit introduces a new hidden site setting: `group_pm_user_limit`, default to `1000` which will raise an error when attempting to create a PM target a large group.
This will bring significant improvements to install speed & storage requirements. For information on how it may affect you, see https://meta.discourse.org/t/324521
This commit:
- removes the `yarn.lock` and replaces with `pnpm-lock.yaml`
- updates workspaces to pnpm format
- adjusts package dependencies to work with pnpm's stricter resolution strategy
- updates Rails app to load modules from more specific node_modules directories
- adds a `.pnpmfile` which automatically cleans up old yarn-managed `node_modules` directories
- updates various scripts to call `pnpm` instead of `yarn`
- updates patches to use pnpm's native patch system instead of patch-package
- adds a patch for licensee to support pnpm
Currently, when the default locale is Japanese, the search for a topic
using its URL, path or ID doesn’t work as expected. It will either
return wrong results or no result at all.
The problem lies with how we process the provided terms in Japanese
mode. For example, if `http://localhost/t/-/55` is provided, currently
this will result in `http localhost t 5 5` to be searched for.
This patch addresses the issue by checking whether the provided term
needs segmenting. If the provided term is a number, or a path or a full
URL, then it doesn’t need segmenting. When that happens we skip the
processing we normally apply for Japanese, making the search return the
expected results.
TagUser.rb is used to set user notification levels for a tag, we don't have a unique index on the notification level itself. This means that there might be some weird case where a user may have multiple of the same notification level on a tag.
This PR adds a migration which de-duplicates this based on defaults, where we keep the earliest record in the event there is multiple notification level per-user-per-tag.
* add data migration to keep only unexpired or most recently expired user password
* refactor to 1:1 relationship between User and UserPassword
* add migration to remove redundant indexes on user passwords
A new setting attribute is used to define the areas (separated by `|`).
In addition, endpoint `/admin/config/site_settings.json` accepts new `filter_area` data.
A previous refactor has moved this function in the controller instead of the route making it inaccessible to the modal.
This commit is fixing this and also adding a spec.
This change introduces a new thread notification level allowing users to get notified when someone replies to the thread.
Users who watch a thread will get a green notification on the chat icon and a user notification (blue). User notifications are consolidated based on thread id to prevent cluttering the original users notification area.
---------
Co-authored-by: Régis Hanol <regis@hanol.fr>
This commit will allow plugin developers to enable/disable the custom homepage.
Usage:
```ruby
register_modifier(:custom_homepage_enabled) do |enabled, args|
true
end
```
Args might contain request and/or current_user.
This commit introduces a little bit of duplication
since the old plugin UIs not using the new plugin show
page look different from ones like AI and Gamification
which have been converted. We can use the new admin
header component on the plugins list, but for the other
pages we are manually rendering a breadcrumb trail and
the list of plugin tabs.
Over time as we convert more plugins to use the new UI
guidelines and show page we can get rid of this duplication.
* DEV: Split slow test in multiple smaller tests
This might be faster because the smaller chunks of the test may run in
parallel.
* DEV: Fabricate reviewables only once
* Do not delete created external upload stubs for 2 days
instead of 1 hour if enable_upload_debug_mode is true,
this aids with server-side debugging.
* If using an API call, return the detailed error message
if enable_upload_debug_mode is true. In this case the user
is not using the UI, so a more detailed message is appropriate.
* Add a prefix to log messages in ExternalUploadHelpers, to
make it easier to find these in logster.
Prior to this fix we were calling `fetch_stats` which is never checking if we have a cache entry. This call is making a lot of SQL calls, so it's better to use the cache.
We're seeing a lot of log noise coming from unhandled exceptions stemming from requests to TopicsController#show where id is passed in as an array.
In the implementation of the method, we assume that if id is present it will be a string. This is because one of the routes to this action uses :id as a URL fragment, and so must be a string. However, there are other routes that go to this endpoint as well. Some of them don't have this URL fragment, so you can pass an arbitrary id query parameter.
Instead of a downstream unhandled exception, we raise a Discourse::InvalidParameters upfront.
In this PR we introduced a new setting `enforce_second_factor_on_external_auth` which disables enforce 2FA when the user is authenticated with an external provider.
https://github.com/discourse/discourse/pull/27506
However, with the first registration with an external provider, we authenticate the user right after activation. In that case, we need to also keep information that the user was authenticated with an external OAuth provider.
We were not updating `searchTerm` when changing the input which was making us always send an empty q parameter.
This commit is also adding tests for:
- initial url with q param
- filtering the bookmarks through the input
Makes it easier to reach the group from the category security
tab, and moves the trash button to the right to avoid misclicks.
Also converts the category permission row to gjs
This is a follow-up of d749227e87.
This patch checks if the key `not_found` is present on the result object
instead of calling `#blank?` on the model, as it can trigger an
`ActiveRecord` relation.
To test the restricted routing when filling up required fields, we fill up the field and then navigate to the root path and checking that we're not redirected.
This is somewhat flaky, and the screenshot shows we are back at the profile page, without any prompt to fill up fields.
My hypothesis is in cases where the backend is "slow" to respond, we're navigating away from the page before the request finishes (which will redirect back to the profile page.)
This PR adds an expectation after saving, to wait until the unrestricted profile page is rendered, before navigating away.
This commit changes the cutoff number for the admins and mods lists on the new /about page from 12 to 6. If the admins or mods lists are bigger than 6, the about page will display the 6 most recently seen admins/mods, and tuck the rest away behind a "view more" button.
Given we are a single-page-app, we hijack the browser's default behavior
for keyboard shortcuts like End because on long topics (20+ posts) we
need to load the last post before really reaching the end of the page.
However, when the last post is already rendered, the End shortcut
currently does nothing, it takes the user to the start of the last post.
If that post is too long, the user will have to scroll down manually.
This change ensures that if the last post of a topic is already rendered
(whether it is in the viewport or not), pressing End will take the user
to the very bottom of the page.
Note for the reviewer: the test added here is for the general case, it
is too hard to test the case where the last post is already rendered,
that isn't covered here.
Follow-up to e3ae57ea7a
The previous commit added an `after_create` callback that triggers a refresh for the user directory whenever a `User` record is created. Theoretically, this approach should work, however, there's a gotcha in practice, because during a real user registration, when the `User` record is created in the database, it's not marked as active until the user verifies their email address and the user directory excludes inactive users, so the initial directory refresh triggered by the `after_create` callback becomes pointless.
To make a new user appear in the user directory immediately after sign up, we need to trigger a refresh via an `after_save` callback when they verify their email address and become active.
Currently, `FlagSerializer#short_description` properly provides
`base_path` to its translations, but `FlagSerializer#description` does
not. This breaks the link to guidelines when flagging a post, for
example.
This patch provides `base_path` for `FlagSerializer#description` too.
Prior this fix a topic created in the future could generate this exception:
```
Job exception: ERROR: a negative number raised to a non-integer power yields a complex result
```
This fix and spec should ensure we don't consider topics in the future as the rest of the `update_scores` function is doing at other places.
This check was checking the wrong scope, causing problems in certain edge conditions, for example:
1. Admin adds an "on signup" field that isn't editable after signup.
2. Admin adds a "for all users" field.
3. User goes and fills up the "for all users" field from 2.
4. User is now stuck on the required fields page without any fields showing.
With this change, we only consider "for all users" fields when asking if required custom fields are filled in.
Covers the use case of doing this in composer:
```javascript
page.execute_script("document.querySelector('.d-editor-input').setSelectionRange(6, 12);")
```
When searching for site texts for admin using the english
version of the text, previously we would show the english
version in the results _even if_ there was another locale
translated version available when a locale was selected
from the dropdown.
This commit adds a "Only show results in selected locale"
checkbox option which will instead make it so the results
shown are in the target locale, making it easier for translators
to tell when there is actually translations vs. missing tranlsations.
Followup 76c56c8284
The change introduced above made it so the expired
bookmark reminders were cleared when using the bulk
action menu for bookmarks. However this also affected
clearing reminders for bookmarks when sending notifications.
When clearing bookmark reminders after sending notifications,
we take into account the auto delete preference:
* never - The bookmark `reminder_at` date should not be cleared,
and the bookmark is kept.
* clear_reminder - The bookmark `reminder_at` date is cleared and
the bookmark is kept
The `never` option made it so "expired" bookmark reminder show
on the user's bookmark list.
This commit fixes the change from the other commit and only
forces clearing of `reminder_at` if using the bookmark bulk
action service.
If there is a codec issue or something trying to process a video file
for thumbnail generation, uploads could hang indefinitely. This fix
ensures that we continue the upload process even if we encounter an
error trying to generate a thumbnail for it.
If you’re viewing a tag and you switch to a different tag via the sidebar or the tags dropdown, after expanding the info section of the tag page via the wrench button, the info section keeps showing the previous tag's details instead of the new one.
This happens because the tag info section makes an ajax request to load the tag's details, and this request is made inside the `didInsertElement` hook which is only fired once when the component is rendered. To fix this, we need to set the result from the ajax request to null and add a `didUpdateAttrs` hook to trigger another request to load the info of the new tag.
Internal topic: t/134809.
This change is preventing the "is dirty check" from happening when clicking delete on this form. This was not good UX and was also causing bugs by leaving the form in a unexpected state.
This commit improves `TopicsController#show` to not load suggested and
related topics unless it is the last page of the topic's view.
Previously, we avoided loading suggested and related topics by the use
of conditionals in the `TopicViewSerializer` to avoid calling
`TopicView#suggested_topics` and `TopicView#related_topics`. However,
this pattern is not reliable as the methods can still be called from
other spots in the code base. Instead, we ensure that
`TopicView#include_suggested` and `TopicView#include_related` is set
correctly on the instance of `TopicView` which ensures that for the
given instance, `TopicView#suggested_topics` and
`TopicView#related_topics` will be a noop.
Previous to this change there is no clean way to apply keyboard shortcuts
to things such as "add poll" and other hidden options in the toolbar
This allows shortcuts to be specified similar to how they are on the toolbar
Co-authored-by: Joffrey JAFFEUX <j.jaffeux@gmail.com>
If we don't get a `videoWidth` back for a video don't try and generate a
thumbnail for it.
Also as part of this change I switched getImageData, the function
throwing the error, to use video.videoWidth instead of canvas.width
because it's very likely we were setting canvas.width too early before
the width could be read. Now that we are reading the value inside of the
setTimeout hopefully we will actually have a width. Just incase we don't
detect a width we will now exit early instead of throwing an error.
We only need to check for `0` and not null because the value is an
integer and will always return a 0 if it can't be read. https://developer.mozilla.org/en-US/docs/Web/API/HTMLVideoElement/videoWidth
See https://meta.discourse.org/t/322363
What did this fix?
===============
Previously, we only triggered this event in the `user.logged_out` method.
This resulted in the event being triggered only when the user was logged
out by the administrator or the site had strict logout mode enabled.
This bug affected customers who managed user status via webhooks.
meta topic: https://meta.discourse.org/t/user-log-out-event-not-triggered-in-webhooks/249464
This commit moves the business logic in the `Admin::UsersController#suspend` and `Admin::UsersController#silence` actions to dedicated service classes. There's no functional changes in this commit.
Internal topic: t/130014.
This commit implements 2 new metrics/stats in the /about page for the _estimated_ numbers of unique visitors from the EU and the rest of the world. This new feature is currently off by default, but it can be enabled by turning on the hidden `display_eu_visitor_stats` site settings via the rails console.
There are a number of assumptions that we're making here in order to estimate the number of unique visitors, specifically:
1. we're assuming that the average of page views per anonymous visitor is similar to the average number of page views that a logged-in visitor makes, and
2. we're assuming that the ratio of logged in visitors from the EU is similar to the ratio of anonymous visitors from the EU
Discourse keeps track of the number of both logged-in and anonymous page views, and also the number of unique logged-in visitors and where they're from. So with those numbers and the assumptions above, we can estimate the number of unique anonymous visitors from the EU and the rest of the world.
Internal topic: t/128480.
We need a way to disable certain checks programatically, e.g. on Discourse hosting. This PR adds a configuration option for this, and makes it so that disabled checks aren't run as part of #run_all.
This patch allows using an AR relation as a model in services without
fetching associated records. It will just check if the relation is empty
or not. In the former case, the execution will stop at that point, as
expected.
This commit introduces a new frontend API to add custom items to the "Site activity" section in the new /about page. The new API is called `addAboutPageActivity` and it works along side the `register_stat` serve-side API which serializes the data that the frontend API consumes. More details of how the two APIs work together is in the JSDoc comment above the API function definition.
Internal topic: t/128545/9.
This commit fixes a bug where the silence button is incorrectly displayed on the admin page of a staff user. It's not actually possible to silence a staff user because the backend correctly prevents it, but the frontend isn't checking if the button should be displayed.
Another small bug that this commit fixes is the similar users list not showing up inside the silence/suspend modals due to also a bug in the frontend.
I've also changed the way similar users are loaded so that they're not returned by the `admin/users#show` endpoint anymore and moved them into a new endpoint that the penalize modals (suspend and silence) can call directly to retrieve the list of users. This is done because the similar users list is never shown on the admin user page (`/admin/users/:user_id/:username`); they're only needed when the suspend or silence modals are opened.
Internal topic: t/130014.
Currently the push_notification_time_window_mins is set to 10
minutes by default. We want to change this to 1 minute, which is the
delay it has been set to on meta and our internal site already for over
a year now.
This conforms to the expectation users have that notifications are
delivered close to immediately.
This commit converts the Backups page in the admin interface
to follow our new admin interface guidelines.
As part of this work, I've also made `AdminPageHeader` and `AdminPageSubheader`
components that can be reused on any admin page for consistency, that handle
the title and action buttons and also breadcrumbs.
Also renamed `AdminPluginFilteredSiteSettings` to `AdminFilteredSiteSettings` since
it can be used generally to show a subset of filtered site settings, not only
settings for a plugin. Not sure if it's ideal to have to define a new route for this
for every config area, but not sure how else to do it right now.
This commit fixes two codepaths which where incorrectly working with capitalized usernames as we were doing a mix of username_lower and non lower username.
Also adds two specs for these cases.
This patch removes two freedom patches:
- `mail_disable_starttls.rb`: this has been fixed in the 2.8 release of
the mail gem, so we don’t need it anymore.
- `rails4.rb`: those methods have been deprecated for a while now and
should have been dropped with Discourse v3.2.
This commit adds a blue dot next to the "What's New"
link in the admin sidebar if the user has not seen the
new features yet, as a followup to 3e5976f843
which removed the tab on the dashboard that had this same
functionality.
When the admin visits the "What's New" page they count
as having seen all the features straight away. This could
be something we want to change, but for now this keeps the
same functionality.
* System user attachment size WIP
* spec check
* controller update
* add max to system_user_max_attachment_size_kb
* DEV: update to use static method for `max_attachment_size_for_user`
add test to use large image.
add check for failure.
* DEV: update `system_user_max_attachment_size_kb` default value to 0
remove unecessary test.
update tests to reflect the new default value of `system_user_max_attachment_size_kb`
* DEV: update maximum_file_size to check when is an attachment made by a system user
Add tests for when `system_user_max_attachment_size_kb` is over and under the limit
Add test for checking interaction with `max_attachment_size_kb`
* DEV: move `max_attachment_size_for_user` to private methods
* DEV: turn `max_attachment_size_for_user` into a static method
* DEV: typo in test case
* DEV: move max_attachment_size_for_user to private class method
* Revert "DEV: move max_attachment_size_for_user to private class method"
This reverts commit 5d5ae0b715.
---------
Co-authored-by: Gabriel Grubba <gabriel@discourse.org>
This has been split out from https://github.com/discourse/discourse/pull/28051
so we can use this same code in plugin specs before merging the core PR,
adds some helpers for creating local backup temp files
and cleaning them up.
We used to show New Features in a tab on the dashboard,
but this could get pushed down the page especially on
our hosting. In 043117ca13
we made a separate What's New page, so this commit removes
the dashboard tab and changes the admin notification to
send the admin to /admin/whats-new instead of the dashboard
tab.
* DEV: Removal of create_post_for_category_and_tag_changes setting
reverting commit: #65f35e1
and adding a migration to remove the setting
ref: t/132320
* DEV: change checks for zeros to check for nils
* DEV: remove create_post_for_category_and_tag_changes migration file
If anything goes wrong, we can always revert back to the previous state.