summaryrefslogtreecommitdiff
path: root/test/unit
diff options
context:
space:
mode:
Diffstat (limited to 'test/unit')
-rw-r--r--test/unit/account_test.rb47
-rw-r--r--test/unit/anonymous_user_test.rb23
-rw-r--r--test/unit/client_certificate_test.rb24
-rw-r--r--test/unit/helpers/session_helper_test.rb4
-rw-r--r--test/unit/helpers/users_helper_test.rb4
-rw-r--r--test/unit/identity_test.rb133
-rw-r--r--test/unit/local_email_test.rb65
-rw-r--r--test/unit/token_test.rb89
-rw-r--r--test/unit/user_test.rb68
-rw-r--r--test/unit/warden_strategy_secure_remote_password_test.rb63
-rw-r--r--test/unit/webfinger/host_meta_presenter_test.rb24
-rw-r--r--test/unit/webfinger/user_presenter_test.rb49
12 files changed, 593 insertions, 0 deletions
diff --git a/test/unit/account_test.rb b/test/unit/account_test.rb
new file mode 100644
index 0000000..b2bfe27
--- /dev/null
+++ b/test/unit/account_test.rb
@@ -0,0 +1,47 @@
+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?, "unexpected errors: #{user.errors.inspect}"
+ assert user.persisted?
+ assert id = user.identity
+ assert_equal user.email_address, id.address
+ assert_equal user.email_address, id.destination
+ user.account.destroy
+ end
+
+ test "create and remove a user account" 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
+ end
+ end
+ end
+
+ test "change username and create alias" do
+ user = Account.create(FactoryGirl.attributes_for(:user))
+ old_id = user.identity
+ old_email = user.email_address
+ user.account.update(FactoryGirl.attributes_for(:user))
+ user.reload
+ old_id.reload
+ assert user.valid?
+ assert user.persisted?
+ assert id = user.identity
+ assert id.persisted?
+ assert_equal user.email_address, id.address
+ assert_equal user.email_address, id.destination
+ assert_equal user.email_address, old_id.destination
+ assert_equal old_email, old_id.address
+ user.account.destroy
+ end
+
+end
diff --git a/test/unit/anonymous_user_test.rb b/test/unit/anonymous_user_test.rb
new file mode 100644
index 0000000..6e94d39
--- /dev/null
+++ b/test/unit/anonymous_user_test.rb
@@ -0,0 +1,23 @@
+require 'test_helper'
+
+class AnonymousUserTest < ActiveSupport::TestCase
+
+ setup do
+ @anonymous = AnonymousUser.new
+ end
+
+ test "has nil values" do
+ assert_nil @anonymous.id
+ assert_nil @anonymous.email_address
+ assert_nil @anonymous.login
+ end
+
+ test "has no messages" do
+ assert_equal [], @anonymous.messages
+ end
+
+ test "has anonymous service level" do
+ assert @anonymous.effective_service_level.is_a? AnonymousServiceLevel
+ end
+
+end
diff --git a/test/unit/client_certificate_test.rb b/test/unit/client_certificate_test.rb
new file mode 100644
index 0000000..036e724
--- /dev/null
+++ b/test/unit/client_certificate_test.rb
@@ -0,0 +1,24 @@
+require 'test_helper'
+
+class ClientCertificateTest < ActiveSupport::TestCase
+
+ test "new cert has all we need" do
+ sample = ClientCertificate.new
+ assert sample.key
+ assert sample.cert
+ assert sample.to_s
+ end
+
+ test "cert has configured prefix" do
+ prefix = "PREFIX"
+ sample = ClientCertificate.new(:prefix => prefix)
+ assert sample.cert.subject.common_name.starts_with?(prefix)
+ end
+
+ test "cert issuer matches ca subject" do
+ sample = ClientCertificate.new
+ cert = OpenSSL::X509::Certificate.new(sample.cert.to_pem)
+ assert_equal ClientCertificate.root_ca.openssl_body.subject, cert.issuer
+ end
+
+end
diff --git a/test/unit/helpers/session_helper_test.rb b/test/unit/helpers/session_helper_test.rb
new file mode 100644
index 0000000..2824733
--- /dev/null
+++ b/test/unit/helpers/session_helper_test.rb
@@ -0,0 +1,4 @@
+require 'test_helper'
+
+class SessionHelperTest < ActionView::TestCase
+end
diff --git a/test/unit/helpers/users_helper_test.rb b/test/unit/helpers/users_helper_test.rb
new file mode 100644
index 0000000..96af37a
--- /dev/null
+++ b/test/unit/helpers/users_helper_test.rb
@@ -0,0 +1,4 @@
+require 'test_helper'
+
+class UsersHelperTest < ActionView::TestCase
+end
diff --git a/test/unit/identity_test.rb b/test/unit/identity_test.rb
new file mode 100644
index 0000000..eca104f
--- /dev/null
+++ b/test/unit/identity_test.rb
@@ -0,0 +1,133 @@
+require 'test_helper'
+
+class IdentityTest < ActiveSupport::TestCase
+ include StubRecordHelper
+
+ setup do
+ @user = find_record :user
+ end
+
+ test "initial identity for a user" do
+ id = Identity.for(@user)
+ assert_equal @user.email_address, id.address
+ assert_equal @user.email_address, id.destination
+ assert_equal @user, id.user
+ end
+
+ test "add alias" do
+ id = Identity.for @user, address: alias_name
+ assert_equal LocalEmail.new(alias_name), id.address
+ assert_equal @user.email_address, id.destination
+ assert_equal @user, id.user
+ end
+
+ test "add forward" do
+ id = Identity.for @user, destination: forward_address
+ assert_equal @user.email_address, id.address
+ assert_equal Email.new(forward_address), id.destination
+ assert_equal @user, id.user
+ end
+
+ test "forward alias" do
+ id = Identity.for @user, address: alias_name, destination: forward_address
+ assert_equal LocalEmail.new(alias_name), id.address
+ assert_equal Email.new(forward_address), id.destination
+ assert_equal @user, id.user
+ end
+
+ test "prevents duplicates" do
+ id = Identity.create_for @user, address: alias_name, destination: forward_address
+ dup = Identity.build_for @user, address: alias_name, destination: forward_address
+ assert !dup.valid?
+ assert_equal ["This alias already exists"], dup.errors[:base]
+ id.destroy
+ end
+
+ test "validates availability" do
+ other_user = find_record :user
+ id = Identity.create_for @user, address: alias_name, destination: forward_address
+ taken = Identity.build_for other_user, address: alias_name
+ assert !taken.valid?
+ assert_equal ["This email has already been taken"], taken.errors[:base]
+ id.destroy
+ end
+
+ test "setting and getting pgp key" do
+ id = Identity.for(@user)
+ id.set_key(:pgp, pgp_key_string)
+ assert_equal pgp_key_string, id.keys[:pgp]
+ end
+
+ test "querying pgp key via couch" do
+ id = Identity.for(@user)
+ id.set_key(:pgp, pgp_key_string)
+ id.save
+ view = Identity.pgp_key_by_email.key(id.address)
+ assert_equal 1, view.rows.count
+ assert result = view.rows.first
+ assert_equal id.address, result["key"]
+ assert_equal id.keys[:pgp], result["value"]
+ id.destroy
+ end
+
+ test "fail to add non-local email address as identity address" do
+ id = Identity.for @user, address: forward_address
+ assert !id.valid?
+ assert_match /needs to end in/, id.errors[:address].first
+ end
+
+ test "alias must meet same conditions as login" do
+ id = Identity.create_for @user, address: alias_name.capitalize
+ assert !id.valid?
+ #hacky way to do this, but okay for now:
+ assert id.errors.messages.flatten(2).include? "Must begin with a lowercase letter"
+ assert id.errors.messages.flatten(2).include? "Only lowercase letters, digits, . - and _ allowed."
+ end
+
+ test "destination must be valid email address" do
+ id = Identity.create_for @user, address: @user.email_address, destination: 'ASKJDLFJD'
+ assert !id.valid?
+ 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?
+ 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.disabled.count
+ end
+
+ def alias_name
+ @alias_name ||= Faker::Internet.user_name
+ end
+
+ def forward_address
+ @forward_address ||= Faker::Internet.email
+ end
+
+ def pgp_key_string
+ @pgp_key ||= "DUMMY PGP KEY ... "+SecureRandom.base64(4096)
+ end
+end
diff --git a/test/unit/local_email_test.rb b/test/unit/local_email_test.rb
new file mode 100644
index 0000000..20ee7f1
--- /dev/null
+++ b/test/unit/local_email_test.rb
@@ -0,0 +1,65 @@
+require 'test_helper'
+
+class LocalEmailTest < ActiveSupport::TestCase
+
+ test "appends domain" do
+ local = LocalEmail.new(handle)
+ assert_equal LocalEmail.new(email), local
+ assert local.valid?
+ end
+
+ test "returns handle" do
+ local = LocalEmail.new(email)
+ assert_equal handle, local.handle
+ end
+
+ test "prints full email" do
+ local = LocalEmail.new(handle)
+ assert_equal email, "#{local}"
+ end
+
+ test "validates domain" do
+ local = LocalEmail.new(Faker::Internet.email)
+ assert !local.valid?
+ 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
+
+ def email
+ handle + "@" + APP_CONFIG[:domain]
+ end
+end
diff --git a/test/unit/token_test.rb b/test/unit/token_test.rb
new file mode 100644
index 0000000..a3c6cf6
--- /dev/null
+++ b/test/unit/token_test.rb
@@ -0,0 +1,89 @@
+require 'test_helper'
+
+class ClientCertificateTest < ActiveSupport::TestCase
+ include StubRecordHelper
+
+ setup do
+ @user = find_record :user
+ end
+
+ test "new token for user" do
+ sample = Token.new(:user_id => @user.id)
+ assert sample.valid?
+ assert_equal @user.id, sample.user_id
+ assert_equal @user, sample.authenticate
+ end
+
+ test "token id is secure" do
+ sample = Token.new(:user_id => @user.id)
+ other = Token.new(:user_id => @user.id)
+ assert sample.id,
+ "id is set on initialization"
+ assert sample.id[0..10] != other.id[0..10],
+ "token id prefixes should not repeat"
+ assert /[g-zG-Z]/.match(sample.id),
+ "should use non hex chars in the token id"
+ assert sample.id.size > 16,
+ "token id should be more than 16 chars long"
+ end
+
+ test "token checks for user" do
+ sample = Token.new
+ assert !sample.valid?, "Token should require a user record"
+ end
+
+ test "token updates timestamps" do
+ sample = Token.new(user_id: @user.id)
+ sample.last_seen_at = 1.minute.ago
+ sample.expects(:save)
+ assert_equal @user, sample.authenticate
+ assert Time.now - sample.last_seen_at < 1.minute, "last_seen_at has not been updated"
+ end
+
+ test "token will not expire if token_expires_after is not set" do
+ sample = Token.new(user_id: @user.id)
+ sample.last_seen_at = 2.years.ago
+ with_config auth: {} do
+ sample.expects(:save)
+ assert_equal @user, sample.authenticate
+ end
+ end
+
+ test "expired token returns nil on authenticate" do
+ sample = Token.new(user_id: @user.id)
+ sample.last_seen_at = 2.hours.ago
+ with_config auth: {token_expires_after: 60} do
+ sample.expects(:destroy)
+ assert_nil sample.authenticate
+ 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 = 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
+ assert_nil Token.find(expired.id)
+ assert_equal fresh, Token.find(fresh.id)
+ fresh.destroy
+ end
+
+
+ test "Token.destroy_all_expired does not interfere with expired.authenticate" do
+ expired = FactoryGirl.create :token, last_seen_at: 2.hours.ago
+ with_config auth: {token_expires_after: 60} do
+ Token.destroy_all_expired
+ end
+ assert_nil expired.authenticate
+ end
+
+end
diff --git a/test/unit/user_test.rb b/test/unit/user_test.rb
new file mode 100644
index 0000000..ffbb7d8
--- /dev/null
+++ b/test/unit/user_test.rb
@@ -0,0 +1,68 @@
+require 'test_helper'
+
+class UserTest < ActiveSupport::TestCase
+
+ include SRP::Util
+ setup do
+ @user = FactoryGirl.build(:user)
+ end
+
+ test "design docs in database are authorative" do
+ assert !User.design_doc.auto_update,
+ "Automatic update of design docs should be disabled"
+ end
+
+ test "test set of attributes should be valid" do
+ @user.valid?
+ assert_equal Hash.new, @user.errors.messages
+ end
+
+ test "test require hex for password_verifier" do
+ @user.password_verifier = "QWER"
+ assert !@user.valid?
+ end
+
+ test "test require alphanumerical for login" do
+ @user.login = "qw#r"
+ assert !@user.valid?
+ end
+
+ test "verifier returns number for the hex in password_verifier" do
+ assert_equal @user.password_verifier.hex, @user.verifier
+ end
+
+ test "salt returns number for the hex in password_salt" do
+ assert_equal @user.password_salt.hex, @user.salt
+ end
+
+ test 'normal user is no admin' do
+ assert !@user.is_admin?
+ end
+
+ test 'user with login in APP_CONFIG is an admin' do
+ admin_login = APP_CONFIG['admins'].first
+ @user.login = admin_login
+ assert @user.is_admin?
+ end
+
+ test "login needs to be unique" do
+ other_user = FactoryGirl.create :user, login: @user.login
+ assert !@user.valid?
+ other_user.destroy
+ end
+
+ test "login needs to be unique amongst aliases" do
+ other_user = FactoryGirl.create :user
+ id = Identity.create_for other_user, address: @user.login
+ assert !@user.valid?
+ id.destroy
+ other_user.destroy
+ end
+
+ test "deprecated public key api still works" do
+ key = SecureRandom.base64(4096)
+ @user.public_key = key
+ assert_equal key, @user.public_key
+ end
+
+end
diff --git a/test/unit/warden_strategy_secure_remote_password_test.rb b/test/unit/warden_strategy_secure_remote_password_test.rb
new file mode 100644
index 0000000..e6fcfbe
--- /dev/null
+++ b/test/unit/warden_strategy_secure_remote_password_test.rb
@@ -0,0 +1,63 @@
+class WardenStrategySecureRemotePasswordTest < ActiveSupport::TestCase
+
+# TODO : turn this into sth. real
+=begin
+ setup do
+ @user = stub :login => "me", :id => 123
+ @client_hex = 'a123'
+ @client_rnd = @client_hex.hex
+ @server_hex = 'b123'
+ @server_rnd = @server_hex.hex
+ @server_rnd_exp = 'e123'.hex
+ @salt = 'stub user salt'
+ @server_handshake = stub :aa => @client_rnd, :bb => @server_rnd, :b => @server_rnd_exp
+ @server_auth = 'adfe'
+ end
+
+
+ test "should perform handshake" do
+ @user.expects(:initialize_auth).
+ with(@client_rnd).
+ returns(@server_handshake)
+ @server_handshake.expects(:to_json).
+ returns({'B' => @server_hex, 'salt' => @salt}.to_json)
+ User.expects(:find).with(@user.login).returns(@user)
+ assert_equal @server_handshake, session[:handshake]
+ assert_response :success
+ assert_json_response :B => @server_hex, :salt => @salt
+ end
+
+ test "should report user not found" do
+ unknown = "login_that_does_not_exist"
+ User.expects(:find).with(unknown).raises(RECORD_NOT_FOUND)
+ post :create, :login => unknown
+ assert_response :success
+ assert_json_error "login" => ["unknown user"]
+ end
+
+ test "should authorize" do
+ session[:handshake] = @server_handshake
+ @server_handshake.expects(:authenticate!).
+ with(@client_rnd).
+ returns(@user)
+ @server_handshake.expects(:to_json).
+ returns({:M2 => @server_auth}.to_json)
+ post :update, :id => @user.login, :client_auth => @client_hex
+ assert_nil session[:handshake]
+ assert_json_response :M2 => @server_auth
+ assert_equal @user.id, session[:user_id]
+ end
+
+ test "should report wrong password" do
+ session[:handshake] = @server_handshake
+ @server_handshake.expects(:authenticate!).
+ with(@client_rnd).
+ raises(WRONG_PASSWORD)
+ post :update, :id => @user.login, :client_auth => @client_hex
+ assert_nil session[:handshake]
+ assert_nil session[:user_id]
+ assert_json_error "password" => ["wrong password"]
+ end
+
+=end
+end
diff --git a/test/unit/webfinger/host_meta_presenter_test.rb b/test/unit/webfinger/host_meta_presenter_test.rb
new file mode 100644
index 0000000..af86404
--- /dev/null
+++ b/test/unit/webfinger/host_meta_presenter_test.rb
@@ -0,0 +1,24 @@
+require 'test_helper'
+require 'webfinger'
+require 'json'
+
+class Webfinger::HostMetaPresenterTest < ActiveSupport::TestCase
+
+ setup do
+ @request = stub(
+ url: "https://#{APP_CONFIG[:domain]}/.well-known/host-meta"
+ )
+ @meta = Webfinger::HostMetaPresenter.new(@request)
+ end
+
+ test "creates proper json" do
+ hash = JSON.parse @meta.to_json
+ assert_equal ["subject", "links"].sort, hash.keys.sort
+ hash.each do |key, value|
+ assert_equal @meta.send(key.to_sym).to_json, value.to_json
+ end
+ end
+
+end
+
+
diff --git a/test/unit/webfinger/user_presenter_test.rb b/test/unit/webfinger/user_presenter_test.rb
new file mode 100644
index 0000000..04aeb22
--- /dev/null
+++ b/test/unit/webfinger/user_presenter_test.rb
@@ -0,0 +1,49 @@
+require 'test_helper'
+require 'webfinger'
+require 'json'
+
+class Webfinger::UserPresenterTest < ActiveSupport::TestCase
+
+
+ setup do
+ @user = stub(
+ username: 'testuser',
+ email_address: "testuser@#{APP_CONFIG[:domain]}"
+ )
+ @request = stub(
+ host: APP_CONFIG[:domain]
+ )
+ end
+
+ test "user without key has no links" do
+ @user.stubs :public_key => nil
+ presenter = Webfinger::UserPresenter.new(@user, @request)
+ assert_equal Hash.new, presenter.links
+ end
+
+ test "user with key has corresponding link" do
+ @user.stubs :public_key => "here's a key"
+ presenter = Webfinger::UserPresenter.new(@user, @request)
+ assert_equal [:public_key], presenter.links.keys
+ assert_equal "PGP", presenter.links[:public_key][:type]
+ assert_equal presenter.send(:key), presenter.links[:public_key][:href]
+ end
+
+ test "key is base64 encoded" do
+ @user.stubs :public_key => "here's a key"
+ presenter = Webfinger::UserPresenter.new(@user, @request)
+ assert_equal Base64.encode64(@user.public_key), presenter.send(:key)
+ end
+
+ test "creates proper json representation" do
+ @user.stubs :public_key => "here's a key"
+ presenter = Webfinger::UserPresenter.new(@user, @request)
+ hash = JSON.parse presenter.to_json
+ assert_equal ["subject", "links"].sort, hash.keys.sort
+ hash.each do |key, value|
+ assert_equal presenter.send(key.to_sym).to_json, value.to_json
+ end
+ end
+
+
+end