Commit Graph

5841 Commits

Author SHA1 Message Date
Javi Martín
cbf11c2514 Use Rails::HTML5::Sanitizer when sanitizing HTML
Since we use a version of Loofah supporting HTML5 since db2d0bb80, the
`Rails::HTML::Sanitizer.best_supported_vendor` method will return the
HTML5 sanitizer. As mentioned in the pull request introducting this
change [1], the libxml2 maintainer wrote:

> it's still a bad idea to use a 20+ years old, unmaintained HTML 4
> parser to sanitize input for the modern web

So we're going with the new default sanitizer.

Note we aren't uncommenting the `action_text.sanitizer_vendor` option
because we don't use Action Text and so it doesn't affect us , and
uncommeting it will raise an error.

Also note we need to change one test because the new sanitizer handles
whitespace slightly differently.

[1] Pull request 48293 in https://github.com/rails/rails
2025-05-20 15:38:52 +02:00
Javi Martín
82c3c6646d Use Rails 7.1 cache format
Just like we mentioned in commit 001eee3d6, according to the Rails
configuration guide [1], with this format, Rails serializes cache
entries more efficiently. Most importantly:

> All formats are backward and forward compatible, meaning cache entries
> written in one format can be read when using another format. This
> behavior makes it easy to migrate between formats without invalidating
> the entire cache.

[1] https://guides.rubyonrails.org/v7.1/configuring.html#config-active-support-cache-format-version
2025-05-20 15:38:52 +02:00
Javi Martín
a6e735dc4e Generate a secure token when initializing a record
This options doesn't affect us because we don't use `has_secure_token`,
so we're just using the new default value.
2025-05-20 15:38:52 +02:00
Javi Martín
e35bf97928 Commit transactions when using return inside them
It doesn't really affect us because we never use `return`, `break` or
`throw` inside transactions, since it would be confusing exactly because
it wouldn't be 100% clear whether the transaction is committed or not.

So we're using the new default value, which will be the only available
option in Rails 7.2 [1].

[1] Commit eccc6061f4 in https://github.com/rails/rails
2025-05-20 15:38:52 +02:00
Javi Martín
d6b642a23d Run after_commit callbacks in order defined
This change doesn't affect us, since we don't use `after_commit`
callbacks, and, among our dependencies, AFAIK only the Devise gem uses
them, and it only defines one after_commit callback when creating a
record and another one when updating it, so we're never going to have
more than one callback being executed after a transaction is finished.
2025-05-20 15:38:52 +02:00
Javi Martín
0d0f3a48ff Use Rails 7.1 marshalling format
Enabling this option is only dangerous when deploying applications using
multiple servers. Since this isn't our case, we can enable it.
2025-05-20 15:38:52 +02:00
Javi Martín
7993f6d1ed Enable before_committed callbacks on all records
This doesn't really affect us because we don't use `before_committed`
callbacks (and neither do any of our dependencies), so we're using the
new default value.
2025-05-20 15:38:52 +02:00
Javi Martín
5ecd65b7dc Precompile filter parameters
This is done for performance reasons. Quoting the pull request
introducing this option [1]:

> A config might be overkill, but I wanted to provide an escape hatch
> for any upgraded apps that might be testing the exact value of the
> action_dispatch.parameter_filter header.

Since we don't test the exact value of action_dispatch.parameter_filter,
we can enable this option.

[1] Pull request 46452 in https://github.com/rails/rails
2025-05-20 15:38:52 +02:00
Javi Martín
529b4d2a98 Don't validate foreign key in required belongs_to
Before this change, every time we saved a record, the association was
validated if we had `belongs_to :something, required: true`. After this
change [1], it's only validated if the `something_id` column is nil (or
`something_type` for polymorphic associations) or if the `something_id`
attribute has changed.

The main difference is that we no longer get validation errors if the
associated record has been deleted. Doesn't affect us much, so we're
going with the new default value.

[1] Pull request 46522 in https://github.com/rails/rails
2025-05-20 15:38:52 +02:00
Javi Martín
364fa2603c Raise exceptions when assigning to attr_readonly attributes
Since we don't use attr_readonly, this option doesn't really affect us.
So we're just using the new default value.
2025-05-20 15:38:52 +02:00
Javi Martín
a1ae4651ff Simplify the way to set the maximum log size
We can use the new configuration option in Rails 7.1, so we don't have
to configure it manually.
2025-05-20 15:38:52 +02:00
Javi Martín
5db773e44f Serialize message data and metadata together
This is the new default option, and its only dangerous when deploying to
applications with multiple servers. Since this isn't our case, we can
enable it.
2025-05-20 15:38:52 +02:00
Javi Martín
e08ba7efbe Use JSON to serialize messages
The new serializer can decrypt legacy messages using the `marshal`
serializer, so there's no risk of losing data when upgrading. Since we
aren't using applications with several servers, where upgrading some
servers might cause issues on the servers that aren't upgraded yet,
we're enabling the option.

[1] See comments in pull request 42846 in https://github.com/rails/rails
2025-05-20 15:38:52 +02:00
Javi Martín
36828ee86b Use SQLCommenter format to format tags in Query Logs
Don't really care about the format, so we'll use the new default one.
2025-05-20 15:38:52 +02:00
Javi Martín
9054d31ab3 Raise exceptions on invalid cache expiration time
It doesn't really affect us (unless some of our dependencies make this
mistake) because we only use `expires_in/expires_at` once and we do it
correctly, but it might be help us detect this issue if we ever
introduce it in the future.
2025-05-20 15:38:51 +02:00
Javi Martín
e45dc5d45a Use BigDecimal argument serializer in Active Job
This option won't even exist in Rails 7.2 [1], and the possibility to
disable it was only added to guarantee safe upgrades in Rails
applications with multiple replicas [2].

Since we don't have applications with multiple replicas, where one
replica could be using Active Job 7.0 and another one could be using
Active Job 7.1 while upgrading, we can enable this options.

[1] Commit 2a761d23d2 in https://github.com/rails/rails
[2] Commit bc1f323338 in https://github.com/rails/rails
2025-05-20 15:38:51 +02:00
Javi Martín
2bedfacf3b Disable deprecated singular association names
This doesn't affect us (since luckily we never use them), and, since
doing something like `Budget::Investment.where(budgets: 1)` would be
very confusing, getting an error when writing this code is IMHO better
than just getting a warning, which was the default before Rails 7.1 [1].

[1] https://guides.rubyonrails.org/v7.1/configuring.html#config-active-record-allow-deprecated-singular-associations-name
2025-05-20 15:38:51 +02:00
Javi Martín
c0bc9bd027 Use Rails 7.1 default options for SQLite
It doesn't really affect us because we don't use SQLite.
2025-05-20 15:38:51 +02:00
Javi Martín
6eebe4e984 Don't run commit callbacks on first saved instances in transaction
It probably doesn't directly affect us, since we don't use
`after_commit` callbacks, and, among our dependencies, AFAIK only the
Devise gem uses them, to send the email with confirmation/reconfirmation
instructions.

The reasons for this change are explained in the guide to configure
Rails [1], while the pull request introducing the change has a couple of
great examples in its description [2].

[1] https://guides.rubyonrails.org/v7.1/configuring.html#config-active-record-run-commit-callbacks-on-first-saved-instances-in-transaction
[2] Pull request 45280 in https://github.com/rails/rails
2025-05-20 15:38:51 +02:00
Javi Martín
fbb40d701b Encrypt Active Record data using SHA256
Since we weren't encrypting any data, we can disable the
support_sha1_for_non_deterministic_encryption option, which should only
be enabled on existing applications that were encrypting data using
SHA1 [1].

[1] https://guides.rubyonrails.org/v7.1/upgrading_ruby_on_rails.html#active-record-encryption-algorithm-changes
2025-05-20 15:38:51 +02:00
Javi Martín
994d86ce2c Don't make ActionController::Parameters equivalent to Hash
The comparison equality was supposed to be deprecated since 2016 [1],
and completely deprecated in Rails 7.1 [2]. This options won't even
exist in the next version of Rails [3].

[1] Pull request 23733 in https://github.com/rails/rails
[2] Pull request 44812 in https://github.com/rails/rails
[3] https://github.com/rails/rails/commit/43e42c1ea
2025-05-20 15:38:51 +02:00
Javi Martín
402b64291c Use the new default headers
The only change between these headers and the ones sent by Rails 7.0
application is that the `"X-Download-Options" => "noopen"` is no longer
sent. Only Internet Explorer used that header, and uploading, previewing
and downloading attachments still works fine on Internet Explorer 11
after this change.

[1] Pull request 43968 in https://github.com/rails/rails
2025-05-20 15:38:51 +02:00
Javi Martín
77d113d640 Don't add autoload_paths to load_path
Quoting the Rails configuration guide [1]:

> applications running in :zeitwerk mode do not need require_dependency,
> so models, controllers, jobs, etc. do not need to be in $LOAD_PATH.
> Setting this to false saves Ruby from checking these directories when
> resolving require calls with relative paths, and saves Bootsnap work
> and RAM, since it does not need to build an index for them.

[1] https://guides.rubyonrails.org/v7.1/configuring.html#config-add-autoload-paths-to-load-path
2025-05-20 15:38:51 +02:00
Javi Martín
65e4a64084 Use preview_paths instead of preview_path
We were getting a deprecation warning in the logs after upgrading to
Rails 7.1:

```
DEPRECATION WARNING: Using preview_path= option is deprecated and will
be removed in Rails 7.2. Please use preview_paths= instead.
```

So we're appending a path to the `preview_paths`, as recommended in the
guide to upgrade to Rails 7.1 [1].

[1] https://guides.rubyonrails.org/v7.1/upgrading_ruby_on_rails.html#support-multiple-preview-paths-for-actionmailer-preview
2025-05-20 15:38:51 +02:00
Javi Martín
ce62da1f88 Silence deprecation warnings in secrets
We were getting a ton of deprecation warnings:

```
DEPRECATION WARNING: `Rails.application.secrets` is deprecated in favor
of `Rails.application.credentials` and will be removed in Rails 7.2
```

However, we don't plan to replace the secrets with credentials in the
foreseeable future because it would affect existing Consul Democracy
installations, so for now we're simply silencing the warnings.
2025-05-20 15:38:51 +02:00
Javi Martín
3d11aa86ce Fix ActiveStorage::IntegrityError when attaching PDFs
This is an error we've only been able to reproduce on one specific
machine and only when using the development environment.

It looks like Rails 7.1.5.1 uses `ActiveStorage::PreviewImageJob` when
we attach a PDF. However, that raises an IntegrityError because we're
removing the metadata from PDFs. That is, the final PDF is no longer the
same PDF that was uploaded.

This issue wasn't present in the original Rails 7.1.0 release, but was
introduced in Rails 7.1.4 [1] and has already been fixed in Rails 7.2.0
[2].

So we're applying the same solution that was applied in Rails 7.2.0:
disabling automatic previews for PDFs when no variants require them by
changing a method in `ActiveStorage::Attachment`.

[1] See commit 6f729dd39 in https://github.com/rails/rails/
[2] See pull request 51351 in https://github.com/rails/rails/
2025-05-20 15:38:47 +02:00
Javi Martín
0b1cfcd5da Upgrade to Rails 7.1
We're disabling `action_controller.raise_on_missing_callback_actions`
because sometimes we include `before_action :something, only: actions`
in concerns, and we include these concerns in controllers that don't
have all these actions.

Note that Rails 7.1 logs to STDOUT by default [1]; we're re-adding the
condition `if ENV["RAILS_LOG_TO_STDOUT"].present?` because we're still
using files and we're rotating the logs to avoid running out of space.

Also note that the GraphQL controller test (which is actually a request
test, since it's got `type: :request`) that was raising an exception no
longer does it thanks to the new default value for the
`config.action_dispatch.show_exceptions` configuration option. So we're
updating the test accordingly. This option doesn't affect regular
controller tests (without the `type: :request` option), so in other
tests we're still checking exceptions.

[1] Pull request 47138 in https://github.com/rails/rails
2025-05-20 13:12:29 +02:00
taitus
e662c704ac Vendor Foundation form builder to remove gem dependency
The "foundation_rails_helper" gem is no longer maintained and is
incompatible with Rails 7.1. To avoid blocking the upgrade, we've vendored
the vendor/foundation_rails_helper/form_builder.rb as a copy of the
original FormBuilder class.

To mantain compatibility with auto_labels and button_class variables, that
are used in the original builder, we are overwriting in the foundation
form builder initializer.

The gem has been removed from the Gemfile and replaced with this vendored
fallback. This workaround is safe to remove once legacy Foundation CSS
support is dropped.

All vendored code retains the original MIT license and attribution.
2025-05-06 17:07:08 +02:00
taitus
b07e429356 Remove monkey patch for connected_to in Rails 7
ros-apartment 3.0.0+ includes official support for connection handling in Rails 7,
so we no longer need to override `ActiveRecord::ConnectionHandling#connected_to`.

References: PR #194 and #243 in ros-apartment
2025-04-11 15:41:59 +02:00
taitus
30da0bc626 Update translations from Crowdin 2025-04-07 15:41:49 +02:00
Javi Martín
962aa388df Remove redundant placeholders in attachment fields
Saying that we're supposed to introduce a descriptive title in a field
labelled as "Title" is redundant. Besides, the text of the placeholder
was barely distinguishable, making it harder to fill in the form.
2025-04-03 15:00:12 +02:00
Javi Martín
4e08f3f147 Add a text to the links to execute dashboard actions
People using screen readers had no idea what these links were about (not
that the icons are very usable for people seeing them either... but
that's a different topic). Axe was reporting this error:

```
link-name: Links must have discernible text (serious)
https://dequeuniversity.com/rules/axe/4.10/link-name?application=axeAPI
The following 1 node violate this rule:

  Selector: #dashboard_action_2_execute
  HTML: <a id="dashboard_action_2_execute" class="unchecked-link"
           rel="nofollow" data-method="post"
           href="/proposals/16-proposal-6-title/dashboard/actions/2/execute">
          <span class="unchecked"></span>
        </a>
  Fix all of the following:
  - Element is in tab order and does not have accessible text
  Fix any of the following:
  - Element does not have text that is visible to screen readers
  - aria-label attribute does not exist or is empty
  - aria-labelledby attribute does not exist, references elements that
    do not exist or references elements that are empty
  - Element has no title attribute
```
2025-04-02 16:02:55 +02:00
Javi Martín
a1bdaf6e8f Add a text to the show password link in management area
We were using an icon for this link, but people who can't see the icon
couldn't know what the link was about. Axe was reporting the following
accessibility error:

```
link-name: Links must have discernible text (serious)
https://dequeuniversity.com/rules/axe/4.10/link-name?application=axeAPI
The following 1 node violate this rule:

  Selector: .show-password
  HTML: <a href="#" class="show-password">
          <span class="icon-eye"></span>
        </a>
  Fix all of the following:
  - Element is in tab order and does not have accessible text
  Fix any of the following:
  - Element does not have text that is visible to screen readers
  - aria-label attribute does not exist or is empty
  - aria-labelledby attribute does not exist, references elements
    that do not exist or references elements that are empty
  - Element has no title attribute
```
2025-04-02 15:57:23 +02:00
Javi Martín
3484c6b7b8 Use a list of links to change group in budgets wizard
The original implementation (which was never merged) had a `<select>`
field for the switch, which offered accessibility issues. So I came up
with a very bad idea, which was emulating the look and feel of a select
field while making it more accessible for keyboard users.

This approach is inconvenient because we were using a bunch of ARIA
roles to do the same thing that can be done with a list of links, going
against the first rule of ARIA, which is:

> "Don’t use ARIA if you can achieve the same semantics with a native
> HTML element or attribute

Not only that, but the control was confusing for people using mobile
phones (select fields don't behave the same way), and we were using
*invalid* ARIA roles in this situation, leading Axe to report a critical
accessibility error:

```
aria-required-children: Certain ARIA roles must contain particular
children (critical)
https://dequeuniversity.com/rules/axe/4.10/aria-required-children?application=axeAPI
The following 1 node violate this rule:

  Selector: ul[data-dropdown-menu="edw1i2-dropdown-menu"]
  HTML: <ul class="dropdown menu" wnenu="edw1i2-dropdown-menu"
            data-disable-hover="true" op="true" role="menubar">
  Fix any of the following:
  - Element has children which are not allowed: button[tabindex]
```

So, at least for now, we're using a simple list of links. We might style
it in the future if we find ways to make usability improvements, but,
for now, it does the job, and it does it better than the custom control
we were using.
2025-04-02 13:40:04 +02:00
Javi Martín
5ba6e7b692 Remove redeemable code
I don't think this feature it was ever used. It was introduced in commit
49dec6061 as part of a feature that was removed in commits 1cd47da9d and
c45a0bd8ac.
2025-03-26 16:42:04 +01:00
Javi Martín
2239b8fdca Remove obsolete questions index in the admin area
We removed the link to this page in commit 83e8d6035 because poll
questions don't really make sense without a poll.

However, this page also contained information about successful
proposals, which might be interesting so administrators don't have to
navigate to the public area in order to find and create questions based
on successful proposals.

So we're keeping the part about successful proposals and linking it from
the proposals part of the admin area.

Note we're using translation keys like `successful_proposals_tab`, which
don't make sense anymore, for the successful proposals. We're doing so
because we've already got translations for these keys and, if we renamed
them, we'd lose the existing translations and our translators would have
to add them again.

Also note we're changing one poll question test a little bit so we
create the question from a successful proposal using the new page. There
are other tests checking how to create a question from the
admin/proposals#show action and other tests checking what happens when
accessing a successful proposal in the admin section, so we don't lose
any test coverage by changing an existing test instead of adding a new
one.

Finally, note that we've removing the `search` method in poll question
because we no longer use it. This currently makes the
`author_visible_name` database column useless; we aren't removing it
right now because we don't want to risk a possible data loss in a patch
release (we're about to release version 2.3.1), but we might remove it
in the future.
2025-03-26 16:42:04 +01:00
Javi Martín
c5018e4a53 Remove obsolete video_url column in poll_questions table
This column isn't used since commit 4c0deb0ec because administrators can
associate videos to the answers since commit 5862eea51. The value of
this attribute isn't used in the public area since commit 8277e3cc2.
2025-03-26 16:42:04 +01:00
Javi Martín
d8c866c5e6 Remove initializers no longer in Rails
These initializers either don't contain any code at all or contain code
that we never use. Since this was the case in most Rails applications,
they're no longer generated in new Rails applications [1].

So we're removing them as well.

[1] See pull requests 42538 and 43237 in https://github.com/rails/rails
2025-03-06 12:11:51 +01:00
Javi Martín
dc05ff0fd6 Downgrade Sass to version 1.77.5
In commit 64bcedc8b, we upgraded Sass from version 1.70 to version 1.80.
However, since then we've noticed a couple of inconvenient things.

First, we're getting some deprecation warnings when compiling the
assets, related to a usage of `map-has-key` in Foundation which is
deprecated since Sass 1.80. Even with the `quiet_deps` flag, these
warnings aren't silenced.

Second, version 1.79 changed the way color functions work [1]. In
particular, functions like `color.adjust` or `darken` would now generate
RGB colors that include float numbers [2]. Browser support for float values
in RGB colors is about 98% at the time of writing [3], meaning some
browsers that are at least 5 or 6 years old will not render these
colors, sometimes resulting in white text over a white background, which
is of course impossible to read.

Finally, we get some deprecation warnings in our code when we remove the
`quiet_deps` flag, caused by the breaking change in mixed declaration
[4] from version 1.77.7 [5]. This warning is tricky; consider the following
code:

```
@mixin normal-selection {
  &::selection,
  *::selection {
    @include background-with-text-contrast($brand, brand, $check-invert-selection: false);
  }
}

.button.hollow {
  @include normal-selection;
  border: 1px solid;
}
```

In this scenario, since normal-selection is a mixin that generates a
nested rule, we're doing a declaration after a nested rule, which is now
deprecated.

The situation gets even more complicated when we define mixins that have
both nested rules and rules that apply to the element itself. Currently,
we sometimes include a mixin and then override some of the properties
the mixin defines, but we wouldn't be able to do so if we can't define
properties after including the mixin.

Right now, the solution seems to be adding `& { }` selectors
after including a mixin, like this:

```
.button.hollow {
  @include normal-selection;

  & {
    border: 1px solid;
  }
}
```

Which is incredibly cumbersome.

So, for now, we're downgrading to version 1.77.5 (we would downgrade to
version 1.77.6, but the sass-embedded gem skipped that version). That
version was released in June 2024, so it isn't very old yet. In the
future, we'll see what to do about the issues mentioned above, since
we'll have to upgrade at some point.

Note we're removing the `silence_deprecations` flag because Sass 1.77
doesn't raise warnings about using `import`.

[1] https://sass-lang.com/documentation/breaking-changes/color-functions/
[2] https://sass-lang.com/documentation/modules/color/#adjust
[3] https://caniuse.com/mdn-css_types_color_rgb_float_values
[4] https://sass-lang.com/documentation/breaking-changes/mixed-decls/
[5] https://sass-lang.com/documentation/js-api/interfaces/deprecations/#mixed_decls
2025-03-05 15:40:03 +01:00
Javi Martín
1eb45299e2 Fix missing Spanish translation
When we renamed this internationalization key in d25f2e725, we forgot to
rename it in Spanish as well.
2025-02-28 12:21:43 +01:00
taitus
7750dfa9f6 Update translations from Crowdin 2025-01-28 17:09:36 +01:00
Sebastia
b8460f2065 Merge pull request #5847 from consuldemocracy/i18n_crowdin
Update translations from Crowdin
2025-01-23 18:41:10 +01:00
taitus
c65495af6e Enable Portuguese (Portugal) by default 2025-01-23 18:22:36 +01:00
taitus
4126f03a58 Update translations from Crowdin 2025-01-23 17:49:58 +01:00
taitus
018b00cd6e Allow managing versions of cookies consent
This can be useful when adding a new cookie or making
modifications that require asking the user again.
2025-01-23 17:16:57 +01:00
taitus
7407c386a6 Render third party cookies in the management component
Set cookie duration to 365 days based on the AEPD's cookie usage guidelines.

Note from the document: "Cookies with a duration of up to 24 months are
considered acceptable as long as they are periodically updated."
Reference: https://www.aepd.es/guias/guia-cookies.pdf
2025-01-23 17:16:55 +01:00
taitus
dc54fda71b Allow accepting all cookies in consent banner and management component
Create cookie consent "all" when accept all cookies

Set cookie duration to 365 days based on the AEPD's cookie usage guidelines.

Note from the document: "Cookies with a duration of up to 24 months are
considered acceptable as long as they are periodically updated."
Reference: https://www.aepd.es/guias/guia-cookies.pdf
2025-01-23 17:03:30 +01:00
taitus
6753505e7c Allow administrators to define the cookies vendors the application uses 2025-01-23 17:03:30 +01:00
taitus
390c749d24 Add switch to management component for essentials cookies 2025-01-23 16:48:55 +01:00
taitus
d35455624f Allow accept essential cookies from management modal 2025-01-23 16:48:55 +01:00