diff --git a/app/assets/stylesheets/login.scss b/app/assets/stylesheets/login.scss
index dcab57c2..e2c35a7c 100644
--- a/app/assets/stylesheets/login.scss
+++ b/app/assets/stylesheets/login.scss
@@ -11,6 +11,9 @@ body {
.login-wrapper {
@include make-row();
+ .footer {
+ z-index: 1;
+ }
}
.login-box {
diff --git a/app/controllers/preferences_controller.rb b/app/controllers/preferences_controller.rb
index 4781f121..3becc7d0 100644
--- a/app/controllers/preferences_controller.rb
+++ b/app/controllers/preferences_controller.rb
@@ -44,7 +44,7 @@ private
end
def user_params
- params.require(:user).permit(:login, :first_name, :last_name, :password_confirmation, :password, :auth_type, :open_id_url)
+ params.require(:user).permit(:login, :first_name, :last_name, :email, :password_confirmation, :password, :auth_type, :open_id_url)
end
# Display notification if preferences are successful updated
diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb
index 12c37c5e..059a1f74 100644
--- a/app/controllers/users_controller.rb
+++ b/app/controllers/users_controller.rb
@@ -187,7 +187,7 @@ class UsersController < ApplicationController
private
def user_params
- params.require(:user).permit(:login, :first_name, :last_name, :password_confirmation, :password, :auth_type, :open_id_url)
+ params.require(:user).permit(:login, :first_name, :last_name, :email, :password_confirmation, :password, :auth_type, :open_id_url)
end
def get_new_user
diff --git a/app/models/user.rb b/app/models/user.rb
index 736db95e..d68cf40f 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -107,6 +107,7 @@ class User < ApplicationRecord
validates_length_of :login, within: 3..80
validates_uniqueness_of :login, on: :create
validate :validate_auth_type
+ validates :email, :allow_blank => true, format: { with: URI::MailTo::EMAIL_REGEXP }
before_create :crypt_password, :generate_token
before_update :crypt_password
diff --git a/app/views/preferences/_profile.html.erb b/app/views/preferences/_profile.html.erb
index b2f67ace..447eeb57 100644
--- a/app/views/preferences/_profile.html.erb
+++ b/app/views/preferences/_profile.html.erb
@@ -4,6 +4,9 @@
<%= pref_with_text_field 'user', 'last_name' %>
+
+ <%= pref_with_text_field 'user', 'email' %>
+
<%= pref_with_select_field('prefs', 'locale', I18n.available_locales.map {|l| l.to_s}) %>
diff --git a/app/views/users/new.html.erb b/app/views/users/new.html.erb
index 4450011e..a46b87af 100644
--- a/app/views/users/new.html.erb
+++ b/app/views/users/new.html.erb
@@ -22,6 +22,10 @@
<%= label_tag "user_login", t('users.desired_login') %>
<%= text_field "user", "login", class: "form-control" %>
+
+ <%= label_tag "user_email", t('users.email_address') %>
+ <%= text_field "user", "email", class: "form-control" %>
+
<%= label_tag "user_password", t('users.choose_password') %>
<%= password_field "user", "password", class: "form-control" %>
diff --git a/config/locales/en.yml b/config/locales/en.yml
index 97626fd2..5ef1aa96 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -51,6 +51,7 @@ en:
user:
auth_type: Auth type
display_name: Display name
+ email: Email address
first_name: First name
last_name: Last name
login: Login
@@ -87,7 +88,7 @@ en:
confirmation: doesn't match confirmation
less_than_or_equal_to: must be less than or equal to %{count}
blank: can't be blank
- invalid: "cannot contain the comma (',') character"
+ invalid: "is not valid"
exclusion: is reserved
odd: must be odd
even: must be even
@@ -961,6 +962,7 @@ en:
change_password_prompt: Enter your new password in the fields below and click 'Change password' to replace your current password with your new one.
password_confirmation_label: Confirm password
destroy_error: There was an error deleting the user %{login}
+ email_address: Email address
choose_password: Choose password
register_with_cas: With your CAS username
label_auth_type: Authentication type
diff --git a/db/migrate/20200720151220_add_email_to_user.rb b/db/migrate/20200720151220_add_email_to_user.rb
new file mode 100644
index 00000000..0f5627ee
--- /dev/null
+++ b/db/migrate/20200720151220_add_email_to_user.rb
@@ -0,0 +1,5 @@
+class AddEmailToUser < ActiveRecord::Migration[5.2]
+ def change
+ add_column :users, :email, :string
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 539e80c0..4995cd50 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
-ActiveRecord::Schema.define(version: 2020_01_09_231555) do
+ActiveRecord::Schema.define(version: 2020_07_20_151220) do
create_table "attachments", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8", force: :cascade do |t|
t.integer "todo_id"
@@ -220,6 +220,7 @@ ActiveRecord::Schema.define(version: 2020_01_09_231555) do
t.string "open_id_url"
t.string "remember_token"
t.datetime "remember_token_expires_at"
+ t.string "email"
t.index ["login"], name: "index_users_on_login"
end
diff --git a/test/controllers/users_controller_test.rb b/test/controllers/users_controller_test.rb
index 04c6a99e..c3dde992 100644
--- a/test/controllers/users_controller_test.rb
+++ b/test/controllers/users_controller_test.rb
@@ -18,7 +18,7 @@ class UsersControllerTest < ActionController::TestCase
get :index
assert_response :success
assert_equal "TRACKS::Manage Users", assigns['page_title']
- assert_equal 4, assigns['total_users']
+ assert_equal 5, assigns['total_users']
assert_equal users_url, session['return-to']
end
diff --git a/test/fixtures/users.yml b/test/fixtures/users.yml
index f43b9602..8df180d6 100644
--- a/test/fixtures/users.yml
+++ b/test/fixtures/users.yml
@@ -48,3 +48,15 @@ ldap_user:
first_name: International
last_name: Harvester
auth_type: CAS
+
+other_user_email:
+ id: 6
+ login: joe
+ crypted_password: <%= BCrypt::Password.create("open") %>
+ token: <%= Digest::SHA1.hexdigest("joeSun Feb 19 14:42:45 GMT 20060.408173979260027") %>
+ is_admin: false
+ first_name: Jane
+ last_name: Doe
+ email: joe@example.org
+ auth_type: database
+
diff --git a/test/integration/stories_test.rb b/test/integration/stories_test.rb
index 8e0f56a4..512a9b38 100644
--- a/test/integration/stories_test.rb
+++ b/test/integration/stories_test.rb
@@ -3,7 +3,7 @@ require 'support/stub_site_config_helper'
class StoriesTest < ActionDispatch::IntegrationTest
include StubSiteConfigHelper
-
+
# ####################################################
# Testing login and signup by different kinds of users
# ####################################################
@@ -11,10 +11,11 @@ class StoriesTest < ActionDispatch::IntegrationTest
admin = new_session_as(:admin_user,"abracadabra")
admin.goes_to_signup
admin.signs_up_with(:user => {:login => "newbie",
+ :email => "test.person@example.org",
:password => "newbiepass",
:password_confirmation => "newbiepass"})
end
-
+
def test_signup_new_user_by_nonadmin
stub_site_config do
SITE_CONFIG['open_signups'] = false
@@ -22,7 +23,7 @@ class StoriesTest < ActionDispatch::IntegrationTest
other_user.goes_to_signup_as_nonadmin
end
end
-
+
def test_open_signup_new_user
stub_site_config do
SITE_CONFIG['open_signups'] = true
@@ -30,6 +31,7 @@ class StoriesTest < ActionDispatch::IntegrationTest
assert_response :success
assert_template "users/new"
post "/users", params: { :user => {:login => "newbie",
+ :email => "test.person@example.org",
:password => "newbiepass",
:password_confirmation => "newbiepass"} }
assert_response :redirect
@@ -37,8 +39,8 @@ class StoriesTest < ActionDispatch::IntegrationTest
assert_response :success
assert_template "todos/index"
end
- end
-
+ end
+
private
module CustomAssertions
@@ -67,7 +69,7 @@ class StoriesTest < ActionDispatch::IntegrationTest
assert_response :success
assert_template "users/new"
end
-
+
def goes_to_signup_as_nonadmin
get "/signup"
assert_response :success
@@ -81,7 +83,6 @@ class StoriesTest < ActionDispatch::IntegrationTest
assert_response :success
assert_template "todos/index"
end
-
end
def new_session_as(user,plainpass)
@@ -92,5 +93,4 @@ class StoriesTest < ActionDispatch::IntegrationTest
yield sess if block_given?
end
end
-
end
diff --git a/test/integration/users_xml_api_test.rb b/test/integration/users_xml_api_test.rb
index cca726d9..f3d2125d 100644
--- a/test/integration/users_xml_api_test.rb
+++ b/test/integration/users_xml_api_test.rb
@@ -1,20 +1,22 @@
require 'test_helper'
class UsersXmlApiTest < ActionDispatch::IntegrationTest
-
+
@@foobar_postdata = "
foobar"
+ @@barfoo_postdata = "
barbarfoo@example.orgfoo"
@@johnny_postdata = "
johnnybarracuda"
-
+ @@barracuda_postdata = "
barracudabarracuda@example.orgjohnny"
+
def test_fails_with_401_if_not_authorized_user
authenticated_post_xml_to_user_create @@foobar_postdata, 'nobody', 'nohow'
assert_401_unauthorized_admin
end
-
+
def test_fails_with_401_if_not_admin_user
authenticated_post_xml_to_user_create @@foobar_postdata, users(:other_user).login, 'sesame'
assert_401_unauthorized_admin
end
-
+
def test_content_type_must_be_xml
authenticated_post_xml_to_user_create @@foobar_postdata, users(:admin_user).login, 'abracadabra', {'CONTENT_TYPE' => "application/x-www-form-urlencoded"}
assert_response 400, "Expected response 400"
@@ -25,12 +27,12 @@ class UsersXmlApiTest < ActionDispatch::IntegrationTest
# authenticated_post_xml_to_user_create "
"
# assert_equal 500, @integration_session.status
# end
-
+
def test_fails_with_invalid_xml_format2
authenticated_post_xml_to_user_create "foo"
assert_response_and_body 400, "Expected post format is valid xml like so: usernameabc123."
end
-
+
def test_xml_simple_param_parsing
authenticated_post_xml_to_user_create
assert @controller.params.has_key?(:user)
@@ -39,18 +41,18 @@ class UsersXmlApiTest < ActionDispatch::IntegrationTest
assert_equal 'foo', @controller.params['user'][:login]
assert_equal 'bar', @controller.params['user'][:password]
end
-
+
def test_fails_with_too_short_password
authenticated_post_xml_to_user_create
assert_responses_with_error "Password is too short (minimum is 5 characters"
end
-
+
def test_fails_with_nonunique_login
existing_login = users(:other_user).login
authenticated_post_xml_to_user_create "#{existing_login}barracuda"
assert_responses_with_error "Login has already been taken"
end
-
+
def test_creates_new_user
assert_difference 'User.count' do
authenticated_post_xml_to_user_create @@johnny_postdata
@@ -61,16 +63,27 @@ class UsersXmlApiTest < ActionDispatch::IntegrationTest
johnny2 = User.authenticate('johnny','barracuda')
assert_not_nil johnny2, "expected user johnny to be authenticated"
end
-
+
+ def test_creates_new_user
+ assert_difference 'User.count' do
+ authenticated_post_xml_to_user_create @@barracuda_postdata
+ assert_response_and_body 200, "User created."
+ end
+ barracuda1 = User.where(:login => 'barracuda').first
+ assert_not_nil barracuda1, "expected user barracuda to be created"
+ barracuda2 = User.authenticate('barracuda','johnny')
+ assert_not_nil barracuda2, "expected user barracuda to be authenticated"
+ end
+
def test_fails_with_get_verb
authenticated_get_xml "/users.xml", users(:admin_user).login, 'abracadabra', {}
end
-
+
def test_get_users_as_xml
get '/users.xml', params: {}, headers: basic_auth_headers()
assert_response :success
assert_select 'users' do
- assert_select 'user', count: 4
+ assert_select 'user', count: 5
end
assert_select 'password', false
end
@@ -81,7 +94,15 @@ class UsersXmlApiTest < ActionDispatch::IntegrationTest
assert_select 'user'
assert_select 'password', false
end
-
+
+ def test_get_email_user_as_xml
+ get "/users/#{users(:other_user_email).id}.xml", params: {}, headers: basic_auth_headers()
+ assert_response :success
+ assert_select 'user'
+ assert_select 'email'
+ assert_select 'password', false
+ end
+
private
def basic_auth_headers(username = users(:admin_user).login, password = 'abracadabra')
@@ -91,4 +112,8 @@ class UsersXmlApiTest < ActionDispatch::IntegrationTest
def authenticated_post_xml_to_user_create(postdata = @@foobar_postdata, user = users(:admin_user).login, password = 'abracadabra', headers = {})
authenticated_post_xml "/users.xml", user, password, postdata, headers
end
+
+ def authenticated_post_xml_to_user_create_with_email(postdata = @@barfoo_postdata, user = users(:admin_user).login, password = 'abracadabra', headers = {})
+ authenticated_post_xml "/users.xml", user, password, postdata, headers
+ end
end
diff --git a/test/models/user_test.rb b/test/models/user_test.rb
index 6e20d6a4..66d5c801 100644
--- a/test/models/user_test.rb
+++ b/test/models/user_test.rb
@@ -89,6 +89,19 @@ class UserTest < ActiveSupport::TestCase
end
end
+ def test_validate_correct_email
+ assert_difference 'User.count' do
+ create_user :email=> 'testi@example.org'
+ end
+ end
+
+ def test_validate_email_format
+ assert_no_difference 'User.count' do
+ u = create_user :email=> 'test'
+ assert_equal ["is not valid"], u.errors[:email]
+ end
+ end
+
def test_display_name_with_first_and_last_name_set
@other_user.first_name = "Jane"
@other_user.last_name = "Doe"