On some sites when bootstrapping communities it is helpful to bootstrap
with a "light weight" invite code.
Use the site setting `invite_code` to set a global invite code.
In this case the administrator can share the code with
a community which is very easy to remember and then anyone who has
that code can easily register accounts.
People without the invite code are not allowed account registration.
Global invite codes are less secure than indevidual codes, in that they
tend to leak in the community however in some cases when starting a brand
new community the security guarantees of invites are not needed.
Rails calls I18n.translate during initialization and by default translation overrides are used. Database migrations would fail if the system tried to migrate from an old version that didn't have the `translation_overrides` table with all its columns yet.
This makes restoring really old backups work again. Running `DISABLE_TRANSLATION_OVERRIDES=1 rake db:migrate` will allow you to upgrade such an old database as well.
Add enable_bookmark_at_desktop_reminders site setting default to false a new hidden site setting to hide the "At Desktop" reminder option so we can restrict this further until it is polished.
Adds 3 config values that allow to set a custom provider of Gravatar-like API accessible from gravatar_base_url. The gravatar_name is purely cosmetic, but helps with associating name with the service that actually provides the avatars. gravatar_login_url is a link relative to gravatar_base_url, which provides the user with the login to the Gravatar service
In some documentation heavy sites larger posts may be desirable.
This is not a setting to change without thinking, however where it is
needed it can make sense. Allow for a 50% increase in max over our
previous maximum.
The old limit of 99000 is arbitrary. Stuff gets riskier the longer posts
get especially with complex markdown, however 99000 is not a threshold
where stuff automatically breaks.
* This PR changes the user activity bookmarks stream to show a new list of bookmarks based on the Bookmark record.
* If a bookmark has a name or reminder it will be shown as metadata above the topic title in the list
* The categories, tags, topic status, and assigned show for each bookmarked post based on the post topic
* Bookmarks can be deleted from the [...] menu in the list
* As well as this, the list of bookmarks from the quick access panel is now drawn from the Bookmarks table for a user:
* All of this new functionality is gated behind the enable_bookmarks_with_reminders site setting
The /bookmarks/ route now redirects directly to /user/:username/activity/bookmarks-with-reminders
* The structure of the Ember for the list of bookmarks is not ideal, this is an MVP PR so we can start testing this functionality internally. There is a little repeated code from topic.js.es6. There is an ongoing effort to start standardizing these lists that will be addressed in future PRs.
* This PR also fixes issues with feature detection for at_desktop bookmark reminders
A custom date and time can now be selected for a bookmark reminder
The reminder will not happen at the exact time but rather at the next 5 minute interval of the bookmark reminder schedule.
This PR also fixes issues with bulk deleting topic bookmarks.
* This PR implements the scheduling and notification system for bookmark reminders. Every 5 minutes a schedule runs to check any reminders that need to be sent before now, limited to **300** reminders at a time. Any leftover reminders will be sent in the next run. This is to avoid having to deal with fickle sidekiq and reminders in the far-flung future, which would necessitate having a background job anyway to clean up any missing `enqueue_at` reminders.
* If a reminder is sent its `reminder_at` time is cleared and the `reminder_last_sent_at` time is filled in. Notifications are only user-level notifications for now.
* All JavaScript and frontend code related to displaying the bookmark reminder notification is contained here. The reminder functionality is now re-enabled in the bookmark modal as well.
* This PR also implements the "Remind me next time I am at my desktop" bookmark reminder functionality. When the user is on a mobile device they are able to select this option. When they choose this option we set a key in Redis saying they have a pending at desktop reminder. The next time they change devices we check if the new device is desktop, and if it is we send reminders using a DistributedMutex. There is also a job to ensure consistency of these reminders in Redis (in case Redis drops the ball) and the at desktop reminders expire after 20 days.
* Also in this PR is a fix to delete all Bookmarks for a user via `UserDestroyer`
* Remove some `.es6` from comments where it does not matter
* Use a post processor for transpilation
This will allow us to eventually use the directory structure to
transpile rather than the extension.
* FIX: Some errors and clean up in confirm-new-email
It would throw an error if the webauthn element wasn't present.
Also I changed things so that no-module is not explicitly
referenced.
* Remove `no-module`
Instead we allow a magic comment: `// discourse-skip-module` to prevent
the asset pipeline from creating a module.
* DEV: Enable babel transpilation based on directory
If it's in `app/assets/javascripts/dicourse` it will be transpiled
even without the `.es6` extension.
* REFACTOR: Remove Tilt/ES6ModuleTranspiler
There are three modifiers:
- serialize_topic_excerpts (boolean)
- csp_extensions (array of strings)
- svg_icons (array of strings)
When multiple themes are active, the values will be combined. The combination method varies based on the setting. CSP/SVG arrays will be combined. serialize_topic_excerpts will use `Enumerable#any`.
* Do not grant badges for posts with no user
* Ensure instructions are correct in Change Owner modal
* Hide user-dependent actions from posts with no user
* Make PostRevisor work with posts with no user
* Ensure posts with no user can be deleted
* discourse-narrative-bot should ignore posts with no user
* Skip TopicLink creation for posts with no user
Pop up a confirmation box when there is input. This prevents accidental closing
of the dialog boxes due to clicking outside.
This adds a development hook on modals in the form of a `beforeClose`
function. Modal windows can abort the close if the funtion returns false.
Additionally fixing a few issues with loop and state on the modal popups:
Escape key with bootbox is keyup.
Updating modal to close on keyup as well so escape key is working.
Fixes an issue where pressing esc will loop immediately back to the modal by:
keydown -> bootbox -> keyup -> acts as "cancel", restores modal
Needs a next call to reopenModal otherwise, keyup is handled again by the modal.
Fixes an issue where pressing esc will loop immediately back to the confirm:
esc keyup will be handled and bubble immediately back to the modal.
Additionally, only handle key events when the #discourse-modal is visible.
This resolves issues where escape or enter events were being handled by
a hidden modal window.
Introduces `/user-cards.json`
Also allows the client-side user model to be passed an existing promise when loading, so that multiple models can share the same AJAX request
Meta: https://meta.discourse.org/t/improve-error-message-when-not-including-name-setting-up-totp/143339
* when the user creates a TOTP second factor method we want
to show them a nicer error if they forget to add a name
or the code from the app, instead of the param missing error
* also add a client-side check for this and for security key name,
no need to bother the server if we can help it
Pop up a confirmation box when there is input. This prevents accidental closing
of the dialog boxes due to clicking outside.
This adds a development hook on modals in the form of a `beforeClose`
function. Modal windows can abort the close if the funtion returns false.
Additionally fixing a few issues with loop and state on the modal popups:
Escape key with bootbox is keyup.
Updating modal to close on keyup as well so escape key is working.
Fixes an issue where pressing esc will loop immediately back to the modal by:
keydown -> bootbox -> keyup -> acts as "cancel", restores modal
Needs a next call to reopenModal otherwise, keyup is handled again by the modal.
Fixes an issue where pressing esc will loop immediately back to the confirm:
esc keyup will be handled and bubble immediately back to the modal.
Additionally, only handle key events when the #discourse-modal is visible.
This resolves issues where escape or enter events were being handled by
a hidden modal window.
* FIX: We need to skip users with associated reviewables when auto-approving them
* Update spec/initializers/track_setting_changes_spec.rb
* Update spec/initializers/track_setting_changes_spec.rb
Co-authored-by: Robin Ward <robin.ward@gmail.com>
PMs will now display an envelope icon next to the topic title in search results. This is especially useful when searching using `in:all`.
Co-authored-by: adam j hartz <hz@mit.edu>
Introduces a new site setting `max_notifications_per_user`.
Out-of-the-box this is set to 10,000. If a user exceeds this number of
notifications, we will delete the oldest notifications keeping only 10,000.
To disable this safeguard set the setting to 0.
Enforcement happens weekly.
This is in place to protect the system from pathological states where a
single user has enormous amounts of notifications causing various queries
to time out. In practice nobody looks back more than a few hundred notifications.
Tracking down concurrency issues from backtraces and manual repros is a fraught process.
Sometimes you've just got to get your hands dirty and do a live debug.
Previously we had many places in the app that called `hostname` to get
hostname of a server. This commit replaces the pattern in 2 ways
1. We cache the result in `Discourse.os_hostname` so it is only ever called once
2. We prefer to use Socket.gethostname which avoids making a shell command
This improves performance as we are not spawning hostname processes throughout
the app lifetime
byebug, ruby-prof, better_errors and rbtrace are very MRI specific, flag
them as such
This helps move forward on potential jruby and truffleruby experiments
### UI Changes
If `SiteSetting.enable_bookmarks_with_reminders` is enabled:
* Clicking "Bookmark" on a topic will create a new Bookmark record instead of a post + user action
* Clicking "Clear Bookmarks" on a topic will delete all the new Bookmark records on a topic
* The topic bookmark buttons control the post bookmark flags correctly and vice-versa
Disabled selecting the "reminder type" for bookmarks in the UI because the backend functionality is not done yet (of sending users notifications etc.)
### Other Changes
* Added delete bookmark route (but no UI yet)
* Added a rake task to sync the old PostAction bookmarks to the new Bookmark table, which can be run as many times as we want for a site (it will not create duplicates).
This is not used in core or official plugins, and has been printing a deprecation notice since v2.3.0beta4. All OpenID 2.0 code and dependencies have been dropped. The user_open_ids table remains for now, in case anyone has missed the deprecation notice, and needs to migrate their data.
Context at https://meta.discourse.org/t/-/113249
When a tag is restricted to a secured category that the user can't see,
the message was saying that it wasn't restricted to any categories.
Now it will say it's restricted to categories you can't access.
This new iteration of select-kit focuses on following best principales and disallowing mutations inside select-kit components. A best effort has been made to avoid breaking changes, however if you content was a flat array, eg: ["foo", "bar"] You will need to set valueProperty=null and nameProperty=null on the component.
Also almost every component should have an `onChange` handler now to decide what to do with the updated data. **select-kit will not mutate your data by itself anymore**
This setting is very high risk and can potentially break all
sorts of features.
To avoid complications and save people from themselves we are
hiding the site setting.
It can still be modified using the console if absolutely needed.
Add nginx location to handle /secure-media-uploads/ requests .ico files were getting a 404 when being looked for via /secure-media-uploads/. this nginx config addition fixes the issue.
When 'categories topics' setting is set to 0, the system will
automatically try to find a value to keep the two columns (categories
and topics) symmetrical.
The value is computed as 1.5x the number of top level categories and at
least 5 topics will always be returned.
Adds a new route `/u/{username}/card.json`, which has a reduced number of fields. This change is behind a hidden site setting, so we can test compatibility before rolling out.
* FEATURE: Replace existing badge owners when using the bulk award feature
* Use ActiveRecord to sanitize title update query, Change replace checkbox text
Co-Authored-By: Robin Ward <robin.ward@gmail.com>
Co-authored-by: Robin Ward <robin.ward@gmail.com>
* UX: Invalid CSV error message now includes information about the malformed line
* Update config/locales/server.en.ym and use line_number instead of lineno
Co-Authored-By: Robin Ward <robin.ward@gmail.com>
Co-authored-by: Robin Ward <robin.ward@gmail.com>
* enqueue spam/dmarc failing emails instead of hiding
* add translations for dmarc/spam enqueued reasons
* unescape quote
* if email_in_authserv_id is blank return gray for all emails
Out-of-the-box Oj uses :object mode, this shifts us to use :compat mode
by default which is safer.
It means any de-serialization going forward will default to this mode.
If we wish to serialize or deserialize arbitrary objects going forward with
no json interfaces we will have to opt in.
* UI: Mass grant a badge from the admin ui
* Send the uploaded CSV and badge ID to the backend
* Read the CSV and grant badge in batches
* UX: Communicate the result to the user
* Don't award if badge is disabled
* Create a 'send_notification' method to remove duplicated code, slightly shrink badge image. Replace router transition with href.
* Dynamically discover current route
The QUnit rake task starts a server in test mode. We need a tweak to allow dynamic CSP hostnames in test mode. This tweak is already present in development mode.
To allow CSP to work, the browser host/port must match what the server sees. Therefore we need to disable the enforce_hostname middleware in test mode. To keep rspec and production as similar as possible, we skip enforce_hostname using an environment variable.
Also move the qunit rake task to use unicorn, for consistency with development and production.
This reverts commit 3193b0f6e6.
This is a temporary revert, we are seeing some CI failures due to this
change so I am reverting till we sort out all the problems.
MaxMind now requires an account with a license key to download files.
Discourse admins can register for such an account at:
https://www.maxmind.com/en/geolite2/signup
License key generation is available in the profile section.
Once registered you can set the license key using `DISCOURSE_MAXMIND_LICENSE_KEY`
This amends it so we unconditionally skip MaxMind DB downloads if no license key exists.
The env var `RAILS_ENABLE_TEST_LOG` didn't seem to do anything if enabled. This now sets the logger to STDOUT if `RAILS_ENABLE_TEST_LOG` is enabled and also introduces `RAILS_TEST_LOG_LEVEL` so the level of the logging in the console can be provided (default info).
Note: I am not sure if the original behaviour is expected. I can add an additional env var to enable the STDOUT logging if required
Added a fix to gracefully error with a Webauthn::SecurityKeyError if somehow a user provides an unkown COSE algorithm when logging in with a security key.
If `COSE::Algorithm.find` returns nil we now fail gracefully and log the algorithm used along with the user ID and the security key params for debugging, as this will help us find other common algorithms to implement for webauthn
This used to work due to side effects.
`rake parallel:migrate` used to work very inconsistently and would only migrate
some of the databases.
This introduces the recommended change to db.yml so the correct database is
found based off TEST_ENV_NUMBER if for some reason we did not set it using
RAILS_DB
Also avoids a bunch of schema dumping which is not needed when migrating
parallel specs
DB number 1 is very odd cause for whatever reason parallel spec is not
setting it.
- Refactor source_url to avoid using eval in development
- Precompile handlebars in development
- Include template compilers when running qunit
- Remove unsafe-eval in development CSP
- Include unsafe-eval only for qunit routes in development
The bug mentioned here
https://meta.discourse.org/t/badge-not-triggering/135896/8
Basically, descriptions for 3 badges: "Out of Love", "Higher Love" and
"Crazy in Love" are granted based on on "max_likes_per_day" and the
description should reflect that.
Currently at
tempting to access an invite via json will result in the following error:
```
HTTP_ACCEPT application/json, text/javascript, */*; q=0.01
GET /invites/xxxxxxx
ActionView::MissingTemplate (Missing template invites/show, application/show with {:locale=>[:en_US, :en], :formats=>[:json], :variants=>[], :handlers=>[:raw, :erb, :html, :builder, :ruby]}. Searched in:
* "/var/www/discourse/app/views"
)
```
According to the [Rails
Source](https://github.com/rails/rails/blob/master/activerecord/lib/active_record/railties/databases.rake#L20)
the `ActiveRecord::Migrator.migrations_paths` are overwritten with the
value of `ActiveRecord::Tasks::DatabaseTasks.migrations_paths` every
time the config is loaded.
This caused a bug for Discourse development where if you ran:
`rake db:drop db:create db:migrate` in one line, you would not get our
post migrations, as those had a custom value for `migrations_paths`.
The fix is to use `ActiveRecord::Tasks::DatabaseTasks.migrations_paths`
to set up all our custom paths. Everything seems to work as expected.
Plugins can add it via API if they need to use `eval`:
```
extend_content_security_policy(script_src: [:unsafe_eval])
```
See https://meta.discourse.org/t/104243
The trouble with having:
/tags/:tag_id/...
and:
/tags/intersection/*tag_ids
for example, is: what happens if you want a tag called intersection?
Under this new scheme. Routes referring to a single tag are unambiguous
because they are prefixed with:
/tag/:tag_id
Routes referring to the collection of tags still start with:
/tags/
This commit just adds the new routes. It doesn't remove the old ones or
cause the new ones to be used.
API keys are now only visible when first created. After that, only the first four characters are stored in the database for identification, along with an sha256 hash of the full key. This makes key usage easier to audit, and ensures attackers would not have access to the live site in the event of a database leak.
This makes the merge lower risk, because we have some time to revert if needed. Once the change is confirmed to be working, we will add a second commit to drop the `key` column.
Note: All of this functionality is hidden behind a hidden, default false, site setting called `enable_bookmarks_with_reminders`. Also, any feedback on Ember code would be greatly appreciated!
This is part 1 of the bookmark improvements. The next PR will address the backend logic to send reminder notifications for bookmarked posts to users. This PR adds the following functionality:
* We are adding a new `bookmarks` table and `Bookmark` model to make the bookmarks a first-class citizen and to allow attaching reminders to them.
* Posts now have a new button in their actions menu that has the icon of an actual book
* Clicking the button opens the new bookmark modal.
* Both name and the reminder type are optional.
* If you close the modal without doing anything, the bookmark is saved with no reminder.
* If you click the Cancel button, no bookmark is saved at all.
* All of the reminder type tiles are dynamic and the times they show will be based on your user timezone set in your profile (this should already be set for you).
* If for some reason a user does not have their timezone set they will not be able to set a reminder, but they will still be able to create a bookmark.
* A bookmark can be deleted by clicking on the book icon again which will be red if the post is bookmarked.
This PR does NOT do anything to migrate or change existing bookmarks in the form of `PostActions`, the two features live side-by-side here. Also this does nothing to the topic bookmarking.
When a component is installed and not assigned to any theme and the user is changing page, we should display a warning.
If the user decides to skip warning or come back later, a warning should not be shown anymore.
Also, when the user clicks "delete" button right after installation, warning about forgotten themes should not be shown.
This feature adds the ability to define synonyms for tags, and the ability to merge one tag into another while keeping it as a synonym. For example, tags named "js" and "java-script" can be synonyms of "javascript". When searching and creating topics using synonyms, they will be mapped to the base tag.
Along with this change is a new UI found on each tag's page (for example, `/tags/javascript`) where more information about the tag can be shown. It will list the synonyms, which categories it's restricted to (if any), and which tag groups it belongs to (if tag group names are public on the `/tags` page by enabling the "tags listed by group" setting). Staff users will be able to manage tags in this UI, merge tags, and add/remove synonyms.
* FEATURE: ability to add all active components to theme
* FIX: add a component to all themes takes only active ones
* FIX: move select components/themes to top
* FIX: improve defaultIsAvailable
* FIX: Add filter(Boolean) and remove btn class
* FEATURE: Ability to add components to all themes
This is the first and functional step from that topic https://dev.discourse.org/t/adding-a-theme-component-is-too-much-work/15398/16
The idea here is that when a new component is added, the user can easily assign it to all themes (parents).
To achieve that, I needed to change a site-setting component to accept `setDefaultValues` action and `setDefaultValuesLabel` translated label.
Also, I needed to add `allowAny` option to disable that for theme selector.
I also refactored backend to accept both parent and child ids with one method to avoid duplication (Renamed `add_child_theme!` to more general `add_relative_theme!`)
* FIX: Improvement after code review
* FIX: Improvement after code review2
* FIX: use mapBy and filterBy directly
When uploading a file to a theme component, and that file is existing and has already been marked as secure, we now automatically mark the file as secure: false, change the ACL, and log the action as the user (also rebake the posts for the upload)
* Add timezone to user_options table
* Also migrate existing timezone values from UserCustomField,
which is where the discourse-calendar plugin is storing them
* Allow user to change their core timezone from Profile
* Auto guess & set timezone on login & invite accept & signup
* Serialize user_options.timezone for group members. this is so discourse-group-timezones can access the core user timezone, as it is being removed in discourse-calendar.
* Annotate user_option with timezone
* Validate timezone values
- Show old and new email address during the process
- Ensure correct user is logged on when attempting to make email changes
- Support reloading a page during the email reset process without resubmit
of form
- Improve tests
- Fixed issue where redirect back to site was not linking correctly in
subfolder setups
Internal refactor of single action into 4 distinct actions that are simpler
to reason about.
This also removes the step that logs on an account after you confirm an
email change, since it is no longer needed which leaves us with safer
internals.
This left me no choice but to amend translations cause the old route was
removed.