* Refactoring to leverage an Article scope
I've been looking at the queries that involve filtering articles based
on scores. There's several places that seem to be close to consistent,
but have some nuanced difference.
This refactor consolidates one of those "almost the same" cases.
* Bump for travis
* Add missing spaces
* Use filter_map over map + reject/compact
* Simplify FactoryBot calls
* Use to_h with block instead of map + to_h
* Use guard clause
We are seeing test failures when an id like "aaabbbcccdd1m" match with
"1m" as the time parameter. I think we only want to match the time
when a ?t= or ?start= (and the permissive &t= or &start=, which might
only be part of the larger REGISTRY_REGEXP and either not effective or
not needed for the video id pattern)
The goal here is these should be valid
"aaabbbcccdd"
"aaabbbcccdd?t=1"
"aaabbbcccdd?start=1h23m55s"
"aaabbbcccdd&t=1"
but not these
"aaabbbcccddt=1"
"aaabbbcccddstart=1"
"aaabbbcccdd123456h"
The same logic may be appropriate to backfill into the prior regexp as
well, my immediate concern is with randomly generated 12-15 character
strings from Fake getting matched during testing (where they were
expected to raise an error during id parsing).
* Remove slash characters from user supplied user search input
Prevents an error when the search term includes '\'
PG::SyntaxError: ERROR: syntax error in tsquery
https://app.honeybadger.io/projects/66984/faults/79391397
I had originally thought to add this cleanup to Search::Username but
decided to move it as close to the generated (invalid) query as
possible to prevent alternate paths finding their way here.
* Add spec
Since there's no existing tests for the scope - I put the test code on
the caller (Search::Username) rather than the model (User), this seems reasonable.
* When the term is empty (or only slashes) just return null relation
* Handle nil input (search for nothing) correctly
One of the request specs sends a username search with no query, so we
can't call nil.delete or nil.empty?, use blank? of empty?
The 400 and 403 error pages show json parsing errors in most browsers,
since "Error: Bad Request" is not a valid json body ('"Error: Bad
Request"' would be, or the object with key error and value of the
string which I've selected is _also_ valid).
Do we have frontend code that's looking for this body before it parses
for some reason, or was this just a mistaken copying from the api
controller in the initial PRs (#2293 for not_authorized, and #6248 for
the bad_request method, which may have just replicated the decision
for not_authorized)?
* Favoring single SQL and computation over enum
Prior to this commit, we ran a SQL statement to generate a list of
articles then applied some minor randomization.
With this commit, I'm removing the randomization in favor of expected
values, and collapsing the result set into a single inline SQL and some
post query simple arithmatic.
Let's check my math. For each article we sum:
* `article.score`
* `article.comments_count` * 14
* a random number between 0 and 5 (`rand(6)`) with expected value of 2.5
* the tag's (taggings_count + 1) / 2
The new SQL query sums the `article.score` and the
`article.comments_count` * 14. I then reduce the remainder of the
equation. From "for each article sum `(rand(5) + (taggings_count + 1) /
2)`" we have the following:
`article_count * (2.5 + (taggings_count + 1) / 2)`
Which is equivalent to:
`article_count * ((taggings_count + 1 + (2.5 * 2)) / 2)`
Which is equivalent to:
`article_count * ((taggings_count + 6) / 2)`
This change reduces computation time by favoring expected values.
* Fixing broken behavior and adding comments
With this refactor, I'm adding documentation and favoring using a common
method that wasn't available at the time of implementation.
In [this commit][1] we had logic that said "if we have a singular tag
use the cache" otherwise use the join. At that time, the implementation
of [Article.cached_tag_with][previous] was as follows, allowing only a
singular tag:
```ruby
scope :cached_tagged_with, ->(tag) { where("cached_tag_list ~* ?",
"^#{tag},| #{tag},|, #{tag}$|^#{tag}$") }
```
The [current implementation][current], as of writing this, allows for
multiple tags and is as follows:
```ruby
scope :cached_tagged_with, lambda { |tag|
case tag
when String, Symbol
# In Postgres regexes, the [[:<:]] and [[:>:]] are equivalent to "start of
# word" and "end of word", respectively. They're similar to `\b` in Perl-
# compatible regexes (PCRE), but that matches at either end of a word.
# They're more comparable to how vim's `\<` and `\>` work.
where("cached_tag_list ~ ?", "[[:<:]]#{tag}[[:>:]]")
when Array
tag.reduce(self) { |acc, elem| acc.cached_tagged_with(elem) }
when Tag
cached_tagged_with(tag.name)
else
raise TypeError, "Cannot search tags for: #{tag.inspect}"
end
}
```
Given that we are content to use the cached tag in the singular tag
case, it seems safe to say that we're comfortable using it in the
multiple tag case.
[1]:af5a391429 (diff-24503fd25ed68e6ebceee4951bc4f9b255b197278d4aa9d86ef9d5afe3f26bea)
[previous]:af5a391429/app/models/article.rb (L151)
[current]:98e97e7aa8/app/models/article.rb (L212-L227)
* Refactoring questions asked of user
In this pull request, I'm extracting and normalizing role-based
questions asked of the user.
Prior to this commit, our codebase has asked two very similar questions
of our user model:
- `user.has_role?(:admin)`
- `user.admin?`
In asking `has_role?(:admin)` we are relying on implementation details
of the rolify gem. In addition, the `has_role?` question asked
throughout controllers or views means that it's harder to create
hieararchies of permissions.
In favoring `user.admin?` as our question, we can use that indirection
as an opportunity to discuss and decide "Should someone with the
`:super_admin` role be `user.admin? == true`?"
The details of this commit is to do three primary things:
1. Ask the `has_role?` questions in "one place" in the code (e.g. the
`Authorizer` module)
2. Extract the role based questions that are on the `User` model and
provde backwards compatable delegation.
3. Structure the code so that it's harder to accidentally call
`user.has_role?` (e.g., make `User#has_role?` and `User#has_any_role?`
private).
This is related to #15624 and the updates are informed by discussion in
PR #15691. This commit supplants #15691.
* Refactoring the liquid tag policy tests
* Fixing typo
* Bump for travis
* Remove modify_hr_tags method definition
this breaks things that call it.
* Remove direct uses of modify_hr_tags fixer method
Remove from class METHODS lists, remove test cases about this behavior, and remove from
methods lists in test cases.
* Remove hr tag modification spec
Still don't understand what problem this was fixing, but I've removed
the test case.
* Escape periods and display the group name properly
* Rename method to dom_safe_name and move to admin helper
* Replace beginning of string digit with underscore then digit
We were previously disallowing empty user agents, but we weren't
blocking requests where the User-Agent header wasn't set at all. This
commit blocks those requests.
This commit also blocks Chrome 74. It's a 2.5-year-old version of an
evergreen browser that releases every 6 weeks, so this is clearly a bot
spoofing this header.