diff --git a/app/helpers/settings_helper.rb b/app/helpers/settings_helper.rb index 5b6f51186..d4fdca786 100644 --- a/app/helpers/settings_helper.rb +++ b/app/helpers/settings_helper.rb @@ -12,12 +12,15 @@ module SettingsHelper { name: "Tags", path: :tags_path }, { name: "Rules", path: :rules_path }, { name: "Merchants", path: :family_merchants_path }, + { name: "Recurring", path: :recurring_transactions_path }, # Advanced section - { name: "AI Prompts", path: :settings_ai_prompts_path }, - { name: "API Key", path: :settings_api_key_path }, - { name: "Self-Hosting", path: :settings_hosting_path, condition: :self_hosted? }, - { name: "Imports", path: :imports_path }, - { name: "SimpleFin", path: :simplefin_items_path }, + { name: "AI Prompts", path: :settings_ai_prompts_path, condition: :admin_user? }, + { name: "LLM Usage", path: :settings_llm_usage_path, condition: :admin_user? }, + { name: "API Key", path: :settings_api_key_path, condition: :admin_user? }, + { name: "Self-Hosting", path: :settings_hosting_path, condition: :self_hosted_and_admin? }, + { name: "Providers", path: :settings_providers_path, condition: :admin_user? }, + { name: "Imports", path: :imports_path, condition: :admin_user? }, + { name: "SimpleFin", path: :simplefin_items_path, condition: :admin_user? }, # More section { name: "Guides", path: :settings_guides_path }, { name: "What's new", path: :changelog_path }, @@ -70,4 +73,12 @@ module SettingsHelper def not_self_hosted? !self_hosted? end + + def admin_user? + Current.user&.admin? == true + end + + def self_hosted_and_admin? + self_hosted? && admin_user? + end end diff --git a/app/views/settings/_settings_nav.html.erb b/app/views/settings/_settings_nav.html.erb index 95d241b32..e937b49a5 100644 --- a/app/views/settings/_settings_nav.html.erb +++ b/app/views/settings/_settings_nav.html.erb @@ -22,7 +22,7 @@ nav_sections = [ ] }, ( - Current.user.admin? ? { + Current.user&.admin? ? { header: t(".advanced_section_title"), items: [ { label: t(".ai_prompts_label"), path: settings_ai_prompts_path, icon: "bot" }, diff --git a/test/system/settings_test.rb b/test/system/settings_test.rb index 51fb26243..4d7ab8447 100644 --- a/test/system/settings_test.rb +++ b/test/system/settings_test.rb @@ -4,6 +4,7 @@ class SettingsTest < ApplicationSystemTestCase setup do sign_in @user = users(:family_admin) + # Base settings available to all users @settings_links = [ [ "Accounts", accounts_path ], [ "Bank Sync", settings_bank_sync_path ], @@ -14,12 +15,18 @@ class SettingsTest < ApplicationSystemTestCase [ "Tags", tags_path ], [ "Rules", rules_path ], [ "Merchants", family_merchants_path ], - [ "AI Prompts", settings_ai_prompts_path ], - [ "API Key", settings_api_key_path ], [ "Guides", settings_guides_path ], [ "What's new", changelog_path ], [ "Feedback", feedback_path ] ] + + # Add admin settings if user is admin + if @user.admin? + @settings_links += [ + [ "AI Prompts", settings_ai_prompts_path ], + [ "API Key", settings_api_key_path ] + ] + end end test "can access settings from sidebar" do @@ -62,6 +69,25 @@ class SettingsTest < ApplicationSystemTestCase assert_no_selector "li", text: I18n.t("settings.settings_nav.billing_label") end + test "does not show admin settings to non-admin users" do + VCR.use_cassette("git_repository_provider/fetch_latest_release_notes") do + # Visit accounts path directly as non-admin user to avoid user menu issues + visit new_session_path + within %(form[action='#{sessions_path}']) do + fill_in "Email", with: users(:family_member).email + fill_in "Password", with: user_password_test + click_on "Log in" + end + + # Go directly to accounts (settings) page + visit accounts_path + + # Assert that admin-only settings are not present in the navigation + assert_no_selector "li", text: "AI Prompts" + assert_no_selector "li", text: "API Key" + end + end + private def open_settings_from_sidebar