OpenProject is the leading open source project management software.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 
openproject/spec/controllers/users_controller_spec.rb

645 lines
21 KiB

#-- copyright
# OpenProject is a project management system.
# Copyright (C) 2012-2015 the OpenProject Foundation (OPF)
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2013 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See doc/COPYRIGHT.rdoc for more details.
#++
require 'spec_helper'
require 'work_package'
describe UsersController, type: :controller do
before do
User.delete_all
end
after do
User.current = nil
end
let(:user) { FactoryGirl.create(:user) }
let(:admin) { FactoryGirl.create(:admin) }
let(:anonymous) { FactoryGirl.create(:anonymous) }
describe 'GET deletion_info' do
describe "WHEN the current user is the requested user
WHEN the setting users_deletable_by_self is set to true" do
let(:params) { { 'id' => user.id.to_s } }
before do
allow(Setting).to receive(:users_deletable_by_self?).and_return(true)
as_logged_in_user user do
get :deletion_info, params
end
end
it { expect(response).to be_success }
it { expect(assigns(:user)).to eq(user) }
it { expect(response).to render_template('deletion_info') }
end
describe "WHEN the current user is the requested user
WHEN the setting users_deletable_by_self is set to false" do
let(:params) { { 'id' => user.id.to_s } }
before do
allow(Setting).to receive(:users_deletable_by_self?).and_return(false)
as_logged_in_user user do
get :deletion_info, params
end
end
it { expect(response.response_code).to eq(404) }
end
describe 'WHEN the current user is the anonymous user' do
let(:params) { { 'id' => anonymous.id.to_s } }
before do
as_logged_in_user anonymous do
get :deletion_info, params
end
end
it {
expect(response).to redirect_to(controller: 'account',
action: 'login',
back_url: @controller.url_for(controller: 'users',
action: 'deletion_info'))
}
end
describe "WHEN the current user is admin
WHEN the setting users_deletable_by_admins is set to true" do
let(:params) { { 'id' => user.id.to_s } }
before do
allow(Setting).to receive(:users_deletable_by_admins?).and_return(true)
as_logged_in_user admin do
get :deletion_info, params
end
end
it { expect(response).to be_success }
it { expect(assigns(:user)).to eq(user) }
it { expect(response).to render_template('deletion_info') }
end
describe "WHEN the current user is admin
WHEN the setting users_deletable_by_admins is set to false" do
let(:params) { { 'id' => user.id.to_s } }
before do
allow(Setting).to receive(:users_deletable_by_admins?).and_return(false)
as_logged_in_user admin do
get :deletion_info, params
end
end
it { expect(response.response_code).to eq(404) }
end
end
describe 'POST destroy' do
describe "WHEN the current user is the requested one
WHEN the setting users_deletable_by_self is set to true" do
let(:params) { { 'id' => user.id.to_s } }
before do
disable_flash_sweep
allow(Setting).to receive(:users_deletable_by_self?).and_return(true)
as_logged_in_user user do
post :destroy, params
end
end
it { expect(response).to redirect_to(controller: 'account', action: 'login') }
it { expect(flash[:notice]).to eq(I18n.t('account.deleted')) }
end
describe "WHEN the current user is the requested one
WHEN the setting users_deletable_by_self is set to false" do
let(:params) { { 'id' => user.id.to_s } }
before do
disable_flash_sweep
allow(Setting).to receive(:users_deletable_by_self?).and_return(false)
as_logged_in_user user do
post :destroy, params
end
end
it { expect(response.response_code).to eq(404) }
end
describe "WHEN the current user is the anonymous user
EVEN when the setting login_required is set to false" do
let(:params) { { 'id' => anonymous.id.to_s } }
before do
allow(@controller).to receive(:find_current_user).and_return(anonymous)
allow(Setting).to receive(:login_required?).and_return(false)
as_logged_in_user anonymous do
post :destroy, params
end
end
# redirecting post is not possible for now
it { expect(response.response_code).to eq(403) }
end
describe "WHEN the current user is the admin
WHEN the setting users_deletable_by_admins is set to true" do
let(:admin) { FactoryGirl.create(:admin) }
let(:params) { { 'id' => user.id.to_s } }
before do
disable_flash_sweep
allow(Setting).to receive(:users_deletable_by_admins?).and_return(true)
as_logged_in_user admin do
post :destroy, params
end
end
it { expect(response).to redirect_to(controller: 'users', action: 'index') }
it { expect(flash[:notice]).to eq(I18n.t('account.deleted')) }
end
describe "WHEN the current user is the admin
WHEN the setting users_deletable_by_admins is set to false" do
let(:admin) { FactoryGirl.create(:admin) }
let(:params) { { 'id' => user.id.to_s } }
before do
disable_flash_sweep
allow(Setting).to receive(:users_deletable_by_admins).and_return(false)
as_logged_in_user admin do
post :destroy, params
end
end
it { expect(response.response_code).to eq(404) }
end
end
describe '#change_status' do
describe 'WHEN activating a registered user' do
let!(:registered_user) do
FactoryGirl.create(:user, status: User::STATUSES[:registered],
language: 'de')
end
before do
with_settings(available_languages: [:en, :de],
bcc_recipients: '1') do
as_logged_in_user admin do
post :change_status, id: registered_user.id,
user: { status: User::STATUSES[:active] },
activate: '1'
end
end
end
it 'should activate the user' do
assert registered_user.reload.active?
end
it 'should send an email to the correct user in the correct language' do
mail = ActionMailer::Base.deliveries.last
refute_nil mail
assert_equal [registered_user.mail], mail.to
mail.parts.each do |part|
assert part.body.encoded.include?(I18n.t(:notice_account_activated,
locale: 'de'))
end
end
end
end
describe 'index' do
describe 'new user button' do
render_views
context 'with password login enabled' do
before do
allow(OpenProject::Configuration).to receive(:disable_password_login?).and_return(false)
as_logged_in_user admin do
get :index
end
end
it 'is shown' do
expect(response.body).to have_selector('a', text: I18n.t('label_user_new'))
end
end
context 'with password login disabled' do
before do
allow(OpenProject::Configuration).to receive(:disable_password_login?).and_return(true)
as_logged_in_user admin do
get :index
end
end
# you must not be able to create new users if password login is disabled
# as users are managed externally
it 'is hidden' do
expect(response.body).not_to have_selector('a', text: I18n.t('label_user_new'))
end
end
end
describe 'with session lifetime' do
# TODO move this section to a proper place because we test a
# before_filter from the application controller
after(:each) do
# reset, so following tests are not affected by the change
User.current = nil
end
shared_examples_for 'index action with disabled session lifetime or inactivity not exceeded' do
it "doesn't logout the user and renders the index action" do
expect(User.current).to eq(admin)
expect(response).to render_template 'index'
end
end
shared_examples_for 'index action with enabled session lifetime and inactivity exceeded' do
it 'logs out the user and redirects with a warning that he has been locked out' do
expect(response.redirect_url).to eq(signin_url + '?back_url=' + CGI::escape(@controller.url_for(controller: 'users', action: 'index')))
expect(User.current).not_to eq(admin)
expect(flash[:warning]).to eq(I18n.t(:notice_forced_logout, ttl_time: Setting.session_ttl))
end
end
context 'disabled' do
before do
allow(Setting).to receive(:session_ttl_enabled?).and_return(false)
@controller.send(:logged_user=, admin)
get :index
end
it_should_behave_like 'index action with disabled session lifetime or inactivity not exceeded'
end
context 'enabled ' do
before do
allow(Setting).to receive(:session_ttl_enabled?).and_return(true)
allow(Setting).to receive(:session_ttl).and_return('120')
@controller.send(:logged_user=, admin)
end
context 'before 120 min of inactivity' do
before do
session[:updated_at] = Time.now - 1.hours
get :index
end
it_should_behave_like 'index action with disabled session lifetime or inactivity not exceeded'
end
context 'after 120 min of inactivity' do
before do
session[:updated_at] = Time.now - 3.hours
get :index
end
it_should_behave_like 'index action with enabled session lifetime and inactivity exceeded'
end
context 'without last activity time in the session' do
before do
allow(Setting).to receive(:session_ttl).and_return('60')
session[:updated_at] = nil
get :index
end
it_should_behave_like 'index action with enabled session lifetime and inactivity exceeded'
end
context 'with ttl = 0' do
before do
allow(Setting).to receive(:session_ttl).and_return('0')
session[:updated_at] = Time.now - 1.hours
get :index
end
it_should_behave_like 'index action with disabled session lifetime or inactivity not exceeded'
end
context 'with ttl < 0' do
before do
allow(Setting).to receive(:session_ttl).and_return('-60')
session[:updated_at] = Time.now - 1.hours
get :index
end
it_should_behave_like 'index action with disabled session lifetime or inactivity not exceeded'
end
context 'with ttl < 5 > 0' do
before do
allow(Setting).to receive(:session_ttl).and_return('4')
session[:updated_at] = Time.now - 1.hours
get :index
end
it_should_behave_like 'index action with disabled session lifetime or inactivity not exceeded'
end
end
end
end
describe '#new' do
context 'with password login enabled' do
before do
allow(OpenProject::Configuration).to receive(:disable_password_login?).and_return(false)
as_logged_in_user admin do
get :new
end
end
it 'should return HTTP 200' do
expect(response.status).to eq 200
end
end
context 'with password login disabled' do
before do
allow(OpenProject::Configuration).to receive(:disable_password_login?).and_return(true)
as_logged_in_user admin do
get :new
end
end
# you must not be able to create new users if password login is disabled
it 'should return HTTP 404' do
expect(response.status).to eq 404
end
end
end
describe '#create' do
context 'with password login enabled' do
before do
allow(OpenProject::Configuration).to receive(:disable_password_login?).and_return(false)
as_logged_in_user admin do
post :create
end
end
it 'should return HTTP 400 due to missing parameters' do
expect(response.status).to eq 400
end
end
context 'with password login disabled' do
before do
allow(OpenProject::Configuration).to receive(:disable_password_login?).and_return(true)
as_logged_in_user admin do
post :create
end
end
# you must not be able to create new users if password login is disabled
it 'should return HTTP 404' do
expect(response.status).to eq 404
end
end
end
describe 'update' do
context 'fields' do
let(:user) {
FactoryGirl.create(:user, firstname: 'Firstname',
admin: true,
login: 'testlogin',
mail_notification: 'all',
force_password_change: false)
}
before do
as_logged_in_user(admin) do
put :update, id: user.id, user: { admin: false,
firstname: 'Changed',
login: 'changedlogin',
mail_notification: 'only_assigned',
force_password_change: true },
pref: { hide_mail: '1', comments_sorting: 'desc' }
end
end
it 'should redirect to the edit page' do
expect(response).to redirect_to(edit_user_url(user))
end
it 'should be assigned their new values' do
user_from_db = User.find(user.id)
expect(user_from_db.admin).to be_falsey
expect(user_from_db.firstname).to eql('Changed')
expect(user_from_db.login).to eql('changedlogin')
expect(user_from_db.mail_notification).to eql('only_assigned')
expect(user_from_db.force_password_change).to eql(true)
expect(user_from_db.pref[:hide_mail]).to be_truthy
expect(user_from_db.pref[:comments_sorting]).to eql('desc')
end
it 'should not send an email' do
expect(ActionMailer::Base.deliveries.empty?).to be_truthy
end
end
context 'with external authentication' do
let(:user) { FactoryGirl.create(:user, identity_url: 'some:identity') }
before do
as_logged_in_user(admin) do
put :update, id: user.id, user: { force_password_change: 'true' }
end
user.reload
end
it 'should ignore setting force_password_change' do
expect(user.force_password_change).to eql(false)
end
end
context 'ldap auth source' do
let(:ldap_auth_source) { FactoryGirl.create(:ldap_auth_source) }
it 'switchting to internal authentication on a password change' do
user.auth_source = ldap_auth_source
as_logged_in_user admin do
put :update, id: user.id, user: { auth_source_id: '', password: 'newpassPASS!', password_confirmation: 'newpassPASS!' }
end
expect(user.reload.auth_source).to be_nil
expect(user.check_password?('newpassPASS!')).to be_truthy
end
end
context 'with disabled_password_choice' do
before do
expect(OpenProject::Configuration).to receive(:disable_password_choice?).and_return(true)
end
it 'ignores password parameters and leaves the password unchanged' do
as_logged_in_user(admin) do
put :update,
id: user.id,
user: { password: 'changedpass!', password_confirmation: 'changedpass!' }
end
expect(user.reload.check_password?('changedpass!')).to be false
end
end
end
describe 'update memberships' do
let(:project) { FactoryGirl.create(:project) }
let(:role) { FactoryGirl.create(:role) }
it 'works' do
# i.e. it should successfully add a user to a project's members
as_logged_in_user admin do
post :edit_membership,
id: user.id,
membership: {
project_id: project.id,
role_ids: [role.id]
},
format: 'js'
end
expect(response.status).to eql(200)
is_member = user.reload.memberships.any? { |m|
m.project_id == project.id && m.role_ids.include?(role.id)
}
expect(is_member).to eql(true)
end
end
describe 'Anonymous should not be able to create a user' do
it 'should redirect to the login page' do
post :create, user: { login: 'psmith', firstname: 'Paul', lastname: 'Smith' }, password: 'psmithPSMITH09', password_confirmation: 'psmithPSMITH09'
expect(response).to redirect_to '/login?back_url=http%3A%2F%2Ftest.host%2Fusers'
end
end
describe 'show' do
describe 'general' do
before do
as_logged_in_user user do
get :show, id: user.id
end
end
it 'responds with success' do
expect(response).to be_success
end
it 'renders the show template' do
expect(response).to render_template 'show'
end
it 'assigns @user' do
expect(assigns(:user)).to eq(user)
end
end
describe 'for user with Activity' do
render_views
let(:work_package) {
FactoryGirl.create(:work_package,
author: user)
}
let!(:member) {
FactoryGirl.create(:member,
project: work_package.project,
principal: user,
roles: [FactoryGirl.create(:role,
permissions: [:view_work_packages])])
}
let!(:journal_1) {
FactoryGirl.create(:work_package_journal,
user: user,
journable_id: work_package.id,
version: Journal.maximum(:version) + 1,
data: FactoryGirl.build(:journal_work_package_journal,
subject: work_package.subject,
status_id: work_package.status_id,
type_id: work_package.type_id,
project_id: work_package.project_id))
}
let!(:journal_2) {
FactoryGirl.create(:work_package_journal,
user: user,
journable_id: work_package.id,
version: Journal.maximum(:version) + 1,
data: FactoryGirl.build(:journal_work_package_journal,
subject: work_package.subject,
status_id: work_package.status_id,
type_id: work_package.type_id,
project_id: work_package.project_id))
}
before do
allow(User).to receive(:current).and_return(user.reload)
allow_any_instance_of(User).to receive(:reported_work_package_count).and_return(42)
get :show, id: user.id
end
it 'should include the number of reported work packages' do
label = Regexp.escape(I18n.t(:label_reported_work_packages))
expect(response.body).to have_selector('p', text: /#{label}.*42/)
end
it 'should have @events_by_day grouped by day' do
expect(assigns(:events_by_day).keys.first.class).to eq(Date)
end
it 'should have more than one event for today' do
expect(assigns(:events_by_day).first.size).to be > 1
end
end
end
end