455 Commits

Author SHA1 Message Date
Javi Martín
4984ac44d3 Use the default job queue to deliver emails
This is the default in Rails 6.1 for Action Mailer, just like it's the
default for Active Storage.
2023-09-11 23:40:37 +02:00
Javi Martín
50dc9dee69 Disable legacy database connection handling
Since we aren't using the old way to handle multiple databases (because
we don't use multiple databases), we can safely enable this option
without breaking anything.
2023-09-11 23:40:37 +02:00
Javi Martín
fe94d84e81 Use 308 as SSL default redirect status
This way user agents will know that the redirection from HTTP to HTTPS
is permanent and not temporary, which is the case if we activate the
`force_ssl` option (which we do by default).
2023-09-11 23:40:37 +02:00
Javi Martín
05eecaf46c Return UTC offests in the utc_to_local method
We don't use this method anywhere, so we might use the new default in
Rails 6.1, which was added when Rails started using tzinfo 2.
2023-09-11 23:40:37 +02:00
Javi Martín
4fe9d4cbcf Use URL-safe CSRF tokens and SameSite in cookies
These measures increase protection against CSRF ataks. The only reason
Rails provides them as a configuration option is there are complex
applications that run one version of the code in some servers while
running an old version of the code in other servers might run into
issues because the the old version won't handle the tokens or cookies
generated by the new version.

Since most Consul applications use just one server and the ones with
more servers would only face this issue for a few seconds (while
upgrading to a new version of Consul Democracy), we can safely enable
these configuration options.
2023-09-11 23:40:37 +02:00
Javi Martín
e8c8b00e94 Skip after callbacks if terminated in active job
Not sure this configuration option does anything, though, since it's
been removed in Rails 7.0 because it was not halting the callbacks.

But, if it does nothing, it's the same as disabling it, which is what we
were doing until now, so in the end using the Rails 6.1 default value
does no harm.
2023-09-11 23:40:37 +02:00
Javi Martín
8a6b9dcb46 Delete action mailbox options since we don't use it
Simply uncommeting them raised an exception.
2023-09-11 23:40:37 +02:00
Javi Martín
8e2b7e231f Configure "retry jitter" option in active job
This way, when several jobs fail at the same time, not all of them will
be retried at the same time.
2023-09-11 23:40:37 +02:00
Javi Martín
600bc793a1 Store Active Storage variants in the database
This mostly benefit people using external services, as now there's no
need to query the service to check whether a variant exists.

For most Consul Democracy installations, this will probably not be
relevant, so we're sticking wih the default value.
2023-09-11 23:40:37 +02:00
Javi Martín
1f67318f84 Delete configuration options that are now redundant
These options are the default options in Rails 6.1, so we no longer need
to customize them.
2023-09-11 23:40:37 +02:00
Javi Martín
13eebe4d7a Remove Wicked PDF monkey patch
This patch was added in commit baefc249f because both ViewComponent and
Wicked PDF monkey-patched the `render` method and so they were
incompatible.

However, Rails 6.1 includes the patch used by ViewComponent, meaning
ViewComponent doesn't monkey-patch the `render` method anymore, and so
it's compatible with Wicked PDF.
2023-09-11 23:40:37 +02:00
Javi Martín
6e9df3be5a Upgrade to Rails 6.1
Note that `Capybara.app_host` now returns `nil` by default and that
breaks tests using `lvh.me` or our custom `app_host` method, so we're
setting `Capybara.app_host` to the value it had in earlier versions of
Rails. I also haven't found a way to remove the code to set the
integration session host in relationable tests which I mentioned in
commit ffc14e499.

Also note that we now filter more parameters, and that they match
regular expressions, so filtering `:passw` means we're filtering
`passwd`, `password`, ...
2023-09-11 23:40:37 +02:00
Javi Martín
a1439d0790 Apply Layout/LineLength rubocop rule
Note we're excluding a few files:

* Configuration files that weren't generated by us
* Migration files that weren't generated by us
* The Gemfile, since it includes an important comment that must be on
  the same line as the gem declaration
* The Budget::Stats class, since the heading statistics are a mess and
  having shorter lines would require a lot of refactoring
2023-08-30 14:46:35 +02:00
Javi Martín
9491b20314 Extract method to get vote counts by votable type 2023-08-30 14:46:34 +02:00
Senén Rodero Rodríguez
b85df50a28 Configure airbrake as Errbit documentation says
Quoting `errbit/errbit/blob/main/app/views/apps/_configuration_instructions.html.erb`

> airbrake.io supports various features that are out of scope for Errbit.
2023-05-29 13:50:33 +02:00
Javi Martín
5c2ca27df1 Update Globalize monkey-patch to forward kw args
This method changed in Globalize version 6.0.1 [1], which we're using since
commit 6072372c9d.

We were getting a deprecation warning in Ruby 2.7:

```
config/initializers/globalize.rb:8: warning: Using the last argument as
keyword parameters is deprecated; maybe ** should be added to the call
```

So we're using the `(...)` arguments syntax to make it compatible with
Ruby 3.0, just like Globalize does when using Ruby 2.7.

[1] See pull request 778 in the globalize/globalize GitHub repo.
2023-01-26 17:19:15 +01:00
Senén Rodero Rodríguez
e08d287ef8 Do not track Apartment::TenantNotFound exceptions through Airbrake
As we do with `ActiveRecord::NotFound` exceptions. Otherwise, we
can quickly flood the third-party application in charge of tracking
exceptions.
2022-12-20 16:46:00 +01:00
Javi Martín
e38b860374 Use the right tenant after Devise redirections
This is something we had read about a long time ago, but didn't find how
to reproduce the issue until now.

As mentioned in the Apartment documentation:

> it's important to consider that you may want to maintain the
> "selected" tenant through different parts of the Rack application
> stack. For example, the Devise gem adds the Warden::Manager middleware
> at the end of the stack in the examples above, our
> Apartment::Elevators::Subdomain middleware would come after it.
> Trouble is, Apartment resets the selected tenant after the request is
> finished, so some redirects (e.g.  authentication) in Devise will be
> run in the context of the "public" tenant. The same issue would also
> effect a gem such as the better_errors gem which inserts a middleware
> quite early in the Rails middleware stack.
>
> To resolve this issue, consider adding the Apartment middleware at a
> location in the Rack stack that makes sense for your needs, e.g.:
>
> Rails.application.config.middleware.insert_before Warden::Manager,
> Apartment::Elevators::Subdomain
>
> Now work done in the Warden middleware is wrapped in the
> Apartment::Tenant.switch context started in the Generic elevator.
2022-11-19 17:49:27 +01:00
Javi Martín
58c9e8462d Only seed tenants when necessary in tests
On my machine, seeding a tenant takes about one second, so skipping this
action when it isn't necessary makes tests creating tenants faster
(although creating a tenant still takes about 3-4 seconds on my
machine).
2022-11-11 01:40:02 +01:00
Eduardo Vilar
0ea61b9b61 Allow different omniauth settings per tenant
Co-Authored-By: Javi Martín <javim@elretirao.net>
2022-11-11 01:39:30 +01:00
Eduardo Vilar
52ebeb7ba6 Consider the current tenant with delayed jobs 2022-11-09 18:19:20 +01:00
Javi Martín
5983006657 Use a custom method to detect the current tenant
The subdomain elevator we were using, which is included in apartment,
didn't work on hosts already including a subdomain (like
demo.consul.dev, for instance). In those cases, we would manually add
the subdomain to the list of excluded subdomains. Since these subdomains
will be different for different CONSUL installations, it meant each
installation had to customize the code. Furthermore, existing
installations using subdomains would stop working.

So we're using a custom method to find the current tenant, based on the
host defined in `default_url_options`.

In order to avoid any side-effects on single-tenant applications, we're
adding a new configuration option to enable multitenancy

We're enabling two ways to handle this configuration option:

a) Change the application_custom.rb file, which is under version control
b) Change the secrets.yml file, which is not under version control

This way people prefering to handle configuration options through
version control can do so, while people who prefer handling
configuration options through te secrets.yml file can do so as well.

We're also disabling the super-annoying warnings mentioning there are no
tenants which we got every time we run migrations on single-tenant
applications. These messages will only be enabled when the multitenancy
feature is enabled too. For this reason, we're also disabling the
multitenancy feature in the development environment by default.
2022-11-09 18:19:20 +01:00
Javi Martín
c483c6036a Install extensions in a shared schema
This way all tenants will be able to access them instead of just the
default one.

The apartment gem recommends using a rake task instead of a migration,
but that's a solution which is primarily meant for new installations.
Migrations are easier to execute on existing installations.

However, since this migration doesn't affect the `schema.rb` file, we
still need to make sure the shared schema is created in tasks which do
not execute migrations, like `db:schema:load` or `db:test:prepare`, just
like the apartment gem recommends. That's why we're enhancing these
tasks so they execute this migration.

Note that there might be cases where the database user isn't a superuser
(as it's usually the case on production environments), meaning commands
to create, alter or drop extensions will fail. There's also the case
where users don't have permissions to create schemas, which is needed in
order to create the shared extensions schema and the schemas used by the
tenants. For these reasons, we're minimizing the number of commands, and
so we only alter or create extensions when it is really necessary.

When users don't have permission, we aren't running the commands but
showing a warning with the steps needed to run the migration manually.
This is only necessary on installations which are going to use
multitenancy; single-tenant applications upgrading don't need to run
this migration, and that's why we aren't raising exceptions when we
can't run it.

For new installations, we'll change the CONSUL installer so extensions
are automatically created in the shared schema.

Also note the plpgsql extension is not handled here. This is a special
extension which must be installed on the pg_catalog schema, which is
always in the search path and so is shared by all tenants.

Finally, we also need to change the `database.yml` file in order to
search for shared extensions while running migrations or model tests,
since none of our enabled extensions are executed during migrations;
we're also adding a rake task for existing installations. Quoting the
apartment documentation:

> your database.yml file must mimic what you've set for your default and
> persistent schemas in Apartment. When you run migrations with Rails,
> it won't know about the extensions schema because Apartment isn't
> injected into the default connection, it's done on a per-request
> basis.
2022-11-09 17:53:31 +01:00
Eduardo Vilar
382abb3666 Add multitenancy with apartment
Co-Authored-By: Javi Martín <javim@elretirao.net>
2022-11-09 17:52:05 +01:00
Senén Rodero
9e0c09ebe1 Merge pull request #5004 from consul/omniauth-log
Configure OmniAuth to send log to Rails logger
2022-10-07 12:54:50 +02:00
Javi Martín
a729967e8a Make Devise::Mailer inherit from ApplicationMailer
This way we remove duplication in the `from:` proc, the helpers, and the
methods we're about to write.
2022-10-06 13:18:05 +02:00
Senén Rodero Rodríguez
ddc7b626f5 Configure OmniAuth to send log to Rails logger
Before this change log generated by OmniAuth was sent to the STDOUT. Now
developers will find those gems log within the `app/log` directory as expected.
2022-10-05 12:48:13 +02:00
Julian Herrero
24276a201e Remove useless answers show view
Until now, in order to edit an answer, we had to click on its title on
the table and then on the "Edit answer" link.

That was tedious and different from what we usually do in the admin
section. Furthermore, the code for the answers table was written twice
and when we modified it we forgot to update the one in the `show`
action, meaning the table here provided less information than the
information present in the answers tables.

Co-Authored-By: Javi Martín <javim@elretirao.net>
2022-09-14 14:45:35 +02:00
Javi Martín
5b844bf231 Use index_with to simplify hash generation
This method was introduced in Rails 6.0. It can be used to take an array
and create a hash where the elements of the array are the indexes of the
hash.
2022-08-24 18:19:02 +02:00
Javi Martín
0b613158da Update TranslationHelper monkey-patch
The `translate` method now receives keyword arguments instead of a hash
of options.
2022-08-24 14:36:49 +02:00
Javi Martín
7fe2309762 Use Rails 6.0 defaults and overwrite them
We can remove the `new_framework_defaults_6_0` file by using Rails 6.0
default options and overwriting the ones we haven't enabled.

We're still using the classic autoloader because we still haven't
checked how switching to zeitwerk will affect the way CONSUL
installations customize their code.

And we're using the default queues for Active Storage because we were
already using them and that will be the default option in Rails 6.1.
2022-08-24 14:36:49 +02:00
Javi Martín
1ea4988e52 Enable collection cache versioning
Similar to the way we enabled cache versioning in commit e01a94d7b. This
only affects caching `ActiveRecord::Relation` objects. I'm not even sure
we cache these objects, though, so we're just enabling the option
because it's the default one in Rails 6.0.
2022-08-24 14:36:49 +02:00
Javi Martín
af1244654c Use MailDeliveryJob to send mail in the background
The default delivery job class in Rails 5.2 (ActionMailer::DeliveryJob)
is deprecated.

This option wasn't already enabled in order to ease the upgrade, since
after upgrading with Rails 6 `MailDeliveryJob`, it won't be possible to
downgrade to Rails 5.2 without risking some crashes in background jobs.
2022-08-24 14:36:49 +02:00
Javi Martín
390a82ff8e Use Rails 6 attachments defaults in Active Storage
In Active Storage 5.2 there was an unexpected behavior: assigning a
collection appended records to the existing collection, instead of
replacing them as it's done in Active Record associations.

It doesn't really affect us, though, since we don't use
`has_many_attached` anywhere.
2022-08-24 14:36:49 +02:00
Javi Martín
3302f8c64d Return false on aborted enqueue in Active Job
In order to prevent a warning:

```
Rails 6.1 will return false when the enqueuing is aborted. Make sure
your code doesn't depend on it returning the instance of the job and set
`config.active_job.return_false_on_aborted_enqueue = true` to remove the
deprecations.
```
2022-08-24 14:36:49 +02:00
Javi Martín
8d7ce6f428 Return content-type header without modification
This is the default in Rails 6.0. I don't think it affects us, though.
2022-08-24 14:36:49 +02:00
Javi Martín
55d4d3cd5c Enable cookies with metadata
This is the default encryption for cookies in Rails 6.0 applications.
The reason it isn't enabled automatically for existing applications is
these cookies are not compatible with running the application with Rails
5. Since this isn't our case, and existing cookies are still read
correctly, we can safely enable it.
2022-08-24 14:36:48 +02:00
Javi Martín
7f7195ac0d Remove hidden UTF input in forms
This feature was kept in Rails mainly for Internet Explorer 8 and
earlier. But those browsers are now used by less than 0.1% of the
population, and we already display an alert for people using that
browser, warning we don't support it.
2022-08-24 14:36:48 +02:00
Javi Martín
ffc14e499a Upgrade to Rails 6.0
All the code in the `bin/` and the `config/` folders has been generated
running `rake app:update`. The only exception is the code in
`config/application.rb` where we've excluded the engines that Rails 6.0
has added, since we don't use them.

There are a few changes in Active Storage which aren't compatible with
the code we were using until now.

Since the method to assign an attachment in ActiveStorage has changed
and is incompatible with the hack we used to allow assigning `nil`
attachments, and since ActiveStorage now supports assigning `nil`
attachments, we're removing the mentioned hack. This makes the
HasAttachment module redundant, so we're removing it.

Another change in ActiveStorage is files are no longer saved before
saving the `ActiveStorage::Attachment` record. This means we need to
manually upload the file when using direct uploads. We also have to
change the width and height validations we used for images; however,
doing so results in very complex code, and we currently have to write
that code for both images and site customization images.

So, for now, we're just uploading the file before checking its
dimensions. Not ideal, though. We might use active_storage_validations
in the future to fix this issue (when they support a proc/lambda, as
mentioned in commit 600f5c35e).

We also need to update a couple of tests due to a small change in
response headers. Now the content disposition returns something like:

```
attachment; filename="budget_investments.csv"; filename*=UTF-8''budget_investments.csv
```

So we're updating regular expression we use to check the filename.

Finally, Rails 6.0.1 changed the way the host is set in integration
tests [1] and so both `Capybara.app_host` and `Capybara.default_host`
were ignored when generating URLs in the relationable examples. The only
way I've found to make it work is to explicitely assign the host to the
integration session. Rails 6.1 will change this setup again, so maybe
then we can remove this hack.

[1] https://github.com/rails/rails/pull/36283/commits/fe00711e9
2022-08-24 14:33:02 +02:00
Finn Heemeyer
c984e666ff Add new GraphQL types, schema (with fields) & base mutation
The current consul GraphQL API has two problems.

1) It uses some unnecessary complicated magic to automatically create
   the GraphQL types and querys using an `api.yml` file. This approach
   is over-engineered, complex and has no benefits. It's just harder to
   understand the code for people which are not familiar with the
   project (like me, lol).

2) It uses a deprecated DSL [1] that is soon going to be removed from
   `graphql-ruby` completely. We are already seeing deprecation warning
   because of this (see References).

There was one problem. I wanted to create the API so that it is fully
backwards compatible with the old one, BUT the old one uses field names
which are directly derived from the ruby code, which results in
snake_case field names - not the GraphQL way. When I'm using the
graphql-ruby Class-based syntax, it automatically creates the fields in
camelCase, which breaks backwards-compatibility.

So I've added deprecated snake_case field names to keep it
backwards-compatible.

[1] https://graphql-ruby.org/schema/class_based_api.html
2022-06-01 11:41:09 +02:00
Javi Martín
5977f2ec3d Simplify methods to get API-public records
Just like we did to tags in commit 2e863fdc5.
2022-05-02 17:16:31 +02:00
Javi Martín
0a3c86b92e Remove method to get votes for budget investments
After commit 0214184b2, this method was only used in two places and was
only useful in one of them. IMHO it isn't worth it add a monkey-patch
for such a minor usage.
2022-05-02 17:16:31 +02:00
Javi Martín
c25ab8e4a6 Remove unused vote extensions methods
These methods aren't used since commit b98244afd.
2022-05-02 17:16:31 +02:00
Javi Martín
b5a4609b56 Make it easier to customize validations
There are CONSUL installations where the validations CONSUL offers by
default don't make sense because they're using a different business
logic. Removing these validations in a custom model was hard, and that's
why in many cases modifying the original CONSUL models was an easier
solution.

Since modifying the original CONSUL models makes the code harder to
maintain, we're now providing a way to easily skip validations in a
custom model. For example, in order to skip the price presence
validation in the Budget::Heading model, we could write a model in
`app/models/custom/budget/heading.rb`:

```
require_dependency Rails.root.join("app", "models", "budget", "heading").to_s

class Budget::Heading
  skip_validation :price, :presence
end
```

In order to skip validation on translatable attributes (defined with
`validates_translation`), we have to use the
`skip_translation_validation` method; for example, to skip the proposal
title presence validation:

```
require_dependency Rails.root.join("app", "models", "proposal").to_s

class Proposal
  skip_translation_validation :title, :presence
end

```

Co-Authored-By: taitus <sebastia.roig@gmail.com>
2022-03-24 17:05:35 +01:00
Javi Martín
dba68c2c04 Fix deprecation warning in Tagging monkey patch
We were getting a warning in Rails 6.0:

DEPRECATION WARNING: Class level methods will no longer inherit scoping
from `public_for_api` in Rails 6.1. To continue using the scoped
relation, pass it into the block directly. To instead access the full
set of models, as Rails 6.1 will, use
`ActsAsTaggableOn::Tag.default_scoped`.
2022-03-21 20:43:50 +01:00
Javi Martín
2e863fdc51 Fix OR condition in public taggings
In SQL, conditions like:

```
tag_id IN (x) AND taggable_type='Debate' OR taggable_type='Proposal'
```

Don't work as intended; we need to write:

```
tag_id IN (x) AND (taggable_type='Debate' OR taggable_type='Proposal')
```

Due to this bug, we were returning taggings for proposals without
intending to do so.

Since the code was very hard to read, we're also simplifying it.
2022-03-21 20:43:50 +01:00
Javi Martín
7212657c02 Remove Paperclip and use just Active Storage 2022-02-23 18:43:48 +01:00
dependabot[bot]
91cd1ce1bc Bump sprockets from 3.7.2 to 4.0.2
Bumps [sprockets](https://github.com/rails/sprockets) from 3.7.2 to 4.0.2.
- [Release notes](https://github.com/rails/sprockets/releases)
- [Changelog](https://github.com/rails/sprockets/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rails/sprockets/compare/v3.7.2...v4.0.2)

---
updated-dependencies:
- dependency-name: sprockets
  dependency-type: direct:production
  update-type: version-update:semver-major
...

(Comment by Javi Martín): After this upgrade, compiling the assets is
significantly slower. Also note we need to explicitely include CKEditor
assets and the default application assets and images; we didn't have to
do so in the past.

Signed-off-by: dependabot[bot] <support@github.com>
2022-01-10 15:01:23 +01:00
Javi Martín
b544ec8988 Remove rollbar gem dependency
We already support Errbit and Airbrake as error monitoring services.
Since some people might not want to setup Errbit and might prefer
Rollbar over Airbrake, we're referencing it in the custom gemfile.
2021-12-08 15:56:17 +01:00
Javi Martín
9f21c27bf1 Include DelayedJob errors in Errbit exceptions
The integration between Airbrake/Errbit and DelayedJob wasn't working
because we require our dependencies in alphabetic order, and so by the
time `airbrake` was required, `delayed_job` wasn't loaded.

So we're manually requiring the integration.
2021-10-08 23:09:27 +02:00