342 lines
12 KiB
Ruby
342 lines
12 KiB
Ruby
|
|
require "spec_helper"
|
||
|
|
|
||
|
|
describe UsersController do
|
||
|
|
include RedirectExpectationHelper
|
||
|
|
include LoginMacros
|
||
|
|
|
||
|
|
shared_examples "an action only authorized admins can access" do |authorized_roles:|
|
||
|
|
before do
|
||
|
|
fake_login_admin(admin)
|
||
|
|
end
|
||
|
|
|
||
|
|
context "when logged in as an admin with no role" do
|
||
|
|
let(:admin) { create(:admin) }
|
||
|
|
|
||
|
|
it "redirects with an error" do
|
||
|
|
subject
|
||
|
|
it_redirects_to_with_error(root_url, "Sorry, only an authorized admin can access the page you were trying to reach.")
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
(Admin::VALID_ROLES - authorized_roles).each do |admin_role|
|
||
|
|
context "when logged in as an admin with role #{admin_role}" do
|
||
|
|
let(:admin) { create(:admin, roles: [admin_role]) }
|
||
|
|
|
||
|
|
it "redirects with an error" do
|
||
|
|
subject
|
||
|
|
it_redirects_to_with_error(root_url, "Sorry, only an authorized admin can access the page you were trying to reach.")
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
authorized_roles.each do |admin_role|
|
||
|
|
context "when logged in as an admin with role #{admin_role}" do
|
||
|
|
let(:admin) { create(:admin, roles: [admin_role]) }
|
||
|
|
|
||
|
|
it "succeeds" do
|
||
|
|
subject
|
||
|
|
success
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
shared_examples "blocks access for banned and suspended users" do
|
||
|
|
context "when logged in as a banned user" do
|
||
|
|
let(:user) { create(:user, banned: true) }
|
||
|
|
|
||
|
|
before do
|
||
|
|
fake_login_known_user(user)
|
||
|
|
end
|
||
|
|
|
||
|
|
it "redirects with an error" do
|
||
|
|
subject
|
||
|
|
it_redirects_to_simple(user_path(user))
|
||
|
|
expect(flash[:error]).to match("Your account has been banned")
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
context "when logged in as a suspended user" do
|
||
|
|
let(:user) { create(:user, suspended: true, suspended_until: 1.week.from_now) }
|
||
|
|
|
||
|
|
before do
|
||
|
|
fake_login_known_user(user)
|
||
|
|
end
|
||
|
|
|
||
|
|
it "redirects with an error" do
|
||
|
|
subject
|
||
|
|
it_redirects_to_simple(user_path(user))
|
||
|
|
expect(flash[:error]).to match("Your account has been suspended")
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
describe "GET #activate" do
|
||
|
|
let(:user) { create(:user, confirmed_at: nil) }
|
||
|
|
|
||
|
|
context "with no activation key" do
|
||
|
|
it "redirects with an error" do
|
||
|
|
get :activate, params: { id: "" }
|
||
|
|
it_redirects_to_with_error(root_path, "Your activation key is missing.")
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
context "with an invalid activation key" do
|
||
|
|
it "redirects with an error" do
|
||
|
|
get :activate, params: { id: "foobar" }
|
||
|
|
it_redirects_to_with_error(root_path, "Your activation key is invalid. If you didn't activate within 14 days, your account was deleted. Please sign up again, or contact support via the link in our footer for more help.")
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
context "with a used activation key" do
|
||
|
|
before { user.activate }
|
||
|
|
|
||
|
|
it "redirects with an error" do
|
||
|
|
expect(user.active?).to be_truthy
|
||
|
|
get :activate, params: { id: user.confirmation_token }
|
||
|
|
it_redirects_to_with_error(user_path(user), "Your account has already been activated.")
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
context "with a valid activation key" do
|
||
|
|
it "activates the account and redirects with a success message" do
|
||
|
|
expect(user.active?).to be_falsey
|
||
|
|
get :activate, params: { id: user.confirmation_token }
|
||
|
|
expect(user.reload.active?).to be_truthy
|
||
|
|
it_redirects_to_with_notice(new_user_session_path, "Account activation complete! Please log in.")
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
describe "show" do
|
||
|
|
let(:user) { create(:user) }
|
||
|
|
|
||
|
|
context "with a valid username" do
|
||
|
|
it "renders the show template" do
|
||
|
|
get :show, params: { id: user }
|
||
|
|
expect(response).to render_template(:show)
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
context "with an invalid username" do
|
||
|
|
it "raises an error" do
|
||
|
|
expect do
|
||
|
|
get :show, params: { id: "nobody" }
|
||
|
|
end.to raise_error ActiveRecord::RecordNotFound
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
describe "GET #change_username" do
|
||
|
|
let(:user) { create(:user) }
|
||
|
|
let(:success) { expect(response).to render_template(:change_username) }
|
||
|
|
subject { get :change_username, params: { id: user } }
|
||
|
|
|
||
|
|
context "when logged in as a valid user" do
|
||
|
|
before do
|
||
|
|
fake_login_known_user(user)
|
||
|
|
end
|
||
|
|
|
||
|
|
it "shows the change username form" do
|
||
|
|
subject
|
||
|
|
success
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
it_behaves_like "an action only authorized admins can access", authorized_roles: %w[superadmin policy_and_abuse]
|
||
|
|
it_behaves_like "blocks access for banned and suspended users"
|
||
|
|
end
|
||
|
|
|
||
|
|
describe "POST #changed_username" do
|
||
|
|
let(:user) { create(:user) }
|
||
|
|
let(:new_username) { "foo1234" }
|
||
|
|
let(:success) do
|
||
|
|
expect(user.reload.login).to eq(new_username)
|
||
|
|
end
|
||
|
|
|
||
|
|
subject do
|
||
|
|
post :changed_username, params: { id: user, new_login: new_username, password: user.password }
|
||
|
|
end
|
||
|
|
|
||
|
|
context "when logged in as a valid user" do
|
||
|
|
before do
|
||
|
|
fake_login_known_user(user)
|
||
|
|
end
|
||
|
|
|
||
|
|
it "updates the user's username" do
|
||
|
|
subject
|
||
|
|
success
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
it_behaves_like "an action only authorized admins can access", authorized_roles: %w[superadmin policy_and_abuse] do
|
||
|
|
# Non-exhaustive check that users who cannot access this page themselves (i.e. because they are banned)
|
||
|
|
# can still be renamed by an admin.
|
||
|
|
let(:user) { create(:user, banned: true) }
|
||
|
|
let(:new_username) { "user#{user.id}" }
|
||
|
|
|
||
|
|
before do
|
||
|
|
allow_any_instance_of(ZohoResourceClient).to receive(:find_ticket).and_return({
|
||
|
|
"status" => "Open",
|
||
|
|
"departmentId" => ""
|
||
|
|
})
|
||
|
|
end
|
||
|
|
|
||
|
|
subject do
|
||
|
|
post :changed_username, params: { id: user, new_login: new_username, ticket_number: 123 }
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
it_behaves_like "blocks access for banned and suspended users"
|
||
|
|
end
|
||
|
|
|
||
|
|
describe "PUT #confirm_change_email" do
|
||
|
|
let(:user) { create(:user, email: "old@example.com", password: "password") }
|
||
|
|
|
||
|
|
context "when logged out" do
|
||
|
|
it "errors and tells the user to log in" do
|
||
|
|
put :confirm_change_email, params: { id: user, new_email: "new@example.com", email_confirmation: "new@example.com", password_check: "password" }
|
||
|
|
|
||
|
|
it_redirects_to_with_error(user_path(user), "Sorry, you don't have permission to access the page you were trying to reach. Please log in.")
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
context "when logged in" do
|
||
|
|
before { fake_login_known_user(user) }
|
||
|
|
|
||
|
|
it "requires reauthentication" do
|
||
|
|
put :confirm_change_email, params: { id: user, new_email: "new@example.com", email_confirmation: "new@example.com" }
|
||
|
|
|
||
|
|
expect(response).to render_template(:change_email)
|
||
|
|
expect(flash[:error]).to eq("You must enter your password.")
|
||
|
|
end
|
||
|
|
|
||
|
|
it "disallows incorrect password" do
|
||
|
|
put :confirm_change_email, params: { id: user, new_email: "new@example.com", email_confirmation: "new@example.com", password_check: "wrong" }
|
||
|
|
|
||
|
|
expect(response).to render_template(:change_email)
|
||
|
|
expect(flash[:error]).to include("Your password was incorrect. Please try again or log out and reset your password via the link on")
|
||
|
|
end
|
||
|
|
|
||
|
|
it "disallows blank email address" do
|
||
|
|
put :confirm_change_email, params: { id: user, new_email: "", email_confirmation: "", password_check: "password" }
|
||
|
|
|
||
|
|
expect(response).to render_template(:change_email)
|
||
|
|
expect(flash[:error]).to eq("You must enter a new email address.")
|
||
|
|
end
|
||
|
|
|
||
|
|
it "requires a valid email address" do
|
||
|
|
put :confirm_change_email, params: { id: user, new_email: "wrong", email_confirmation: "wrong", password_check: "password" }
|
||
|
|
|
||
|
|
expect(response).to render_template(:change_email)
|
||
|
|
expect(assigns[:user].errors.full_messages).to include("Email should look like an email address.")
|
||
|
|
end
|
||
|
|
|
||
|
|
it "disallows non-matching email confirmation" do
|
||
|
|
put :confirm_change_email, params: { id: user, new_email: "new@example.com", email_confirmation: "different@example.com", password_check: "password" }
|
||
|
|
|
||
|
|
expect(response).to render_template(:change_email)
|
||
|
|
expect(flash[:error]).to eq("The email addresses you entered do not match. Please try again.")
|
||
|
|
end
|
||
|
|
|
||
|
|
it "allows case-insensitive email confirmation" do
|
||
|
|
put :confirm_change_email, params: { id: user, new_email: "new@example.com", email_confirmation: "NEW@example.com", password_check: "password" }
|
||
|
|
|
||
|
|
expect(response).to render_template(:confirm_change_email)
|
||
|
|
expect(flash[:error]).to be_blank
|
||
|
|
end
|
||
|
|
|
||
|
|
it "disallows using another user's email" do
|
||
|
|
create(:user, email: "new@example.com")
|
||
|
|
put :confirm_change_email, params: { id: user, new_email: "new@example.com", email_confirmation: "new@example.com", password_check: "password" }
|
||
|
|
|
||
|
|
expect(response).to render_template(:change_email)
|
||
|
|
expect(assigns[:user].errors.full_messages.first).to include("This email is already associated with another account. Please try again with a different email address.")
|
||
|
|
expect(assigns[:user].email).to eq("old@example.com")
|
||
|
|
end
|
||
|
|
|
||
|
|
it "disallows using current email" do
|
||
|
|
put :confirm_change_email, params: { id: user, new_email: "old@example.com", email_confirmation: "old@example.com", password_check: "password" }
|
||
|
|
|
||
|
|
expect(response).to render_template(:change_email)
|
||
|
|
expect(flash[:error]).to eq("Your new email address must be different from your current email.")
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
describe "POST #changed_email" do
|
||
|
|
let(:user) { create(:user, email: "old@example.com") }
|
||
|
|
|
||
|
|
context "when logged out" do
|
||
|
|
it "errors and tells the user to log in" do
|
||
|
|
post :changed_email, params: { id: user, new_email: "new@example.com" }
|
||
|
|
|
||
|
|
it_redirects_to_with_error(user_path(user), "Sorry, you don't have permission to access the page you were trying to reach. Please log in.")
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
context "when logged in" do
|
||
|
|
before { fake_login_known_user(user) }
|
||
|
|
|
||
|
|
it "requires a valid email address" do
|
||
|
|
post :changed_email, params: { id: user, new_email: "wrong" }
|
||
|
|
|
||
|
|
expect(response).to render_template(:change_email)
|
||
|
|
expect(assigns[:user].errors.full_messages).to include("Email should look like an email address.")
|
||
|
|
expect(assigns[:user].email).to eq("old@example.com")
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
describe "GET #reconfirm_email" do
|
||
|
|
let(:user) { create(:user) }
|
||
|
|
|
||
|
|
context "when logged out" do
|
||
|
|
it "errors and tells the user to log in" do
|
||
|
|
get :reconfirm_email, params: { id: user, confirmation_token: "foo" }
|
||
|
|
|
||
|
|
it_redirects_to_with_error(user_path(user), "Sorry, you don't have permission to access the page you were trying to reach. Please log in.")
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
context "when logged in as the wrong user" do
|
||
|
|
let(:another_user) { create(:user) }
|
||
|
|
|
||
|
|
before { fake_login_known_user(another_user) }
|
||
|
|
|
||
|
|
it "errors and tells the user to log out" do
|
||
|
|
get :reconfirm_email, params: { id: user, confirmation_token: "foo" }
|
||
|
|
|
||
|
|
it_redirects_to_with_error(user_path(user), "You are not logged in to the account whose email you are trying to change. Please log out and try again.")
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
context "when logged in as right user" do
|
||
|
|
before { fake_login_known_user(user) }
|
||
|
|
|
||
|
|
it "disallows invalid tokens" do
|
||
|
|
get :reconfirm_email, params: { id: user, confirmation_token: "foo" }
|
||
|
|
|
||
|
|
it_redirects_to_with_error(change_email_user_path(user), "This email confirmation link is invalid or expired. Please check your email for the correct link or submit the email change form again.")
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
describe "destroy" do
|
||
|
|
let(:user) { create(:user) }
|
||
|
|
|
||
|
|
before do
|
||
|
|
fake_login_known_user(user)
|
||
|
|
end
|
||
|
|
|
||
|
|
context "no log items" do
|
||
|
|
it "successfully destroys and redirects with success message" do
|
||
|
|
login = user.login
|
||
|
|
delete :destroy, params: { id: login }
|
||
|
|
it_redirects_to_with_notice(delete_confirmation_path, "You have successfully deleted your account.")
|
||
|
|
expect(User.find_by(login: login)).to be_nil
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|