diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index e58c8b9..79f7715 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -6,12 +6,6 @@ class ApplicationController < ActionController::Base before_action :ensure_onboarded, unless: :devise_controller? before_action :setup_locale - # Strong parameters for account. - # Used for account creation and update. - def account_permitted_parameters - params.require(:account).permit(:name) - end - private # Automatically include account_id in all URL options if it is already present in the params. diff --git a/app/views/kiqr/preferences/_form.html.erb b/app/views/kiqr/settings/_form.html.erb similarity index 70% rename from app/views/kiqr/preferences/_form.html.erb rename to app/views/kiqr/settings/_form.html.erb index 03d2434..931ece9 100644 --- a/app/views/kiqr/preferences/_form.html.erb +++ b/app/views/kiqr/settings/_form.html.erb @@ -1,4 +1,9 @@ -<%= simple_form_for(user, url: user_preferences_path, method: :patch) do |f| %> +<%= simple_form_for(user, url: settings_path, method: :patch) do |f| %> + + <%= f.simple_fields_for :personal_account, user.personal_account do |pa| %> + <%= pa.input :name %> + <% end %> + <%= f.input :locale, label: t(".locale.label"), placeholder: t(".locale.placeholder"), required: true, autofocus: true, prompt: t(".locale.prompt"), as: :select, collection: options_for_locale %> <%= f.input :time_zone, label: t(".time_zone.label"), placeholder: t(".time_zone.placeholder"), required: true, autofocus: true %>
diff --git a/app/views/kiqr/preferences/edit.html.erb b/app/views/kiqr/settings/edit.html.erb similarity index 100% rename from app/views/kiqr/preferences/edit.html.erb rename to app/views/kiqr/settings/edit.html.erb diff --git a/app/views/partials/navigations/_protected.html.erb b/app/views/partials/navigations/_protected.html.erb index d04333a..9b6752d 100644 --- a/app/views/partials/navigations/_protected.html.erb +++ b/app/views/partials/navigations/_protected.html.erb @@ -2,7 +2,7 @@
<%= render(PageLayouts::Settings::NavigationItem::Component.new( - label: t('.items.preferences.label'), - description: t('.items.preferences.description'), + label: t('.items.user_profile.label'), + description: t('.items.user_profile.description'), icon: "fa fa-sliders", - path: edit_user_preferences_path, - active: current_base_path?(edit_user_preferences_path) + path: edit_settings_path, + active: current_base_path?(edit_settings_path) )) %> <%= render(PageLayouts::Settings::NavigationItem::Component.new( diff --git a/config/initializers/kiqr.rb b/config/initializers/kiqr.rb index e2f477d..e8bac0b 100644 --- a/config/initializers/kiqr.rb +++ b/config/initializers/kiqr.rb @@ -10,6 +10,11 @@ # with default "from" parameter. config.default_from_email = "please-change-me-at-config-initializers@example.com" + # ==> Account attributes + # Strong parameters for account. Used for account creation and update. + # Affects both personal and team accounts. + config.account_attributes = [:name] + # ==> Locales # Configure the available locales in the application. # This is used to validate the locale of the user. diff --git a/config/locales/kiqr.en.yml b/config/locales/kiqr.en.yml index c33353f..e992e09 100644 --- a/config/locales/kiqr.en.yml +++ b/config/locales/kiqr.en.yml @@ -11,21 +11,21 @@ en: sign_in: "Sign in" register: "Create account" settings: - account_settings: "Account settings" - user_settings: "Your personal settings" + account_settings: "Team settings" + user_settings: "User account" items: account: label: "Profile" - description: "Edit your account profile" + description: "Edit your team's profile" members: - label: "Team members" + label: "Members" description: "Manage team members" user: label: "Login credentials" description: "Change user email or password" - preferences: - label: "Preferences" - description: "Change your personal settings" + user_profile: + label: "Settings" + description: "Personal profile & settings" two_factor: label: "Two-factor authentication" description: "One-time passwords" diff --git a/gems/kiqr/app/controllers/kiqr/accounts_controller.rb b/gems/kiqr/app/controllers/kiqr/accounts_controller.rb index 45b9e07..6f48687 100644 --- a/gems/kiqr/app/controllers/kiqr/accounts_controller.rb +++ b/gems/kiqr/app/controllers/kiqr/accounts_controller.rb @@ -1,13 +1,13 @@ module Kiqr class AccountsController < KiqrController - before_action :setup_account, only: %i[edit update] + before_action :ensure_team_and_setup_account, only: %i[edit update] def new @account = Account.new end def create - @account = Account.new(account_permitted_parameters) + @account = Account.new(account_params) if @account.valid? Kiqr::Services::Accounts::Create.call!(account: @account, user: current_user) @@ -19,7 +19,7 @@ def create end def update - @account.assign_attributes(account_permitted_parameters) + @account.assign_attributes(account_params) if @account.valid? Kiqr::Services::Accounts::Update.call!(account: @account, user: current_user) @@ -32,8 +32,13 @@ def update private - def setup_account + def account_params + params.require(:account).permit(Kiqr.config.account_attributes) + end + + def ensure_team_and_setup_account @account = Account.find(current_account.id) + redirect_to edit_settings_path if @account.personal? end def form_submit_path diff --git a/gems/kiqr/app/controllers/kiqr/onboarding_controller.rb b/gems/kiqr/app/controllers/kiqr/onboarding_controller.rb index c0d59c7..e3b0030 100644 --- a/gems/kiqr/app/controllers/kiqr/onboarding_controller.rb +++ b/gems/kiqr/app/controllers/kiqr/onboarding_controller.rb @@ -22,7 +22,7 @@ def new end def create - @account = Account.new(account_permitted_parameters) + @account = Account.new(account_params) if @account.valid? Kiqr::Services::Accounts::Create.call!(account: @account, user: current_user, personal: true) @@ -35,6 +35,10 @@ def create private + def account_params + params.require(:account).permit(Kiqr.config.account_attributes) + end + # This is the path to redirect to after the onboarding process # is completed. By default, it redirects to the dashboard. def after_onboarding_path diff --git a/gems/kiqr/app/controllers/kiqr/preferences_controller.rb b/gems/kiqr/app/controllers/kiqr/settings_controller.rb similarity index 51% rename from gems/kiqr/app/controllers/kiqr/preferences_controller.rb rename to gems/kiqr/app/controllers/kiqr/settings_controller.rb index aedc5da..0afc72a 100644 --- a/gems/kiqr/app/controllers/kiqr/preferences_controller.rb +++ b/gems/kiqr/app/controllers/kiqr/settings_controller.rb @@ -1,13 +1,11 @@ module Kiqr - class PreferencesController < ApplicationController - def edit - @user = current_user - end + class SettingsController < KiqrController + before_action :setup_user, only: %i[edit update] def update - @user = current_user if @user.update(preferences_params) - redirect_to edit_user_preferences_path, notice: t(".updated") + kiqr_flash_message(:notice, :settings_updated) + redirect_to edit_settings_path else render :edit, status: :unprocessable_entity end @@ -15,6 +13,10 @@ def update private + def setup_user + @user = current_user + end + def options_for_locale I18n.available_locales.map do |locale| [I18n.t("languages.#{locale}"), locale] @@ -23,7 +25,8 @@ def options_for_locale helper_method :options_for_locale def preferences_params - params.require(:user).permit(:time_zone, :locale) + personal_account_attributes = Kiqr.config.account_attributes.prepend(:id) + params.require(:user).permit(:time_zone, :locale, personal_account_attributes: personal_account_attributes) end end end diff --git a/gems/kiqr/app/models/account.rb b/gems/kiqr/app/models/account.rb index 46946fa..a1cad03 100644 --- a/gems/kiqr/app/models/account.rb +++ b/gems/kiqr/app/models/account.rb @@ -16,4 +16,8 @@ class Account < ApplicationRecord def has_member?(user) users.include? user end + + def team? + !personal + end end diff --git a/gems/kiqr/app/models/user.rb b/gems/kiqr/app/models/user.rb index 4aad1b4..c47f8d1 100644 --- a/gems/kiqr/app/models/user.rb +++ b/gems/kiqr/app/models/user.rb @@ -8,6 +8,7 @@ class User < ApplicationRecord # User belongs to a personal account. belongs_to :personal_account, class_name: "Account", optional: true, dependent: :destroy validates_associated :personal_account + accepts_nested_attributes_for :personal_account # User can have many team accounts. has_many :account_users, dependent: :destroy diff --git a/gems/kiqr/config/locales/kiqr/en.yml b/gems/kiqr/config/locales/kiqr/en.yml index 8657ecc..d223ffd 100644 --- a/gems/kiqr/config/locales/kiqr/en.yml +++ b/gems/kiqr/config/locales/kiqr/en.yml @@ -10,6 +10,7 @@ en: invitation_expired: "The invitation has expired." account_user_destroyed: "Member has successfully been removed from the team." omniauth_email_taken: "An account with this email already exists. Please sign in to that account first and then link your %{provider} account." + settings_updated: "Your settings have been updated successfully." accounts: new: title: "Create a new team account" @@ -92,10 +93,10 @@ en: new: title: "Setup your personal account" description: "Finish the registration by setting up your user profile." - preferences: + settings: edit: - title: "User preferences" - description: "Update your user preferences." + title: "Settings" + description: "Personal profile & settings" form: time_zone: label: "Time zone" @@ -105,8 +106,6 @@ en: prompt: "Select a language" placeholder: "Select your preferred language" submit_button: "Save changes" - update: - updated: "User preferences have been updated." registrations: new: heading: diff --git a/gems/kiqr/lib/kiqr/config.rb b/gems/kiqr/lib/kiqr/config.rb index 365acde..4af930d 100644 --- a/gems/kiqr/lib/kiqr/config.rb +++ b/gems/kiqr/lib/kiqr/config.rb @@ -13,6 +13,11 @@ class Config # with default "from" parameter. config_accessor :default_from_email, default: "please-change-me-at-config-initializers@example.com" + # ==> Account attributes + # Strong parameters for account. Used for account creation and update. + # Affects both personal and team accounts. + config_accessor :account_attributes, default: [:name] + # ==> Locales # Configure the available locales in the application. # This is used to validate the locale of the user. diff --git a/gems/kiqr/lib/kiqr/rails/routes.rb b/gems/kiqr/lib/kiqr/rails/routes.rb index e877b1a..fd33117 100644 --- a/gems/kiqr/lib/kiqr/rails/routes.rb +++ b/gems/kiqr/lib/kiqr/rails/routes.rb @@ -19,7 +19,7 @@ def kiqr_routes(options = {}) get "two-factor/disable", controller: options[:controllers][:two_factor], action: "disable", as: :disable_two_factor post "two-factor/verify", controller: options[:controllers][:two_factor], action: "verify", as: :verify_two_factor delete "two-factor/destroy", controller: options[:controllers][:two_factor], action: "destroy", as: :destroy_two_factor - resource :preferences, controller: options[:controllers][:preferences], only: %i[edit update], as: :user_preferences + resource :settings, controller: options[:controllers][:settings], only: %i[edit update], as: :settings end end @@ -36,7 +36,7 @@ def default_controllers(options) options[:controllers][:registrations] ||= "kiqr/registrations" options[:controllers][:sessions] ||= "kiqr/sessions" options[:controllers][:two_factor] ||= "kiqr/two_factor" - options[:controllers][:preferences] ||= "kiqr/preferences" + options[:controllers][:settings] ||= "kiqr/settings" options[:controllers][:omniauth] ||= "kiqr/omniauth" options end @@ -59,7 +59,7 @@ def account_routes(options) get "select-account", controller: options[:controllers][:accounts], action: :select, as: :select_account scope "(/team/:account_id)", account_id: %r{[^/]+} do - resource :account, only: [:edit, :update], path: "profile", controller: options[:controllers][:accounts] + resource :account, only: [:edit, :update], controller: options[:controllers][:accounts] resources :account_users, controller: options[:controllers][:account_users], only: [:index, :edit, :update, :destroy], path: "members" end end diff --git a/test/controllers/kiqr/accounts_controller_test.rb b/test/controllers/kiqr/accounts_controller_test.rb index 9f3a634..f6ccea4 100644 --- a/test/controllers/kiqr/accounts_controller_test.rb +++ b/test/controllers/kiqr/accounts_controller_test.rb @@ -7,10 +7,10 @@ class Kiqr::AccountsControllerTest < ActionDispatch::IntegrationTest assert_response :success end - test "can render edit account page" do + test "redirect to profile edit if personal account" do sign_in create(:user) get edit_account_path - assert_response :success + assert_redirected_to edit_settings_path end test "can create new team account" do @@ -33,17 +33,6 @@ class Kiqr::AccountsControllerTest < ActionDispatch::IntegrationTest # assert_template :new end - test "can update personal accounts" do - user = create(:user) - sign_in user - - patch account_path, params: {account: {name: "New name"}} - user.reload - - assert_redirected_to edit_account_path - assert_equal "New name", user.personal_account.name - end - test "can update team accounts" do user = create(:user) account = create(:account, name: "Team account") @@ -59,9 +48,12 @@ class Kiqr::AccountsControllerTest < ActionDispatch::IntegrationTest test "re-renders form if form data is invalid" do user = create(:user) + account = create(:account, name: "Team account") + account.account_users << AccountUser.create(user:, owner: true) + sign_in user - patch account_path, params: {account: {name: "no"}} + patch account_path(account_id: account), params: {account: {name: "no"}} assert_response :unprocessable_entity end end diff --git a/test/controllers/kiqr/preferences_controller_test.rb b/test/controllers/kiqr/preferences_controller_test.rb deleted file mode 100644 index 57e0f8f..0000000 --- a/test/controllers/kiqr/preferences_controller_test.rb +++ /dev/null @@ -1,20 +0,0 @@ -require "test_helper" - -class Kiqr::PreferencesControllerTest < ActionDispatch::IntegrationTest - test "should get edit page" do - user = create(:user) - sign_in(user) - get edit_user_preferences_path - assert_response :success - end - - test "can update user preferences" do - user = create(:user, time_zone: "UTC", locale: "en") - sign_in(user) - - patch user_preferences_path, params: {user: {time_zone: "Stockholm", locale: "sv"}} - assert_redirected_to edit_user_preferences_path - assert_equal "Stockholm", user.reload.time_zone - assert_equal "sv", user.reload.locale - end -end diff --git a/test/controllers/kiqr/settings_controller_test.rb b/test/controllers/kiqr/settings_controller_test.rb new file mode 100644 index 0000000..a16a846 --- /dev/null +++ b/test/controllers/kiqr/settings_controller_test.rb @@ -0,0 +1,31 @@ +require "test_helper" + +class Kiqr::PreferencesControllerTest < ActionDispatch::IntegrationTest + test "should get edit page" do + user = create(:user) + sign_in(user) + get edit_settings_path + assert_response :success + end + + test "can update user fields" do + user = create(:user, time_zone: "UTC", locale: "en") + sign_in(user) + + patch settings_path, params: {user: {time_zone: "Stockholm", locale: "sv"}} + assert_redirected_to edit_settings_path + assert_equal "Stockholm", user.reload.time_zone + assert_equal "sv", user.reload.locale + end + + test "can update personal account fields" do + user = create(:user) + sign_in user + + patch settings_path, params: {user: {personal_account_attributes: {name: "Personal account name"}}} + user.reload + + assert_redirected_to edit_settings_path + assert_equal "Personal account name", user.personal_account.name + end +end diff --git a/test/system/accounts/accounts_test.rb b/test/system/accounts/accounts_test.rb index f367e16..4613b72 100644 --- a/test/system/accounts/accounts_test.rb +++ b/test/system/accounts/accounts_test.rb @@ -1,23 +1,6 @@ require "application_system_test_case" class EditAccountsTest < ApplicationSystemTestCase - test "can edit personal account" do - user = create(:user) - - sign_in(user) - visit edit_account_path - assert_selector("input[name='account[name]']") - - # Fill the personal account form - fill_in_account_fields - - click_on "commit" - assert_text I18n.t("kiqr.flash_messages.account_updated") - - user.personal_account.reload - assert_equal "New name", user.personal_account.name - end - test "can edit team account" do user = create(:user) team_account = create(:account, name: "Team account") diff --git a/test/system/users/settings_test.rb b/test/system/users/settings_test.rb new file mode 100644 index 0000000..28ed6a6 --- /dev/null +++ b/test/system/users/settings_test.rb @@ -0,0 +1,23 @@ +require "application_system_test_case" + +class SettingsTest < ApplicationSystemTestCase + test "can edit user and personal account" do + user = create(:user) + + sign_in(user) + visit edit_settings_path + + # Fill the personal account form + select "Swedish", from: "user[locale]" + fill_in "user[personal_account_attributes][name]", with: "New name" + + click_on "commit" + assert_text I18n.t("kiqr.flash_messages.settings_updated") + + user.reload + + assert_current_path edit_settings_path + assert_equal "New name", user.personal_account.name + assert_equal "sv", user.locale + end +end