diff options
-rw-r--r-- | Gemfile.lock | 10 | ||||
-rw-r--r-- | config/defaults.yml | 6 | ||||
-rw-r--r-- | core/leap_web_core.gemspec | 2 | ||||
-rw-r--r-- | core/lib/extensions/couchrest.rb | 8 | ||||
-rw-r--r-- | test/integration/os_detection_test.rb (renamed from test/integration/home_test.rb) | 2 | ||||
-rw-r--r-- | users/app/views/users/_change_password.html.haml | 21 | ||||
-rw-r--r-- | users/app/views/users/_change_pgp_key.html.haml | 13 | ||||
-rw-r--r-- | users/app/views/users/_change_service_level.html.haml | 18 | ||||
-rw-r--r-- | users/app/views/users/_destroy_account.html.haml | 27 | ||||
-rw-r--r-- | users/app/views/users/_edit.html.haml | 93 | ||||
-rw-r--r-- | users/test/integration/browser/account_test.rb | 66 |
11 files changed, 150 insertions, 116 deletions
diff --git a/Gemfile.lock b/Gemfile.lock index d1fd014..918fdba 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -25,7 +25,7 @@ PATH leap_web_core (0.2.8) couchrest (~> 1.1.3) couchrest_model (~> 2.0.0) - couchrest_session_store (~> 0.2.2) + couchrest_session_store (~> 0.2.4) json rails (~> 3.2.11) @@ -105,12 +105,12 @@ GEM mime-types (~> 1.15) multi_json (~> 1.0) rest-client (~> 1.6.1) - couchrest_model (2.0.0) + couchrest_model (2.0.1) activemodel (>= 3.0) couchrest (~> 1.1.3) mime-types (>= 1.15) tzinfo (>= 0.3.22) - couchrest_session_store (0.2.2) + couchrest_session_store (0.2.4) actionpack couchrest couchrest_model @@ -145,7 +145,7 @@ GEM haml (~> 3.1) railties (>= 3.1, < 4.1) hike (1.2.3) - i18n (0.6.5) + i18n (0.6.9) journey (1.0.4) jquery-rails (3.0.4) railties (>= 3.0, < 5.0) @@ -162,7 +162,7 @@ GEM mime-types (~> 1.16) treetop (~> 1.4.8) metaclass (0.0.1) - mime-types (1.25) + mime-types (1.25.1) mini_portile (0.5.1) mocha (0.13.3) metaclass (~> 0.0.1) diff --git a/config/defaults.yml b/config/defaults.yml index 4530d47..260915e 100644 --- a/config/defaults.yml +++ b/config/defaults.yml @@ -40,6 +40,10 @@ common: &common handle_blacklist: [certmaster, ssladmin, arin-admin, administrator, www-data, maildrop] # handles that will be allowed despite being in /etc/passwd or rfc2142 handle_whitelist: [] + # actions enabled in the account settings + # see /users/app/views/users/_edit.html.haml for a list. + user_actions: ['destroy_account'] + admin_actions: ['change_pgp_key', 'change_service_level', 'destroy_account'] service_levels: &service_levels service_levels: @@ -72,6 +76,7 @@ development: domain: example.org secret_token: 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' payment: [] + reraise_errors: true test: <<: *downloads @@ -83,6 +88,7 @@ test: domain: test.me secret_token: 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' payment: [billing] + reraise_errors: true production: <<: *downloads diff --git a/core/leap_web_core.gemspec b/core/leap_web_core.gemspec index 4109a03..7ca4d90 100644 --- a/core/leap_web_core.gemspec +++ b/core/leap_web_core.gemspec @@ -19,7 +19,7 @@ Gem::Specification.new do |s| s.add_dependency "couchrest", "~> 1.1.3" s.add_dependency "couchrest_model", "~> 2.0.0" - s.add_dependency "couchrest_session_store", "~> 0.2.2" + s.add_dependency "couchrest_session_store", "~> 0.2.4" s.add_dependency "json" end diff --git a/core/lib/extensions/couchrest.rb b/core/lib/extensions/couchrest.rb index 84cfbb3..9f27c3a 100644 --- a/core/lib/extensions/couchrest.rb +++ b/core/lib/extensions/couchrest.rb @@ -23,10 +23,6 @@ module CouchRest end end - module Errors - class ConnectionFailed < CouchRestModelError; end - end - module Connection module ClassMethods @@ -36,7 +32,9 @@ module CouchRest rescue RestClient::Unauthorized, Errno::EHOSTUNREACH, Errno::ECONNREFUSED => e - raise CouchRest::Model::Errors::ConnectionFailed.new(e.to_s) + message = "Could not connect to couch database #{db} due to #{e.to_s}" + Rails.logger.warn message + raise e.class.new(message) if APP_CONFIG[:reraise_errors] end end diff --git a/test/integration/home_test.rb b/test/integration/os_detection_test.rb index 126a420..cb254aa 100644 --- a/test/integration/home_test.rb +++ b/test/integration/os_detection_test.rb @@ -1,6 +1,6 @@ require 'test_helper' -class AccountTest < BrowserIntegrationTest +class OsDetectionTest < BrowserIntegrationTest setup do Capybara.current_driver = Capybara.javascript_driver diff --git a/users/app/views/users/_change_password.html.haml b/users/app/views/users/_change_password.html.haml new file mode 100644 index 0000000..425e3ee --- /dev/null +++ b/users/app/views/users/_change_password.html.haml @@ -0,0 +1,21 @@ +-# +-# CHANGE PASSWORD +-# +-# * everything about this form is handled with javascript. So take care when changing any ids. +-# * the login is required when changing the password because it is used as part of the salt when calculating the password verifier. +-# however, we don't want the user to change their login without generating a new key, so we hide the ui for this +-# (although it works perfectly fine to change username if the field was visible). +-# + +- form_options = {:url => '/not-used', :html => {:class => user_form_class('form-horizontal'), :id => 'update_login_and_password', :data => {token: session[:token]}}, :validate => true} += simple_form_for @user, form_options do |f| + %legend= t(:change_password) + = hidden_field_tag 'user_param', @user.to_param + .hidden + = f.input :login, :label => t(:username), :required => false, :input_html => {:id => :srp_username} + = f.input :password, :required => false, :validate => true, :input_html => { :id => :srp_password } + = f.input :password_confirmation, :required => false, :input_html => { :id => :srp_password_confirmation } + .control-group + .controls + = f.submit t(:save), :class => 'btn btn-primary' + diff --git a/users/app/views/users/_change_pgp_key.html.haml b/users/app/views/users/_change_pgp_key.html.haml new file mode 100644 index 0000000..e465125 --- /dev/null +++ b/users/app/views/users/_change_pgp_key.html.haml @@ -0,0 +1,13 @@ +-# +-# CHANGE PGP KEY +-# +-# this will be replaced by a identities controller/view at some point +-# + +- form_options = {:html => {:class => user_form_class('form-horizontal'), :id => 'update_pgp_key', :data => {token: session[:token]}}, :validate => true} += simple_form_for [:api, @user], form_options do |f| + %legend= t(:advanced_options) + = f.input :public_key, :as => :text, :hint => t(:use_ascii_key), :input_html => {:class => "full-width", :rows => 4} + .control-group + .controls + = f.submit t(:save), :class => 'btn', :data => {"loading-text" => "Saving..."} diff --git a/users/app/views/users/_change_service_level.html.haml b/users/app/views/users/_change_service_level.html.haml new file mode 100644 index 0000000..61e67d9 --- /dev/null +++ b/users/app/views/users/_change_service_level.html.haml @@ -0,0 +1,18 @@ +-# TODO: probably won't want here, but here for now. Also, we will need way to ensure payment if they pick a non-free plan. +-# +-# SERVICE LEVEL +-# +- if APP_CONFIG[:service_levels] + - form_options = {:html => {:class => user_form_class('form-horizontal'), :id => 'update_service_level', :data => {token: session[:token]}}, :validate => true} + = simple_form_for @user, form_options do |f| + %legend= t(:service_level) + - if @user != current_user + = t(:desired_service_level) + = f.select :desired_service_level_code, ServiceLevel.authenticated_select_options, :selected => @user.desired_service_level.id + - if @user != current_user + %p + = t(:effective_service_level) + = f.select :effective_service_level_code, ServiceLevel.authenticated_select_options, :selected => @user.effective_service_level.id + .control-group + .controls + = f.submit t(:save), :class => 'btn', :data => {"loading-text" => "Saving..."} diff --git a/users/app/views/users/_destroy_account.html.haml b/users/app/views/users/_destroy_account.html.haml new file mode 100644 index 0000000..445f3c4 --- /dev/null +++ b/users/app/views/users/_destroy_account.html.haml @@ -0,0 +1,27 @@ +-# +-# DESTROY ACCOUNT +-# + +%legend + - if @user == current_user + = t(:destroy_my_account) + - else + = t(:admin_destroy_account, :username => @user.login) +%p= t(:destroy_account_info) += link_to user_path(@user), :method => :delete, :confirm => t(:are_you_sure), :class => "btn btn-danger" do + %i.icon-remove.icon-white + = t(:destroy_my_account) +- if @user != current_user and @user.enabled? + %legend + = t(:deactivate_account, :username => @user.login) + %p= t(:deactivate_description) + = link_to deactivate_user_path(@user), :method => :post, :class => "btn btn-warning" do + %i.icon-pause.icon-white + = t(:deactivate) +- elsif @user != current_user and !@user.enabled? + %legend + = t(:enable_account, :username => @user.login) + %p= t(:enable_description) + = link_to enable_user_path(@user), :method => :post, :class => "btn btn-warning" do + %i.icon-ok.icon-white + = t(:enable) diff --git a/users/app/views/users/_edit.html.haml b/users/app/views/users/_edit.html.haml index 0b36d6e..1d2b68a 100644 --- a/users/app/views/users/_edit.html.haml +++ b/users/app/views/users/_edit.html.haml @@ -1,85 +1,14 @@ -# -# edit user form, used by both show and edit actions. -# - --# --# CHANGE PASSWORD --# --# * everything about this form is handled with javascript. So take care when changing any ids. --# * the login is required when changing the password because it is used as part of the salt when calculating the password verifier. --# however, we don't want the user to change their login without generating a new key, so we hide the ui for this --# (although it works perfectly fine to change username if the field was visible). --# - -- form_options = {:url => '/not-used', :html => {:class => user_form_class('form-horizontal'), :id => 'update_login_and_password', :data => {token: session[:token]}}, :validate => true} -= simple_form_for @user, form_options do |f| - %legend= t(:change_password) - = hidden_field_tag 'user_param', @user.to_param - .hidden - = f.input :login, :label => t(:username), :required => false, :input_html => {:id => :srp_username} - = f.input :password, :required => false, :validate => true, :input_html => { :id => :srp_password } - = f.input :password_confirmation, :required => false, :input_html => { :id => :srp_password_confirmation } - .control-group - .controls - = f.submit t(:save), :class => 'btn btn-primary' - --# --# CHANGE PGP KEY --# --# this will be replaced by a identities controller/view at some point --# - -- form_options = {:html => {:class => user_form_class('form-horizontal'), :id => 'update_pgp_key', :data => {token: session[:token]}}, :validate => true} -= simple_form_for [:api, @user], form_options do |f| - %legend= t(:advanced_options) - = f.input :public_key, :as => :text, :hint => t(:use_ascii_key), :input_html => {:class => "full-width", :rows => 4} - .control-group - .controls - = f.submit t(:save), :class => 'btn', :data => {"loading-text" => "Saving..."} - - --# TODO: probably won't want here, but here for now. Also, we will need way to ensure payment if they pick a non-free plan. --# --# SERVICE LEVEL --# -- if APP_CONFIG[:service_levels] - - form_options = {:html => {:class => user_form_class('form-horizontal'), :id => 'update_service_level', :data => {token: session[:token]}}, :validate => true} - = simple_form_for @user, form_options do |f| - %legend= t(:service_level) - - if @user != current_user - = t(:desired_service_level) - = f.select :desired_service_level_code, ServiceLevel.authenticated_select_options, :selected => @user.desired_service_level.id - - if @user != current_user - %p - = t(:effective_service_level) - = f.select :effective_service_level_code, ServiceLevel.authenticated_select_options, :selected => @user.effective_service_level.id - .control-group - .controls - = f.submit t(:save), :class => 'btn', :data => {"loading-text" => "Saving..."} --# --# DESTROY ACCOUNT --# - -%legend - - if @user == current_user - = t(:destroy_my_account) - - else - = t(:admin_destroy_account, :username => @user.login) -%p= t(:destroy_account_info) -= link_to user_path(@user), :method => :delete, :confirm => t(:are_you_sure), :class => "btn btn-danger" do - %i.icon-remove.icon-white - = t(:destroy_my_account) -- if @user != current_user and @user.enabled? - %legend - = t(:deactivate_account, :username => @user.login) - %p= t(:deactivate_description) - = link_to deactivate_user_path(@user), :method => :post, :class => "btn btn-warning" do - %i.icon-pause.icon-white - = t(:deactivate) -- elsif @user != current_user and !@user.enabled? - %legend - = t(:enable_account, :username => @user.login) - %p= t(:enable_description) - = link_to enable_user_path(@user), :method => :post, :class => "btn btn-warning" do - %i.icon-ok.icon-white - = t(:enable) +-# We render a bunch of forms here. Which we use depends upon config settings +-# user_actions and admin_actions. They both include an array of actions +-# allowed to users and admins. +-# Possible forms are: +-# 'change_password' +-# 'change_pgp_key' +-# 'change_service_level' +-# 'destroy_account' +- actions = APP_CONFIG[admin? ? :admin_actions : :user_actions] || [] +- actions.each do |action| + = render action diff --git a/users/test/integration/browser/account_test.rb b/users/test/integration/browser/account_test.rb index 3d281ae..4cefe35 100644 --- a/users/test/integration/browser/account_test.rb +++ b/users/test/integration/browser/account_test.rb @@ -51,35 +51,57 @@ class AccountTest < BrowserIntegrationTest assert page.has_content?('has already been taken') end - test "change password" do + test "default user actions" do username, password = submit_signup click_on "Account Settings" - within('#update_login_and_password') do - fill_in 'Password', with: "other password" - fill_in 'Password confirmation', with: "other password" - click_on 'Save' + assert page.has_content? I18n.t('destroy_my_account') + assert page.has_no_css? '#update_login_and_password' + assert page.has_no_css? '#update_pgp_key' + end + + test "default admin actions" do + username, password = submit_signup + with_config admins: [username] do + click_on "Account Settings" + assert page.has_content? I18n.t('destroy_my_account') + assert page.has_no_css? '#update_login_and_password' + assert page.has_css? '#update_pgp_key' + end + end + + test "change password" do + with_config user_actions: ['change_password'] do + username, password = submit_signup + click_on "Account Settings" + within('#update_login_and_password') do + fill_in 'Password', with: "other password" + fill_in 'Password confirmation', with: "other password" + click_on 'Save' + end + click_on 'Logout' + attempt_login(username, "other password") + assert page.has_content?("Welcome #{username}") + User.find_by_login(username).account.destroy end - click_on 'Logout' - attempt_login(username, "other password") - assert page.has_content?("Welcome #{username}") - User.find_by_login(username).account.destroy end test "change pgp key" do - pgp_key = FactoryGirl.build :pgp_key - username, password = submit_signup - click_on "Account Settings" - within('#update_pgp_key') do - fill_in 'Public key', with: pgp_key - click_on 'Save' + with_config user_actions: ['change_pgp_key'] do + pgp_key = FactoryGirl.build :pgp_key + username, password = submit_signup + click_on "Account Settings" + within('#update_pgp_key') do + fill_in 'Public key', with: pgp_key + click_on 'Save' + end + page.assert_selector 'input[value="Saving..."]' + # at some point we're done: + page.assert_no_selector 'input[value="Saving..."]' + assert page.has_field? 'Public key', with: pgp_key.to_s + user = User.find_by_login(username) + assert_equal pgp_key, user.public_key + user.account.destroy end - page.assert_selector 'input[value="Saving..."]' - # at some point we're done: - page.assert_no_selector 'input[value="Saving..."]' - assert page.has_field? 'Public key', with: pgp_key.to_s - user = User.find_by_login(username) - assert_equal pgp_key, user.public_key - user.account.destroy end |