Commit Graph

2871 Commits

Author SHA1 Message Date
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
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
4699e767ec Apply Layout/SpaceAfterComma rubocop rule 2019-10-22 18:48:22 +02:00
Javi Martín
aace7aea02 Apply Layout/SpaceAroundOperators rubocop rule
We were a bit inconsistent when aligning equal signs vertically.
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
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
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
denialtorres
bb627a7117 Edit Budget Investment only in accepting phase (#3716)
This way users who made a typo can fix it before the investment is reviewed.
2019-10-18 13:59:14 +02:00
Javier Martín
dd6e603d9e Merge pull request #3754 from consul/flaky_results_spec
Fix flaky officing results spec
2019-10-10 20:56:51 +02:00
Javi Martín
56e62a41b6 Fix duplicate given order creating answers
It's possible to have a given order greater than the number of answers;
we don't have any validation rules for that. So the check for the number
of answers isn't enough.

Checking the maximum given order in the answers is safer. Another option
would be to reorder the answers every time we add a new one, but I'm not
sure whether that's the expected behaviour.

Note even after this change the action is not thread-safe, as it is
possible to create two questions with the same given order with two
simultaneous requests.
2019-10-10 00:36:57 +02:00
Javi Martín
2f569002cf Fix typos in translatable spec
We want to create a new investment for a budget, and not for another
investment.
2019-10-09 22:22:44 +02:00
Javi Martín
ef2b2317e5 Fix flaky officing results spec
The page could have "7777" as a content for the poll's name, since that
name is generated using a random hexadecimal number.

Restricting the search to the area of the page where the "7777" used to
be solves the problem.
2019-10-09 21:57:20 +02:00
Javi Martín
9a299aeeb5 Fix checkbox label containing links
The link tags were being stripped out by `content_tag`.
2019-10-09 19:46:47 +02:00
Javi Martín
391f58eb90 Sanitize dashboard action before displaying it
We were using `<%==`, which is the same as using `raw`.

Note ERB Lint doesn't warn us of this usage. Brakeman does warn us,
though.
2019-10-08 19:10:14 +02:00
Javi Martín
00a6f5b601 Remove <%== usage displaying settings
Using `<%==` is the same as using `raw`. I'm not sure if we meant
`sanitize` in this case, or it's just a typo. I'm assuming the latter
since we don't use anything similar in any other places.
2019-10-08 19:10:14 +02:00
Javi Martín
9eee79f218 Sanitize markdown output
We were using the markdown renderer with the `filter_html` option set to
false, so we weren't removing hypothetical `<script>` tags.
2019-10-08 18:46:21 +02:00
Javi Martín
928312e218 Use sanitize in translations with links
Sometimes we're interpolating a link inside a translation, and marking
the whole translations as HTML safe.

However, some translations added by admins to the database or through
crowdin are not entirely under our control.

Although AFAIK crowdin checks for potential cross-site scripting
attacks, it's a good practice to sanitize parts of a string potentially
out of our control before marking the string as HTML safe.
2019-10-08 18:46:21 +02:00
Javi Martín
75a28fafcb Sanitize label texts automatically
This way we can remove all those `html_safe` calls and we avoid
potential XSS attacks in label texts.
2019-10-08 18:46:21 +02:00
Javi Martín
2ffbae890e Sanitize valuation explanations
If we don't sanitize them, valuators might attempt Cross-Site Scripting
attacks.
2019-10-08 18:46:20 +02:00
Javi Martín
8b73cfc019 Sanitize annotation context before displaying it
There's a case where we would face a Cross-Site Scripting attack. An
attacker could use the browser's developer tools to add (on their
browser) a `<code>` tag with a `<script>` tag inside in the text of the
draft version. After doing so, commenting on that text would result in
the attacker's JavaScript being executed.
2019-10-08 18:46:20 +02:00
Javi Martín
0f485308b7 Sanitize CKEditor content before displaying it
It's possible to create a newsletter or a proposed action with
<script> tags by filling in the body using a textarea instead of a
CKEditor. While we trust our administrators not to do so, it's better to
completely eliminate that possibility.
2019-10-08 18:46:20 +02:00
Javi Martín
db1ccb18c7 Use safe_join instead of html_safe
The name `html_safe` is very confusing, and many developers (including
me a few years ago) think what that method does is convert the HTML
contents to safe content. It's actually quite the opposite: it marks the
string as safe, so the HTML inside it isn't stripped out by Rails.

In some cases we were marking strings as safe because we wanted to add
some HTML. However, it meant the whole string was considered safe, and
not just the contents which were under our control.

In particular, some translations added by admins to the database or
through crowding were marked as safe, when it wasn't necessarily the
case.

Although AFAIK crowdin checks for potential cross-site scripting
attacks, it's a good practice to sanitize parts of a string potentially
out of our control before marking the string as HTML safe.
2019-10-08 18:46:20 +02:00
Javi Martín
20ca6beb30 Remove unneeded html_safe and raw calls
There's no HTML in these texts, or it has already been escaped by Rails
`link_to` helper method.
2019-10-08 13:20:22 +02:00
Javi Martín
6fa67b5e53 Use active record translations for labels
This way we can simplify the way we generate form fields. In some cases,
we also use the human attribute in table headers, which IMHO makes
sense.

I haven't moved all of them: for example, sometimes a label is
different depending on whether it's shown to administrators, valuators,
or users. And I haven't touched the ones related to devise, since I
wasn't sure about possible side effects.

Note I've also removed placeholders when they had the same text as their
labels, since they weren't helpful. On the contrary, the added redundant
text to the form, potentially distracting users.
2019-10-07 01:56:23 +02:00
Javier Martín
42dbbf5507 Merge pull request #3735 from consul/rubocop_lint
Add rubocop lint rules
2019-10-05 15:50:01 +02:00
Javier Martín
fb2476a651 Merge pull request #3738 from consul/rubocop_fixes
Add rubocop rule for multiline blocks
2019-10-05 15:40:19 +02:00
Javi Martín
871fa020a5 Add and apply ParenthesesAsGroupedExpression rule 2019-10-05 15:03:26 +02:00
Javi Martín
447c970eb3 Remove unused block arguments
There are more cases where we have unused block arguments, but I'm only
changing the obvious ones.
2019-10-05 15:03:26 +02:00
Javi Martín
2fed7b9db3 Add and apply AmbiguousRegexpLiteral rule
This is a very subtle behaviour: `match /attachment/i` could represent a
regular expression, but it could also represent a division like
`match / attachment / i`. So we need to make an exception to the usual
way we omit parenthesis in RSpec expectations.
2019-10-05 14:47:19 +02:00
Javi Martín
d6eb9f8fb6 Add and apply ShadowingOuterLocalVariable rule
Naming two variables the same way is confusing at the very least, and
can lead to hard to debug errors. That's why the Ruby interpreter issues
a warning when we do so.
2019-10-05 14:47:19 +02:00
Javi Martín
70a07c095f Add and apply Style/BlockDelimiters rubocop rule
We were already using it most of the time, but there were a few places
were we used brackets for multiline blocks.
2019-10-05 14:44:14 +02:00
Javi Martín
21f9d8e1b4 Fix missing double quotes
It could be argued that the following lines use single quotes to escape
double quotes, but on the other hand, using a single quote isn't a
great benefit.
2019-10-05 14:32:46 +02:00
Javi Martín
78c6f6f7e9 Use the same key for "signin" and "signup" texts
We were using the same texts in several places
2019-10-05 14:07:23 +02:00
Javier Martín
f018706e6b Merge pull request #3740 from consul/remove_obsolete_code
Remove leftover code
2019-10-05 04:11:58 +02:00
cyrillefr
44b2a07878 Moderate legislation proposals (#3602)
Moderate legislation proposals

- added a controller for moderation/legislation
- updated view to appropriate link + added route
- added a spec
- Feature test
- test for faded
- javascripts for visual effects
2019-10-05 04:02:39 +02:00
Javi Martín
ad14636255 Use Tag instead of ActsAsTaggableOn::Tag
It's shorter, it's easier to extend its behaviour, and it's easier to
integrate with other parts of our application, like translations.
2019-10-05 03:38:44 +02:00
Javi Martín
e524374293 Use new foundation helper classes in tests 2019-10-03 17:30:12 +02:00
Javi Martín
2ce3cfab5e Remove @process instance variable
Note we cannot name this variable `process` because in a controller spec
the word `process` is a method, like `get` or `post`.
2019-09-30 16:43:10 +02:00
Javi Martín
a8903d80ce Remove instance variables in draft version spec
This one is a bit different than our usual scenario, since we create
three annotations and we only use two of them in the specs (because we
visit the path to that annotation). So there are probably better options
than the combination of `let!` and `before` I've chosen.
2019-09-30 16:43:10 +02:00
Javi Martín
5c81a70fa7 Use factory bot blocks to create complex data
Having two questions, each of them with two comments, made the code hard
to follow.

Grouping the comments inside the block creating the questions makes it
easier to know which comment belongs to which question, even if the code
is still not 100% readable.

We also remove instance variables, which by the way used the same
variable name for two different things.
2019-09-30 16:43:10 +02:00
Javi Martín
86366da28c Declare local variables outside a block
We couldn't declare them inside the block because they would be
considered local variables and its value would be lost when the block
was finished. So we were using instance variables instead.

However, with instance variables we don't get any warnings when we
misspell their names. We can avoid them by declaring the local variables
before the block starts.
2019-09-30 16:43:10 +02:00
Javi Martín
91c21b0982 Remove instance variables in RSpec
Instance variables might lead to hard-to-detect issues, since using a
nonexistent instance variable will return `nil` instead of raising an
error.
2019-09-30 16:43:10 +02:00
Javi Martín
f70e10fe9f Remove unused instance variables
These variables were declared but never used.
2019-09-30 16:37:34 +02:00
Javi Martín
7783547419 Remove rest of unused variables
I haven't found an elegant way to remove them, but since they were the
only three variables left out of 383 we used to have, I can live with
this low percentage of inelegant solutions.
2019-09-30 15:47:13 +02:00
Javi Martín
f5fe8c1279 Use factory bot blocks to create complex data
We had four headings, some of them had investments, and some of them
didn't, and it was very hard to scan the code and check which investment
belongs to which heading.

Grouping the investments inside the block creating the heading makes
that task much easier, even if the code is still not 100% readable.

We also avoid unused variables which were there to keep the code
vertically algined.
2019-09-30 15:47:13 +02:00
Javi Martín
d0d1c9972c Remove unused variables following their parent
There's a very common pattern in our test, where the setup only has two
lines:

variable = create(:something)
unused_variable = create(:something_else, something: variable)

In this case, since there's a blank line below these ones and then we'll
get to the body of the test, and the second variable is going to be
created based on the first variable, we can remove the useless
assignment and the readability is still OK.

Another option we almost unanimously discarded was:

variable = create(:something)
_unused_variable = create(:something_else, something: variable)

We don't use it anywhere else, either.

One more option we considered but found a bit too much for simple tests:

variable = create(:something) do |something|
  create(:something_else, something: variable)
end

Then of course we could move the setup to `let` and `before` blocks, but
the tests could get over-structured really quickly.
2019-09-30 15:47:13 +02:00