The following methods have long been deprecated in ruby due to flaws in their implementation per http://blade.nagaokaut.ac.jp/cgi-bin/vframe.rb/ruby/ruby-core/29293?29179-31097:
URI.escape
URI.unescape
URI.encode
URI.unencode
escape/encode are just aliases for one another. This PR uses the Addressable gem to replace these methods with its own encode, unencode, and encode_component methods where appropriate.
I have put all references to Addressable::URI here into the UrlHelper to keep them corralled in one place to make changes to this implementation easier.
Addressable is now also an explicit gem dependency.
* DEV: Remove unused omit_stats variable from user serializer
This was hard-coded to true in a8b5192efd, and is no longer used anywhere
* Remove attribute declarations
When uploading a theme/component, depending on the extension of the
file and the OS/Browser being used, the content type might differ.
This adds the "application/x-zip-compressed" content type that is being
sent by most Browsers on latest Windows when uploading a .zip file.
* i was incorrectly toggling the transformed post property
instead of the actual property in the emberjs post model
which broke the bookmark/unbookmark functionality
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.
It's possibly that when trying to upload a backup the free space check
will output scientific notation resulting in an incorrect "There is not
enough space on disk" error.
The free space check uses the Linux `print` command which could return a
number using scientific notation like `1.60459e+10` and when ruby
converts it to an integer it will have the value of `1` instead of
`16045879296`. Which means even though you have 16GB of free space you
could not upload a 1GB backup file.
This commit uses the `printf` command instead which allows you to
specify that you do not want scientific notation.
I'm not sure why this hasn't been an issue before, but I was
experiencing it locally in development.
But the "synonyms" can't use the TagSerializer yet. We still have some
code from the discourse-tagging plugin that uses "text" instead of
"name", "count" instead of "topic_count", etc. We should make the js
consistent with the TagSerializer and then stop using tag_counts_json.
Ember was throwing this error preventing the reorder categories feature
from working:
```
access theidproperty (of <(unknown):ember1803>). ... the object in question
is a special kind of Ember object (a proxy). Therefore, it is still necessary
to use.get('id')in this case.
```
So I updated it to use the `get` method
https://api.emberjs.com/ember/3.14/functions/@ember%2Fobject/get
Follow up to: 6e5fedb312
If for some reason an URL was create in this format:
```
?slug[]=foo&slug[]=bar
```
This would have create an exception of this kind:
```
NoMethodError (undefined method `tr' for ["foo", "bar"]:Array
Did you mean? try)
```
We like to stay as close as possible to latest with rubocop cause the cops
get better.
This update required some code changes, specifically the default is to avoid
explicit returns where implicit is done
Also this renames a few rules
When the tag is muted and topic contains that tag, we should not mark that message as NEW.
There are 3 possible settings which site admin can set.
remove_muted_tags_from_latest - always
It means that if the topic got at least one muted tag, we should not mark that topic as NEW
remove_muted_tags_from_latest - only muted
Similar to above, however, if at least one tag is not muted, the topic is marked as NEW
remove_muted_tags_from_latest - never
Basically, mute tag setting is ignored and all topics are set as NEW
This is another refactoring in the multi-step process to remove all uses
of our custom Render Buffer.
Previous commit: da66950cf5 in this
series.
This commit affects the display of the backup logs. It is just a
refactor and does not change any functionality.
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.
Fixes an issue where updates to the first post in a topic would be visible only for staff.
Before, because the empty tag would find its way to `PostRevisor`, `TopicsController#update` would create a hidden revision, and later `PostsController#update` would only update that revision.
After this change, `TopicsController` doesn't create a revision at all (unless necessary), so `PostsController` can create it (and correctly decide whether the revision should be hidden or not).
* DEV: Add API to alter uploads Markdown
* DEV: Extract data attributes from image / download Markdown
For example '[test|attachment|hello=world]' will generate an 'a' element
with a data attribute: 'data-hello=world'.
This commit also makes MarkdownIt to transform '|attachment' into
'class="attachment"'. This transformation used to be a part of the
process which resolves short URLs (i.e. upload://).
* DEV: Export imageNameFromFileName
This reapplies commit b643526d9a after
being reverted in commit f65c453555.
Unlike the original commit, this does a single pass and does not take
into account unfinished code blocks.
This is another refactoring in the multi-step process to remove all uses
of our custom Render Buffer.
Previous commit: 54e4559aea in this
series.
This commit affects the display of the backup upload progress bar. It is
just a refactor and does not change any functionality.
This is another refactoring in the multi-step process to remove all uses
of our custom Render Buffer.
Previous commit: f269e45978 in this
series.
This commit affects the display of topic timers. It is just a refactor
and does not change any functionality.
When uploading an image file with dots in the filename we were splitting the string on dots and getting the last of the split items as the extension-less filename. However this did not work with filenames that have dots. We now just remove the extension using substr.
This is another refactoring in the multi-step process to remove all uses
of our custom Render Buffer.
Previous commit: fe9293b8b5 in this
series.
This commit affects the display of popup input tips, like in the
composer when the title is too short or too long. It is just a refactor
and does not change any functionality.
This is another refactoring in the multi-step process to remove all uses
of our custom Render Buffer.
Previous commit: 2290ec9e87 in this
series.
This commit affects the display of input tips. It is just a refactor and
does not change any functionality.
This is another refactoring in the multi-step process to remove all uses
of our custom Render Buffer.
Previous commit: 80f4b9e227 in this
series.
This commit affects the display of translated counts that is used in
multiple places like showing how many posts are selected using the
select posts feature on a topic. It is just a refactor and does not
change any functionality.
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
This is another refactoring in the multi-step process to remove all uses
of our custom Render Buffer.
Previous commit: bb31e7f5b6 in the series.
This commit affects the display of the Webhooks Deliver Status column. It
is just a refactor and does not change any functionality.
If a badge grouping happens to have been deleted a 500 error will be
thrown when looking a user's badges.
This fix allows the badge page to still be shown without any errors. The
badge with the missing badge grouping is still displayed.
I'll follow up with a separate pr/commit that will ensure if a badge
grouping is deleted, all badges with that badge_grouping_id will also be
updated.
* the code to get current user already got their
user_option record as well, so adding the timezone
column to the attributes returned should not create
any additional overhead. this timezone will be very
useful for getting momentjs dates relative to the
user's timezone
The tag-drop component uses the passed in categories to calculate paths,
but only the last category is relevant, since, from a category we can
calculate its ancestors.
Some endpoints are returning i18n keys instead of translated messages
and with these changes, the site_texts endpoint can help translating
those.
Pagination part is needed for better wildcard support. For example,
looking for 'js.notifications' would set 'has_more' to true, but return
only the first 50 messages with no way of fetching the remaining.
* Support for custom messages and redirects when creating posts
When a post/topic is created Discourse serializes a `NewPostResult`
object. Normally this contains a status like `created_post` or
errors describing why the post could not be created.
There are times when a plugin might want to take the inputted post
and do something in the background. In this case, the plugin
can return a custom `message` and `route_to` attribute in the
`NewPostResult`.
If present, the message will be displayed in an alert, and when "Ok" is
clicked the user will be routed to the new URL.
* Destroy the draft in parallel
This reverts commit 700bd280e4.
Oops looks like this breaks tests:
```
Module Failed: widget:quick-access-item
Test Failed: escapedContent attribute is not escaped
Assertion Failed: TypeError: Cannot read property 'match' of undefined
Expected: true, Actual: false
Test Failed: anonymous
Assertion Failed: failed, expected argument to be truthy, was: 0
Expected: true, Actual: 0
Assertion Failed: Element .enable-anonymous not found.
Test Failed: anonymous - switch back
Assertion Failed: failed, expected argument to be truthy, was: 0
Expected: true, Actual: 0
Assertion Failed: Element .disable-anonymous not found.
Test Failed: log out
Assertion Failed: failed, expected argument to be truthy, was: 0
Expected: true, Actual: 0
Assertion Failed: Element .logout not found.
Test Failed: content attribute is escaped
Assertion Failed: TypeError: Cannot read property 'match' of undefined
Expected: true, Actual: false
```
* 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
Note:
```
def foo(bar: 1)
end
foo({bar: 2})
# raises a deprecation, instead use:
foo(**{bar: 2})
```
Additionally when matching regexes always use strings. It does not make
sense to match a non string to a regex.
I could not replicate the failure locally, but it was consistently
failing on CI with:
```
Assertion Failed: it should escape watched words
Expected: <img src="x">, Actual: <img src="x">
```
This commit removes an extra space that was added originally, but I
don't think it is really needed after double checking how it displays in
the UI. The `x` icon and the word have sufficient spacing between them.
If we need to we can tweak it in css instead.
Follow up to: bb31e7f5b6
This commit fixes this failing test:
`Assertion Failed: it should escape watched words`
Now that we have a handlebars template we can us it for escaping because
it does that for us.
This is another refactoring in the multi-step process to remove all uses
of our custom Render Buffer.
Previous commit: 2673cad142 in this
series.
This commit affects the display of watched words on the admin watched
word page. It is just a refactor and does not change any functionality.
We already cache failed onebox URL requests client-side, we now want to cache this on the server-side for extra protection. failed onebox previews will be cached for 1 hour, and any more requests for that URL will fail with a 404 status. Forcing a rebake via the Rebake HTML action will delete the failed URL cache (like how the oneboxer preview cache is deleted).
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)
If a user has more than 60 active sessions, the oldest sessions will be terminated automatically. This protects performance when logging in and when loading the list of recently used devices.
This affects login_required sites which use SSO or have only one authenticator enabled. Previously, logging out would redirect to the homepage, which would then redirect to the identity provider. Now, users will be redirected to the Discourse login page. This avoids the confusing situation where a user appears to remain logged in after clicking logout.
Sites which have explicitly defined a logout_redirect url are not affected by this change.
For context, see https://meta.discourse.org/t/134138/2
This is a bottom up rewrite of Discourse cache to support faster performance
and a limited surface area.
ActiveSupport::Cache::Store accepts many options we do not use, this partial
implementation only picks the bits out that we do use and want to support.
Additionally params are named which avoids typos such as "expires_at" vs "expires_in"
This also moves a few spots in Discourse to use Discourse.cache over setex
Performance of setex and Discourse.cache.write is similar.
Discourse.cache is a more consistent method to use and offers clean fallback
if you are skipping redis
This is part of a larger change that both optimizes Discoruse.cache and omits
use of setex on $redis in favor of consistently using discourse cache
Bench does reveal that use of Rails.cache and Discourse.cache is 1.25x slower
than redis.setex / get so a re-implementation will follow prior to porting
This commit mostly get rid of the later() call and encapsulate all pie chart display logic inside discourse-poll-pie-canvas widget instead of sharing it between discourse-poll-pie-chart and discourse-poll-pie-canvas
This is another refactoring in the multi-step process to remove all uses
of our custom Render Buffer.
Previous commit: e0199e8094 in this
series.
This commit affects the table header sorting on the user directory page.
It is just a refactor and should not change any functionality.
* UX: adds hover effect on lightboxed images
This commits also adds two scss functions:
- is-light-color-scheme()
- is-dark-color-scheme()
This hover effect won't be added on dark color schemes, as images already standout nicely on dark backgrounds.
Co-Authored-By: David Taylor <david@taylorhq.com>
This commit corresponds to d84c34ad which applies the same changes to
the server-side. This changes the category routes, except for the routes
that contain tags.
This amends our API so we provide it with the draft key when saving a post
this means post creator can clean up the draft consistently even if we are
doing fancy stuff like replying to a new topic or new pm or whatever.
There will be some followup work to clean it up so client never calls destroy
on draft during normal operation and the #create/#update endpoints takes care of it
every time
This is another refactoring in the multi-step process to remove all uses
of our custom Render Buffer.
Previous commit: d0ad5ecc6d in this
series.
This commit affects the table header sorting on the admin directory page.
It is just a refactor and should not change any functionality.
If current value is nil we should use `&.` combined with `dig` to protect diff from erroring
It is happening when for example theme is delete (new value is empty)
* DEV: Remove buffered rendering from group-index-toggle
This is the first step in a refactor to remove all uses of our Buffered
Renderer:
01e2d5a670/app/assets/javascripts/discourse-common/lib/buffered-render.js.es6 (L3)
This commit affects the header sorting on the group member and the group
requests pages. It is a refactor only with no change in functionality.
When we receive a list of categories, we should store them so that we
are able to query them in the browser without a page refresh.
This removes a previous fix for the same issue that was much less
general.
This commit attempts to fix two issues that affect quoted images.
The first issue is observed while loading. The 'position: absolute' CSS
property makes 'width' and 'height' behave differently. Instead of using
the known image size, this makes it use the computed width and height of
the image, which should be the right size, as shown to the user.
The second issue is caused by 'object-fit: cover' property which trimmed
the left and right sides of wide pictures to make them fit inside the
quote.
* instead of using encodeURIComponent in imageNameFromFileName,
we just replace the bad characters that we wanted to get rid
of in the first place where we introduced encodeURIComponent.
as per review
Meta: https://meta.discourse.org/t/image-name-has-20-in-file-name/134136
We were ending up with [file%20name](url) in the markdown preview, which looked weird and
affected the alt text. this is because we were calling encodeURIComponent, which has been left in place because this is a valid thing to do for some cases. (e.g. f674b9e)
* 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
When category is dismissed, `dismiss_new` message is sent to fronted to clean state.
In addition, I noticed that when old dismiss new button is clicked, no message is sent so I decided to kill two birds with one stone.
In non-login-required sites, we prevent secure uploads already used in PMs from being used in public topics.
In login_required sites, secure uploads should be reusable in any topic, PM or not.
The plan is to switch over all cases where filterMode is set, but, to
prevent breaking plugins and themes, the category and noSubcategories
need to be inferred from any given filterMode before that can happen.
- 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.
* FEATURE: Normalize the service worker route
Update cache headers so they are not immutable outside of the rails app
Add the ability to purge the service worker cache from localhost
Rails -> nginx will pass immutable flags so the file is cached until reloaded.
In most cases, nginx will have its cache flushed on rebuild (new image)
For those needing dynamic re-caching (such as upgrading via the UI),
a rake task for flushing the service worker script is provided
through `assets:flush_sw`
The secure media functionality relied on `SiteSetting.enable_s3_uploads?` which, as we found in dev, did not take into account global S3 settings via `GlobalSetting.use_s3?`. We now use `SiteSetting.Upload.enable_s3_uploads` instead to be more consistent.
Also, we now validate `enable_s3_uploads` changes, because if `GlobalSetting.use_s3?` is true users should NOT be enabling S3 uploads manually.
If a post starts with a post quote and has no other text content,
then the email excerpt was the name of the person quoted and
nothing else. The intention was to show the contents of the
first paragraph or div after the quote.
With this change, a quote followed by an image will use the
image as the excerpt. A quote followed by a onebox will use the
onebox.
- Avoid using User#find and then fetching the user_stat association just to update a counter - We did this for every post in the topic.
- Avoid having to query the topic_allowed_user table everytime we want add a new topic_allowed_user
- Use pluck to fetch just what we need.
The group card and group members page were affecting each other and were
leaking members list and the query parameters which led to bad UX
experience and sub-optimal performance (client made more queries because
it was loading fewer members).
This commit refactors the group model to make it more consistent, remove
dead code, move error handling outside of model.
isPrivateMessages represents that the tag list is shown in the context
of private messages and pmOnly represents that the tag is used only in
private messages.
This PR introduces a new secure media setting. When enabled, it prevent unathorized access to media uploads (files of type image, video and audio). When the `login_required` setting is enabled, then all media uploads will be protected from unauthorized (anonymous) access. When `login_required`is disabled, only media in private messages will be protected from unauthorized access.
A few notes:
- the `prevent_anons_from_downloading_files` setting no longer applies to audio and video uploads
- the `secure_media` setting can only be enabled if S3 uploads are already enabled and configured
- upload records have a new column, `secure`, which is a boolean `true/false` of the upload's secure status
- when creating a public post with an upload that has already been uploaded and is marked as secure, the post creator will raise an error
- when enabling or disabling the setting on a site with existing uploads, the rake task `uploads:ensure_correct_acl` should be used to update all uploads' secure status and their ACL on S3