From 9f4b1bcf315f09fd6d302ad187281ec4ed443f04 Mon Sep 17 00:00:00 2001 From: Azul Date: Thu, 17 Oct 2013 12:05:26 +0200 Subject: blacklist system logins for aliases and logins We blacklist based on three things: * blacklist in APP_CONFIG[:handle_blacklist] * emails in RFC 2142 * usernames in /etc/passwd The latter two can be allowed by explicitly whitelisting them in APP_CONFIG[:handle_whitelist]. We stick to blocking names that have been configured as both blacklisted and whitelisted - better be save than sorry. --- users/test/unit/local_email_test.rb | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) (limited to 'users/test') diff --git a/users/test/unit/local_email_test.rb b/users/test/unit/local_email_test.rb index b25f46f..20ee7f1 100644 --- a/users/test/unit/local_email_test.rb +++ b/users/test/unit/local_email_test.rb @@ -24,6 +24,37 @@ class LocalEmailTest < ActiveSupport::TestCase assert_equal ["needs to end in @#{LocalEmail.domain}"], local.errors[:email] end + test "blacklists rfc2142" do + black_listed = LocalEmail.new('hostmaster') + assert !black_listed.valid? + end + + test "blacklists etc passwd" do + black_listed = LocalEmail.new('nobody') + assert !black_listed.valid? + end + + test "whitelist overwrites automatic blacklists" do + with_config handle_whitelist: ['nobody', 'hostmaster'] do + white_listed = LocalEmail.new('nobody') + assert white_listed.valid? + white_listed = LocalEmail.new('hostmaster') + assert white_listed.valid? + end + end + + test "blacklists from config" do + black_listed = LocalEmail.new('www-data') + assert !black_listed.valid? + end + + test "blacklist from config overwrites whitelist" do + with_config handle_whitelist: ['www-data'] do + black_listed = LocalEmail.new('www-data') + assert !black_listed.valid? + end + end + def handle @handle ||= Faker::Internet.user_name end -- cgit v1.2.3 From 18c6f005d0eb0099a1d41235818564fbab94fb1b Mon Sep 17 00:00:00 2001 From: Azul Date: Fri, 18 Oct 2013 12:20:23 +0200 Subject: test logging in through the API using python with umlauts --- users/test/integration/api/python/umlauts.py | 79 ++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100755 users/test/integration/api/python/umlauts.py (limited to 'users/test') diff --git a/users/test/integration/api/python/umlauts.py b/users/test/integration/api/python/umlauts.py new file mode 100755 index 0000000..96fecbf --- /dev/null +++ b/users/test/integration/api/python/umlauts.py @@ -0,0 +1,79 @@ +#!/usr/bin/env python +# coding: utf-8 + +# under development + +import requests +import json +import string +import random +import srp._pysrp as srp +import binascii + +safe_unhexlify = lambda x: binascii.unhexlify(x) if (len(x) % 2 == 0) else binascii.unhexlify('0'+x) + +# using globals for now +# server = 'https://dev.bitmask.net/1' +server = 'http://api.lvh.me:3000/1' + +def run_tests(): + login = 'test_' + id_generator() + password = id_generator() + "äöì" + id_generator() + usr = srp.User( login, password, srp.SHA256, srp.NG_1024 ) + print_and_parse(signup(login, password)) + + auth = print_and_parse(authenticate(usr)) + verify_or_debug(auth, usr) + assert usr.authenticated() + + +# let's have some random name +def id_generator(size=6, chars=string.ascii_lowercase + string.digits): + return ''.join(random.choice(chars) for x in range(size)) + +# log the server communication +def print_and_parse(response): + request = response.request + print request.method + ': ' + response.url + if hasattr(request, 'data'): + print " " + json.dumps(response.request.data) + print " -> " + response.text + try: + return json.loads(response.text) + except ValueError: + return None + +def signup(login, password): + salt, vkey = srp.create_salted_verification_key( login, password, srp.SHA256, srp.NG_1024 ) + user_params = { + 'user[login]': login, + 'user[password_verifier]': binascii.hexlify(vkey), + 'user[password_salt]': binascii.hexlify(salt) + } + print json.dumps(user_params) + return requests.post(server + '/users.json', data = user_params, verify = False) + +def authenticate(usr): + session = requests.session() + uname, A = usr.start_authentication() + params = { + 'login': uname, + 'A': binascii.hexlify(A) + } + init = print_and_parse(session.post(server + '/sessions', data = params, verify=False)) + M = usr.process_challenge( safe_unhexlify(init['salt']), safe_unhexlify(init['B']) ) + return session.put(server + '/sessions/' + uname, verify = False, + data = {'client_auth': binascii.hexlify(M)}) + +def verify_or_debug(auth, usr): + if ( 'errors' in auth ): + print ' u = "%x"' % usr.u + print ' x = "%x"' % usr.x + print ' v = "%x"' % usr.v + print ' S = "%x"' % usr.S + print ' K = "' + binascii.hexlify(usr.K) + '"' + print ' M = "' + binascii.hexlify(usr.M) + '"' + else: + usr.verify_session( safe_unhexlify(auth["M2"]) ) + +run_tests() -- cgit v1.2.3 From 315a7c9aa3d6cc6cde51a67b6dcc91aea085f518 Mon Sep 17 00:00:00 2001 From: Azul Date: Mon, 28 Oct 2013 10:48:53 +0100 Subject: reset button loading... state on error (#4231) including test refactored error display some --- users/test/integration/browser/account_test.rb | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'users/test') diff --git a/users/test/integration/browser/account_test.rb b/users/test/integration/browser/account_test.rb index 1deda45..243ccfb 100644 --- a/users/test/integration/browser/account_test.rb +++ b/users/test/integration/browser/account_test.rb @@ -27,6 +27,20 @@ class AccountTest < BrowserIntegrationTest User.find_by_login(username).account.destroy end + test "failed login" do + username, password = submit_signup + click_on 'Logout' + click_on 'Log In' + fill_in 'Username', with: username + fill_in 'Password', with: "wrong password" + click_on 'Log In' + assert page.has_selector? 'input.btn-primary.disabled' + assert page.has_content? I18n.t(:invalid_user_pass) + assert page.has_no_content?("Welcome #{username}") + assert page.has_no_selector? 'input.btn-primary.disabled' + User.find_by_login(username).account.destroy + end + test "change password" do username, password = submit_signup click_on "Account Settings" -- cgit v1.2.3 From 1ef3e9df271934b983ff5afe60c2dcf34c090a98 Mon Sep 17 00:00:00 2001 From: Azul Date: Mon, 28 Oct 2013 11:08:31 +0100 Subject: no need to create a user for testing failed login attempt --- users/test/integration/browser/account_test.rb | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'users/test') diff --git a/users/test/integration/browser/account_test.rb b/users/test/integration/browser/account_test.rb index 243ccfb..8e03856 100644 --- a/users/test/integration/browser/account_test.rb +++ b/users/test/integration/browser/account_test.rb @@ -28,17 +28,14 @@ class AccountTest < BrowserIntegrationTest end test "failed login" do - username, password = submit_signup - click_on 'Logout' + visit '/' click_on 'Log In' - fill_in 'Username', with: username + fill_in 'Username', with: "username" fill_in 'Password', with: "wrong password" click_on 'Log In' assert page.has_selector? 'input.btn-primary.disabled' assert page.has_content? I18n.t(:invalid_user_pass) - assert page.has_no_content?("Welcome #{username}") assert page.has_no_selector? 'input.btn-primary.disabled' - User.find_by_login(username).account.destroy end test "change password" do -- cgit v1.2.3 From dd88c7f84cb3c497c6327c364b3c08993c51a08f Mon Sep 17 00:00:00 2001 From: Azul Date: Mon, 28 Oct 2013 12:47:46 +0100 Subject: notify user their account was successfully deleted (refs #4216) Also fixes a cornercase when admins deleted their own account. So far they would be redirected to the users list - which then refused access. Now they'll be redirected to the home landing page as well. --- users/test/integration/browser/account_test.rb | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'users/test') diff --git a/users/test/integration/browser/account_test.rb b/users/test/integration/browser/account_test.rb index 8e03856..b712c95 100644 --- a/users/test/integration/browser/account_test.rb +++ b/users/test/integration/browser/account_test.rb @@ -38,6 +38,14 @@ class AccountTest < BrowserIntegrationTest assert page.has_no_selector? 'input.btn-primary.disabled' end + test "account destruction" do + username, password = submit_signup + click_on I18n.t('account_settings') + click_on I18n.t('destroy_my_account') + page.save_screenshot('/tmp/destroy.png') + assert page.has_content?(I18n.t('account_destroyed')) + end + test "change password" do username, password = submit_signup click_on "Account Settings" -- cgit v1.2.3 From f6924bfe3b540c384fa53e55db9db3a64a34ced3 Mon Sep 17 00:00:00 2001 From: Azul Date: Wed, 30 Oct 2013 20:13:16 +0100 Subject: test helper to expect_logout. Currently it expects both the session and the token to be cleared. This might change. But we'll always have a definition of what it means to logout we can test this way. --- users/test/functional/sessions_controller_test.rb | 14 +++----------- users/test/functional/users_controller_test.rb | 1 + users/test/functional/v1/sessions_controller_test.rb | 19 ++----------------- users/test/support/auth_test_helper.rb | 14 ++++++++++++++ 4 files changed, 20 insertions(+), 28 deletions(-) (limited to 'users/test') diff --git a/users/test/functional/sessions_controller_test.rb b/users/test/functional/sessions_controller_test.rb index a630e6e..28143da 100644 --- a/users/test/functional/sessions_controller_test.rb +++ b/users/test/functional/sessions_controller_test.rb @@ -41,20 +41,12 @@ class SessionsControllerTest < ActionController::TestCase assert_json_error :login => I18n.t(:all_strategies_failed) end - test "logout should reset warden user" do - expect_warden_logout + test "destory should logout" do + login + expect_logout delete :destroy assert_response :redirect assert_redirected_to root_url end - def expect_warden_logout - raw = mock('raw session') do - expects(:inspect) - end - request.env['warden'].expects(:raw_session).returns(raw) - request.env['warden'].expects(:logout) - end - - end diff --git a/users/test/functional/users_controller_test.rb b/users/test/functional/users_controller_test.rb index 052de04..75d900f 100644 --- a/users/test/functional/users_controller_test.rb +++ b/users/test/functional/users_controller_test.rb @@ -91,6 +91,7 @@ class UsersControllerTest < ActionController::TestCase user.expects(:destroy) login user + expect_logout delete :destroy, :id => @current_user.id assert_response :redirect diff --git a/users/test/functional/v1/sessions_controller_test.rb b/users/test/functional/v1/sessions_controller_test.rb index ff9fca1..4200e8f 100644 --- a/users/test/functional/v1/sessions_controller_test.rb +++ b/users/test/functional/v1/sessions_controller_test.rb @@ -52,26 +52,11 @@ class V1::SessionsControllerTest < ActionController::TestCase assert_equal @user.id, token.user_id end - test "logout should reset session" do - expect_warden_logout - delete :destroy - assert_response 204 - end - - test "logout should destroy token" do + test "destroy should logout" do login - expect_warden_logout - @token.expects(:destroy) + expect_logout delete :destroy assert_response 204 end - def expect_warden_logout - raw = mock('raw session') do - expects(:inspect) - end - request.env['warden'].expects(:raw_session).returns(raw) - request.env['warden'].expects(:logout) - end - end diff --git a/users/test/support/auth_test_helper.rb b/users/test/support/auth_test_helper.rb index 609f115..50e9453 100644 --- a/users/test/support/auth_test_helper.rb +++ b/users/test/support/auth_test_helper.rb @@ -38,12 +38,26 @@ module AuthTestHelper end end + def expect_logout + expect_warden_logout + @token.expects(:destroy) if @token + end + protected def header_for_token_auth @token = find_record(:token, :authenticate => @current_user) ActionController::HttpAuthentication::Token.encode_credentials @token.id end + + def expect_warden_logout + raw = mock('raw session') do + expects(:inspect) + end + request.env['warden'].expects(:raw_session).returns(raw) + request.env['warden'].expects(:logout) + end + end class ActionController::TestCase -- cgit v1.2.3 From 99ecdbf71632970d4c83f99beea325e5d213e4c6 Mon Sep 17 00:00:00 2001 From: Azul Date: Tue, 5 Nov 2013 12:12:13 +0100 Subject: disabled identities to block handles after a user was deleted --- users/test/unit/account_test.rb | 3 ++- users/test/unit/identity_test.rb | 20 ++++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) (limited to 'users/test') diff --git a/users/test/unit/account_test.rb b/users/test/unit/account_test.rb index 94a9980..a8c6efd 100644 --- a/users/test/unit/account_test.rb +++ b/users/test/unit/account_test.rb @@ -13,7 +13,8 @@ class AccountTest < ActiveSupport::TestCase end test "create and remove a user account" do - assert_no_difference "Identity.count" do + # We keep an identity that will block the handle from being reused. + assert_difference "Identity.count" do assert_no_difference "User.count" do user = Account.create(FactoryGirl.attributes_for(:user)) user.account.destroy diff --git a/users/test/unit/identity_test.rb b/users/test/unit/identity_test.rb index 0842a77..8270689 100644 --- a/users/test/unit/identity_test.rb +++ b/users/test/unit/identity_test.rb @@ -90,6 +90,26 @@ class IdentityTest < ActiveSupport::TestCase assert id.errors.messages[:destination].include? "needs to be a valid email address" end + test "disabled identity" do + id = Identity.for(@user) + id.disable + assert_equal @user.email_address, id.address + assert_equal nil, id.destination + assert_equal nil, id.user + assert !id.enabled? + assert id.valid? + end + + test "disabled identity blocks handle" do + id = Identity.for(@user) + id.disable + id.save + other_user = find_record :user + taken = Identity.build_for other_user, address: id.address + assert !taken.valid? + id.destroy + end + def alias_name @alias_name ||= Faker::Internet.user_name end -- cgit v1.2.3 From 4a2490cc5eac1803be80fade65bbe9d32fa0bd9b Mon Sep 17 00:00:00 2001 From: Azul Date: Tue, 5 Nov 2013 17:03:55 +0100 Subject: Identity.destroy_all_disabled will clean up disabled identities This is mostly for cleaning up after tests so far. But we might expand this to destroy all identities disabled before a certain date. --- users/test/unit/account_test.rb | 4 ++++ users/test/unit/identity_test.rb | 11 ++++++++++- 2 files changed, 14 insertions(+), 1 deletion(-) (limited to 'users/test') diff --git a/users/test/unit/account_test.rb b/users/test/unit/account_test.rb index a8c6efd..4fb3c3d 100644 --- a/users/test/unit/account_test.rb +++ b/users/test/unit/account_test.rb @@ -2,6 +2,10 @@ require 'test_helper' class AccountTest < ActiveSupport::TestCase + teardown do + Identity.destroy_all_disabled + end + test "create a new account" do user = Account.create(FactoryGirl.attributes_for(:user)) assert user.valid? diff --git a/users/test/unit/identity_test.rb b/users/test/unit/identity_test.rb index 8270689..78ef52c 100644 --- a/users/test/unit/identity_test.rb +++ b/users/test/unit/identity_test.rb @@ -107,7 +107,16 @@ class IdentityTest < ActiveSupport::TestCase other_user = find_record :user taken = Identity.build_for other_user, address: id.address assert !taken.valid? - id.destroy + Identity.destroy_all_disabled + end + + test "destroy all disabled identities" do + id = Identity.for(@user) + id.disable + id.save + assert Identity.count > 0 + Identity.destroy_all_disabled + assert_equal 0, Identity.count end def alias_name -- cgit v1.2.3 From 40f24e2887672957acf7ecedce58e692cc9505ca Mon Sep 17 00:00:00 2001 From: Azul Date: Wed, 6 Nov 2013 10:10:44 +0100 Subject: refactor: extract method on account test also test one can't login anymore after destroying the account. --- users/test/integration/browser/account_test.rb | 35 ++++++++++++++------------ 1 file changed, 19 insertions(+), 16 deletions(-) (limited to 'users/test') diff --git a/users/test/integration/browser/account_test.rb b/users/test/integration/browser/account_test.rb index b712c95..6e9aab5 100644 --- a/users/test/integration/browser/account_test.rb +++ b/users/test/integration/browser/account_test.rb @@ -19,31 +19,24 @@ class AccountTest < BrowserIntegrationTest test "successful login" do username, password = submit_signup click_on 'Logout' - click_on 'Log In' - fill_in 'Username', with: username - fill_in 'Password', with: password - click_on 'Log In' + attempt_login(username, password) assert page.has_content?("Welcome #{username}") User.find_by_login(username).account.destroy end test "failed login" do visit '/' - click_on 'Log In' - fill_in 'Username', with: "username" - fill_in 'Password', with: "wrong password" - click_on 'Log In' - assert page.has_selector? 'input.btn-primary.disabled' - assert page.has_content? I18n.t(:invalid_user_pass) - assert page.has_no_selector? 'input.btn-primary.disabled' + attempt_login("username", "wrong password") + assert_invalid_login(page) end test "account destruction" do username, password = submit_signup click_on I18n.t('account_settings') click_on I18n.t('destroy_my_account') - page.save_screenshot('/tmp/destroy.png') assert page.has_content?(I18n.t('account_destroyed')) + attempt_login(username, password) + assert_invalid_login(page) end test "change password" do @@ -55,10 +48,7 @@ class AccountTest < BrowserIntegrationTest click_on 'Save' end click_on 'Logout' - click_on 'Log In' - fill_in 'Username', with: username - fill_in 'Password', with: "other password" - click_on 'Log In' + attempt_login(username, "other password") assert page.has_content?("Welcome #{username}") User.find_by_login(username).account.destroy end @@ -100,6 +90,19 @@ class AccountTest < BrowserIntegrationTest assert page.has_content?("server failed") end + def attempt_login(username, password) + click_on 'Log In' + fill_in 'Username', with: username + fill_in 'Password', with: password + click_on 'Log In' + end + + def assert_invalid_login(page) + assert page.has_selector? 'input.btn-primary.disabled' + assert page.has_content? I18n.t(:invalid_user_pass) + assert page.has_no_selector? 'input.btn-primary.disabled' + end + def inject_malicious_js page.execute_script <<-EOJS var calc = new srp.Calculate(); -- cgit v1.2.3 From 44d273fd03645af5e546133adf4e9906800d3d5f Mon Sep 17 00:00:00 2001 From: Azul Date: Wed, 6 Nov 2013 10:20:33 +0100 Subject: integration test for blocking handles after account destroyed has not been run yet. --- users/test/integration/browser/account_test.rb | 12 ++++++++++++ users/test/support/integration_test_helper.rb | 6 +++--- 2 files changed, 15 insertions(+), 3 deletions(-) (limited to 'users/test') diff --git a/users/test/integration/browser/account_test.rb b/users/test/integration/browser/account_test.rb index 6e9aab5..b349489 100644 --- a/users/test/integration/browser/account_test.rb +++ b/users/test/integration/browser/account_test.rb @@ -6,6 +6,10 @@ class AccountTest < BrowserIntegrationTest Capybara.current_driver = Capybara.javascript_driver end + teardown do + Identity.destroy_all_disabled + end + test "normal account workflow" do username, password = submit_signup assert page.has_content?("Welcome #{username}") @@ -39,6 +43,14 @@ class AccountTest < BrowserIntegrationTest assert_invalid_login(page) end + test "handle blocked after account destruction" do + username, password = submit_signup + click_on I18n.t('account_settings') + click_on I18n.t('destroy_my_account') + submit_signup(username) + assert page.has_content?('has already been taken') + end + test "change password" do username, password = submit_signup click_on "Account Settings" diff --git a/users/test/support/integration_test_helper.rb b/users/test/support/integration_test_helper.rb index cfe72cf..51e47c6 100644 --- a/users/test/support/integration_test_helper.rb +++ b/users/test/support/integration_test_helper.rb @@ -1,7 +1,7 @@ module IntegrationTestHelper - def submit_signup - username = "test_#{SecureRandom.urlsafe_base64}".downcase - password = SecureRandom.base64 + def submit_signup(username = nil, password = nil) + username ||= "test_#{SecureRandom.urlsafe_base64}".downcase + password ||= SecureRandom.base64 visit '/users/new' fill_in 'Username', with: username fill_in 'Password', with: password -- cgit v1.2.3 From ded302ebc6a9e145775f7847c5e89f91d683c777 Mon Sep 17 00:00:00 2001 From: Azul Date: Wed, 6 Nov 2013 11:55:43 +0100 Subject: use the account lifecycle from UsersController#destroy --- users/test/functional/users_controller_test.rb | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'users/test') diff --git a/users/test/functional/users_controller_test.rb b/users/test/functional/users_controller_test.rb index 75d900f..9c5f8d9 100644 --- a/users/test/functional/users_controller_test.rb +++ b/users/test/functional/users_controller_test.rb @@ -77,7 +77,11 @@ class UsersControllerTest < ActionController::TestCase test "admin can destroy user" do user = find_record :user + + # we destroy the user record and the associated data... user.expects(:destroy) + Identity.expects(:disable_all_for).with(user) + Ticket.expects(:destroy_all_from).with(user) login :is_admin? => true delete :destroy, :id => user.id @@ -88,7 +92,11 @@ class UsersControllerTest < ActionController::TestCase test "user can cancel account" do user = find_record :user + + # we destroy the user record and the associated data... user.expects(:destroy) + Identity.expects(:disable_all_for).with(user) + Ticket.expects(:destroy_all_from).with(user) login user expect_logout -- cgit v1.2.3 From a0e72e6ee7786e3b1fd7276f1c64912c606f4559 Mon Sep 17 00:00:00 2001 From: Azul Date: Thu, 7 Nov 2013 12:46:28 +0100 Subject: only check number of disabled identities to make test more robust --- users/test/unit/identity_test.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'users/test') diff --git a/users/test/unit/identity_test.rb b/users/test/unit/identity_test.rb index 78ef52c..eca104f 100644 --- a/users/test/unit/identity_test.rb +++ b/users/test/unit/identity_test.rb @@ -116,7 +116,7 @@ class IdentityTest < ActiveSupport::TestCase id.save assert Identity.count > 0 Identity.destroy_all_disabled - assert_equal 0, Identity.count + assert_equal 0, Identity.disabled.count end def alias_name -- cgit v1.2.3 From e2c0962077cf759b23639276cca42606ea2135ec Mon Sep 17 00:00:00 2001 From: Azul Date: Thu, 7 Nov 2013 23:27:27 +0100 Subject: Token.destroy_all_expired to cleanup expired tokens (#4411) --- users/test/unit/token_test.rb | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'users/test') diff --git a/users/test/unit/token_test.rb b/users/test/unit/token_test.rb index f56c576..445a20c 100644 --- a/users/test/unit/token_test.rb +++ b/users/test/unit/token_test.rb @@ -61,6 +61,21 @@ class ClientCertificateTest < ActiveSupport::TestCase end end + test "Token.destroy_all_expired cleans up expired tokens only" do + expired = Token.new(user_id: @user.id) + expired.last_seen_at = 2.hours.ago + expired.save + fresh = Token.new(user_id: @user.id) + fresh.save + with_config auth: {token_expires_after: 60} do + Token.destroy_all_expired + end + assert_nil Token.find(expired.id) + assert_equal fresh, Token.find(fresh.id) + fresh.destroy + end + + end -- cgit v1.2.3 From a7cd2ef0877e79302f27fb175384a0cf4ded52d9 Mon Sep 17 00:00:00 2001 From: Azul Date: Thu, 7 Nov 2013 23:36:37 +0100 Subject: fix cornercase of non expiring tokens --- users/test/factories.rb | 4 +++- users/test/unit/token_test.rb | 18 ++++++++++-------- 2 files changed, 13 insertions(+), 9 deletions(-) (limited to 'users/test') diff --git a/users/test/factories.rb b/users/test/factories.rb index c87e290..f5fb77d 100644 --- a/users/test/factories.rb +++ b/users/test/factories.rb @@ -19,6 +19,8 @@ FactoryGirl.define do end end - factory :token + factory :token do + user + end end diff --git a/users/test/unit/token_test.rb b/users/test/unit/token_test.rb index 445a20c..6c9f209 100644 --- a/users/test/unit/token_test.rb +++ b/users/test/unit/token_test.rb @@ -7,9 +7,6 @@ class ClientCertificateTest < ActiveSupport::TestCase @user = find_record :user end - teardown do - end - test "new token for user" do sample = Token.new(:user_id => @user.id) assert sample.valid? @@ -61,12 +58,17 @@ class ClientCertificateTest < ActiveSupport::TestCase end end + test "Token.destroy_all_expired is noop if no expiry is set" do + expired = FactoryGirl.create :token, last_seen_at: 2.hours.ago + with_config auth: {} do + Token.destroy_all_expired + end + assert_equal expired, Token.find(expired.id) + end + test "Token.destroy_all_expired cleans up expired tokens only" do - expired = Token.new(user_id: @user.id) - expired.last_seen_at = 2.hours.ago - expired.save - fresh = Token.new(user_id: @user.id) - fresh.save + expired = FactoryGirl.create :token, last_seen_at: 2.hours.ago + fresh = FactoryGirl.create :token with_config auth: {token_expires_after: 60} do Token.destroy_all_expired end -- cgit v1.2.3 From d82ea5da2aa705bcfa74f2a8b42a197883b694e3 Mon Sep 17 00:00:00 2001 From: jessib Date: Thu, 21 Nov 2013 12:15:03 -0800 Subject: Refactoring of code, and tests. --- users/test/functional/keys_controller_test.rb | 31 +++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 users/test/functional/keys_controller_test.rb (limited to 'users/test') diff --git a/users/test/functional/keys_controller_test.rb b/users/test/functional/keys_controller_test.rb new file mode 100644 index 0000000..9cc88d1 --- /dev/null +++ b/users/test/functional/keys_controller_test.rb @@ -0,0 +1,31 @@ +require 'test_helper' + +class KeysControllerTest < ActionController::TestCase + + test "get existing public key" do + public_key = 'my public key' + @user = stub_record :user, :public_key => public_key + User.stubs(:find_by_login).with(@user.login).returns(@user) + get :show, :login => @user.login + assert_response :success + assert_equal "text/html", response.content_type + assert_equal public_key, response.body + end + + test "get non-existing public key for user" do + @user = stub_record :user + User.stubs(:find_by_login).with(@user.login).returns(@user) + get :show, :login => @user.login + assert_response :success + assert_equal "text/html", response.content_type + assert_equal '', response.body.strip + end + + test "get public key for non-existing user" do + get :show, :login => 'asdkljslksjfdlskfj' + assert_response :success + assert_equal "text/html", response.content_type + assert_equal '', response.body.strip + end + +end -- cgit v1.2.3 From 299dfdf4164ee10de63aa2543935eeed65437b3f Mon Sep 17 00:00:00 2001 From: jessib Date: Mon, 25 Nov 2013 11:31:33 -0800 Subject: Give 404 error if one goes to /key/user for non-existing user. --- users/test/functional/keys_controller_test.rb | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'users/test') diff --git a/users/test/functional/keys_controller_test.rb b/users/test/functional/keys_controller_test.rb index 9cc88d1..b69cbc0 100644 --- a/users/test/functional/keys_controller_test.rb +++ b/users/test/functional/keys_controller_test.rb @@ -13,6 +13,7 @@ class KeysControllerTest < ActionController::TestCase end test "get non-existing public key for user" do + # this isn't a scenerio that should generally occur. @user = stub_record :user User.stubs(:find_by_login).with(@user.login).returns(@user) get :show, :login => @user.login @@ -22,10 +23,10 @@ class KeysControllerTest < ActionController::TestCase end test "get public key for non-existing user" do - get :show, :login => 'asdkljslksjfdlskfj' - assert_response :success - assert_equal "text/html", response.content_type - assert_equal '', response.body.strip + # 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' + } end end -- cgit v1.2.3 From 7de12c71ce7eb4eeb6e0795275434ed4a4120c25 Mon Sep 17 00:00:00 2001 From: Azul Date: Tue, 26 Nov 2013 11:22:47 +0100 Subject: ignore attempts to empty public_key, refactor refactor: prepare validations of the uploaded pgp keys --- users/test/integration/api/account_flow_test.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'users/test') diff --git a/users/test/integration/api/account_flow_test.rb b/users/test/integration/api/account_flow_test.rb index e41befa..90f2a97 100644 --- a/users/test/integration/api/account_flow_test.rb +++ b/users/test/integration/api/account_flow_test.rb @@ -114,9 +114,9 @@ class AccountFlowTest < RackTest # should not overwrite public key: put "http://api.lvh.me:3000/1/users/" + @user.id + '.json', :user => {:blee => :blah}, :format => :json assert_equal test_public_key, Identity.for(@user).keys[:pgp] - # should overwrite public key: - put "http://api.lvh.me:3000/1/users/" + @user.id + '.json', :user => {:public_key => nil}, :format => :json - assert_nil Identity.for(@user).keys[:pgp] + # should not empty public key: + put "http://api.lvh.me:3000/1/users/" + @user.id + '.json', :user => {:public_key => ""}, :format => :json + assert_equal test_public_key, Identity.for(@user).keys[:pgp] end end -- cgit v1.2.3 From e34141c3265c6daeda92bcb83fa508de00551bc3 Mon Sep 17 00:00:00 2001 From: Azul Date: Tue, 26 Nov 2013 14:39:42 +0100 Subject: simple validation for pgp key format --- users/test/factories.rb | 8 ++++++ users/test/integration/api/account_flow_test.rb | 34 +++++++++++++++++-------- users/test/integration/browser/account_test.rb | 4 +-- 3 files changed, 34 insertions(+), 12 deletions(-) (limited to 'users/test') diff --git a/users/test/factories.rb b/users/test/factories.rb index f5fb77d..ae00d43 100644 --- a/users/test/factories.rb +++ b/users/test/factories.rb @@ -23,4 +23,12 @@ FactoryGirl.define do user end + factory :pgp_key do + keyblock <<-EOPGP +-----BEGIN PGP PUBLIC KEY BLOCK----- ++Dummy+PGP+KEY+++Dummy+PGP+KEY+++Dummy+PGP+KEY+++Dummy+PGP+KEY+ +#{SecureRandom.base64(4032)} +-----END PGP PUBLIC KEY BLOCK----- + EOPGP + end end diff --git a/users/test/integration/api/account_flow_test.rb b/users/test/integration/api/account_flow_test.rb index 90f2a97..9aee38b 100644 --- a/users/test/integration/api/account_flow_test.rb +++ b/users/test/integration/api/account_flow_test.rb @@ -96,27 +96,41 @@ class AccountFlowTest < RackTest assert server_auth["M2"] end - test "update user" do + test "changing login" do server_auth = @srp.authenticate(self) - test_public_key = 'asdlfkjslfdkjasd' original_login = @user.login new_login = 'zaph' User.find_by_login(new_login).try(:destroy) Identity.by_address.key(new_login + '@' + APP_CONFIG[:domain]).each do |identity| identity.destroy end - put "http://api.lvh.me:3000/1/users/" + @user.id + '.json', :user => {:public_key => test_public_key, :login => new_login}, :format => :json + put "http://api.lvh.me:3000/1/users/" + @user.id + '.json', :user => {:login => new_login}, :format => :json assert last_response.successful? - assert_equal test_public_key, Identity.for(@user).keys[:pgp] # does not change login if no password_verifier is present assert_equal original_login, @user.login - # eventually probably want to remove most of this into a non-integration functional test - # should not overwrite public key: - put "http://api.lvh.me:3000/1/users/" + @user.id + '.json', :user => {:blee => :blah}, :format => :json - assert_equal test_public_key, Identity.for(@user).keys[:pgp] - # should not empty public key: + end + + test "upload pgp key" do + server_auth = @srp.authenticate(self) + key = FactoryGirl.build :pgp_key + put "http://api.lvh.me:3000/1/users/" + @user.id + '.json', :user => {:public_key => key}, :format => :json + assert_equal key, Identity.for(@user).keys[:pgp] + end + + # eventually probably want to remove most of this into a non-integration + # functional test + test "prevent uploading invalid key" do + server_auth = @srp.authenticate(self) + put "http://api.lvh.me:3000/1/users/" + @user.id + '.json', :user => {:public_key => :blah}, :format => :json + assert_nil Identity.for(@user).keys[:pgp] + end + + test "prevent emptying public key" do + server_auth = @srp.authenticate(self) + key = FactoryGirl.build :pgp_key + put "http://api.lvh.me:3000/1/users/" + @user.id + '.json', :user => {:public_key => key}, :format => :json put "http://api.lvh.me:3000/1/users/" + @user.id + '.json', :user => {:public_key => ""}, :format => :json - assert_equal test_public_key, Identity.for(@user).keys[:pgp] + assert_equal key, Identity.for(@user).keys[:pgp] end end diff --git a/users/test/integration/browser/account_test.rb b/users/test/integration/browser/account_test.rb index b349489..3d281ae 100644 --- a/users/test/integration/browser/account_test.rb +++ b/users/test/integration/browser/account_test.rb @@ -66,7 +66,7 @@ class AccountTest < BrowserIntegrationTest end test "change pgp key" do - pgp_key = "My PGP Key Stub" + pgp_key = FactoryGirl.build :pgp_key username, password = submit_signup click_on "Account Settings" within('#update_pgp_key') do @@ -76,7 +76,7 @@ class AccountTest < BrowserIntegrationTest 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 + 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 -- cgit v1.2.3 From dade6497424a869db5f1dfb030f88f4711278b81 Mon Sep 17 00:00:00 2001 From: Azul Date: Wed, 27 Nov 2013 09:43:28 +0100 Subject: minor: rename test to what it actually tests [skip ci] --- users/test/integration/api/account_flow_test.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'users/test') diff --git a/users/test/integration/api/account_flow_test.rb b/users/test/integration/api/account_flow_test.rb index 9aee38b..edd0859 100644 --- a/users/test/integration/api/account_flow_test.rb +++ b/users/test/integration/api/account_flow_test.rb @@ -96,7 +96,7 @@ class AccountFlowTest < RackTest assert server_auth["M2"] end - test "changing login" do + test "prevent changing login without changing password_verifier" do server_auth = @srp.authenticate(self) original_login = @user.login new_login = 'zaph' -- cgit v1.2.3 From ce1d6ddacca09062ed90a40de559454c7ce912b5 Mon Sep 17 00:00:00 2001 From: jessib Date: Mon, 9 Dec 2013 11:50:47 -0800 Subject: Update tests to reflect using plaintext key. --- users/test/functional/keys_controller_test.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'users/test') diff --git a/users/test/functional/keys_controller_test.rb b/users/test/functional/keys_controller_test.rb index b69cbc0..863be93 100644 --- a/users/test/functional/keys_controller_test.rb +++ b/users/test/functional/keys_controller_test.rb @@ -8,7 +8,7 @@ class KeysControllerTest < ActionController::TestCase User.stubs(:find_by_login).with(@user.login).returns(@user) get :show, :login => @user.login assert_response :success - assert_equal "text/html", response.content_type + assert_equal "text/text", response.content_type assert_equal public_key, response.body end @@ -18,7 +18,7 @@ class KeysControllerTest < ActionController::TestCase User.stubs(:find_by_login).with(@user.login).returns(@user) get :show, :login => @user.login assert_response :success - assert_equal "text/html", response.content_type + assert_equal "text/text", response.content_type assert_equal '', response.body.strip end -- cgit v1.2.3 From 5ed00a63ea3da98e8dfaef88752f8afe851c81e9 Mon Sep 17 00:00:00 2001 From: Azul Date: Fri, 13 Dec 2013 14:10:41 +0100 Subject: make the possible actions for users and admins configurable with tests --- users/test/integration/browser/account_test.rb | 66 +++++++++++++++++--------- 1 file changed, 44 insertions(+), 22 deletions(-) (limited to 'users/test') 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 -- cgit v1.2.3 From 91aea91d7091b740630551ec17d0274236545f4c Mon Sep 17 00:00:00 2001 From: jessib Date: Mon, 16 Dec 2013 11:49:16 -0800 Subject: Add test. --- users/test/functional/sessions_controller_test.rb | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'users/test') diff --git a/users/test/functional/sessions_controller_test.rb b/users/test/functional/sessions_controller_test.rb index 28143da..8b49005 100644 --- a/users/test/functional/sessions_controller_test.rb +++ b/users/test/functional/sessions_controller_test.rb @@ -17,6 +17,13 @@ class SessionsControllerTest < ActionController::TestCase assert_template "sessions/new" end + test "redirect to root_url if logged in" do + login + get :new + assert_response :redirect + assert_redirected_to root_url + end + test "renders json" do get :new, :format => :json assert_response :success -- cgit v1.2.3