diff options
27 files changed, 392 insertions, 163 deletions
@@ -21,6 +21,13 @@ test/dummy/log/* test/dummy/tmp/* *.pyc +# Ignore files created on server by working as user leap-webapp +# in its homedir /srv/leap/webapp +/.bash_history +/.ssh +/.viminfo + + # ignore the disabled customization directories that # i keep around for testing purposes. config/customization.* diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 45b5fd6..232ebcb 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -11,8 +11,9 @@ services: # Cache gems in between builds cache: + key: shared paths: - - vendor/ + - vendor/ruby # This is a basic example for a gem or script which doesn't use # services such as redis or postgres diff --git a/Gemfile.lock b/Gemfile.lock index ca0cb63..e944e86 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -26,44 +26,44 @@ GEM remote: https://rubygems.org/ specs: SyslogLogger (2.0) - actionmailer (4.2.7.1) - actionpack (= 4.2.7.1) - actionview (= 4.2.7.1) - activejob (= 4.2.7.1) + actionmailer (4.2.8) + actionpack (= 4.2.8) + actionview (= 4.2.8) + activejob (= 4.2.8) mail (~> 2.5, >= 2.5.4) rails-dom-testing (~> 1.0, >= 1.0.5) - actionpack (4.2.7.1) - actionview (= 4.2.7.1) - activesupport (= 4.2.7.1) + actionpack (4.2.8) + actionview (= 4.2.8) + activesupport (= 4.2.8) rack (~> 1.6) rack-test (~> 0.6.2) rails-dom-testing (~> 1.0, >= 1.0.5) rails-html-sanitizer (~> 1.0, >= 1.0.2) - actionview (4.2.7.1) - activesupport (= 4.2.7.1) + actionview (4.2.8) + activesupport (= 4.2.8) builder (~> 3.1) erubis (~> 2.7.0) rails-dom-testing (~> 1.0, >= 1.0.5) - rails-html-sanitizer (~> 1.0, >= 1.0.2) - activejob (4.2.7.1) - activesupport (= 4.2.7.1) + rails-html-sanitizer (~> 1.0, >= 1.0.3) + activejob (4.2.8) + activesupport (= 4.2.8) globalid (>= 0.3.0) - activemodel (4.2.7.1) - activesupport (= 4.2.7.1) + activemodel (4.2.8) + activesupport (= 4.2.8) builder (~> 3.1) - activerecord (4.2.7.1) - activemodel (= 4.2.7.1) - activesupport (= 4.2.7.1) + activerecord (4.2.8) + activemodel (= 4.2.8) + activesupport (= 4.2.8) arel (~> 6.0) - activesupport (4.2.7.1) + activesupport (4.2.8) i18n (~> 0.7) - json (~> 1.7, >= 1.7.7) minitest (~> 5.1) thread_safe (~> 0.3, >= 0.3.4) tzinfo (~> 1.1) - addressable (2.4.0) - arel (6.0.3) - autoprefixer-rails (6.4.0.2) + addressable (2.5.0) + public_suffix (~> 2.0, >= 2.0.2) + arel (6.0.4) + autoprefixer-rails (6.7.7) execjs better_errors (2.1.1) coderay (>= 1.0.0) @@ -74,28 +74,28 @@ GEM bootstrap-sass (3.3.7) autoprefixer-rails (>= 5.2.1) sass (>= 3.3.4) - braintree (2.65.0) + braintree (2.72.0) builder (>= 2.0.0) buftok (0.2.0) - builder (3.2.2) - byebug (9.0.5) - capybara (2.7.1) + builder (3.2.3) + byebug (9.0.6) + capybara (2.12.1) addressable mime-types (>= 1.16) nokogiri (>= 1.3.3) rack (>= 1.0.0) rack-test (>= 0.5.4) xpath (~> 2.0) - client_side_validations (4.2.5) + client_side_validations (4.2.12) jquery-rails (>= 3.1.2, < 5.0.0) - js_regex (~> 1.0, >= 1.0.9) + js_regex (~> 1.0, >= 1.0.19) rails (>= 4.0.0, < 4.3.0) - client_side_validations-simple_form (3.2.4) - client_side_validations (~> 4.2.3) - simple_form (~> 3.2) + client_side_validations-simple_form (3.4.0) + client_side_validations (~> 4.2.12) + simple_form (~> 3.4) cliver (0.3.2) coderay (1.1.1) - concurrent-ruby (1.0.2) + concurrent-ruby (1.0.5) couchrest (2.0.0) httpclient (~> 2.8) mime-types (>= 1.15) @@ -118,36 +118,36 @@ GEM multi_test (>= 0.1.2) cucumber-core (1.5.0) gherkin (~> 4.0) - cucumber-rails (1.4.4) + cucumber-rails (1.4.5) capybara (>= 1.1.2, < 3) - cucumber (>= 1.3.8, < 3) + cucumber (>= 1.3.8, < 4) mime-types (>= 1.16, < 4) nokogiri (~> 1.5) railties (>= 3, < 5.1) cucumber-wire (0.0.1) debug_inspector (0.0.2) - diff-lcs (1.2.5) - domain_name (0.5.20160615) + diff-lcs (1.3) + domain_name (0.5.20170223) unf (>= 0.0.5, < 1.0.0) - equalizer (0.0.10) + equalizer (0.0.11) erubis (2.7.0) execjs (2.7.0) - factory_girl (4.7.0) + factory_girl (4.8.0) activesupport (>= 3.0.0) - factory_girl_rails (4.7.0) - factory_girl (~> 4.7.0) + factory_girl_rails (4.8.0) + factory_girl (~> 4.8.0) railties (>= 3.0.0) fake_braintree (0.8.0) activesupport braintree (~> 2.32) capybara (>= 2.2.0) sinatra - faker (1.6.6) + faker (1.7.3) i18n (~> 0.5) - faraday (0.9.2) + faraday (0.11.0) multipart-post (>= 1.2, < 3) - ffi (1.9.14) - gherkin (4.0.0) + ffi (1.9.18) + gherkin (4.1.0) globalid (0.3.7) activesupport (>= 4.1.0) haml (4.0.7) @@ -158,37 +158,45 @@ GEM haml (>= 4.0.6, < 5.0) html2haml (>= 1.0.1) railties (>= 4.0.1) - html2haml (2.0.0) + html2haml (2.1.0) erubis (~> 2.7.0) - haml (~> 4.0.0) - nokogiri (~> 1.6.0) + haml (~> 4.0) + nokogiri (>= 1.6.0) ruby_parser (~> 3.5) - http (1.0.4) + http (2.2.1) addressable (~> 2.3) http-cookie (~> 1.0) http-form_data (~> 1.0.1) http_parser.rb (~> 0.6.0) - http-cookie (1.0.2) + http-cookie (1.0.3) domain_name (~> 0.5) http-form_data (1.0.1) - http_accept_language (2.0.5) + http_accept_language (2.1.0) http_parser.rb (0.6.0) - httpclient (2.8.1) - i18n (0.7.0) + httpclient (2.8.3) + i18n (0.8.1) i18n-missing_translations (0.0.1) - jquery-rails (4.1.1) + jquery-rails (4.2.2) rails-dom-testing (>= 1, < 3) railties (>= 4.2.0) thor (>= 0.14, < 2.0) - js_regex (1.0.17) - regexp_parser (= 0.3.6) - json (1.8.3) - kaminari (0.17.0) - actionpack (>= 3.0.0) - activesupport (>= 3.0.0) + js_regex (1.2.1) + regexp_parser (>= 0.3.6, <= 0.4.2) + kaminari (1.0.1) + activesupport (>= 4.1.0) + kaminari-actionview (= 1.0.1) + kaminari-activerecord (= 1.0.1) + kaminari-core (= 1.0.1) + kaminari-actionview (1.0.1) + actionview + kaminari-core (= 1.0.1) + kaminari-activerecord (1.0.1) + activerecord + kaminari-core (= 1.0.1) + kaminari-core (1.0.1) launchy (2.4.3) addressable (~> 2.3) - libv8 (3.16.14.15) + libv8 (3.16.14.19-x86_64-linux) loofah (2.0.3) nokogiri (>= 1.5.9) mail (2.6.4) @@ -201,21 +209,19 @@ GEM mime-types-data (~> 3.2015) mime-types-data (3.2016.0521) mini_portile2 (2.1.0) - minitest (5.9.0) - minitest-stub-const (0.5) - mocha (1.1.0) + minitest (5.10.1) + minitest-stub-const (0.6) + mocha (1.2.1) metaclass (~> 0.0.1) multi_json (1.12.1) multi_test (0.1.2) multipart-post (2.0.0) naught (1.1.0) - nokogiri (1.6.8) + nokogiri (1.7.0.1) mini_portile2 (~> 2.1.0) - pkg-config (~> 1.1.7) - phantomjs-binaries (2.1.1.0) + phantomjs-binaries (2.1.1.1) sys-uname (= 0.9.0) - pkg-config (1.1.7) - poltergeist (1.10.0) + poltergeist (1.13.0) capybara (~> 2.1) cliver (~> 0.3.1) websocket-driver (>= 0.2.0) @@ -223,27 +229,28 @@ GEM coderay (~> 1.1.0) method_source (~> 0.8.1) slop (~> 3.4) - rack (1.6.4) + public_suffix (2.0.5) + rack (1.6.5) rack-protection (1.5.3) rack rack-test (0.6.3) rack (>= 1.0) - rails (4.2.7.1) - actionmailer (= 4.2.7.1) - actionpack (= 4.2.7.1) - actionview (= 4.2.7.1) - activejob (= 4.2.7.1) - activemodel (= 4.2.7.1) - activerecord (= 4.2.7.1) - activesupport (= 4.2.7.1) + rails (4.2.8) + actionmailer (= 4.2.8) + actionpack (= 4.2.8) + actionview (= 4.2.8) + activejob (= 4.2.8) + activemodel (= 4.2.8) + activerecord (= 4.2.8) + activesupport (= 4.2.8) bundler (>= 1.3.0, < 2.0) - railties (= 4.2.7.1) + railties (= 4.2.8) sprockets-rails rails-deprecated_sanitizer (1.0.3) activesupport (>= 4.2.0.alpha) - rails-dom-testing (1.0.7) + rails-dom-testing (1.0.8) activesupport (>= 4.2.0.beta, < 5.0) - nokogiri (~> 1.6.0) + nokogiri (~> 1.6) rails-deprecated_sanitizer (>= 1.0.1) rails-html-sanitizer (1.0.3) loofah (~> 2.0) @@ -252,74 +259,73 @@ GEM railties (~> 4.0) rails_warden (0.5.8) warden (>= 1.0.0) - railties (4.2.7.1) - actionpack (= 4.2.7.1) - activesupport (= 4.2.7.1) + railties (4.2.8) + actionpack (= 4.2.8) + activesupport (= 4.2.8) rake (>= 0.8.7) thor (>= 0.18.1, < 2.0) - rake (11.2.2) + rake (12.0.0) rdiscount (2.2.0.1) ref (2.0.0) - regexp_parser (0.3.6) - responders (2.2.0) + regexp_parser (0.4.2) + responders (2.3.0) railties (>= 4.2.0, < 5.1) ruby-srp (0.2.1) - ruby_parser (3.8.2) + ruby_parser (3.8.4) sexp_processor (~> 4.1) - sass (3.4.22) + sass (3.4.23) sass-rails (5.0.6) railties (>= 4.0.0, < 6) sass (~> 3.1) sprockets (>= 2.8, < 4.0) sprockets-rails (>= 2.0, < 4.0) tilt (>= 1.1, < 3) - sexp_processor (4.7.0) - simple_form (3.2.1) + sexp_processor (4.8.0) + simple_form (3.4.0) actionpack (> 4, < 5.1) activemodel (> 4, < 5.1) simple_oauth (0.3.1) - sinatra (1.4.7) + sinatra (1.4.8) rack (~> 1.5) rack-protection (~> 1.4) tilt (>= 1.3, < 3) slop (3.6.0) - sprockets (3.7.0) + sprockets (3.7.1) concurrent-ruby (~> 1.0) rack (> 1, < 3) - sprockets-rails (3.1.1) + sprockets-rails (3.2.0) actionpack (>= 4.0) activesupport (>= 4.0) sprockets (>= 3.0.0) sys-uname (0.9.0) ffi (>= 1.0.0) - therubyracer (0.12.2) - libv8 (~> 3.16.14.0) + therubyracer (0.12.3) + libv8 (~> 3.16.14.15) ref - thor (0.19.1) - thread_safe (0.3.5) - tilt (2.0.5) - twitter (5.16.0) - addressable (~> 2.3) + thor (0.19.4) + thread_safe (0.3.6) + tilt (2.0.6) + twitter (6.1.0) + addressable (~> 2.5) buftok (~> 0.2.0) - equalizer (= 0.0.10) - faraday (~> 0.9.0) - http (~> 1.0) + equalizer (= 0.0.11) + faraday (~> 0.11.0) + http (~> 2.1) http_parser.rb (~> 0.6.0) - json (~> 1.8) - memoizable (~> 0.4.0) - naught (~> 1.0) - simple_oauth (~> 0.3.0) + memoizable (~> 0.4.2) + naught (~> 1.1) + simple_oauth (~> 0.3.1) tzinfo (1.2.2) thread_safe (~> 0.1) - uglifier (3.0.1) + uglifier (3.1.7) execjs (>= 0.3.0, < 3) unf (0.2.0.beta2) valid_email (0.0.13) activemodel mail (~> 2.6.1) - warden (1.2.6) + warden (1.2.7) rack (>= 1.0) - websocket-driver (0.6.4) + websocket-driver (0.6.5) websocket-extensions (>= 0.1.0) websocket-extensions (0.1.2) xpath (2.0.0) @@ -374,4 +380,4 @@ DEPENDENCIES valid_email BUNDLED WITH - 1.12.5 + 1.14.3 diff --git a/app/controllers/keys_controller.rb b/app/controllers/keys_controller.rb index fb28901..dbb5d96 100644 --- a/app/controllers/keys_controller.rb +++ b/app/controllers/keys_controller.rb @@ -3,15 +3,16 @@ class KeysController < ApplicationController # # Render the user's key as plain text, without a layout. # - # We will show blank page if user doesn't have key (which shouldn't generally occur) - # and a 404 error if user doesn't exist + # 404 error if user doesn't exist + # + # blank result if user doesn't have key (which shouldn't generally occur) # def show user = User.find_by_login(params[:login]) if user render text: user.public_key, content_type: 'text/text' else - raise ActionController::RoutingError.new('Not Found') + head 404 end end diff --git a/app/controllers/pages_controller.rb b/app/controllers/pages_controller.rb index b9c601a..4508450 100644 --- a/app/controllers/pages_controller.rb +++ b/app/controllers/pages_controller.rb @@ -9,6 +9,8 @@ class PagesController < ApplicationController def show @show_navigation = false render page_name + rescue ActionView::MissingTemplate + raise ActionController::RoutingError.new('Not Found') end private diff --git a/app/models/account.rb b/app/models/account.rb index d722caa..3283bcc 100644 --- a/app/models/account.rb +++ b/app/models/account.rb @@ -47,7 +47,7 @@ class Account user_invite_code.save end end - rescue StandardError => ex + rescue VALIDATION_FAILED => ex user.errors.add(:base, ex.to_s) if user ensure if creation_problem?(user, identity) @@ -62,6 +62,9 @@ class Account update_login(attrs[:login]) @user.update_attributes attrs.slice(:password_verifier, :password_salt) end + if attrs[:recovery_code_verifier].present? + @user.update_attributes attrs.slice(:recovery_code_verifier, :recovery_code_salt) + end # TODO: move into identity controller key = update_pgp_key(attrs[:public_key]) @user.errors.set :public_key, key.errors.full_messages diff --git a/app/models/user.rb b/app/models/user.rb index 9cebbca..f8869cd 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -8,6 +8,8 @@ class User < CouchRest::Model::Base property :login, String, :accessible => true property :password_verifier, String, :accessible => true property :password_salt, String, :accessible => true + property :recovery_code_verifier, String, :accessible => true + property :recovery_code_salt, String, :accessible => true property :contact_email, String, :accessible => true property :contact_email_key, String, :accessible => true property :invite_code, String, :accessible => true @@ -33,8 +35,8 @@ class User < CouchRest::Model::Base validate :identity_is_valid - validates :password_salt, :password_verifier, - :format => { :with => /\A[\dA-Fa-f]+\z/, :message => "Only hex numbers allowed" } + validates :password_salt, :password_verifier, :recovery_code_verifier, :recovery_code_salt, + :format => { :with => /\A[\h]*\z/, :message => "Only hex numbers allowed" } validates :password, :presence => true, :confirmation => true, @@ -230,7 +232,7 @@ class User < CouchRest::Model::Base def identity_is_valid return if identity.valid? identity.errors.each do |attribute, error| - self.errors.add(:login, error) + errors.add(:login, error) unless errors[:login].include? error end end diff --git a/config/customization/.gitkeep b/config/customization/.gitkeep deleted file mode 100644 index e69de29..0000000 --- a/config/customization/.gitkeep +++ /dev/null diff --git a/config/environments/test.rb b/config/environments/test.rb index 0ba4fbd..ecbbedc 100644 --- a/config/environments/test.rb +++ b/config/environments/test.rb @@ -18,12 +18,11 @@ Rails.application.configure do config.serve_static_files = true config.static_cache_control = 'public, max-age=3600' - # Show full error reports and disable caching. - config.consider_all_requests_local = true + # Disable caching. config.action_controller.perform_caching = false - # Raise exceptions instead of rendering exception templates. - config.action_dispatch.show_exceptions = false + # Render the exception templates so we can test them as well. + config.action_dispatch.show_exceptions = true # Disable request forgery protection in test environment. config.action_controller.allow_forgery_protection = false diff --git a/config/routes.rb b/config/routes.rb index b152c9c..d3d2cec 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -3,8 +3,11 @@ LeapWeb::Application.routes.draw do # Please do not use root_path or root_url. Use home_path and home_url instead, # so that the path will be correctly prefixed with the locale. # - root :to => "home#index" - get '(:locale)' => 'home#index', :locale => CommonLanguages.match_available, :as => 'home' + + scope format: 'html' do + root :to => "home#index" + get '(:locale)' => 'home#index', :locale => CommonLanguages.match_available, :as => 'home' + end # # HTTP Error Handling @@ -58,6 +61,8 @@ LeapWeb::Application.routes.draw do get "/.well-known/host-meta" => 'webfinger#host_meta' get "/webfinger" => 'webfinger#search' - get "/key/:login" => 'keys#show' + get "/key/:login" => 'keys#show', + :constraints => { :login => /[^\/]+/ }, + :defaults => { :format => :text } end diff --git a/engines/billing/test/functional/subscriptions_controller_test.rb b/engines/billing/test/functional/subscriptions_controller_test.rb index 1e98eff..592ffc3 100644 --- a/engines/billing/test/functional/subscriptions_controller_test.rb +++ b/engines/billing/test/functional/subscriptions_controller_test.rb @@ -53,13 +53,13 @@ class SubscriptionsControllerTest < ActionController::TestCase test "subscribe creates subscription" do user = find_record :user - user.expects(:save).returns(true) login user payment_methods = [stub(:token => 'user_token')] Braintree::Customer.any_instance.stubs(:payment_methods).returns(payment_methods) - user.expects(:save).returns(true) + user.expects(:update_attributes).returns(true).twice post :subscribe, :id => "1", :first_name => "Test", :last_name => "Testing", :company => "RGSoC", :email => "any@email.com", :phone => "555-888-1234" + user.validate assert assigns(:result).success? assert_not_nil flash[:success] @@ -67,12 +67,13 @@ class SubscriptionsControllerTest < ActionController::TestCase test "unsubscribe cancels subscription" do user = find_record :user - user.expects(:save).returns(true) result = Braintree::Subscription.create(payment_method_token: 'user_token', plan_id: '1') user.subscription_id = result.subscription.id login user + user.expects(:update_attributes).returns(true) delete :unsubscribe, :id => "1" + user.validate assert assigns(:result).success? assert_not_nil flash[:success] diff --git a/engines/support/app/controllers/tickets_controller.rb b/engines/support/app/controllers/tickets_controller.rb index 8cccc2f..c20ef6a 100644 --- a/engines/support/app/controllers/tickets_controller.rb +++ b/engines/support/app/controllers/tickets_controller.rb @@ -19,7 +19,7 @@ class TicketsController < ApplicationController end def create - @ticket = Ticket.new(params[:ticket]) + @ticket = Ticket.new ticket_params #protecting posted_by isn't working, so this should protect it: @ticket.comments.last.posted_by = current_user.id @@ -89,6 +89,12 @@ class TicketsController < ApplicationController @title = t("layouts.title.tickets") end + def ticket_params + # make sure we have everything we need... + params.require(:ticket).require(:comments_attributes).require('0') + params.require(:ticket) + end + private # diff --git a/engines/support/app/mailers/ticket_mailer.rb b/engines/support/app/mailers/ticket_mailer.rb index 9a83345..38f9a39 100644 --- a/engines/support/app/mailers/ticket_mailer.rb +++ b/engines/support/app/mailers/ticket_mailer.rb @@ -4,7 +4,7 @@ class TicketMailer < ActionMailer::Base def self.send_notice(ticket, comment, url) reply_recipients(ticket, comment.user).each do |email, key| - TicketMailer.notice(ticket, comment, url, email, key).deliver + TicketMailer.notice(ticket, comment, url, email, key).deliver_now end end diff --git a/engines/support/test/functional/tickets_controller_test.rb b/engines/support/test/functional/tickets_controller_test.rb index 5c2b346..2f1e661 100644 --- a/engines/support/test/functional/tickets_controller_test.rb +++ b/engines/support/test/functional/tickets_controller_test.rb @@ -78,6 +78,16 @@ class TicketsControllerTest < ActionController::TestCase assert_nil assigns(:tickets).detect{|t| t.created_by != @user} end + + test "should rerender form on missing info" do + params = { :subject => "unauth ticket test subject", + :comments_attributes => {"0" => {}} + } + assert_raises ActionController::ParameterMissing do + post :create, :ticket => params + end + end + test "should create unauthenticated ticket" do params = {:subject => "unauth ticket test subject", :comments_attributes => {"0" => {"body" =>"body of test ticket"}}} diff --git a/engines/support/test/unit/account_extension_test.rb b/engines/support/test/unit/account_extension_test.rb index 0ecb1aa..1b97062 100644 --- a/engines/support/test/unit/account_extension_test.rb +++ b/engines/support/test/unit/account_extension_test.rb @@ -10,7 +10,7 @@ class AccountExtensionTest < ActiveSupport::TestCase t = FactoryGirl.create :ticket_with_creator u = t.created_by_user Account.new(u).destroy - assert_equal nil, Ticket.find(t.id) + assert_nil Ticket.find(t.id) end end diff --git a/engines/support/test/unit/ticket_test.rb b/engines/support/test/unit/ticket_test.rb index 373f06c..048704c 100644 --- a/engines/support/test/unit/ticket_test.rb +++ b/engines/support/test/unit/ticket_test.rb @@ -42,7 +42,7 @@ class TicketTest < ActiveSupport::TestCase t = FactoryGirl.create :ticket_with_creator u = t.created_by_user Ticket.destroy_all_from(u) - assert_equal nil, Ticket.find(t.id) + assert_nil Ticket.find(t.id) end =begin # TODO: do once have current_user stuff in order diff --git a/test/functional/api/users_controller_test.rb b/test/functional/api/users_controller_test.rb index b69770d..88ecae0 100644 --- a/test/functional/api/users_controller_test.rb +++ b/test/functional/api/users_controller_test.rb @@ -95,11 +95,13 @@ class Api::UsersControllerTest < ApiControllerTest end test "admin can show is_admin property" do - user = FactoryGirl.create :user, login: "admin2" - login user - api_get :show, :id => user.id, :format => :json - assert_response :success - assert_json_response user.to_hash.merge(:is_admin => true) + admin = FactoryGirl.create :user + with_config(admins: [admin.login]) do + login admin + api_get :show, :id => admin.id, :format => :json + assert_response :success + assert_json_response admin.to_hash.merge(:is_admin => true) + end end test "normal users cannot show user" do diff --git a/test/functional/keys_controller_test.rb b/test/functional/keys_controller_test.rb index 863be93..1d437e7 100644 --- a/test/functional/keys_controller_test.rb +++ b/test/functional/keys_controller_test.rb @@ -2,6 +2,13 @@ require 'test_helper' class KeysControllerTest < ActionController::TestCase + test "get key for username with dot" do + assert_routing 'key/username.with.dot', controller: 'keys', + action: 'show', + login: 'username.with.dot', + format: :text + end + test "get existing public key" do public_key = 'my public key' @user = stub_record :user, :public_key => public_key @@ -23,10 +30,9 @@ class KeysControllerTest < ActionController::TestCase end test "get public key for non-existing user" do - # raise 404 error if user doesn't exist (doesn't need to be this routing error, but seems fine to assume for now): - assert_raise(ActionController::RoutingError) { - get :show, :login => 'asdkljslksjfdlskfj' - } + # raise 404 error if user doesn't exist + get :show, :login => 'asdkljslksjfdlskfj' + assert_response :not_found end end diff --git a/test/integration/api/update_account_test.rb b/test/integration/api/update_account_test.rb index 1492006..108f05d 100644 --- a/test/integration/api/update_account_test.rb +++ b/test/integration/api/update_account_test.rb @@ -28,6 +28,12 @@ class UpdateAccountTest < SrpTest assert server_auth["M2"] end + test "update recovery code via api" do + authenticate + update_user recovery_code_verifier: "123", recovery_code_salt: "456" + assert last_response.successful? + end + test "change login with password_verifier" do authenticate new_login = 'zaph' diff --git a/test/integration/regression/key_discovery_test.rb b/test/integration/regression/key_discovery_test.rb new file mode 100644 index 0000000..2a38a78 --- /dev/null +++ b/test/integration/regression/key_discovery_test.rb @@ -0,0 +1,23 @@ +require 'test_helper' + +# This is not really a browser test - key discovery is used from bitmask. +# However we need to make sure to test the full rack stack to replicate +# exception handling. +class KeyDiscoveryTest < RackStackTest + include Capybara::DSL + + setup do + # make sure we test the whole stack... + Capybara.current_driver = Capybara.javascript_driver + end + + teardown do + # Revert Capybara.current_driver to Capybara.default_driver + Capybara.use_default_driver + end + + def test_404_on_non_existing_user + visit '/key/asjkholifweatg' + assert_equal 404, status_code + end +end diff --git a/test/integration/regression/provider_info_test.rb b/test/integration/regression/provider_info_test.rb new file mode 100644 index 0000000..2aaf6f6 --- /dev/null +++ b/test/integration/regression/provider_info_test.rb @@ -0,0 +1,20 @@ +require 'test_helper' + +class ProviderInfoTest < BrowserIntegrationTest + + def test_404_on_missing_page + visit '/about' + assert_equal 404, status_code + end + + def test_404_on_missing_language_page + visit '/de/about' + assert_equal 404, status_code + end + + def test_404_en_fallback + visit '/de/bye' + assert_equal 200, status_code + end + +end diff --git a/test/integration/routes/no_route_test.rb b/test/integration/routes/no_route_test.rb new file mode 100644 index 0000000..a570f85 --- /dev/null +++ b/test/integration/routes/no_route_test.rb @@ -0,0 +1,17 @@ +require 'test_helper' + +class NoRouteTest < ActionDispatch::IntegrationTest + + def test_path_with_dot + assert_no_route '.viminfo' + end + + def assert_no_route(path, options = {}) + options[:method] ||= :get + path = "/#{path}" unless path.first == "/" + params = @routes.recognize_path(path, method: :get) + flunk "Expected no route to '#{path}' but found: #{params.inspect}" + rescue ActionController::RoutingError + pass + end +end diff --git a/test/support/browser_integration_test.rb b/test/support/browser_integration_test.rb index 1f5e3d2..c0fef0a 100644 --- a/test/support/browser_integration_test.rb +++ b/test/support/browser_integration_test.rb @@ -1,33 +1,18 @@ +require_relative 'rack_stack_test' + # # BrowserIntegrationTest # # Use this class for capybara based integration tests for the ui. # -require 'capybara/rails' -class BrowserIntegrationTest < ActionDispatch::IntegrationTest +class BrowserIntegrationTest < RackStackTest # let's use dom_id inorder to identify sections include ActionView::RecordIdentifier CONFIG_RU = (Rails.root + 'config.ru').to_s OUTER_APP = Rack::Builder.parse_file(CONFIG_RU).first - require 'capybara/poltergeist' - - Capybara.register_driver :rack_test do |app| - Capybara::RackTest::Driver.new(app) - end - - Capybara.register_driver :poltergeist do |app| - Capybara::Poltergeist::Driver.new(app) - end - - # this is integration testing. So let's make the whole - # rack stack available... - Capybara.app = OUTER_APP - Capybara.run_server = true - Capybara.app_host = 'http://lvh.me:3003' - Capybara.server_port = 3003 Capybara.javascript_driver = :poltergeist Capybara.default_max_wait_time = 5 diff --git a/test/support/rack_stack_test.rb b/test/support/rack_stack_test.rb new file mode 100644 index 0000000..eb49d1e --- /dev/null +++ b/test/support/rack_stack_test.rb @@ -0,0 +1,32 @@ +require 'capybara/rails' +# +# RackStackTest +# +# Tests that will use the entire rack stack from capybara. +# +class RackStackTest < ActionDispatch::IntegrationTest + + CONFIG_RU = (Rails.root + 'config.ru').to_s + OUTER_APP = Rack::Builder.parse_file(CONFIG_RU).first + + # this is integration testing. So let's make the whole + # rack stack available... + Capybara.app = OUTER_APP + Capybara.run_server = true + Capybara.app_host = 'http://lvh.me:3003' + Capybara.server_port = 3003 + + # WARNING: this creates an error in the test as soon as there + # is an error in rails. Use the javascript driver for testing + # error rendering + Capybara.register_driver :rack_test do |app| + Capybara::RackTest::Driver.new(app) + end + + require 'capybara/poltergeist' + + Capybara.register_driver :poltergeist do |app| + Capybara::Poltergeist::Driver.new(app) + end + +end diff --git a/test/unit/account_test.rb b/test/unit/account_test.rb index d56541a..058e196 100644 --- a/test/unit/account_test.rb +++ b/test/unit/account_test.rb @@ -26,6 +26,7 @@ class AccountTest < ActiveSupport::TestCase user = Account.create(FactoryGirl.attributes_for(:user)) assert !user.valid?, "user should not be valid" assert !user.persisted?, "user should not have been saved" + assert_has_errors user, invite_code: "This is not a valid code" end end @@ -47,6 +48,25 @@ class AccountTest < ActiveSupport::TestCase end end + test "error on reused username" do + with_config invite_required: false do + attributes = FactoryGirl.attributes_for :user + user = Account.create attributes + dup = Account.create attributes + assert !dup.valid? + assert_has_errors dup, login: "has already been taken" + user.account.destroy + end + end + + test "error on invalid username" do + with_config invite_required: false do + attributes = FactoryGirl.attributes_for :user, login: "a" + user = Account.create attributes + assert !user.valid? + assert_has_errors user, login: "Must have at least two characters" + end + end test "create and remove a user account" do # We keep an identity that will block the handle from being reused. @@ -76,6 +96,42 @@ class AccountTest < ActiveSupport::TestCase user.account.destroy end + test "create recovery code if it does not exist" do + user = Account.create(FactoryGirl.attributes_for(:user, :invite_code => @testcode.invite_code)) + user.account.update(:recovery_code_verifier => "abc", :recovery_code_salt => "123") + user.reload + + assert_equal "abc", user.recovery_code_verifier + assert_equal "123", user.recovery_code_salt + + user.account.destroy + end + + test "update recovery code that already exists" do + user = Account.create(FactoryGirl.attributes_for(:user, + :invite_code => @testcode.invite_code, + :recovery_code_verifier => "000", + :recovery_code_salt => "111")) + + user.account.update(:recovery_code_verifier => "abc", :recovery_code_salt => "123") + user.reload + + assert_equal "abc", user.recovery_code_verifier + assert_equal "123", user.recovery_code_salt + + user.account.destroy + end + + test "update password" do + user = Account.create(FactoryGirl.attributes_for(:user, :invite_code => @testcode.invite_code)) + user.account.update(:password_verifier => "551A8B", :password_salt => "551A8B") + + assert_equal "551A8B", user.password_verifier + assert_equal "551A8B", user.password_salt + + user.account.destroy + end + test "Invite code count goes up by 1 when the invite code is entered" do with_config invite_required: true do user = Account.create(FactoryGirl.attributes_for(:user, :invite_code => @testcode.invite_code)) @@ -110,4 +166,32 @@ class AccountTest < ActiveSupport::TestCase user.account.enable assert_equal(cert.fingerprint, Identity.for(user).cert_fingerprints.keys.first) end + + # Pixelated relies on the ability to test invite codes without sending a + # username and password yet. + # So we better make sure we return the appropriate errors + test "errors trying to create account with invite only" do + with_config invite_required: true do + user = Account.create invite_code: @testcode.invite_code + assert user.errors[:invite_code].blank? + end + end + + test "errors trying to create account with invalid invite only" do + with_config invite_required: true do + user = Account.create invite_code: "wrong_invite_code" + assert_has_errors user, invite_code: "This is not a valid code" + end + end + + # Tests for the presence of the errors given. + # Does not test for the absence of other errors - so there may be more. + def assert_has_errors(record, errors) + errors.each do |field, field_errors| + Array(field_errors).each do |error| + assert_includes record.errors[field], error + end + end + end + end diff --git a/test/unit/identity_test.rb b/test/unit/identity_test.rb index e9173af..6836487 100644 --- a/test/unit/identity_test.rb +++ b/test/unit/identity_test.rb @@ -122,8 +122,8 @@ class IdentityTest < ActiveSupport::TestCase @id = Identity.for(@user) @id.orphan! assert_equal @user.email_address, @id.address - assert_equal nil, @id.destination - assert_equal nil, @id.user + assert_nil @id.destination + assert_nil @id.user assert @id.orphaned? assert @id.valid? end diff --git a/test/unit/user_test.rb b/test/unit/user_test.rb index 02e94df..ab7add0 100644 --- a/test/unit/user_test.rb +++ b/test/unit/user_test.rb @@ -28,6 +28,16 @@ class UserTest < ActiveSupport::TestCase assert !@user.valid? end + test "validates hex for recovery_code_verifier" do + @user.recovery_code_verifier = "1234567abcdef" + assert @user.valid? + end + + test "validates recovery_code_verifier with non hex chars" do + @user.recovery_code_verifier = "gkpq" + assert !@user.valid? + end + test "test require alphanumerical for login" do @user.login = "qw#r" assert !@user.valid? @@ -73,7 +83,8 @@ class UserTest < ActiveSupport::TestCase test "user to hash includes id, login, valid and enabled" do hash = @user.to_hash - assert_equal @user.id, hash[:id] + assert_nil @user.id + assert_nil hash[:id] assert_equal @user.valid?, hash[:ok] assert_equal @user.login, hash[:login] assert_equal @user.enabled?, hash[:enabled] |