Commit b2ce4407 authored by Illya Klymov's avatar Illya Klymov

Fix 404 for importing as developer

Fix 404 on import page when user have sufficient permissions
to create project but not to admin it
parent 85b9ccc0
...@@ -5,7 +5,8 @@ class Projects::ImportsController < Projects::ApplicationController ...@@ -5,7 +5,8 @@ class Projects::ImportsController < Projects::ApplicationController
include ImportUrlParams include ImportUrlParams
# Authorize # Authorize
before_action :authorize_admin_project! before_action :authorize_admin_project!, only: [:new, :create]
before_action :require_namespace_project_creation_permission, only: :show
before_action :require_no_repo, only: [:new, :create] before_action :require_no_repo, only: [:new, :create]
before_action :redirect_if_progress, only: [:new, :create] before_action :redirect_if_progress, only: [:new, :create]
before_action :redirect_if_no_import, only: :show before_action :redirect_if_no_import, only: :show
...@@ -51,6 +52,10 @@ class Projects::ImportsController < Projects::ApplicationController ...@@ -51,6 +52,10 @@ class Projects::ImportsController < Projects::ApplicationController
end end
end end
def require_namespace_project_creation_permission
render_404 unless current_user.can?(:admin_project, @project) || current_user.can?(:create_projects, @project.namespace)
end
def redirect_if_progress def redirect_if_progress
if @project.import_in_progress? if @project.import_in_progress?
redirect_to project_import_path(@project) redirect_to project_import_path(@project)
......
---
title: Fix 404 when importing project with developer permission
merge_request: 35667
author:
type: fixed
...@@ -8,33 +8,15 @@ RSpec.describe Projects::ImportsController do ...@@ -8,33 +8,15 @@ RSpec.describe Projects::ImportsController do
before do before do
sign_in(user) sign_in(user)
project.add_maintainer(user)
end end
describe 'GET #show' do describe 'GET #show' do
context 'when repository does not exists' do context 'when the user has maintainer rights' do
it 'renders template' do before do
get :show, params: { namespace_id: project.namespace.to_param, project_id: project } project.add_maintainer(user)
expect(response).to render_template :show
end
it 'sets flash.now if params is present' do
get :show, params: { namespace_id: project.namespace.to_param, project_id: project, continue: { to: '/', notice_now: 'Started' } }
expect(flash.now[:notice]).to eq 'Started'
end end
end
context 'when repository exists' do
let(:project) { create(:project_empty_repo, import_url: 'https://github.com/vim/vim.git') }
let(:import_state) { project.import_state }
context 'when import is in progress' do
before do
import_state.update(status: :started)
end
context 'when repository does not exists' do
it 'renders template' do it 'renders template' do
get :show, params: { namespace_id: project.namespace.to_param, project_id: project } get :show, params: { namespace_id: project.namespace.to_param, project_id: project }
...@@ -42,82 +24,138 @@ RSpec.describe Projects::ImportsController do ...@@ -42,82 +24,138 @@ RSpec.describe Projects::ImportsController do
end end
it 'sets flash.now if params is present' do it 'sets flash.now if params is present' do
get :show, params: { namespace_id: project.namespace.to_param, project_id: project, continue: { to: '/', notice_now: 'In progress' } } get :show, params: { namespace_id: project.namespace.to_param, project_id: project, continue: { to: '/', notice_now: 'Started' } }
expect(flash.now[:notice]).to eq 'In progress' expect(flash.now[:notice]).to eq 'Started'
end end
end end
context 'when import failed' do context 'when repository exists' do
before do let(:project) { create(:project_empty_repo, import_url: 'https://github.com/vim/vim.git') }
import_state.update(status: :failed) let(:import_state) { project.import_state }
end
it 'redirects to new_namespace_project_import_path' do context 'when import is in progress' do
get :show, params: { namespace_id: project.namespace.to_param, project_id: project } before do
import_state.update(status: :started)
end
expect(response).to redirect_to new_project_import_path(project) it 'renders template' do
end get :show, params: { namespace_id: project.namespace.to_param, project_id: project }
end
context 'when import finished' do expect(response).to render_template :show
before do end
import_state.update(status: :finished)
it 'sets flash.now if params is present' do
get :show, params: { namespace_id: project.namespace.to_param, project_id: project, continue: { to: '/', notice_now: 'In progress' } }
expect(flash.now[:notice]).to eq 'In progress'
end
end end
context 'when project is a fork' do context 'when import failed' do
it 'redirects to namespace_project_path' do before do
allow_any_instance_of(Project).to receive(:forked?).and_return(true) import_state.update(status: :failed)
end
it 'redirects to new_namespace_project_import_path' do
get :show, params: { namespace_id: project.namespace.to_param, project_id: project } get :show, params: { namespace_id: project.namespace.to_param, project_id: project }
expect(flash[:notice]).to eq 'The project was successfully forked.' expect(response).to redirect_to new_project_import_path(project)
expect(response).to redirect_to project_path(project)
end end
end end
context 'when project is external' do context 'when import finished' do
it 'redirects to namespace_project_path' do before do
get :show, params: { namespace_id: project.namespace.to_param, project_id: project } import_state.update(status: :finished)
end
expect(flash[:notice]).to eq 'The project was successfully imported.' context 'when project is a fork' do
expect(response).to redirect_to project_path(project) it 'redirects to namespace_project_path' do
allow_any_instance_of(Project).to receive(:forked?).and_return(true)
get :show, params: { namespace_id: project.namespace.to_param, project_id: project }
expect(flash[:notice]).to eq 'The project was successfully forked.'
expect(response).to redirect_to project_path(project)
end
end end
end
context 'when continue params is present' do context 'when project is external' do
let(:params) do it 'redirects to namespace_project_path' do
{ get :show, params: { namespace_id: project.namespace.to_param, project_id: project }
to: project_path(project),
notice: 'Finished' expect(flash[:notice]).to eq 'The project was successfully imported.'
} expect(response).to redirect_to project_path(project)
end
end end
it 'redirects to internal params[:to]' do context 'when continue params is present' do
get :show, params: { namespace_id: project.namespace.to_param, project_id: project, continue: params } let(:params) do
{
to: project_path(project),
notice: 'Finished'
}
end
it 'redirects to internal params[:to]' do
get :show, params: { namespace_id: project.namespace.to_param, project_id: project, continue: params }
expect(flash[:notice]).to eq params[:notice]
expect(response).to redirect_to params[:to]
end
expect(flash[:notice]).to eq params[:notice] it 'does not redirect to external params[:to]' do
expect(response).to redirect_to params[:to] params[:to] = "//google.com"
get :show, params: { namespace_id: project.namespace.to_param, project_id: project, continue: params }
expect(response).not_to redirect_to params[:to]
end
end end
end
it 'does not redirect to external params[:to]' do context 'when import never happened' do
params[:to] = "//google.com" before do
import_state.update(status: :none)
end
get :show, params: { namespace_id: project.namespace.to_param, project_id: project, continue: params } it 'redirects to namespace_project_path' do
expect(response).not_to redirect_to params[:to] get :show, params: { namespace_id: project.namespace.to_param, project_id: project }
expect(response).to redirect_to project_path(project)
end end
end end
end end
end
context 'when project is in group' do
let(:project) { create(:project_empty_repo, import_url: 'https://github.com/vim/vim.git', namespace: group) }
context 'when user has developer access to group and import is in progress' do
let(:import_state) { project.import_state }
context 'when import never happened' do
before do before do
import_state.update(status: :none) group.add_developer(user)
import_state.update!(status: :started)
end end
it 'redirects to namespace_project_path' do context 'when group allows developers to create projects' do
get :show, params: { namespace_id: project.namespace.to_param, project_id: project } let(:group) { create(:group, project_creation_level: Gitlab::Access::DEVELOPER_MAINTAINER_PROJECT_ACCESS) }
expect(response).to redirect_to project_path(project) it 'renders template' do
get :show, params: { namespace_id: project.namespace.to_param, project_id: project }
expect(response).to render_template :show
end
end
context 'when group prohibits developers to create projects' do
let(:group) { create(:group, project_creation_level: Gitlab::Access::MAINTAINER_PROJECT_ACCESS) }
it 'returns 404 response' do
get :show, params: { namespace_id: project.namespace.to_param, project_id: project }
expect(response).to have_gitlab_http_status(:not_found)
end
end end
end end
end end
...@@ -128,6 +166,7 @@ RSpec.describe Projects::ImportsController do ...@@ -128,6 +166,7 @@ RSpec.describe Projects::ImportsController do
let(:project) { create(:project) } let(:project) { create(:project) }
before do before do
project.add_maintainer(user)
allow(RepositoryImportWorker).to receive(:perform_async) allow(RepositoryImportWorker).to receive(:perform_async)
post :create, params: { project: params, namespace_id: project.namespace.to_param, project_id: project } post :create, params: { project: params, namespace_id: project.namespace.to_param, project_id: project }
......
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