Commit Graph

9884 Commits

Author SHA1 Message Date
Javi Martín
e3bfcbcd25 Apply Style/ClassVars rubocop rule
Class variables in Ruby are not the same as instance variables of a
class. They're particularly tricky when it comes to inheritance and
modules.

In the case of the Measurable module, for example, using a class
variable will make all classes including the Measurable module share
the same value. However, that's not what we want; we want the variable
to be different for every class. And that's accomplished using a class
instance variable.

Although in this case it would probably be better to remove the caching
variable. I don't think these methods are called more than once during a
request, and even if they did it's highly unlikely the would become a
bottleneck.
2019-10-26 13:03:49 +02:00
Javi Martín
dfe9ab2c69 Apply Style/ClassCheck rubocop rule
We were already using `is_a?` almost everywhere.
2019-10-26 13:03:49 +02:00
Javi Martín
f07c422f21 Apply Layout/SpaceInLambdaLiteral rubocop rule
I had mixed feelings about this rule, since I like spaces where
possible.

However, I changed my mind when I realized writing `->(thing) { }` was
similar to defining a method, and we don't have a space before the
parenthesis when defining a method.
2019-10-26 13:03:49 +02:00
Javi Martín
a0554f5bba Apply Layout/LeadingBlankLines rubocop rule
This rule is pretty obvious. However, we weren't following it in a
couple of places.
2019-10-26 13:03:48 +02:00
Javi Martín
e21565628f Apply Layout/IndentAssignment rubocop rule
There was one place where we weren't applying it.
2019-10-26 13:03:48 +02:00
Javi Martín
97e826f2a4 Don't use update_attribute
This method is ambiguous. Sometimes we use it to set invalid data in
tests (which can usually be done with `update_column`), and other times
we use it instead of `update!`.

I'm removing it because, even if sometimes it could make sense to use
it, it's too similar to `update_attributes` (which is an alias for
`update` and runs validations), making it confusing.

However, there's one case where we're still using it: in the
ActsAsParanoidAliases module, we need to invoke the callbacks, which
`update_column` skips, but tests related to translations fail if we use
`update!`. The reason for this is the tests check what happens if we
restore a record without restoring its translations. But that will make
the record invalid, since there's a validation rule checking it has at
least one translation.

I'm not blacklisting any other method which skips validations because we
know they skip validations and use them anyway (hopefully with care).
2019-10-25 23:17:50 +02:00
Javi Martín
bbce3479cf Simplify touching a budget when a phase changes
The `belongs_to` method already has that option, so there's no need to
do it manually in an `after_save` callback.
2019-10-25 23:17:49 +02:00
Javi Martín
1da0fe1ee2 Apply Rails/HasAndBelongsToMany rubocop rule
We were using it everywhere except in one place.
2019-10-25 19:29:12 +02:00
Javi Martín
42d2e5b3ad Apply Rails/InverseOf rubocop rule
Not doing so has a few gotchas when working with relations, particularly
with records which are not stored in the database.

I'm excluding the related content file because it's got a very peculiar
relationship with itself: the `has_one :opposite_related_content` has no
inverse; the relation itself is its inverse. It's a false positive since
the inverse condition is true:

```
content.opposite_related_content.opposite_related_content.object_id ==
  content.object_id
```
2019-10-25 19:29:12 +02:00
Javi Martín
94d2496f8f Add missing has_many relations for users
Usually when we specify a `belongs_to` relations, we also specify its
equivalent `has_many`. That allows us to write, for example:
`topic.user.topics`.
2019-10-25 19:27:30 +02:00
Javi Martín
915e2792fc Use self.name for same-table relations
Personally reading the class name made me take some time to realize it
was a same-table relation.
2019-10-25 19:03:14 +02:00
Javi Martín
27ed26d6f2 Remove unnecessary class names in relations
Just like we do in the Budget module, and in some places in the Poll and
Legislation modules, we don't need to specify the class name when the
name of the relation matches the name of a class in the same module.
2019-10-25 19:03:14 +02:00
Javi Martín
fda53a0a2a Remove unnecessary foreign_key options
When we specify `belongs_to :author`, ActiveRecord automatically uses
`author_id` as the foreign key.
2019-10-25 19:03:10 +02:00
Javier Martín
86e159662f Merge pull request #3802 from consul/html_area
Make HTML areas independent of CKEditor
2019-10-25 17:31:12 +02:00
Javi Martín
e844b0b2db Remove CKEditor divs
This way the HTML does not depend on CKEditor, and changing the editor
we use in textareas will require very few changes.
2019-10-25 17:00:18 +02:00
Javi Martín
6ef07f8a54 Use text_area instead of cktext_area
We're going to change CKEditor to an inline editor, and the "ckeditor"
gem doesn't provide an option to do so.

Since using `cktext_area` would automatically generate a "classic"
iframe CKEditor, we need to use `text_area` and load the editor using
JavaScript. Personally I prefer this option anyway.

Note in the jQuery selector we need to use `textarea.html-area`; using
just `.html-area` would fail if there's an error message associated to
the textarea, since Rails will add the `.html-area` class to the error
message.
2019-10-25 16:34:25 +02:00
Javi Martín
025923ac4e Set current locale as HTML language in all layouts
The same way it's done in the application layout. Not doing so causes
accessibility issues affecting screen reader users.
2019-10-25 15:34:40 +02:00
Javi Martín
8ff728ee83 Use the shared partial to render errors
We were using it most of the time, but in some places we still had
duplicated code.
2019-10-25 15:15:47 +02:00
Javi Martín
57ef380379 Add and apply Layout/ExtraSpacing rubocop rule 2019-10-24 18:11:58 +02:00
Javi Martín
033f3c33e3 Add SpaceAroundEqualsInParameterDefault rule
We were using it in most places, but not everywhere.
2019-10-24 17:56:03 +02:00
Javi Martín
d938077813 Remove empty lines around if and when body
Unfortunately, there doesn't seem to be a Rubocop rule for this one.
I've found these empty lines thanks to Rufo.
2019-10-24 17:56:03 +02:00
Javi Martín
d0d681a44b Add and apply EmptyLineAfterGuardClause rule
We were inconsistent on this one. I consider it particularly useful when
a method starts with a `return` statement.

In other cases, we probably shouldn't have a guard rule in the middle of
a method in any case, but that's a different refactoring.
2019-10-24 17:56:03 +02:00
Javi Martín
db97f9d08c Add and apply rubocop rules for empty lines
We were very inconsistent regarding these rules.

Personally I prefer no empty lines around blocks, clases, etc... as
recommended by the Ruby style guide [1], and they're the default values
in rubocop, so those are the settings I'm applying.

The exception is the `private` access modifier, since we were leaving
empty lines around it most of the time. That's the default rubocop rule
as well. Personally I don't have a strong preference about this one.


[1] https://rubystyle.guide/#empty-lines-around-bodies
2019-10-24 17:11:47 +02:00
Javier Martín
b6750e8f17 Merge pull request #3792 from consul/rubocop_find_by
Apply rubocop FindBy rules
2019-10-24 16:47:21 +02:00
Javi Martín
49e55b4dc4 Apply Rails/DynamicFindBy rubocop rule
We were already using `find_by` most of the time.

Since there are false positives related to our `find_by_slug_or_id!` and
`find_by_manger_login` methods, which cannot be replaced with `find_by`,
I'm adding it indicating the "refactor" severity.
2019-10-23 20:05:40 +02:00
Javi Martín
93c6347b45 Apply Rails/FindBy rubocop rule
We were already using it in most places.
2019-10-23 18:29:09 +02:00
Javi Martín
69e3e67c85 Avoid "Overwriting existing method open" warning
In Ruby, the Kernel class defined the `open` method, which is available
for (almost) every object. So creating a scope with the name `open`
generates a warning indicating we are overwriting the existing `open`
method.

While this warning is pretty much harmless and we could ignore it, it
generates a lot of noise in the logs. So I'm "undefining" the method
before generating the scope, so we don't get the warning all the time.
2019-10-23 18:07:50 +02:00
Javi Martín
26e050b9f2 Remove redundant scopes
These scopes were already defined by the `enum :task` method.
2019-10-23 18:03:53 +02:00
decabeza
974064a742 Update icons scss to use fontawesome icons 2019-10-23 15:49:15 +02:00
decabeza
18975a3963 Add font-awesome-sass gem
Now can use all icons from https://fontawesome.com.
2019-10-23 15:49:15 +02:00
Javi Martín
49c3402833 Use update! instead of update_attributes!
It's what we use almost everywhere, and it's shorter.
2019-10-23 14:39:31 +02:00
Javi Martín
7ca55c44e0 Apply Rails/SaveBang rubocop rule
Having exceptions is better than having silent bugs.

There are a few methods I've kept the same way they were.

The `RelatedContentScore#score_with_opposite` method is a bit peculiar:
it creates scores for both itself and the opposite related content,
which means the opposite related content will try to create the same
scores as well.

We've already got a test to check `Budget::Ballot#add_investment` when
creating a line fails ("Edge case voting a non-elegible investment").

Finally, the method `User#send_oauth_confirmation_instructions` doesn't
update the record when the email address isn't already present, leading
to the test "Try to register with the email of an already existing user,
when an unconfirmed email was provided by oauth" fo fail if we raise an
exception for an invalid user. That's because updating a user's email
doesn't update the database automatically, but instead a confirmation
email is sent.

There are also a few false positives for classes which don't have bang
methods (like the GraphQL classes) or destroying attachments.

For these reasons, I'm adding the rule with a "Refactor" severity,
meaning it's a rule we can break if necessary.
2019-10-23 14:39:31 +02:00
Javi Martín
431074c99f Add save! method to ActiveModel models
This way we make it clear we expect records to be valid when we save
them, just like we do with ActiveRecord models.
2019-10-23 14:32:42 +02:00
Javi Martín
35bbd87093 Fix adding blank comments to existing annotations
We were using the `present?` method, which will always return true for a
comment object.
2019-10-23 04:28:08 +02:00
Javi Martín
38b7307450 Use respond_to? instead of try
Usually when we use `try` we actually mean `try!`, which is the same as
the safe navigation operator. However, there are a few cases where we
actually mean to execute a method if the object responds to that method.

In those cases using `try` would actually be OK, but in order to avoid
confusion as to whether we mean to check for `respond_to?` or we mean to
use safe navigation, I'm removing all usages of `try`.
2019-10-22 17:37:51 +02:00
Javi Martín
1004ac01f8 Add and apply Style/SafeNavigation rubocop rule
We were already using it most of the time, but not always.
2019-10-22 17:37:51 +02:00
Javi Martín
6ceca143b4 Remove redundant check deleting content blocks
The `find` method raises an exception if nothing is found, so there's no
need to check if it found something.
2019-10-22 17:37:51 +02:00
Javi Martín
68ca29fa8b Convert markdown to HTML on demand
We were converting markdown to HTML every time we saved a record, which
has the same problems as sanitizing HTML before saving it to the
database, particularly because the body of a legislation draft is stored
in a translations table.

Performance-wise this isn't a problem: converting a text with more than
200_000 characters takes about a milisecond on my machine.

Note we need to modify a migration generated by globalize, since the
method `create_translation_table!` would fail now that we don't define
`translates :body_html` in the model.
2019-10-21 21:32:43 +02:00
Javi Martín
7bf4e4d611 Sanitize descriptions in the views
Sanitizing descriptions before saving a record has a few drawbacks:

1. It makes the application rely on data being safe in the database. If
somehow dangerous data enters the database, the application will be
vulnerable to XSS attacks
2. It makes the code complicated
3. It isn't backwards compatible; if we decide to disallow a certain
HTML tag in the future, we'd need to sanitize existing data.

On the other hand, sanitizing the data in the view means we don't need
to triple-check dangerous HTML has already been stripped when we see the
method `auto_link_already_sanitized_html`, since now every time we use
it we sanitize the text in the same line we call this method.

We could also sanitize the data twice, both when saving to the database
and when displaying values in the view. However, doing so wouldn't make
the application safer, since we sanitize text introduced through
textarea fields but we don't sanitize text introduced through input
fields.

Finally, we could also overwrite the `description` method so it
sanitizes the text. But we're already introducing Globalize which
overwrites that method, and overwriting it again is a bit too confusing
in my humble opinion. It can also lead to hard-to-debug behaviour.
2019-10-21 21:32:02 +02:00
Javi Martín
ae2576020e Extract method to use WYSIWYGSanitizer in views
This is similar to methods we use like `sanitize` or `markdown`.
2019-10-21 21:32:02 +02:00
Javier Martín
a8713793a5 Merge pull request #3779 from consul/jquery_xss
Use jQuery's text() instead of html() where safer
2019-10-21 21:18:47 +02:00
Javi Martín
7f1bfc6bd7 Avoid using html() to set languages description
The jQuery html() function does not filter <script> tags, so if somehow
an attacker introduced a <script> in the translation, we would be
vulnerable to a XSS attack.

Note using $.parseHTML wouldn't solve the problem, since it doesn't
filter attributes in image tags.

Since changing the text of the part which doesn't have the count wasn't
very clean, I've added another <span> tag for the part with the
description, and so we can use jQuery's text() function to replace it.
2019-10-21 20:24:50 +02:00
Javi Martín
d61e8cb6a6 Use text() instead of html()
Using html() makes it possible to insert <script> tags in the DOM, and
in this case we aren't supposed to be inserting any HTML.

I haven't found a way to focus on a field with Capybara, then add a
character, and focus on another field. So I've manually triggered the
change event in the test.
2019-10-21 20:24:50 +02:00
Javi Martín
31c2379a4e Don't sanitize <span> tags in HTML attributes
Doing so will cause the `<span>` tag to be rendered in the document,
instead of being rendered as a data attribute.
2019-10-21 20:24:50 +02:00
Javi Martín
9340d189cb Fix investments search with numbers in their title 2019-10-21 19:27:16 +02:00
Javi Martín
8aa4c630d7 Make search_by_title_or_id behave like a scope
There's no need to pass the collection of results when we use methods
like `where`.
2019-10-21 19:27:15 +02:00
Javier Martín
2f9995f566 Merge pull request #3766 from consul/relative_urls
Use relative URLs where possible
2019-10-20 18:33:13 +02:00
Javier Martín
c1d6cd4e4b Merge pull request #2151 from consul/feature-flag-api
Feature flag api
2019-10-20 18:21:28 +02:00
Javi Martín
27468b0b7b Use relative URLs where possible
In general, we always use relative URLs (using `_path`), but sometimes
we were accidentally using absolute URLs (using `_url`). It's been
reported i might cause some isuses if accepting both HTTP and HTTPS
connections, although we've never seen the case.

In any case, this change makes the code more consistent and makes the
generated HTML cleaner.
2019-10-20 17:26:14 +02:00
Javi Martín
11e52dbe98 Remove kaminari_path
The main reason to use it was the `rel` attribute for previous/next
pages not being indexed correctly by certain search engines when using a
relative URL. However, AFAIK that only applied to `<link>` tags, not to
`<a>` tags, and only if a `<base>` tag was defined.

In any case, it looks like the same search engines don't use the `rel`
attribute for previous/next to index pages anymore.
2019-10-20 17:26:14 +02:00