diff options
Diffstat (limited to 'spec/controllers/users_controller_spec.rb')
-rw-r--r-- | spec/controllers/users_controller_spec.rb | 925 |
1 files changed, 0 insertions, 925 deletions
diff --git a/spec/controllers/users_controller_spec.rb b/spec/controllers/users_controller_spec.rb deleted file mode 100644 index 916befe3f62..00000000000 --- a/spec/controllers/users_controller_spec.rb +++ /dev/null @@ -1,925 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -RSpec.describe UsersController do - # This user should have the same e-mail address associated with the GPG key prepared for tests - let(:user) { create(:user, email: GpgHelpers::User1.emails[0]) } - let(:private_user) { create(:user, private_profile: true) } - let(:public_user) { create(:user) } - - describe 'GET #show' do - context 'with rendered views' do - render_views - - describe 'when logged in' do - before do - sign_in(user) - end - - it 'renders the show template' do - get :show, params: { username: user.username } - - expect(response).to be_successful - expect(response).to render_template('show') - end - end - - describe 'when logged out' do - it 'renders the show template' do - get :show, params: { username: user.username } - - expect(response).to have_gitlab_http_status(:ok) - expect(response).to render_template('show') - end - end - end - - context 'when public visibility level is restricted' do - before do - stub_application_setting(restricted_visibility_levels: [Gitlab::VisibilityLevel::PUBLIC]) - end - - context 'when logged out' do - it 'redirects to login page' do - get :show, params: { username: user.username } - expect(response).to redirect_to new_user_session_path - end - end - - context 'when logged in' do - before do - sign_in(user) - end - - it 'renders show' do - get :show, params: { username: user.username } - expect(response).to have_gitlab_http_status(:ok) - expect(response).to render_template('show') - end - end - end - - context 'when a user by that username does not exist' do - context 'when logged out' do - it 'redirects to login page' do - get :show, params: { username: 'nonexistent' } - expect(response).to redirect_to new_user_session_path - end - end - - context 'when logged in' do - before do - sign_in(user) - end - - it 'renders 404' do - get :show, params: { username: 'nonexistent' } - expect(response).to have_gitlab_http_status(:not_found) - end - end - end - - context 'json with events' do - let(:project) { create(:project) } - - before do - project.add_developer(user) - Gitlab::DataBuilder::Push.build_sample(project, user) - - sign_in(user) - end - - it 'loads events' do - get :show, params: { username: user }, format: :json - - expect(assigns(:events)).not_to be_empty - end - - it 'hides events if the user cannot read cross project' do - allow(Ability).to receive(:allowed?).and_call_original - expect(Ability).to receive(:allowed?).with(user, :read_cross_project) { false } - - get :show, params: { username: user }, format: :json - - expect(assigns(:events)).to be_empty - end - - it 'hides events if the user has a private profile' do - Gitlab::DataBuilder::Push.build_sample(project, private_user) - - get :show, params: { username: private_user.username }, format: :json - - expect(assigns(:events)).to be_empty - end - end - end - - describe 'GET #activity' do - context 'with rendered views' do - render_views - - describe 'when logged in' do - before do - sign_in(user) - end - - it 'renders the show template' do - get :show, params: { username: user.username } - - expect(response).to be_successful - expect(response).to render_template('show') - end - end - - describe 'when logged out' do - it 'renders the show template' do - get :activity, params: { username: user.username } - - expect(response).to have_gitlab_http_status(:ok) - expect(response).to render_template('show') - end - end - end - - context 'when public visibility level is restricted' do - before do - stub_application_setting(restricted_visibility_levels: [Gitlab::VisibilityLevel::PUBLIC]) - end - - context 'when logged out' do - it 'redirects to login page' do - get :activity, params: { username: user.username } - expect(response).to redirect_to new_user_session_path - end - end - - context 'when logged in' do - before do - sign_in(user) - end - - it 'renders show' do - get :activity, params: { username: user.username } - expect(response).to have_gitlab_http_status(:ok) - expect(response).to render_template('show') - end - end - end - - context 'when a user by that username does not exist' do - context 'when logged out' do - it 'redirects to login page' do - get :activity, params: { username: 'nonexistent' } - expect(response).to redirect_to new_user_session_path - end - end - - context 'when logged in' do - before do - sign_in(user) - end - - it 'renders 404' do - get :activity, params: { username: 'nonexistent' } - expect(response).to have_gitlab_http_status(:not_found) - end - end - end - - context 'json with events' do - let(:project) { create(:project) } - - before do - project.add_developer(user) - Gitlab::DataBuilder::Push.build_sample(project, user) - - sign_in(user) - end - - it 'loads events' do - get :activity, params: { username: user }, format: :json - - expect(assigns(:events)).not_to be_empty - end - - it 'hides events if the user cannot read cross project' do - allow(Ability).to receive(:allowed?).and_call_original - expect(Ability).to receive(:allowed?).with(user, :read_cross_project) { false } - - get :activity, params: { username: user }, format: :json - - expect(assigns(:events)).to be_empty - end - - it 'hides events if the user has a private profile' do - Gitlab::DataBuilder::Push.build_sample(project, private_user) - - get :activity, params: { username: private_user.username }, format: :json - - expect(assigns(:events)).to be_empty - end - end - end - - describe "#ssh_keys" do - describe "non existent user" do - it "does not generally work" do - get :ssh_keys, params: { username: 'not-existent' } - - expect(response).not_to be_successful - end - end - - describe "user with no keys" do - it "does generally work" do - get :ssh_keys, params: { username: user.username } - - expect(response).to be_successful - end - - it "renders all keys separated with a new line" do - get :ssh_keys, params: { username: user.username } - - expect(response.body).to eq("") - end - - it "responds with text/plain content type" do - get :ssh_keys, params: { username: user.username } - expect(response.content_type).to eq("text/plain") - end - end - - describe "user with keys" do - let!(:key) { create(:key, user: user) } - let!(:another_key) { create(:another_key, user: user) } - let!(:deploy_key) { create(:deploy_key, user: user) } - - describe "while signed in" do - before do - sign_in(user) - end - - it "does generally work" do - get :ssh_keys, params: { username: user.username } - - expect(response).to be_successful - end - - it "renders all non deploy keys separated with a new line" do - get :ssh_keys, params: { username: user.username } - - expect(response.body).not_to eq('') - expect(response.body).to eq(user.all_ssh_keys.join("\n")) - - expect(response.body).to include(key.key.sub(' dummy@gitlab.com', '')) - expect(response.body).to include(another_key.key.sub(' dummy@gitlab.com', '')) - - expect(response.body).not_to include(deploy_key.key) - end - - it "does not render the comment of the key" do - get :ssh_keys, params: { username: user.username } - expect(response.body).not_to match(/dummy@gitlab.com/) - end - - it "responds with text/plain content type" do - get :ssh_keys, params: { username: user.username } - - expect(response.content_type).to eq("text/plain") - end - end - - describe 'when logged out' do - before do - sign_out(user) - end - - it "still does generally work" do - get :ssh_keys, params: { username: user.username } - - expect(response).to be_successful - end - - it "renders all non deploy keys separated with a new line" do - get :ssh_keys, params: { username: user.username } - - expect(response.body).not_to eq('') - expect(response.body).to eq(user.all_ssh_keys.join("\n")) - - expect(response.body).to include(key.key.sub(' dummy@gitlab.com', '')) - expect(response.body).to include(another_key.key.sub(' dummy@gitlab.com', '')) - - expect(response.body).not_to include(deploy_key.key) - end - - it "does not render the comment of the key" do - get :ssh_keys, params: { username: user.username } - expect(response.body).not_to match(/dummy@gitlab.com/) - end - - it "responds with text/plain content type" do - get :ssh_keys, params: { username: user.username } - - expect(response.content_type).to eq("text/plain") - end - end - end - end - - describe "#gpg_keys" do - describe "non existent user" do - it "does not generally work" do - get :gpg_keys, params: { username: 'not-existent' } - - expect(response).not_to be_successful - end - end - - describe "user with no keys" do - it "does generally work" do - get :gpg_keys, params: { username: user.username } - - expect(response).to be_successful - end - - it "renders all keys separated with a new line" do - get :gpg_keys, params: { username: user.username } - - expect(response.body).to eq("") - end - - it "responds with text/plain content type" do - get :gpg_keys, params: { username: user.username } - - expect(response.content_type).to eq("text/plain") - end - end - - describe "user with keys" do - let!(:gpg_key) { create(:gpg_key, user: user) } - let!(:another_gpg_key) { create(:another_gpg_key, user: user) } - - describe "while signed in" do - before do - sign_in(user) - end - - it "does generally work" do - get :gpg_keys, params: { username: user.username } - - expect(response).to be_successful - end - - it "renders all verified keys separated with a new line" do - get :gpg_keys, params: { username: user.username } - - expect(response.body).not_to eq('') - expect(response.body).to eq(user.gpg_keys.select(&:verified?).map(&:key).join("\n")) - - expect(response.body).to include(gpg_key.key) - expect(response.body).to include(another_gpg_key.key) - end - - it "responds with text/plain content type" do - get :gpg_keys, params: { username: user.username } - - expect(response.content_type).to eq("text/plain") - end - end - - describe 'when logged out' do - before do - sign_out(user) - end - - it "still does generally work" do - get :gpg_keys, params: { username: user.username } - - expect(response).to be_successful - end - - it "renders all verified keys separated with a new line" do - get :gpg_keys, params: { username: user.username } - - expect(response.body).not_to eq('') - expect(response.body).to eq(user.gpg_keys.map(&:key).join("\n")) - - expect(response.body).to include(gpg_key.key) - expect(response.body).to include(another_gpg_key.key) - end - - it "responds with text/plain content type" do - get :gpg_keys, params: { username: user.username } - - expect(response.content_type).to eq("text/plain") - end - end - - describe 'when revoked' do - before do - sign_in(user) - another_gpg_key.revoke - end - - it "doesn't render revoked keys" do - get :gpg_keys, params: { username: user.username } - - expect(response.body).not_to eq('') - - expect(response.body).to include(gpg_key.key) - expect(response.body).not_to include(another_gpg_key.key) - end - - it "doesn't render revoked keys for non-authorized users" do - sign_out(user) - get :gpg_keys, params: { username: user.username } - - expect(response.body).not_to eq('') - - expect(response.body).to include(gpg_key.key) - expect(response.body).not_to include(another_gpg_key.key) - end - end - end - end - - describe 'GET #calendar' do - context 'for user' do - let(:project) { create(:project) } - - before do - sign_in(user) - project.add_developer(user) - end - - context 'with public profile' do - it 'renders calendar' do - push_data = Gitlab::DataBuilder::Push.build_sample(project, public_user) - EventCreateService.new.push(project, public_user, push_data) - - get :calendar, params: { username: public_user.username }, format: :json - - expect(response).to have_gitlab_http_status(:ok) - end - end - - context 'with private profile' do - it 'does not render calendar' do - push_data = Gitlab::DataBuilder::Push.build_sample(project, private_user) - EventCreateService.new.push(project, private_user, push_data) - - get :calendar, params: { username: private_user.username }, format: :json - - expect(response).to have_gitlab_http_status(:not_found) - end - end - end - - context 'forked project' do - let(:project) { create(:project) } - let(:forked_project) { Projects::ForkService.new(project, user).execute } - - before do - sign_in(user) - project.add_developer(user) - - push_data = Gitlab::DataBuilder::Push.build_sample(project, user) - - fork_push_data = Gitlab::DataBuilder::Push - .build_sample(forked_project, user) - - EventCreateService.new.push(project, user, push_data) - EventCreateService.new.push(forked_project, user, fork_push_data) - end - - it 'includes forked projects' do - get :calendar, params: { username: user.username } - expect(assigns(:contributions_calendar).projects.count).to eq(2) - end - end - end - - describe 'GET #calendar_activities' do - let!(:project) { create(:project) } - let(:user) { create(:user) } - - before do - allow_next_instance_of(User) do |instance| - allow(instance).to receive(:contributed_projects_ids).and_return([project.id]) - end - - sign_in(user) - project.add_developer(user) - end - - it 'assigns @calendar_date' do - get :calendar_activities, params: { username: user.username, date: '2014-07-31' } - expect(assigns(:calendar_date)).to eq(Date.parse('2014-07-31')) - end - - context 'for user' do - context 'with public profile' do - let(:issue) { create(:issue, project: project, author: user) } - let(:note) { create(:note, noteable: issue, author: user, project: project) } - - render_views - - before do - create_push_event - create_note_event - end - - it 'renders calendar_activities' do - get :calendar_activities, params: { username: public_user.username } - - expect(assigns[:events]).not_to be_empty - end - - it 'avoids N+1 queries', :request_store do - get :calendar_activities, params: { username: public_user.username } - - control = ActiveRecord::QueryRecorder.new { get :calendar_activities, params: { username: public_user.username } } - - create_push_event - create_note_event - - expect { get :calendar_activities, params: { username: public_user.username } }.not_to exceed_query_limit(control) - end - end - - context 'with private profile' do - it 'does not render calendar_activities' do - push_data = Gitlab::DataBuilder::Push.build_sample(project, private_user) - EventCreateService.new.push(project, private_user, push_data) - - get :calendar_activities, params: { username: private_user.username } - expect(response).to have_gitlab_http_status(:not_found) - end - end - - context 'external authorization' do - subject { get :calendar_activities, params: { username: user.username } } - - it_behaves_like 'disabled when using an external authorization service' - end - - def create_push_event - push_data = Gitlab::DataBuilder::Push.build_sample(project, public_user) - EventCreateService.new.push(project, public_user, push_data) - end - - def create_note_event - EventCreateService.new.leave_note(note, public_user) - end - end - end - - describe 'GET #contributed' do - let(:project) { create(:project, :public) } - - subject do - get :contributed, params: { username: author.username }, format: format - end - - before do - sign_in(user) - - project.add_developer(public_user) - project.add_developer(private_user) - create(:push_event, project: project, author: author) - - subject - end - - shared_examples_for 'renders contributed projects' do - it 'renders contributed projects' do - expect(assigns[:contributed_projects]).not_to be_empty - expect(response).to have_gitlab_http_status(:ok) - end - end - - %i(html json).each do |format| - context "format: #{format}" do - let(:format) { format } - - context 'with public profile' do - let(:author) { public_user } - - it_behaves_like 'renders contributed projects' - end - - context 'with private profile' do - let(:author) { private_user } - - it 'returns 404' do - expect(response).to have_gitlab_http_status(:not_found) - end - - context 'with a user that has the ability to read private profiles', :enable_admin_mode do - let(:user) { create(:admin) } - - it_behaves_like 'renders contributed projects' - end - end - end - end - end - - describe 'GET #starred' do - let(:project) { create(:project, :public) } - - subject do - get :starred, params: { username: author.username }, format: format - end - - before do - author.toggle_star(project) - - sign_in(user) - subject - end - - shared_examples_for 'renders starred projects' do - it 'renders starred projects' do - expect(response).to have_gitlab_http_status(:ok) - expect(assigns[:starred_projects]).not_to be_empty - end - end - - %i(html json).each do |format| - context "format: #{format}" do - let(:format) { format } - - context 'with public profile' do - let(:author) { public_user } - - it_behaves_like 'renders starred projects' - end - - context 'with private profile' do - let(:author) { private_user } - - it 'returns 404' do - expect(response).to have_gitlab_http_status(:not_found) - end - - context 'with a user that has the ability to read private profiles', :enable_admin_mode do - let(:user) { create(:admin) } - - it_behaves_like 'renders starred projects' - end - end - end - end - end - - describe 'GET #snippets' do - before do - sign_in(user) - end - - context 'format html' do - it 'renders snippets page' do - get :snippets, params: { username: user.username } - expect(response).to have_gitlab_http_status(:ok) - expect(response).to render_template('show') - end - end - - context 'format json' do - it 'response with snippets json data' do - get :snippets, params: { username: user.username }, format: :json - expect(response).to have_gitlab_http_status(:ok) - expect(json_response).to have_key('html') - end - end - - context 'external authorization' do - subject { get :snippets, params: { username: user.username } } - - it_behaves_like 'disabled when using an external authorization service' - end - end - - describe 'GET #exists' do - before do - sign_in(user) - end - - context 'when user exists' do - it 'returns JSON indicating the user exists' do - get :exists, params: { username: user.username } - - expected_json = { exists: true }.to_json - expect(response.body).to eq(expected_json) - end - - context 'when the casing is different' do - let(:user) { create(:user, username: 'CamelCaseUser') } - - it 'returns JSON indicating the user exists' do - get :exists, params: { username: user.username.downcase } - - expected_json = { exists: true }.to_json - expect(response.body).to eq(expected_json) - end - end - end - - context 'when the user does not exist' do - it 'returns JSON indicating the user does not exist' do - get :exists, params: { username: 'foo' } - - expected_json = { exists: false }.to_json - expect(response.body).to eq(expected_json) - end - - context 'when a user changed their username' do - let(:redirect_route) { user.namespace.redirect_routes.create(path: 'old-username') } - - it 'returns JSON indicating a user by that username does not exist' do - get :exists, params: { username: 'old-username' } - - expected_json = { exists: false }.to_json - expect(response.body).to eq(expected_json) - end - end - end - end - - describe 'GET #suggests' do - context 'when user exists' do - it 'returns JSON indicating the user exists and a suggestion' do - get :suggests, params: { username: user.username } - - expected_json = { exists: true, suggests: ["#{user.username}1"] }.to_json - expect(response.body).to eq(expected_json) - end - - context 'when the casing is different' do - let(:user) { create(:user, username: 'CamelCaseUser') } - - it 'returns JSON indicating the user exists and a suggestion' do - get :suggests, params: { username: user.username.downcase } - - expected_json = { exists: true, suggests: ["#{user.username.downcase}1"] }.to_json - expect(response.body).to eq(expected_json) - end - end - end - - context 'when the user does not exist' do - it 'returns JSON indicating the user does not exist' do - get :suggests, params: { username: 'foo' } - - expected_json = { exists: false, suggests: [] }.to_json - expect(response.body).to eq(expected_json) - end - - context 'when a user changed their username' do - let(:redirect_route) { user.namespace.redirect_routes.create(path: 'old-username') } - - it 'returns JSON indicating a user by that username does not exist' do - get :suggests, params: { username: 'old-username' } - - expected_json = { exists: false, suggests: [] }.to_json - expect(response.body).to eq(expected_json) - end - end - end - end - - describe '#ensure_canonical_path' do - before do - sign_in(user) - end - - context 'for a GET request' do - context 'when requesting users at the root path' do - context 'when requesting the canonical path' do - let(:user) { create(:user, username: 'CamelCaseUser') } - - context 'with exactly matching casing' do - it 'responds with success' do - get :show, params: { username: user.username } - - expect(response).to be_successful - end - end - - context 'with different casing' do - it 'redirects to the correct casing' do - get :show, params: { username: user.username.downcase } - - expect(response).to redirect_to(user) - expect(controller).not_to set_flash[:notice] - end - end - end - - context 'when requesting a redirected path' do - let(:redirect_route) { user.namespace.redirect_routes.create(path: 'old-path') } - - it 'redirects to the canonical path' do - get :show, params: { username: redirect_route.path } - - expect(response).to redirect_to(user) - expect(controller).to set_flash[:notice].to(user_moved_message(redirect_route, user)) - end - - context 'when the old path is a substring of the scheme or host' do - let(:redirect_route) { user.namespace.redirect_routes.create(path: 'http') } - - it 'does not modify the requested host' do - get :show, params: { username: redirect_route.path } - - expect(response).to redirect_to(user) - expect(controller).to set_flash[:notice].to(user_moved_message(redirect_route, user)) - end - end - - context 'when the old path is substring of users' do - let(:redirect_route) { user.namespace.redirect_routes.create(path: 'ser') } - - it 'redirects to the canonical path' do - get :show, params: { username: redirect_route.path } - - expect(response).to redirect_to(user) - expect(controller).to set_flash[:notice].to(user_moved_message(redirect_route, user)) - end - end - end - end - - context 'when requesting users under the /users path' do - context 'when requesting the canonical path' do - let(:user) { create(:user, username: 'CamelCaseUser') } - - context 'with exactly matching casing' do - it 'responds with success' do - get :projects, params: { username: user.username } - - expect(response).to be_successful - end - end - - context 'with different casing' do - it 'redirects to the correct casing' do - get :projects, params: { username: user.username.downcase } - - expect(response).to redirect_to(user_projects_path(user)) - expect(controller).not_to set_flash[:notice] - end - end - end - - context 'when requesting a redirected path' do - let(:redirect_route) { user.namespace.redirect_routes.create(path: 'old-path') } - - it 'redirects to the canonical path' do - get :projects, params: { username: redirect_route.path } - - expect(response).to redirect_to(user_projects_path(user)) - expect(controller).to set_flash[:notice].to(user_moved_message(redirect_route, user)) - end - - context 'when the old path is a substring of the scheme or host' do - let(:redirect_route) { user.namespace.redirect_routes.create(path: 'http') } - - it 'does not modify the requested host' do - get :projects, params: { username: redirect_route.path } - - expect(response).to redirect_to(user_projects_path(user)) - expect(controller).to set_flash[:notice].to(user_moved_message(redirect_route, user)) - end - end - - context 'when the old path is substring of users' do - let(:redirect_route) { user.namespace.redirect_routes.create(path: 'ser') } - - # I.e. /users/ser should not become /ufoos/ser - it 'does not modify the /users part of the path' do - get :projects, params: { username: redirect_route.path } - - expect(response).to redirect_to(user_projects_path(user)) - expect(controller).to set_flash[:notice].to(user_moved_message(redirect_route, user)) - end - end - end - end - end - end - - context 'token authentication' do - it_behaves_like 'authenticates sessionless user', :show, :atom, public: true do - before do - default_params.merge!(username: user.username) - end - end - end - - def user_moved_message(redirect_route, user) - "User '#{redirect_route.path}' was moved to '#{user.full_path}'. Please update any links and bookmarks that may still have the old path." - end -end |