Fix 2FA authentication spoofing
## Summary
This is security fix for vulnerability described at
https://gitlab.com/gitlab-org/gitlab-ce/issues/14900.
Attacker was able to bypass password authentication of users that have 2FA enabled, and consequently sign is as a different user, without knowing his password, if he managed to guess 2FA One Time Password for that user.
It was also possible to enumerate users and check if they have 2FA enabled, because GitLab responded with different error for each case.
## Fix
This MR attempts to change default user search scope if `otp_user_id` session variable has been set. If it is present, it means that user has 2FA enabled, and has already been verified with login and password. In this case we should look for user with `otp_user_id` first, before picking it up by `login`.
Both, 2FA authentication spoofing and 2FA discovery have been covered by specs.
## Further work
Current 2FA code is a bit tricky, so it probably needs some refactoring.
See merge request !1947
This commit attempts to change default user search scope if otp_user_id
session variable has been set. If it is present, it means that user has
2FA enabled, and has already been verified with login and password. In
this case we should look for user with otp_user_id first, before picking
it up by login.
Fix Error 500 after renaming a project path
Renaming the path of a project would result in an Error 500 due to `@repository` being memoized with the old path. An Error 500 would result:
```
Started GET "/testing2/test1" for 127.0.0.1 at 2016-04-04 12:42:30 +0000
Processing by ProjectsController#show as HTML
Parameters: {"namespace_id"=>"testing2", "id"=>"test1"}
Completed 200 OK in 637ms (Views: 194.2ms | ActiveRecord: 111.8ms)
Started GET "/testing2/test1/edit" for 127.0.0.1 at 2016-04-04 12:42:33 +0000
Processing by ProjectsController#edit as HTML
Parameters: {"namespace_id"=>"testing2", "id"=>"test1"}
Completed 200 OK in 594ms (Views: 183.8ms | ActiveRecord: 87.4ms)
Started PATCH "/testing2/test1" for 127.0.0.1 at 2016-04-04 12:42:41 +0000
Processing by ProjectsController#update as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"[FILTERED]", "project"=>{"nam
e"=>"test123", "path"=>"test123"}, "namespace_id"=>"testing2", "id"=>"test1"}
Completed 500 Internal Server Error in 1852ms (ActiveRecord: 124.0ms)
ActionView::Template::Error (no repository for such path):
2: %legend
3: Builds:
4:
5: - unless @repository.gitlab_ci_yml
6: .form-group
7: .col-sm-offset-2.col-sm-10
8: %p Builds need to be configured before you can begin using Contin
uous Integration.
app/models/repository.rb:59:in `block in empty?'
lib/repository_cache.rb:19:in `fetch'
app/models/repository.rb:59:in `empty?'
app/models/repository.rb:471:in `gitlab_ci_yml'
app/views/projects/_builds_settings.html.haml:5:in `_app_views_projects__build
s_settings_html_haml__782034335636359229_73397600'
app/views/projects/edit.html.haml:87:in `block in _app_views_projects_edit_htm
l_haml___2388082585934859365_47390860'
app/views/projects/edit.html.haml:8:in `_app_views_projects_edit_html_haml___2
388082585934859365_47390860'
app/controllers/projects_controller.rb:54:in `block (2 levels) in update'
app/controllers/projects_controller.rb:43:in `update'
lib/gitlab/middleware/go.rb:16:in `call'
```
Closes#14885
See merge request !3528
When importing members, and user does not have permissions to read
members in a source project, do not leak information about source
project existence. Notifiy user that project has not been found instead.
Fix sorting issues/mrs by votes on the groups page
Closes#14394
The `non_archived` scope applied here https://gitlab.com/gitlab-org/gitlab-ce/blob/master/app/controllers/concerns/issues_action.rb#L5 overrides the previous `ORDER BY` applied inside the IssuesFinder, with the default scope of the Project model, resulting in SQL errors.
```ruby
Issue.reorder(created_at: :desc).joins(:project).to_sql
=> "SELECT issues.*
FROM issues INNER JOIN projects ON projects.id = issues.project_id
ORDER BY issues.created_at DESC"
Issue.reorder(created_at: :desc).joins(:project).merge(Project.non_archived).to_sql
=> "SELECT issues.*
FROM issues INNER JOIN projects ON projects.id = issues.project_id
WHERE projects.archived = 'f'
ORDER BY projects.id DESC"
Issue.reorder(created_at: :desc).joins(:project).merge(Project.non_archived.only(:where)).to_sql
=> "SELECT issues.*
FROM issues INNER JOIN projects ON projects.id = issues.project_id
WHERE projects.archived = 'f'
ORDER BY issues.created_at DESC"
```
/cc @yorickpeterse
See merge request !3333
In the real world a project always has a repository. This fact allows
code such as Issue#related_branches to work without explicitly checking
if a repository exists.