From c0d5099a23da59d8235abe488c3cb5cb3302a365 Mon Sep 17 00:00:00 2001 From: Colin Darie Date: Thu, 24 May 2018 23:40:23 +0200 Subject: [PATCH] Users forms: TOS acceptance, notifications deactivation --- app/controllers/application_controller.rb | 8 +++ .../packs/src/components/users.scss | 6 +-- app/models/user.rb | 4 ++ app/views/devise/registrations/edit.html.erb | 2 +- app/views/devise/registrations/new.html.erb | 2 + config/locales/en.yml | 11 +++++ .../20180523145630_devise_create_users.rb | 1 - ...180524205809_add_custom_fields_to_users.rb | 6 +++ db/schema.rb | 4 +- test/fixtures/users.yml | 3 ++ test/models/user_test.rb | 2 + test/system/users_test.rb | 49 +++++++++++++++++++ 12 files changed, 91 insertions(+), 7 deletions(-) create mode 100644 db/migrate/20180524205809_add_custom_fields_to_users.rb diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 09705d1..37ba566 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -1,2 +1,10 @@ class ApplicationController < ActionController::Base + before_action :configure_devise_parameters, if: :devise_controller? + + protected + + def configure_devise_parameters + devise_parameter_sanitizer.permit(:sign_up, keys: [:tos_accepted]) + devise_parameter_sanitizer.permit(:account_update, keys: [:notifications_enabled]) + end end diff --git a/app/javascript/packs/src/components/users.scss b/app/javascript/packs/src/components/users.scss index dc42ca4..05ae08f 100644 --- a/app/javascript/packs/src/components/users.scss +++ b/app/javascript/packs/src/components/users.scss @@ -1,5 +1,3 @@ -.new_user { - .form-check-label.boolean { - color: inherit; - } +.form-check-label.optional.boolean { + color: inherit; } diff --git a/app/models/user.rb b/app/models/user.rb index 791ed72..a398135 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -12,10 +12,12 @@ # encrypted_password :string(255) default(""), not null # last_sign_in_at :datetime # last_sign_in_ip :string(255) +# notifications_enabled :boolean default(TRUE), not null # remember_created_at :datetime # reset_password_sent_at :datetime # reset_password_token :string(255) # sign_in_count :integer default(0), not null +# tos_accepted :boolean default(FALSE), not null # unconfirmed_email :string(255) # created_at :datetime not null # updated_at :datetime not null @@ -32,4 +34,6 @@ class User < ApplicationRecord # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable devise :database_authenticatable, :registerable, :recoverable, :rememberable, :validatable, :confirmable + + validates :tos_accepted, acceptance: true end diff --git a/app/views/devise/registrations/edit.html.erb b/app/views/devise/registrations/edit.html.erb index 9d99eb0..4ab2468 100644 --- a/app/views/devise/registrations/edit.html.erb +++ b/app/views/devise/registrations/edit.html.erb @@ -1,7 +1,6 @@ <%= devise_form_container do %>

<%= t('.title', resource: resource_name.to_s.humanize) %>

- <%= simple_form_for(resource, as: resource_name, url: registration_path(resource_name), html: { method: :put }) do |f| %> <%= f.input :email, autofocus: true, autocomplete: "email" %> @@ -25,6 +24,7 @@ <%= f.input :password_confirmation, autocomplete: "off" %> + <%= f.input :notifications_enabled %> <%= f.button :submit, t('.update'), class: "btn-primary" %> <% end %> diff --git a/app/views/devise/registrations/new.html.erb b/app/views/devise/registrations/new.html.erb index ed81d21..69a0e09 100644 --- a/app/views/devise/registrations/new.html.erb +++ b/app/views/devise/registrations/new.html.erb @@ -9,6 +9,8 @@ <%= f.input :password_confirmation, autocomplete: "off" %> + <%= f.input :tos_accepted, label: t('.tos_acceptance_html') %> + <%= f.button :submit, t('.sign_up'), class: "btn-primary" %> <% end %> diff --git a/config/locales/en.yml b/config/locales/en.yml index d6fe953..c7c3395 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -1,4 +1,15 @@ en: + activerecord: + attributes: + user: + tos_accepted: "Terms of service" + notifications_enabled: "Notifications enabled" + + devise: + registrations: + new: + tos_acceptance_html: "You must accept our Terms of service" + shared: navbar: sign_up: "Sign up" diff --git a/db/migrate/20180523145630_devise_create_users.rb b/db/migrate/20180523145630_devise_create_users.rb index 4ba28dc..b0c5e73 100644 --- a/db/migrate/20180523145630_devise_create_users.rb +++ b/db/migrate/20180523145630_devise_create_users.rb @@ -32,7 +32,6 @@ class DeviseCreateUsers < ActiveRecord::Migration[5.2] # t.string :unlock_token # Only if unlock strategy is :email or :both # t.datetime :locked_at - t.timestamps null: false end diff --git a/db/migrate/20180524205809_add_custom_fields_to_users.rb b/db/migrate/20180524205809_add_custom_fields_to_users.rb new file mode 100644 index 0000000..2864b70 --- /dev/null +++ b/db/migrate/20180524205809_add_custom_fields_to_users.rb @@ -0,0 +1,6 @@ +class AddCustomFieldsToUsers < ActiveRecord::Migration[5.2] + def change + add_column :users, :tos_accepted, :boolean, null: false, default: false + add_column :users, :notifications_enabled, :boolean, null: false, default: true + end +end diff --git a/db/schema.rb b/db/schema.rb index da6be3d..8483285 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: 2018_05_23_145630) do +ActiveRecord::Schema.define(version: 2018_05_24_205809) do create_table "users", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8", force: :cascade do |t| t.string "email", default: "", null: false @@ -29,6 +29,8 @@ ActiveRecord::Schema.define(version: 2018_05_23_145630) do t.string "unconfirmed_email" t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.boolean "tos_accepted", default: false, null: false + t.boolean "notifications_enabled", default: true, null: false t.index ["confirmation_token"], name: "index_users_on_confirmation_token", unique: true t.index ["email"], name: "index_users_on_email", unique: true t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true diff --git a/test/fixtures/users.yml b/test/fixtures/users.yml index 5f2b5ad..b6f3831 100644 --- a/test/fixtures/users.yml +++ b/test/fixtures/users.yml @@ -12,10 +12,12 @@ # encrypted_password :string(255) default(""), not null # last_sign_in_at :datetime # last_sign_in_ip :string(255) +# notifications_enabled :boolean default(TRUE), not null # remember_created_at :datetime # reset_password_sent_at :datetime # reset_password_token :string(255) # sign_in_count :integer default(0), not null +# tos_accepted :boolean default(FALSE), not null # unconfirmed_email :string(255) # created_at :datetime not null # updated_at :datetime not null @@ -37,3 +39,4 @@ user1: email: user@chexpire.org encrypted_password: <%= User.new.send(:password_digest, 'password') %> confirmed_at: <%= 1.minute.ago %> + tos_accepted: true diff --git a/test/models/user_test.rb b/test/models/user_test.rb index 469c567..11697d6 100644 --- a/test/models/user_test.rb +++ b/test/models/user_test.rb @@ -12,10 +12,12 @@ # encrypted_password :string(255) default(""), not null # last_sign_in_at :datetime # last_sign_in_ip :string(255) +# notifications_enabled :boolean default(TRUE), not null # remember_created_at :datetime # reset_password_sent_at :datetime # reset_password_token :string(255) # sign_in_count :integer default(0), not null +# tos_accepted :boolean default(FALSE), not null # unconfirmed_email :string(255) # created_at :datetime not null # updated_at :datetime not null diff --git a/test/system/users_test.rb b/test/system/users_test.rb index 3031785..03e456a 100644 --- a/test/system/users_test.rb +++ b/test/system/users_test.rb @@ -11,6 +11,7 @@ class UsersTest < ApplicationSystemTestCase fill_in("user[email]", with: email) fill_in("user[password]", with: password) fill_in("user[password_confirmation]", with: password) + check "user[tos_accepted]" click_button I18n.t("devise.registrations.new.sign_up") @@ -58,4 +59,52 @@ class UsersTest < ApplicationSystemTestCase assert_equal root_path, page.current_path assert page.has_content?(I18n.t("shared.navbar.sign_in")) end + + test "tos must be accepted at signup" do + visit new_user_registration_path + + email = "user@example.org" + fill_in("user[email]", with: email) + fill_in("user[password]", with: "password") + fill_in("user[password_confirmation]", with: "password") + + click_button I18n.t("devise.registrations.new.sign_up") + + assert_nil User.find_by(email: email) + + within ".user_tos_accepted" do + page.has_selector? ".invalid-feedback" + end + + # email is prefilled + assert_equal email, find_field("user[email]").value + + fill_in("user[password]", with: "password") + fill_in("user[password_confirmation]", with: "password") + check "user[tos_accepted]" + + click_button I18n.t("devise.registrations.new.sign_up") + + assert_equal root_path, page.current_path + assert_not_nil User.find_by!(email: email, tos_accepted: true) + end + + test "an user can globally disable its notifications" do + user = users(:user1) + login_as user + + visit edit_user_registration_path + + assert_equal user.email, find_field("user[email]").value + + assert find_field("user[notifications_enabled]").value + uncheck "user[notifications_enabled]" + + fill_in("user[current_password]", with: "password") + + click_button I18n.t("devise.registrations.edit.update") + + user.reload + refute user.notifications_enabled + end end