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

This commit is contained in:
Douwe Maan 2015-10-20 16:16:08 +02:00
parent 97eafd4b3d
commit 2f7fc7e9f7
3 changed files with 38 additions and 13 deletions

View File

@ -118,8 +118,8 @@ class ApplicationController < ActionController::Base
end
project_path = "#{namespace}/#{id}"
@project = Project.find_with_namespace(project_path)
@project = Project.find_with_namespace(project_path) ||
Project.find_with_namespace(project_path, case_sensitive: false)
if @project and can?(current_user, :read_project, @project)
if @project.path_with_namespace != project_path

View File

@ -235,7 +235,7 @@ class Project < ActiveRecord::Base
where('projects.archived = ?', false).where('LOWER(projects.name) LIKE :query', query: "%#{query.downcase}%")
end
def find_with_namespace(id)
def find_with_namespace(id, case_sensitive: true)
namespace_path, project_path = id.split('/')
return nil if !namespace_path || !project_path
@ -243,11 +243,18 @@ class Project < ActiveRecord::Base
# 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
# query).
unscoped.
projects = unscoped.
joins(:namespace).
iwhere('namespaces.path' => namespace_path).
iwhere('projects.path' => project_path).
take
iwhere('namespaces.path' => namespace_path)
projects =
if case_sensitive
projects.where('projects.path' => project_path)
else
projects.iwhere('projects.path' => project_path)
end
projects.take
end
def visibility_levels

View File

@ -51,16 +51,34 @@ describe ProjectsController do
end
context "when requested with case sensitive namespace and project path" do
it "redirects to the normalized path for case mismatch" do
get :show, namespace_id: public_project.namespace.path, id: public_project.path.upcase
context "when there is a match with the same casing" do
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
it "loads the page if normalized path matches request path" do
get :show, namespace_id: public_project.namespace.path, id: public_project.path
context "when there is a match with different casing" do
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
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