Commit 8fe4352e authored by Robert Speicher's avatar Robert Speicher Committed by Robert Speicher

Merge branch 'project-path-case-sensitivity' into 'master'

Prefer project with exact path to differently cased one when both exist.

Fixes #3113.

See merge request !1649
parent 613f368c
...@@ -124,7 +124,6 @@ class ApplicationController < ActionController::Base ...@@ -124,7 +124,6 @@ class ApplicationController < ActionController::Base
project_path = "#{namespace}/#{id}" project_path = "#{namespace}/#{id}"
@project = Project.find_with_namespace(project_path) @project = Project.find_with_namespace(project_path)
if @project and can?(current_user, :read_project, @project) if @project and can?(current_user, :read_project, @project)
if @project.path_with_namespace != project_path if @project.path_with_namespace != project_path
redirect_to request.original_url.gsub(project_path, @project.path_with_namespace) and return redirect_to request.original_url.gsub(project_path, @project.path_with_namespace) and return
......
...@@ -243,11 +243,12 @@ class Project < ActiveRecord::Base ...@@ -243,11 +243,12 @@ class Project < ActiveRecord::Base
# Use of unscoped ensures we're not secretly adding any ORDER BYs, which # Use of unscoped ensures we're not secretly adding any ORDER BYs, which
# have a negative impact on performance (and aren't needed for this # have a negative impact on performance (and aren't needed for this
# query). # query).
unscoped. projects = unscoped.
joins(:namespace). joins(:namespace).
iwhere('namespaces.path' => namespace_path). iwhere('namespaces.path' => namespace_path)
iwhere('projects.path' => project_path).
take projects.where('projects.path' => project_path).take ||
projects.iwhere('projects.path' => project_path).take
end end
def visibility_levels def visibility_levels
......
module Gitlab module Gitlab
module Database module Database
def self.mysql? def self.mysql?
ActiveRecord::Base.connection.adapter_name.downcase == 'mysql' ActiveRecord::Base.connection.adapter_name.downcase == 'mysql2'
end end
def self.postgresql? def self.postgresql?
......
...@@ -23,16 +23,39 @@ describe ProjectsController do ...@@ -23,16 +23,39 @@ describe ProjectsController do
end end
context "when requested with case sensitive namespace and project path" do context "when requested with case sensitive namespace and project path" do
it "redirects to the normalized path for case mismatch" do context "when there is a match with the same casing" do
get :show, namespace_id: public_project.namespace.path, id: public_project.path.upcase it "loads the project" do
get :show, namespace_id: public_project.namespace.path, id: public_project.path
expect(response).to redirect_to("/#{public_project.path_with_namespace}") expect(assigns(:project)).to eq(public_project)
expect(response.status).to eq(200)
end
end end
it "loads the page if normalized path matches request path" do context "when there is a match with different casing" do
get :show, namespace_id: public_project.namespace.path, id: public_project.path it "redirects to the normalized path" do
get :show, namespace_id: public_project.namespace.path, id: public_project.path.upcase
expect(response.status).to eq(200) expect(assigns(:project)).to eq(public_project)
expect(response).to redirect_to("/#{public_project.path_with_namespace}")
end
# MySQL queries are case insensitive by default, so this spec would fail.
if Gitlab::Database.postgresql?
context "when there is also a match with the same casing" do
let!(:other_project) { create(:project, :public, namespace: public_project.namespace, path: public_project.path.upcase) }
it "loads the exactly matched project" do
get :show, namespace_id: public_project.namespace.path, id: public_project.path.upcase
expect(assigns(:project)).to eq(other_project)
expect(response.status).to eq(200)
end
end
end
end end
end end
end end
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment