2019-04-15 06:17:05 -04:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
2014-05-23 04:22:00 -04:00
|
|
|
require('spec_helper')
|
|
|
|
|
|
|
|
describe ProjectsController do
|
2019-04-09 11:38:58 -04:00
|
|
|
include ExternalAuthorizationServiceHelpers
|
2017-09-29 04:04:50 -04:00
|
|
|
include ProjectForksHelper
|
|
|
|
|
2017-08-02 15:55:11 -04:00
|
|
|
let(:project) { create(:project) }
|
|
|
|
let(:public_project) { create(:project, :public) }
|
2017-01-25 16:44:33 -05:00
|
|
|
let(:user) { create(:user) }
|
2018-06-05 17:18:06 -04:00
|
|
|
let(:jpg) { fixture_file_upload('spec/fixtures/rails_sample.jpg', 'image/jpg') }
|
|
|
|
let(:txt) { fixture_file_upload('spec/fixtures/doc_sample.txt', 'text/plain') }
|
2014-05-23 04:22:00 -04:00
|
|
|
|
2017-08-30 13:24:49 -04:00
|
|
|
describe 'GET new' do
|
|
|
|
context 'with an authenticated user' do
|
|
|
|
let(:group) { create(:group) }
|
|
|
|
|
|
|
|
before do
|
|
|
|
sign_in(user)
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when namespace_id param is present' do
|
|
|
|
context 'when user has access to the namespace' do
|
|
|
|
it 'renders the template' do
|
|
|
|
group.add_owner(user)
|
|
|
|
|
2018-12-17 17:52:17 -05:00
|
|
|
get :new, params: { namespace_id: group.id }
|
2017-08-30 13:24:49 -04:00
|
|
|
|
2017-10-19 14:28:19 -04:00
|
|
|
expect(response).to have_gitlab_http_status(200)
|
2017-08-30 13:24:49 -04:00
|
|
|
expect(response).to render_template('new')
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when user does not have access to the namespace' do
|
|
|
|
it 'responds with status 404' do
|
2018-12-17 17:52:17 -05:00
|
|
|
get :new, params: { namespace_id: group.id }
|
2017-08-30 13:24:49 -04:00
|
|
|
|
2017-10-19 14:28:19 -04:00
|
|
|
expect(response).to have_gitlab_http_status(404)
|
2017-08-30 13:24:49 -04:00
|
|
|
expect(response).not_to render_template('new')
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2016-11-03 07:01:23 -04:00
|
|
|
describe 'GET index' do
|
|
|
|
context 'as a user' do
|
|
|
|
it 'redirects to root page' do
|
|
|
|
sign_in(user)
|
|
|
|
|
|
|
|
get :index
|
|
|
|
|
|
|
|
expect(response).to redirect_to(root_path)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'as a guest' do
|
|
|
|
it 'redirects to Explore page' do
|
|
|
|
get :index
|
|
|
|
|
|
|
|
expect(response).to redirect_to(explore_root_path)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2015-02-24 11:02:11 -05:00
|
|
|
describe "GET show" do
|
2016-04-29 17:06:22 -04:00
|
|
|
context "user not project member" do
|
2017-06-14 14:18:56 -04:00
|
|
|
before do
|
|
|
|
sign_in(user)
|
|
|
|
end
|
2016-04-29 17:06:22 -04:00
|
|
|
|
|
|
|
context "user does not have access to project" do
|
2017-08-02 15:55:11 -04:00
|
|
|
let(:private_project) { create(:project, :private) }
|
2016-04-29 17:06:22 -04:00
|
|
|
|
|
|
|
it "does not initialize notification setting" do
|
2018-12-17 17:52:17 -05:00
|
|
|
get :show, params: { namespace_id: private_project.namespace, id: private_project }
|
2016-04-29 17:06:22 -04:00
|
|
|
expect(assigns(:notification_setting)).to be_nil
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context "user has access to project" do
|
2019-04-05 07:33:01 -04:00
|
|
|
before do
|
|
|
|
expect(::Gitlab::GitalyClient).to receive(:allow_ref_name_caching).and_call_original
|
|
|
|
end
|
|
|
|
|
2016-04-29 17:06:22 -04:00
|
|
|
context "and does not have notification setting" do
|
|
|
|
it "initializes notification as disabled" do
|
2018-12-17 17:52:17 -05:00
|
|
|
get :show, params: { namespace_id: public_project.namespace, id: public_project }
|
2016-05-19 19:20:06 -04:00
|
|
|
expect(assigns(:notification_setting).level).to eq("global")
|
2016-04-29 17:06:22 -04:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context "and has notification setting" do
|
|
|
|
before do
|
|
|
|
setting = user.notification_settings_for(public_project)
|
2016-05-19 19:20:06 -04:00
|
|
|
setting.level = :watch
|
2016-04-29 17:06:22 -04:00
|
|
|
setting.save
|
|
|
|
end
|
|
|
|
|
|
|
|
it "shows current notification setting" do
|
2018-12-17 17:52:17 -05:00
|
|
|
get :show, params: { namespace_id: public_project.namespace, id: public_project }
|
2016-05-19 19:20:06 -04:00
|
|
|
expect(assigns(:notification_setting).level).to eq("watch")
|
2016-04-29 17:06:22 -04:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
2016-09-16 15:15:39 -04:00
|
|
|
|
|
|
|
describe "when project repository is disabled" do
|
|
|
|
render_views
|
|
|
|
|
|
|
|
before do
|
2017-12-22 03:18:28 -05:00
|
|
|
project.add_developer(user)
|
2016-09-16 15:15:39 -04:00
|
|
|
project.project_feature.update_attribute(:repository_access_level, ProjectFeature::DISABLED)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'shows wiki homepage' do
|
2018-12-17 17:52:17 -05:00
|
|
|
get :show, params: { namespace_id: project.namespace, id: project }
|
2016-09-16 15:15:39 -04:00
|
|
|
|
|
|
|
expect(response).to render_template('projects/_wiki')
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'shows issues list page if wiki is disabled' do
|
|
|
|
project.project_feature.update_attribute(:wiki_access_level, ProjectFeature::DISABLED)
|
2017-03-15 02:38:47 -04:00
|
|
|
create(:issue, project: project)
|
2016-09-16 15:15:39 -04:00
|
|
|
|
2018-12-17 17:52:17 -05:00
|
|
|
get :show, params: { namespace_id: project.namespace, id: project }
|
2016-09-16 15:15:39 -04:00
|
|
|
|
|
|
|
expect(response).to render_template('projects/issues/_issues')
|
2017-03-16 02:46:12 -04:00
|
|
|
expect(assigns(:issuable_meta_data)).not_to be_nil
|
2016-09-16 15:15:39 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
it 'shows customize workflow page if wiki and issues are disabled' do
|
|
|
|
project.project_feature.update_attribute(:wiki_access_level, ProjectFeature::DISABLED)
|
|
|
|
project.project_feature.update_attribute(:issues_access_level, ProjectFeature::DISABLED)
|
|
|
|
|
2018-12-17 17:52:17 -05:00
|
|
|
get :show, params: { namespace_id: project.namespace, id: project }
|
2016-09-16 15:15:39 -04:00
|
|
|
|
|
|
|
expect(response).to render_template("projects/_customize_workflow")
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'shows activity if enabled by user' do
|
|
|
|
user.update_attribute(:project_view, 'activity')
|
|
|
|
|
2018-12-17 17:52:17 -05:00
|
|
|
get :show, params: { namespace_id: project.namespace, id: project }
|
2016-09-16 15:15:39 -04:00
|
|
|
|
|
|
|
expect(response).to render_template("projects/_activity")
|
|
|
|
end
|
|
|
|
end
|
2016-04-29 17:06:22 -04:00
|
|
|
end
|
2015-02-24 11:02:11 -05:00
|
|
|
|
2017-10-03 04:35:01 -04:00
|
|
|
context 'when the storage is not available', :broken_storage do
|
2017-09-12 06:26:59 -04:00
|
|
|
set(:project) { create(:project, :broken_storage) }
|
|
|
|
|
2017-05-17 12:17:15 -04:00
|
|
|
before do
|
|
|
|
project.add_developer(user)
|
|
|
|
sign_in(user)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'renders a 503' do
|
2018-12-17 17:52:17 -05:00
|
|
|
get :show, params: { namespace_id: project.namespace, id: project }
|
2017-05-17 12:17:15 -04:00
|
|
|
|
2017-10-19 14:28:19 -04:00
|
|
|
expect(response).to have_gitlab_http_status(503)
|
2017-05-17 12:17:15 -04:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2016-07-18 06:58:50 -04:00
|
|
|
context "project with empty repo" do
|
|
|
|
let(:empty_project) { create(:project_empty_repo, :public) }
|
|
|
|
|
2017-06-14 14:18:56 -04:00
|
|
|
before do
|
|
|
|
sign_in(user)
|
|
|
|
end
|
2016-07-18 06:58:50 -04:00
|
|
|
|
|
|
|
User.project_views.keys.each do |project_view|
|
|
|
|
context "with #{project_view} view set" do
|
|
|
|
before do
|
2018-07-02 06:43:06 -04:00
|
|
|
user.update(project_view: project_view)
|
2016-07-18 06:58:50 -04:00
|
|
|
|
2018-12-17 17:52:17 -05:00
|
|
|
get :show, params: { namespace_id: empty_project.namespace, id: empty_project }
|
2016-07-18 06:58:50 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
it "renders the empty project view" do
|
|
|
|
expect(response).to render_template('empty')
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2016-09-23 03:42:07 -04:00
|
|
|
context "project with broken repo" do
|
|
|
|
let(:empty_project) { create(:project_broken_repo, :public) }
|
|
|
|
|
2017-06-14 14:18:56 -04:00
|
|
|
before do
|
|
|
|
sign_in(user)
|
|
|
|
end
|
2016-09-23 03:42:07 -04:00
|
|
|
|
|
|
|
User.project_views.keys.each do |project_view|
|
|
|
|
context "with #{project_view} view set" do
|
|
|
|
before do
|
2018-07-02 06:43:06 -04:00
|
|
|
user.update(project_view: project_view)
|
2016-09-23 03:42:07 -04:00
|
|
|
|
2018-12-17 17:52:17 -05:00
|
|
|
get :show, params: { namespace_id: empty_project.namespace, id: empty_project }
|
2016-09-23 03:42:07 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
it "renders the empty project view" do
|
|
|
|
allow(Project).to receive(:repo).and_raise(Gitlab::Git::Repository::NoRepository)
|
|
|
|
|
|
|
|
expect(response).to render_template('projects/no_repo')
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2015-10-01 10:05:20 -04:00
|
|
|
context "rendering default project view" do
|
2017-01-25 16:44:33 -05:00
|
|
|
let(:public_project) { create(:project, :public, :repository) }
|
|
|
|
|
2015-10-01 10:05:20 -04:00
|
|
|
render_views
|
2016-05-19 19:20:06 -04:00
|
|
|
|
2015-10-17 13:27:02 -04:00
|
|
|
it "renders the activity view" do
|
2015-10-01 10:05:20 -04:00
|
|
|
allow(controller).to receive(:current_user).and_return(user)
|
|
|
|
allow(user).to receive(:project_view).and_return('activity')
|
2015-10-17 13:27:02 -04:00
|
|
|
|
2018-12-17 17:52:17 -05:00
|
|
|
get :show, params: { namespace_id: public_project.namespace, id: public_project }
|
2015-10-01 10:05:20 -04:00
|
|
|
expect(response).to render_template('_activity')
|
|
|
|
end
|
|
|
|
|
2015-10-17 13:27:02 -04:00
|
|
|
it "renders the files view" do
|
2015-10-01 10:05:20 -04:00
|
|
|
allow(controller).to receive(:current_user).and_return(user)
|
|
|
|
allow(user).to receive(:project_view).and_return('files')
|
2015-10-17 13:27:02 -04:00
|
|
|
|
2018-12-17 17:52:17 -05:00
|
|
|
get :show, params: { namespace_id: public_project.namespace, id: public_project }
|
2015-10-01 10:05:20 -04:00
|
|
|
expect(response).to render_template('_files')
|
|
|
|
end
|
2017-10-16 16:21:51 -04:00
|
|
|
|
|
|
|
it "renders the readme view" do
|
|
|
|
allow(controller).to receive(:current_user).and_return(user)
|
|
|
|
allow(user).to receive(:project_view).and_return('readme')
|
|
|
|
|
2018-12-17 17:52:17 -05:00
|
|
|
get :show, params: { namespace_id: public_project.namespace, id: public_project }
|
2017-10-16 16:21:51 -04:00
|
|
|
expect(response).to render_template('_readme')
|
|
|
|
end
|
2015-10-01 10:05:20 -04:00
|
|
|
end
|
2015-10-17 12:20:04 -04:00
|
|
|
|
2016-01-22 11:55:12 -05:00
|
|
|
context "when the url contains .atom" do
|
2017-08-02 15:55:11 -04:00
|
|
|
let(:public_project_with_dot_atom) { build(:project, :public, name: 'my.atom', path: 'my.atom') }
|
2016-01-22 11:55:12 -05:00
|
|
|
|
2016-07-25 14:16:19 -04:00
|
|
|
it 'expects an error creating the project' do
|
2016-02-04 07:20:55 -05:00
|
|
|
expect(public_project_with_dot_atom).not_to be_valid
|
2016-01-22 11:55:12 -05:00
|
|
|
end
|
|
|
|
end
|
2016-05-14 05:33:14 -04:00
|
|
|
|
|
|
|
context 'when the project is pending deletions' do
|
|
|
|
it 'renders a 404 error' do
|
2017-08-02 15:55:11 -04:00
|
|
|
project = create(:project, pending_delete: true)
|
2016-05-14 05:33:14 -04:00
|
|
|
sign_in(user)
|
|
|
|
|
2018-12-17 17:52:17 -05:00
|
|
|
get :show, params: { namespace_id: project.namespace, id: project }
|
2016-05-14 05:33:14 -04:00
|
|
|
|
|
|
|
expect(response.status).to eq 404
|
|
|
|
end
|
|
|
|
end
|
2017-02-03 08:00:26 -05:00
|
|
|
|
|
|
|
context "redirection from http://someproject.git" do
|
|
|
|
it 'redirects to project page (format.html)' do
|
2017-08-02 15:55:11 -04:00
|
|
|
project = create(:project, :public)
|
2017-02-03 08:00:26 -05:00
|
|
|
|
2018-12-17 17:52:17 -05:00
|
|
|
get :show, params: { namespace_id: project.namespace, id: project }, format: :git
|
2017-02-03 08:00:26 -05:00
|
|
|
|
2017-10-19 14:28:19 -04:00
|
|
|
expect(response).to have_gitlab_http_status(302)
|
2017-02-03 08:00:26 -05:00
|
|
|
expect(response).to redirect_to(namespace_project_path)
|
|
|
|
end
|
|
|
|
end
|
2017-11-30 08:26:08 -05:00
|
|
|
|
|
|
|
context 'when the project is forked and has a repository', :request_store do
|
|
|
|
let(:public_project) { create(:project, :public, :repository) }
|
2017-12-04 10:58:44 -05:00
|
|
|
let(:other_user) { create(:user) }
|
2017-11-30 08:26:08 -05:00
|
|
|
|
|
|
|
render_views
|
|
|
|
|
|
|
|
before do
|
|
|
|
# View the project as a user that does not have any rights
|
2017-12-04 10:58:44 -05:00
|
|
|
sign_in(other_user)
|
2017-11-30 08:26:08 -05:00
|
|
|
|
|
|
|
fork_project(public_project)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'does not increase the number of queries when the project is forked' do
|
2017-12-04 10:58:44 -05:00
|
|
|
expected_query = /#{public_project.fork_network.find_forks_in(other_user.namespace).to_sql}/
|
2017-11-30 08:26:08 -05:00
|
|
|
|
2018-12-17 17:52:17 -05:00
|
|
|
expect { get(:show, params: { namespace_id: public_project.namespace, id: public_project }) }
|
Allow public forks to be deduplicated
When a project is forked, the new repository used to be a deep copy of everything
stored on disk by leveraging `git clone`. This works well, and makes isolation
between repository easy. However, the clone is at the start 100% the same as the
origin repository. And in the case of the objects in the object directory, this
is almost always going to be a lot of duplication.
Object Pools are a way to create a third repository that essentially only exists
for its 'objects' subdirectory. This third repository's object directory will be
set as alternate location for objects. This means that in the case an object is
missing in the local repository, git will look in another location. This other
location is the object pool repository.
When Git performs garbage collection, it's smart enough to check the
alternate location. When objects are duplicated, it will allow git to
throw one copy away. This copy is on the local repository, where to pool
remains as is.
These pools have an origin location, which for now will always be a
repository that itself is not a fork. When the root of a fork network is
forked by a user, the fork still clones the full repository. Async, the
pool repository will be created.
Either one of these processes can be done earlier than the other. To
handle this race condition, the Join ObjectPool operation is
idempotent. Given its idempotent, we can schedule it twice, with the
same effect.
To accommodate the holding of state two migrations have been added.
1. Added a state column to the pool_repositories column. This column is
managed by the state machine, allowing for hooks on transitions.
2. pool_repositories now has a source_project_id. This column in
convenient to have for multiple reasons: it has a unique index allowing
the database to handle race conditions when creating a new record. Also,
it's nice to know who the host is. As that's a short link to the fork
networks root.
Object pools are only available for public project, which use hashed
storage and when forking from the root of the fork network. (That is,
the project being forked from itself isn't a fork)
In this commit message I use both ObjectPool and Pool repositories,
which are alike, but different from each other. ObjectPool refers to
whatever is on the disk stored and managed by Gitaly. PoolRepository is
the record in the database.
2018-12-03 08:49:58 -05:00
|
|
|
.not_to exceed_query_limit(2).for_query(expected_query)
|
2017-11-30 08:26:08 -05:00
|
|
|
end
|
|
|
|
end
|
2015-02-24 11:02:11 -05:00
|
|
|
end
|
2015-06-23 01:24:39 -04:00
|
|
|
|
2018-09-03 09:16:23 -04:00
|
|
|
describe 'GET edit' do
|
2019-06-03 03:32:12 -04:00
|
|
|
it 'allows an admin user to access the page' do
|
|
|
|
sign_in(create(:user, :admin))
|
|
|
|
|
|
|
|
get :edit,
|
|
|
|
params: {
|
|
|
|
namespace_id: project.namespace.path,
|
|
|
|
id: project.path
|
|
|
|
}
|
|
|
|
|
|
|
|
expect(response).to have_gitlab_http_status(200)
|
|
|
|
end
|
|
|
|
|
2018-09-03 09:16:23 -04:00
|
|
|
it 'sets the badge API endpoint' do
|
|
|
|
sign_in(user)
|
|
|
|
project.add_maintainer(user)
|
|
|
|
|
|
|
|
get :edit,
|
2018-12-17 17:52:17 -05:00
|
|
|
params: {
|
|
|
|
namespace_id: project.namespace.path,
|
|
|
|
id: project.path
|
|
|
|
}
|
2018-09-03 09:16:23 -04:00
|
|
|
|
|
|
|
expect(assigns(:badge_api_endpoint)).not_to be_nil
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2019-07-03 03:13:00 -04:00
|
|
|
describe '#housekeeping' do
|
|
|
|
let(:group) { create(:group) }
|
|
|
|
let(:project) { create(:project, group: group) }
|
|
|
|
let(:housekeeping) { Projects::HousekeepingService.new(project) }
|
|
|
|
|
|
|
|
context 'when authenticated as owner' do
|
|
|
|
before do
|
|
|
|
group.add_owner(user)
|
|
|
|
sign_in(user)
|
|
|
|
|
|
|
|
allow(Projects::HousekeepingService).to receive(:new).with(project, :gc).and_return(housekeeping)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'forces a full garbage collection' do
|
|
|
|
expect(housekeeping).to receive(:execute).once
|
|
|
|
|
|
|
|
post :housekeeping,
|
|
|
|
params: {
|
|
|
|
namespace_id: project.namespace.path,
|
|
|
|
id: project.path
|
|
|
|
}
|
|
|
|
|
|
|
|
expect(response).to have_gitlab_http_status(302)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when authenticated as developer' do
|
|
|
|
let(:developer) { create(:user) }
|
|
|
|
|
|
|
|
before do
|
|
|
|
group.add_developer(developer)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'does not execute housekeeping' do
|
|
|
|
expect(housekeeping).not_to receive(:execute)
|
|
|
|
|
|
|
|
post :housekeeping,
|
|
|
|
params: {
|
|
|
|
namespace_id: project.namespace.path,
|
|
|
|
id: project.path
|
|
|
|
}
|
|
|
|
|
|
|
|
expect(response).to have_gitlab_http_status(302)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2016-04-04 17:59:54 -04:00
|
|
|
describe "#update" do
|
|
|
|
render_views
|
|
|
|
|
|
|
|
let(:admin) { create(:admin) }
|
2017-05-01 16:46:30 -04:00
|
|
|
|
|
|
|
before do
|
|
|
|
sign_in(admin)
|
|
|
|
end
|
2016-04-04 17:59:54 -04:00
|
|
|
|
2017-12-01 08:58:49 -05:00
|
|
|
shared_examples_for 'updating a project' do
|
|
|
|
context 'when only renaming a project path' do
|
|
|
|
it "sets the repository to the right path after a rename" do
|
2018-06-14 07:18:25 -04:00
|
|
|
original_repository_path = Gitlab::GitalyClient::StorageSettings.allow_disk_access do
|
|
|
|
project.repository.path
|
|
|
|
end
|
2016-04-04 17:59:54 -04:00
|
|
|
|
2017-12-01 08:58:49 -05:00
|
|
|
expect { update_project path: 'renamed_path' }
|
|
|
|
.to change { project.reload.path }
|
|
|
|
expect(project.path).to include 'renamed_path'
|
2017-07-13 09:32:31 -04:00
|
|
|
|
2018-06-14 07:18:25 -04:00
|
|
|
assign_repository_path = Gitlab::GitalyClient::StorageSettings.allow_disk_access do
|
|
|
|
assigns(:repository).path
|
|
|
|
end
|
|
|
|
|
2017-12-01 08:58:49 -05:00
|
|
|
if project.hashed_storage?(:repository)
|
2018-06-14 07:18:25 -04:00
|
|
|
expect(assign_repository_path).to eq(original_repository_path)
|
2017-12-01 08:58:49 -05:00
|
|
|
else
|
2018-06-14 07:18:25 -04:00
|
|
|
expect(assign_repository_path).to include(project.path)
|
2017-12-01 08:58:49 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
expect(response).to have_gitlab_http_status(302)
|
|
|
|
end
|
2017-07-13 09:32:31 -04:00
|
|
|
end
|
2016-04-04 17:59:54 -04:00
|
|
|
|
2017-12-01 08:58:49 -05:00
|
|
|
context 'when project has container repositories with tags' do
|
|
|
|
before do
|
|
|
|
stub_container_registry_config(enabled: true)
|
|
|
|
stub_container_registry_tags(repository: /image/, tags: %w[rc1])
|
|
|
|
create(:container_repository, project: project, name: :image)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'does not allow to rename the project' do
|
|
|
|
expect { update_project path: 'renamed_path' }
|
|
|
|
.not_to change { project.reload.path }
|
2017-07-13 09:32:31 -04:00
|
|
|
|
2018-06-24 23:19:13 -04:00
|
|
|
expect(controller).to set_flash.now[:alert].to(/container registry tags/)
|
2017-12-01 08:58:49 -05:00
|
|
|
expect(response).to have_gitlab_http_status(200)
|
|
|
|
end
|
2017-07-13 09:32:31 -04:00
|
|
|
end
|
|
|
|
|
2017-12-01 08:58:49 -05:00
|
|
|
it 'updates Fast Forward Merge attributes' do
|
|
|
|
controller.instance_variable_set(:@project, project)
|
|
|
|
|
|
|
|
params = {
|
|
|
|
merge_method: :ff
|
|
|
|
}
|
2017-09-20 05:10:23 -04:00
|
|
|
|
2017-12-01 08:58:49 -05:00
|
|
|
put :update,
|
2018-12-17 17:52:17 -05:00
|
|
|
params: {
|
|
|
|
namespace_id: project.namespace,
|
|
|
|
id: project.id,
|
|
|
|
project: params
|
|
|
|
}
|
2017-09-20 05:10:23 -04:00
|
|
|
|
2017-12-01 08:58:49 -05:00
|
|
|
expect(response).to have_gitlab_http_status(302)
|
|
|
|
params.each do |param, value|
|
|
|
|
expect(project.public_send(param)).to eq(value)
|
|
|
|
end
|
|
|
|
end
|
2017-09-20 05:10:23 -04:00
|
|
|
|
2019-03-20 09:39:07 -04:00
|
|
|
it 'does not update namespace' do
|
|
|
|
controller.instance_variable_set(:@project, project)
|
|
|
|
|
|
|
|
params = {
|
|
|
|
namespace_id: 'test'
|
|
|
|
}
|
|
|
|
|
|
|
|
expect do
|
|
|
|
put :update,
|
|
|
|
params: {
|
|
|
|
namespace_id: project.namespace,
|
|
|
|
id: project.id,
|
|
|
|
project: params
|
|
|
|
}
|
2019-03-26 04:30:16 -04:00
|
|
|
end.not_to change { project.namespace.reload }
|
2019-03-20 09:39:07 -04:00
|
|
|
end
|
|
|
|
|
2017-12-01 08:58:49 -05:00
|
|
|
def update_project(**parameters)
|
|
|
|
put :update,
|
2018-12-17 17:52:17 -05:00
|
|
|
params: {
|
|
|
|
namespace_id: project.namespace.path,
|
|
|
|
id: project.path,
|
|
|
|
project: parameters
|
|
|
|
}
|
2017-09-20 05:10:23 -04:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2017-12-01 08:58:49 -05:00
|
|
|
context 'hashed storage' do
|
|
|
|
let(:project) { create(:project, :repository) }
|
|
|
|
|
|
|
|
it_behaves_like 'updating a project'
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'legacy storage' do
|
|
|
|
let(:project) { create(:project, :repository, :legacy_storage) }
|
|
|
|
|
|
|
|
it_behaves_like 'updating a project'
|
2016-04-04 17:59:54 -04:00
|
|
|
end
|
2019-04-09 11:38:58 -04:00
|
|
|
|
|
|
|
context 'as maintainer' do
|
|
|
|
before do
|
|
|
|
project.add_maintainer(user)
|
|
|
|
sign_in(user)
|
|
|
|
end
|
|
|
|
|
|
|
|
it_behaves_like 'unauthorized when external service denies access' do
|
|
|
|
subject do
|
|
|
|
put :update,
|
|
|
|
params: {
|
|
|
|
namespace_id: project.namespace,
|
|
|
|
id: project,
|
|
|
|
project: { description: 'Hello world' }
|
|
|
|
}
|
|
|
|
project.reload
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'updates when the service allows access' do
|
|
|
|
external_service_allow_access(user, project)
|
|
|
|
|
|
|
|
expect { subject }.to change(project, :description)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'does not update when the service rejects access' do
|
|
|
|
external_service_deny_access(user, project)
|
|
|
|
|
|
|
|
expect { subject }.not_to change(project, :description)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
2016-04-04 17:59:54 -04:00
|
|
|
end
|
|
|
|
|
2017-05-09 11:09:20 -04:00
|
|
|
describe '#transfer' do
|
|
|
|
render_views
|
|
|
|
|
2017-08-01 14:51:52 -04:00
|
|
|
let(:project) { create(:project, :repository) }
|
2017-05-09 11:09:20 -04:00
|
|
|
let(:admin) { create(:admin) }
|
|
|
|
let(:new_namespace) { create(:namespace) }
|
|
|
|
|
|
|
|
it 'updates namespace' do
|
|
|
|
sign_in(admin)
|
|
|
|
|
|
|
|
put :transfer,
|
2018-12-17 17:52:17 -05:00
|
|
|
params: {
|
|
|
|
namespace_id: project.namespace.path,
|
|
|
|
new_namespace_id: new_namespace.id,
|
|
|
|
id: project.path
|
|
|
|
},
|
2017-05-09 11:09:20 -04:00
|
|
|
format: :js
|
|
|
|
|
|
|
|
project.reload
|
|
|
|
|
2017-05-18 12:22:02 -04:00
|
|
|
expect(project.namespace).to eq(new_namespace)
|
2017-10-19 14:28:19 -04:00
|
|
|
expect(response).to have_gitlab_http_status(200)
|
2017-05-09 11:09:20 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
context 'when new namespace is empty' do
|
|
|
|
it 'project namespace is not changed' do
|
|
|
|
controller.instance_variable_set(:@project, project)
|
|
|
|
sign_in(admin)
|
|
|
|
|
2017-05-18 12:22:02 -04:00
|
|
|
old_namespace = project.namespace
|
2017-05-09 11:09:20 -04:00
|
|
|
|
|
|
|
put :transfer,
|
2018-12-17 17:52:17 -05:00
|
|
|
params: {
|
|
|
|
namespace_id: old_namespace.path,
|
|
|
|
new_namespace_id: nil,
|
|
|
|
id: project.path
|
|
|
|
},
|
2017-05-09 11:09:20 -04:00
|
|
|
format: :js
|
|
|
|
|
|
|
|
project.reload
|
|
|
|
|
2017-05-18 12:22:02 -04:00
|
|
|
expect(project.namespace).to eq(old_namespace)
|
2017-10-19 14:28:19 -04:00
|
|
|
expect(response).to have_gitlab_http_status(200)
|
2017-05-16 12:41:50 -04:00
|
|
|
expect(flash[:alert]).to eq 'Please select a new namespace for your project.'
|
2017-05-09 11:09:20 -04:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2015-11-26 02:11:35 -05:00
|
|
|
describe "#destroy" do
|
|
|
|
let(:admin) { create(:admin) }
|
|
|
|
|
|
|
|
it "redirects to the dashboard" do
|
|
|
|
controller.instance_variable_set(:@project, project)
|
|
|
|
sign_in(admin)
|
|
|
|
|
|
|
|
orig_id = project.id
|
2018-12-17 17:52:17 -05:00
|
|
|
delete :destroy, params: { namespace_id: project.namespace, id: project }
|
2015-11-26 02:11:35 -05:00
|
|
|
|
|
|
|
expect { Project.find(orig_id) }.to raise_error(ActiveRecord::RecordNotFound)
|
2017-10-19 14:28:19 -04:00
|
|
|
expect(response).to have_gitlab_http_status(302)
|
2015-11-26 02:11:35 -05:00
|
|
|
expect(response).to redirect_to(dashboard_projects_path)
|
|
|
|
end
|
2016-09-01 07:42:17 -04:00
|
|
|
|
2016-09-08 08:20:11 -04:00
|
|
|
context "when the project is forked" do
|
2019-01-16 07:09:29 -05:00
|
|
|
let(:project) { create(:project, :repository) }
|
2017-09-29 04:04:50 -04:00
|
|
|
let(:forked_project) { fork_project(project, nil, repository: true) }
|
2016-09-01 07:42:17 -04:00
|
|
|
let(:merge_request) do
|
2016-09-02 09:36:59 -04:00
|
|
|
create(:merge_request,
|
2017-09-29 04:04:50 -04:00
|
|
|
source_project: forked_project,
|
2016-09-02 09:36:59 -04:00
|
|
|
target_project: project)
|
2016-09-01 07:42:17 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
it "closes all related merge requests" do
|
2016-09-02 07:36:25 -04:00
|
|
|
project.merge_requests << merge_request
|
|
|
|
sign_in(admin)
|
2016-09-01 07:42:17 -04:00
|
|
|
|
2018-12-17 17:52:17 -05:00
|
|
|
delete :destroy, params: { namespace_id: forked_project.namespace, id: forked_project }
|
2016-09-02 07:36:25 -04:00
|
|
|
|
|
|
|
expect(merge_request.reload.state).to eq('closed')
|
2016-09-01 07:42:17 -04:00
|
|
|
end
|
|
|
|
end
|
2015-11-26 02:11:35 -05:00
|
|
|
end
|
|
|
|
|
2017-08-24 02:20:36 -04:00
|
|
|
describe 'PUT #new_issuable_address for issue' do
|
2016-10-18 14:03:31 -04:00
|
|
|
subject do
|
2017-08-24 02:20:36 -04:00
|
|
|
put :new_issuable_address,
|
2018-12-17 17:52:17 -05:00
|
|
|
params: {
|
|
|
|
namespace_id: project.namespace,
|
|
|
|
id: project,
|
|
|
|
issuable_type: 'issue'
|
|
|
|
}
|
2016-10-18 14:03:31 -04:00
|
|
|
user.reload
|
|
|
|
end
|
|
|
|
|
|
|
|
before do
|
|
|
|
sign_in(user)
|
2017-12-22 03:18:28 -05:00
|
|
|
project.add_developer(user)
|
2016-10-18 14:03:31 -04:00
|
|
|
allow(Gitlab.config.incoming_email).to receive(:enabled).and_return(true)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'has http status 200' do
|
2017-10-19 14:28:19 -04:00
|
|
|
expect(response).to have_gitlab_http_status(200)
|
2016-10-18 14:03:31 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
it 'changes the user incoming email token' do
|
|
|
|
expect { subject }.to change { user.incoming_email_token }
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'changes projects new issue address' do
|
2017-08-24 02:20:36 -04:00
|
|
|
expect { subject }.to change { project.new_issuable_address(user, 'issue') }
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
describe 'PUT #new_issuable_address for merge request' do
|
|
|
|
subject do
|
|
|
|
put :new_issuable_address,
|
2018-12-17 17:52:17 -05:00
|
|
|
params: {
|
|
|
|
namespace_id: project.namespace,
|
|
|
|
id: project,
|
|
|
|
issuable_type: 'merge_request'
|
|
|
|
}
|
2017-08-24 02:20:36 -04:00
|
|
|
user.reload
|
|
|
|
end
|
|
|
|
|
|
|
|
before do
|
|
|
|
sign_in(user)
|
2017-12-22 03:18:28 -05:00
|
|
|
project.add_developer(user)
|
2017-08-24 02:20:36 -04:00
|
|
|
allow(Gitlab.config.incoming_email).to receive(:enabled).and_return(true)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'has http status 200' do
|
|
|
|
expect(response).to have_http_status(200)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'changes the user incoming email token' do
|
|
|
|
expect { subject }.to change { user.incoming_email_token }
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'changes projects new merge request address' do
|
|
|
|
expect { subject }.to change { project.new_issuable_address(user, 'merge_request') }
|
2016-10-18 14:03:31 -04:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2014-06-26 03:49:14 -04:00
|
|
|
describe "POST #toggle_star" do
|
2014-07-14 09:17:59 -04:00
|
|
|
it "toggles star if user is signed in" do
|
2014-06-26 03:49:14 -04:00
|
|
|
sign_in(user)
|
2015-02-12 13:17:35 -05:00
|
|
|
expect(user.starred?(public_project)).to be_falsey
|
2015-06-23 01:24:39 -04:00
|
|
|
post(:toggle_star,
|
2018-12-17 17:52:17 -05:00
|
|
|
params: {
|
|
|
|
namespace_id: public_project.namespace,
|
|
|
|
id: public_project
|
|
|
|
})
|
2015-02-12 13:17:35 -05:00
|
|
|
expect(user.starred?(public_project)).to be_truthy
|
2015-06-23 01:24:39 -04:00
|
|
|
post(:toggle_star,
|
2018-12-17 17:52:17 -05:00
|
|
|
params: {
|
|
|
|
namespace_id: public_project.namespace,
|
|
|
|
id: public_project
|
|
|
|
})
|
2015-02-12 13:17:35 -05:00
|
|
|
expect(user.starred?(public_project)).to be_falsey
|
2014-06-26 03:49:14 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
it "does nothing if user is not signed in" do
|
2015-06-23 01:24:39 -04:00
|
|
|
post(:toggle_star,
|
2018-12-17 17:52:17 -05:00
|
|
|
params: {
|
|
|
|
namespace_id: project.namespace,
|
|
|
|
id: public_project
|
|
|
|
})
|
2015-02-12 13:17:35 -05:00
|
|
|
expect(user.starred?(public_project)).to be_falsey
|
2015-06-23 01:24:39 -04:00
|
|
|
post(:toggle_star,
|
2018-12-17 17:52:17 -05:00
|
|
|
params: {
|
|
|
|
namespace_id: project.namespace,
|
|
|
|
id: public_project
|
|
|
|
})
|
2015-02-12 13:17:35 -05:00
|
|
|
expect(user.starred?(public_project)).to be_falsey
|
2014-06-26 03:49:14 -04:00
|
|
|
end
|
|
|
|
end
|
2015-10-13 06:24:44 -04:00
|
|
|
|
2015-10-18 06:37:50 -04:00
|
|
|
describe "DELETE remove_fork" do
|
2015-10-13 06:24:44 -04:00
|
|
|
context 'when signed in' do
|
|
|
|
before do
|
|
|
|
sign_in(user)
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'with forked project' do
|
2017-09-29 04:04:50 -04:00
|
|
|
let(:forked_project) { fork_project(create(:project, :public), user) }
|
2015-10-13 18:04:22 -04:00
|
|
|
|
2016-07-25 14:16:19 -04:00
|
|
|
it 'removes fork from project' do
|
2015-10-13 18:04:22 -04:00
|
|
|
delete(:remove_fork,
|
2018-12-17 17:52:17 -05:00
|
|
|
params: {
|
|
|
|
namespace_id: forked_project.namespace.to_param,
|
|
|
|
id: forked_project.to_param
|
|
|
|
},
|
|
|
|
format: :js)
|
2015-10-13 06:24:44 -04:00
|
|
|
|
2017-09-29 04:04:50 -04:00
|
|
|
expect(forked_project.reload.forked?).to be_falsey
|
2015-10-18 06:37:50 -04:00
|
|
|
expect(flash[:notice]).to eq('The fork relationship has been removed.')
|
2015-10-13 06:24:44 -04:00
|
|
|
expect(response).to render_template(:remove_fork)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2015-10-13 18:04:22 -04:00
|
|
|
context 'when project not forked' do
|
2017-08-02 15:55:11 -04:00
|
|
|
let(:unforked_project) { create(:project, namespace: user.namespace) }
|
2015-10-13 06:24:44 -04:00
|
|
|
|
2016-07-25 14:16:19 -04:00
|
|
|
it 'does nothing if project was not forked' do
|
2015-10-13 18:04:22 -04:00
|
|
|
delete(:remove_fork,
|
2018-12-17 17:52:17 -05:00
|
|
|
params: {
|
|
|
|
namespace_id: unforked_project.namespace,
|
|
|
|
id: unforked_project
|
|
|
|
},
|
|
|
|
format: :js)
|
2015-10-13 18:04:22 -04:00
|
|
|
|
|
|
|
expect(flash[:notice]).to be_nil
|
|
|
|
expect(response).to render_template(:remove_fork)
|
|
|
|
end
|
2015-10-13 06:24:44 -04:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
it "does nothing if user is not signed in" do
|
2015-10-13 18:04:22 -04:00
|
|
|
delete(:remove_fork,
|
2018-12-17 17:52:17 -05:00
|
|
|
params: {
|
|
|
|
namespace_id: project.namespace,
|
|
|
|
id: project
|
|
|
|
},
|
|
|
|
format: :js)
|
2017-10-19 14:28:19 -04:00
|
|
|
expect(response).to have_gitlab_http_status(401)
|
2015-10-13 06:24:44 -04:00
|
|
|
end
|
|
|
|
end
|
2016-06-20 06:37:27 -04:00
|
|
|
|
|
|
|
describe "GET refs" do
|
2018-12-10 08:58:34 -05:00
|
|
|
let(:project) { create(:project, :public, :repository) }
|
2017-01-25 16:44:33 -05:00
|
|
|
|
2017-11-06 23:32:51 -05:00
|
|
|
it 'gets a list of branches and tags' do
|
2018-12-10 08:58:34 -05:00
|
|
|
get :refs, params: { namespace_id: project.namespace, id: project, sort: 'updated_desc' }
|
2016-06-20 06:37:27 -04:00
|
|
|
|
2019-07-16 04:03:49 -04:00
|
|
|
expect(json_response['Branches']).to include('master')
|
|
|
|
expect(json_response['Tags'].first).to eq('v1.1.0')
|
|
|
|
expect(json_response['Tags'].last).to eq('v1.0.0')
|
|
|
|
expect(json_response['Commits']).to be_nil
|
2016-06-20 06:37:27 -04:00
|
|
|
end
|
|
|
|
|
2016-07-25 14:16:19 -04:00
|
|
|
it "gets a list of branches, tags and commits" do
|
2018-12-10 08:58:34 -05:00
|
|
|
get :refs, params: { namespace_id: project.namespace, id: project, ref: "123456" }
|
2016-06-20 06:37:27 -04:00
|
|
|
|
2019-07-16 04:03:49 -04:00
|
|
|
expect(json_response["Branches"]).to include("master")
|
|
|
|
expect(json_response["Tags"]).to include("v1.0.0")
|
|
|
|
expect(json_response["Commits"]).to include("123456")
|
2016-06-20 06:37:27 -04:00
|
|
|
end
|
2018-06-19 23:34:58 -04:00
|
|
|
|
|
|
|
context "when preferred language is Japanese" do
|
|
|
|
before do
|
|
|
|
user.update!(preferred_language: 'ja')
|
|
|
|
sign_in(user)
|
|
|
|
end
|
|
|
|
|
|
|
|
it "gets a list of branches, tags and commits" do
|
2018-12-10 08:58:34 -05:00
|
|
|
get :refs, params: { namespace_id: project.namespace, id: project, ref: "123456" }
|
2018-06-19 23:34:58 -04:00
|
|
|
|
2019-07-16 04:03:49 -04:00
|
|
|
expect(json_response["Branches"]).to include("master")
|
|
|
|
expect(json_response["Tags"]).to include("v1.0.0")
|
|
|
|
expect(json_response["Commits"]).to include("123456")
|
2018-06-19 23:34:58 -04:00
|
|
|
end
|
|
|
|
end
|
2018-12-10 08:58:34 -05:00
|
|
|
|
|
|
|
context 'when private project' do
|
|
|
|
let(:project) { create(:project, :repository) }
|
|
|
|
|
|
|
|
context 'as a guest' do
|
|
|
|
it 'renders forbidden' do
|
|
|
|
user = create(:user)
|
|
|
|
project.add_guest(user)
|
|
|
|
|
|
|
|
sign_in(user)
|
2019-01-02 15:47:45 -05:00
|
|
|
get :refs, params: { namespace_id: project.namespace, id: project }
|
2018-12-10 08:58:34 -05:00
|
|
|
|
|
|
|
expect(response).to have_gitlab_http_status(404)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
2016-06-20 06:37:27 -04:00
|
|
|
end
|
2017-04-20 04:56:41 -04:00
|
|
|
|
|
|
|
describe 'POST #preview_markdown' do
|
2018-07-05 22:21:50 -04:00
|
|
|
before do
|
2017-04-20 04:56:41 -04:00
|
|
|
sign_in(user)
|
2018-07-05 22:21:50 -04:00
|
|
|
end
|
2017-04-20 04:56:41 -04:00
|
|
|
|
2018-07-05 22:21:50 -04:00
|
|
|
it 'renders json in a correct format' do
|
2018-12-17 17:52:17 -05:00
|
|
|
post :preview_markdown, params: { namespace_id: public_project.namespace, id: public_project, text: '*Markdown* text' }
|
2017-04-20 04:56:41 -04:00
|
|
|
|
2019-07-16 04:03:49 -04:00
|
|
|
expect(json_response.keys).to match_array(%w(body references))
|
2017-04-20 04:56:41 -04:00
|
|
|
end
|
2018-07-05 22:21:50 -04:00
|
|
|
|
2019-04-04 09:08:34 -04:00
|
|
|
context 'when not authorized' do
|
|
|
|
let(:private_project) { create(:project, :private) }
|
|
|
|
|
|
|
|
it 'returns 404' do
|
|
|
|
post :preview_markdown, params: { namespace_id: private_project.namespace, id: private_project, text: '*Markdown* text' }
|
|
|
|
|
|
|
|
expect(response).to have_gitlab_http_status(404)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2018-07-05 22:21:50 -04:00
|
|
|
context 'state filter on references' do
|
|
|
|
let(:issue) { create(:issue, :closed, project: public_project) }
|
|
|
|
let(:merge_request) { create(:merge_request, :closed, target_project: public_project) }
|
|
|
|
|
|
|
|
it 'renders JSON body with state filter for issues' do
|
2018-12-17 17:52:17 -05:00
|
|
|
post :preview_markdown, params: {
|
|
|
|
namespace_id: public_project.namespace,
|
|
|
|
id: public_project,
|
|
|
|
text: issue.to_reference
|
|
|
|
}
|
2018-07-05 22:21:50 -04:00
|
|
|
|
|
|
|
expect(json_response['body']).to match(/\##{issue.iid} \(closed\)/)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'renders JSON body with state filter for MRs' do
|
2018-12-17 17:52:17 -05:00
|
|
|
post :preview_markdown, params: {
|
|
|
|
namespace_id: public_project.namespace,
|
|
|
|
id: public_project,
|
|
|
|
text: merge_request.to_reference
|
|
|
|
}
|
2018-07-05 22:21:50 -04:00
|
|
|
|
|
|
|
expect(json_response['body']).to match(/\!#{merge_request.iid} \(closed\)/)
|
|
|
|
end
|
|
|
|
end
|
2017-04-20 04:56:41 -04:00
|
|
|
end
|
2017-05-11 16:57:03 -04:00
|
|
|
|
2017-05-18 15:56:39 -04:00
|
|
|
describe '#ensure_canonical_path' do
|
|
|
|
before do
|
|
|
|
sign_in(user)
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'for a GET request' do
|
|
|
|
context 'when requesting the canonical path' do
|
|
|
|
context "with exactly matching casing" do
|
|
|
|
it "loads the project" do
|
2018-12-17 17:52:17 -05:00
|
|
|
get :show, params: { namespace_id: public_project.namespace, id: public_project }
|
2017-05-18 15:56:39 -04:00
|
|
|
|
|
|
|
expect(assigns(:project)).to eq(public_project)
|
2017-10-19 14:28:19 -04:00
|
|
|
expect(response).to have_gitlab_http_status(200)
|
2017-05-18 15:56:39 -04:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context "with different casing" do
|
|
|
|
it "redirects to the normalized path" do
|
2018-12-17 17:52:17 -05:00
|
|
|
get :show, params: { namespace_id: public_project.namespace, id: public_project.path.upcase }
|
2017-05-18 15:56:39 -04:00
|
|
|
|
|
|
|
expect(assigns(:project)).to eq(public_project)
|
|
|
|
expect(response).to redirect_to("/#{public_project.full_path}")
|
|
|
|
expect(controller).not_to set_flash[:notice]
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when requesting a redirected path' do
|
|
|
|
let!(:redirect_route) { public_project.redirect_routes.create!(path: "foo/bar") }
|
|
|
|
|
|
|
|
it 'redirects to the canonical path' do
|
2018-12-17 17:52:17 -05:00
|
|
|
get :show, params: { namespace_id: 'foo', id: 'bar' }
|
2017-05-18 15:56:39 -04:00
|
|
|
|
|
|
|
expect(response).to redirect_to(public_project)
|
|
|
|
expect(controller).to set_flash[:notice].to(project_moved_message(redirect_route, public_project))
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'redirects to the canonical path (testing non-show action)' do
|
2018-12-17 17:52:17 -05:00
|
|
|
get :refs, params: { namespace_id: 'foo', id: 'bar' }
|
2017-05-18 15:56:39 -04:00
|
|
|
|
2017-06-29 13:06:35 -04:00
|
|
|
expect(response).to redirect_to(refs_project_path(public_project))
|
2017-05-18 15:56:39 -04:00
|
|
|
expect(controller).to set_flash[:notice].to(project_moved_message(redirect_route, public_project))
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'for a POST request' do
|
|
|
|
context 'when requesting the canonical path with different casing' do
|
|
|
|
it 'does not 404' do
|
2018-12-17 17:52:17 -05:00
|
|
|
post :toggle_star, params: { namespace_id: public_project.namespace, id: public_project.path.upcase }
|
2017-05-18 15:56:39 -04:00
|
|
|
|
2017-10-19 14:28:19 -04:00
|
|
|
expect(response).not_to have_gitlab_http_status(404)
|
2017-05-18 15:56:39 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
it 'does not redirect to the correct casing' do
|
2018-12-17 17:52:17 -05:00
|
|
|
post :toggle_star, params: { namespace_id: public_project.namespace, id: public_project.path.upcase }
|
2017-05-18 15:56:39 -04:00
|
|
|
|
2017-10-19 14:28:19 -04:00
|
|
|
expect(response).not_to have_gitlab_http_status(301)
|
2017-05-18 15:56:39 -04:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when requesting a redirected path' do
|
|
|
|
let!(:redirect_route) { public_project.redirect_routes.create!(path: "foo/bar") }
|
|
|
|
|
|
|
|
it 'returns not found' do
|
2018-12-17 17:52:17 -05:00
|
|
|
post :toggle_star, params: { namespace_id: 'foo', id: 'bar' }
|
2017-05-18 15:56:39 -04:00
|
|
|
|
2017-10-19 14:28:19 -04:00
|
|
|
expect(response).to have_gitlab_http_status(404)
|
2017-05-18 15:56:39 -04:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'for a DELETE request' do
|
|
|
|
before do
|
|
|
|
sign_in(create(:admin))
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when requesting the canonical path with different casing' do
|
|
|
|
it 'does not 404' do
|
2018-12-17 17:52:17 -05:00
|
|
|
delete :destroy, params: { namespace_id: project.namespace, id: project.path.upcase }
|
2017-05-18 15:56:39 -04:00
|
|
|
|
2017-10-19 14:28:19 -04:00
|
|
|
expect(response).not_to have_gitlab_http_status(404)
|
2017-05-18 15:56:39 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
it 'does not redirect to the correct casing' do
|
2018-12-17 17:52:17 -05:00
|
|
|
delete :destroy, params: { namespace_id: project.namespace, id: project.path.upcase }
|
2017-05-18 15:56:39 -04:00
|
|
|
|
2017-10-19 14:28:19 -04:00
|
|
|
expect(response).not_to have_gitlab_http_status(301)
|
2017-05-18 15:56:39 -04:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when requesting a redirected path' do
|
|
|
|
let!(:redirect_route) { project.redirect_routes.create!(path: "foo/bar") }
|
|
|
|
|
|
|
|
it 'returns not found' do
|
2018-12-17 17:52:17 -05:00
|
|
|
delete :destroy, params: { namespace_id: 'foo', id: 'bar' }
|
2017-05-18 15:56:39 -04:00
|
|
|
|
2017-10-19 14:28:19 -04:00
|
|
|
expect(response).to have_gitlab_http_status(404)
|
2017-05-18 15:56:39 -04:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2017-07-31 17:34:47 -04:00
|
|
|
describe '#export' do
|
|
|
|
before do
|
|
|
|
sign_in(user)
|
|
|
|
|
2018-07-11 10:36:08 -04:00
|
|
|
project.add_maintainer(user)
|
2017-07-31 17:34:47 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
context 'when project export is enabled' do
|
|
|
|
it 'returns 302' do
|
2018-12-17 17:52:17 -05:00
|
|
|
get :export, params: { namespace_id: project.namespace, id: project }
|
2017-07-31 17:34:47 -04:00
|
|
|
|
2017-10-19 14:28:19 -04:00
|
|
|
expect(response).to have_gitlab_http_status(302)
|
2017-07-31 17:34:47 -04:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when project export is disabled' do
|
|
|
|
before do
|
|
|
|
stub_application_setting(project_export_enabled?: false)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'returns 404' do
|
2018-12-17 17:52:17 -05:00
|
|
|
get :export, params: { namespace_id: project.namespace, id: project }
|
2017-07-31 17:34:47 -04:00
|
|
|
|
2017-10-19 14:28:19 -04:00
|
|
|
expect(response).to have_gitlab_http_status(404)
|
2017-07-31 17:34:47 -04:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
describe '#download_export' do
|
|
|
|
before do
|
|
|
|
sign_in(user)
|
|
|
|
|
2018-07-11 10:36:08 -04:00
|
|
|
project.add_maintainer(user)
|
2017-07-31 17:34:47 -04:00
|
|
|
end
|
|
|
|
|
2018-06-25 09:10:26 -04:00
|
|
|
context 'object storage enabled' do
|
|
|
|
context 'when project export is enabled' do
|
|
|
|
it 'returns 302' do
|
2018-12-17 17:52:17 -05:00
|
|
|
get :download_export, params: { namespace_id: project.namespace, id: project }
|
2017-07-31 17:34:47 -04:00
|
|
|
|
2018-06-25 09:10:26 -04:00
|
|
|
expect(response).to have_gitlab_http_status(302)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when project export is disabled' do
|
|
|
|
before do
|
|
|
|
stub_application_setting(project_export_enabled?: false)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'returns 404' do
|
2018-12-17 17:52:17 -05:00
|
|
|
get :download_export, params: { namespace_id: project.namespace, id: project }
|
2018-06-25 09:10:26 -04:00
|
|
|
|
|
|
|
expect(response).to have_gitlab_http_status(404)
|
|
|
|
end
|
2017-07-31 17:34:47 -04:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
describe '#remove_export' do
|
|
|
|
before do
|
|
|
|
sign_in(user)
|
|
|
|
|
2018-07-11 10:36:08 -04:00
|
|
|
project.add_maintainer(user)
|
2017-07-31 17:34:47 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
context 'when project export is enabled' do
|
|
|
|
it 'returns 302' do
|
2018-12-17 17:52:17 -05:00
|
|
|
post :remove_export, params: { namespace_id: project.namespace, id: project }
|
2017-07-31 17:34:47 -04:00
|
|
|
|
2017-10-19 14:28:19 -04:00
|
|
|
expect(response).to have_gitlab_http_status(302)
|
2017-07-31 17:34:47 -04:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when project export is disabled' do
|
|
|
|
before do
|
|
|
|
stub_application_setting(project_export_enabled?: false)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'returns 404' do
|
2018-12-17 17:52:17 -05:00
|
|
|
post :remove_export, params: { namespace_id: project.namespace, id: project }
|
2017-07-31 17:34:47 -04:00
|
|
|
|
2017-10-19 14:28:19 -04:00
|
|
|
expect(response).to have_gitlab_http_status(404)
|
2017-07-31 17:34:47 -04:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
describe '#generate_new_export' do
|
|
|
|
before do
|
|
|
|
sign_in(user)
|
|
|
|
|
2018-07-11 10:36:08 -04:00
|
|
|
project.add_maintainer(user)
|
2017-07-31 17:34:47 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
context 'when project export is enabled' do
|
|
|
|
it 'returns 302' do
|
2018-12-17 17:52:17 -05:00
|
|
|
post :generate_new_export, params: { namespace_id: project.namespace, id: project }
|
2017-07-31 17:34:47 -04:00
|
|
|
|
2017-10-19 14:28:19 -04:00
|
|
|
expect(response).to have_gitlab_http_status(302)
|
2017-07-31 17:34:47 -04:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when project export is disabled' do
|
|
|
|
before do
|
|
|
|
stub_application_setting(project_export_enabled?: false)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'returns 404' do
|
2018-12-17 17:52:17 -05:00
|
|
|
post :generate_new_export, params: { namespace_id: project.namespace, id: project }
|
2017-07-31 17:34:47 -04:00
|
|
|
|
2017-10-19 14:28:19 -04:00
|
|
|
expect(response).to have_gitlab_http_status(404)
|
2017-07-31 17:34:47 -04:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2018-11-28 14:06:02 -05:00
|
|
|
context 'private project with token authentication' do
|
|
|
|
let(:private_project) { create(:project, :private) }
|
|
|
|
|
|
|
|
it_behaves_like 'authenticates sessionless user', :show, :atom do
|
|
|
|
before do
|
|
|
|
default_params.merge!(id: private_project, namespace_id: private_project.namespace)
|
|
|
|
|
|
|
|
private_project.add_maintainer(user)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'public project with token authentication' do
|
|
|
|
let(:public_project) { create(:project, :public) }
|
|
|
|
|
|
|
|
it_behaves_like 'authenticates sessionless user', :show, :atom, public: true do
|
|
|
|
before do
|
|
|
|
default_params.merge!(id: public_project, namespace_id: public_project.namespace)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2019-01-18 07:19:31 -05:00
|
|
|
describe 'GET resolve' do
|
|
|
|
shared_examples 'resolvable endpoint' do
|
|
|
|
it 'redirects to the project page' do
|
|
|
|
get :resolve, params: { id: project.id }
|
|
|
|
|
|
|
|
expect(response).to have_gitlab_http_status(302)
|
|
|
|
expect(response).to redirect_to(project_path(project))
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'with an authenticated user' do
|
|
|
|
before do
|
|
|
|
sign_in(user)
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when user has access to the project' do
|
|
|
|
before do
|
|
|
|
project.add_developer(user)
|
|
|
|
end
|
|
|
|
|
|
|
|
it_behaves_like 'resolvable endpoint'
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when user has no access to the project' do
|
|
|
|
it 'gives 404 for existing project' do
|
|
|
|
get :resolve, params: { id: project.id }
|
|
|
|
|
|
|
|
expect(response).to have_gitlab_http_status(404)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'gives 404 for non-existing project' do
|
|
|
|
get :resolve, params: { id: '0' }
|
|
|
|
|
|
|
|
expect(response).to have_gitlab_http_status(404)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'non authenticated user' do
|
|
|
|
context 'with a public project' do
|
|
|
|
let(:project) { public_project }
|
|
|
|
|
|
|
|
it_behaves_like 'resolvable endpoint'
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'gives 404 for private project' do
|
|
|
|
get :resolve, params: { id: project.id }
|
|
|
|
|
|
|
|
expect(response).to have_gitlab_http_status(404)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2017-05-11 16:57:03 -04:00
|
|
|
def project_moved_message(redirect_route, project)
|
|
|
|
"Project '#{redirect_route.path}' was moved to '#{project.full_path}'. Please update any links and bookmarks that may still have the old path."
|
|
|
|
end
|
2014-05-26 08:17:46 -04:00
|
|
|
end
|