summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Gemfile.lock4
-rw-r--r--core/leap_web_core.gemspec2
-rw-r--r--core/lib/extensions/couchrest.rb35
-rw-r--r--core/lib/tasks/leap_web_core_tasks.rake29
-rw-r--r--lib/leap_web/version.rb2
-rw-r--r--users/app/controllers/keys_controller.rb12
-rw-r--r--users/app/models/account.rb11
-rw-r--r--users/app/models/identity.rb6
-rw-r--r--users/app/models/pgp_key.rb48
-rw-r--r--users/config/routes.rb2
-rw-r--r--users/test/factories.rb8
-rw-r--r--users/test/functional/keys_controller_test.rb32
-rw-r--r--users/test/integration/api/account_flow_test.rb34
-rw-r--r--users/test/integration/browser/account_test.rb4
14 files changed, 194 insertions, 35 deletions
diff --git a/Gemfile.lock b/Gemfile.lock
index e6096fd..8d80546 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -25,7 +25,7 @@ PATH
leap_web_core (0.2.5)
couchrest (~> 1.1.3)
couchrest_model (~> 2.0.0)
- couchrest_session_store (~> 0.2.0)
+ couchrest_session_store (~> 0.2.1)
json
rails (~> 3.2.11)
@@ -110,7 +110,7 @@ GEM
couchrest (~> 1.1.3)
mime-types (>= 1.15)
tzinfo (>= 0.3.22)
- couchrest_session_store (0.2.0)
+ couchrest_session_store (0.2.1)
actionpack
couchrest
couchrest_model
diff --git a/core/leap_web_core.gemspec b/core/leap_web_core.gemspec
index e98c892..c745f00 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.0"
+ s.add_dependency "couchrest_session_store", "~> 0.2.1"
s.add_dependency "json"
end
diff --git a/core/lib/extensions/couchrest.rb b/core/lib/extensions/couchrest.rb
index 91dfc1c..84cfbb3 100644
--- a/core/lib/extensions/couchrest.rb
+++ b/core/lib/extensions/couchrest.rb
@@ -47,28 +47,45 @@ module CouchRest
def self.load_all_models_with_engines
self.load_all_models_without_engines
return unless defined?(Rails)
- Dir[Rails.root + 'app/models/**/*.rb'].each do |path|
- require path
- end
Dir[Rails.root + '*/app/models/**/*.rb'].each do |path|
require path
end
end
- def self.all_models_and_proxies
- callbacks = migrate_each_model(find_models)
- callbacks += migrate_each_proxying_model(find_proxying_models)
- cleanup(callbacks)
+ class << self
+ alias_method_chain :load_all_models, :engines
+ end
+
+ def dump_all_models
+ prepare_directory
+ find_models.each do |model|
+ model.design_docs.each do |design|
+ dump_design(model, design)
+ end
+ end
end
+ protected
+ def dump_design(model, design)
+ dir = prepare_directory model.name.tableize
+ filename = design.id.sub('_design/','') + '.json'
+ puts dir + filename
+ design.checksum
+ File.open(dir + filename, "w") do |file|
+ file.write(JSON.pretty_generate(design.to_hash))
+ end
+ end
- class << self
- alias_method_chain :load_all_models, :engines
+ def prepare_directory(dir = '')
+ dir = Rails.root + 'tmp' + 'designs' + dir
+ Dir.mkdir(dir) unless Dir.exists?(dir)
+ return dir
end
end
end
+
end
class ModelRailtie
diff --git a/core/lib/tasks/leap_web_core_tasks.rake b/core/lib/tasks/leap_web_core_tasks.rake
index ae5b79b..ec6abac 100644
--- a/core/lib/tasks/leap_web_core_tasks.rake
+++ b/core/lib/tasks/leap_web_core_tasks.rake
@@ -1,4 +1,25 @@
-# desc "Explaining what the task does"
-# task :leap_web_core do
-# # Task goes here
-# end
+namespace :couchrest do
+
+ desc "Dump all the design docs found in each model"
+ task :dump => :environment do
+ CouchRest::Model::Utils::Migrate.load_all_models
+ CouchRest::Model::Utils::Migrate.dump_all_models
+ end
+end
+
+namespace :cleanup do
+
+ desc "Cleanup all expired session documents"
+ task :sessions => :environment do
+ # make sure this is the same as in
+ # config/initializers/session_store.rb
+ store = CouchRest::Session::Store.new expire_after: 1800
+ store.cleanup(store.expired)
+ end
+
+ desc "Cleanup all expired tokens"
+ task :tokens => :environment do
+ Token.destroy_all_expired
+ end
+end
+
diff --git a/lib/leap_web/version.rb b/lib/leap_web/version.rb
index 009ee29..f6f99ae 100644
--- a/lib/leap_web/version.rb
+++ b/lib/leap_web/version.rb
@@ -1,3 +1,3 @@
module LeapWeb
- VERSION = "0.2.5" unless defined?(LeapWeb::VERSION)
+ VERSION = "0.2.8.rc" unless defined?(LeapWeb::VERSION)
end
diff --git a/users/app/controllers/keys_controller.rb b/users/app/controllers/keys_controller.rb
new file mode 100644
index 0000000..949f2c0
--- /dev/null
+++ b/users/app/controllers/keys_controller.rb
@@ -0,0 +1,12 @@
+class KeysController < ApplicationController
+
+ def show
+ user = User.find_by_login(params[:login])
+ # layout won't be included if we render text
+ # 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
+ user ? (render text: user.public_key) : (raise ActionController::RoutingError.new('Not Found'))
+
+ end
+
+end
diff --git a/users/app/models/account.rb b/users/app/models/account.rb
index 5c943bb..cf998e4 100644
--- a/users/app/models/account.rb
+++ b/users/app/models/account.rb
@@ -27,7 +27,8 @@ class Account
@user.update_attributes attrs.slice(:password_verifier, :password_salt)
end
# TODO: move into identity controller
- update_pgp_key(attrs[:public_key]) if attrs.has_key? :public_key
+ key = update_pgp_key(attrs[:public_key])
+ @user.errors.set :public_key, key.errors.full_messages
@user.save && save_identities
@user.refresh_identity
end
@@ -49,8 +50,12 @@ class Account
end
def update_pgp_key(key)
- @new_identity ||= Identity.for(@user)
- @new_identity.set_key(:pgp, key)
+ PgpKey.new(key).tap do |key|
+ if key.present? && key.valid?
+ @new_identity ||= Identity.for(@user)
+ @new_identity.set_key(:pgp, key)
+ end
+ end
end
def save_identities
diff --git a/users/app/models/identity.rb b/users/app/models/identity.rb
index 97966d0..cbb540e 100644
--- a/users/app/models/identity.rb
+++ b/users/app/models/identity.rb
@@ -94,9 +94,9 @@ class Identity < CouchRest::Model::Base
read_attribute('keys') || HashWithIndifferentAccess.new
end
- def set_key(type, value)
- return if keys[type] == value
- write_attribute('keys', keys.merge(type => value))
+ def set_key(type, key)
+ return if keys[type] == key.to_s
+ write_attribute('keys', keys.merge(type => key.to_s))
end
# for LoginFormatValidation
diff --git a/users/app/models/pgp_key.rb b/users/app/models/pgp_key.rb
new file mode 100644
index 0000000..66f8660
--- /dev/null
+++ b/users/app/models/pgp_key.rb
@@ -0,0 +1,48 @@
+class PgpKey
+ include ActiveModel::Validations
+
+ KEYBLOCK_IDENTIFIERS = [
+ '-----BEGIN PGP PUBLIC KEY BLOCK-----',
+ '-----END PGP PUBLIC KEY BLOCK-----',
+ ]
+
+ # mostly for testing.
+ attr_accessor :keyblock
+
+ validate :validate_keyblock_format
+
+ def initialize(keyblock = nil)
+ @keyblock = keyblock
+ end
+
+ def to_s
+ @keyblock
+ end
+
+ def present?
+ @keyblock.present?
+ end
+
+ # allow comparison with plain keyblock strings.
+ def ==(other)
+ self.equal?(other) or
+ # relax the comparison on line ends.
+ self.to_s.tr_s("\n\r", '') == other.tr_s("\r\n", '')
+ end
+
+ protected
+
+ def validate_keyblock_format
+ if keyblock_identifier_missing?
+ errors.add :public_key_block,
+ "does not look like an armored pgp public key block"
+ end
+ end
+
+ def keyblock_identifier_missing?
+ KEYBLOCK_IDENTIFIERS.find do |identify|
+ !@keyblock.include?(identify)
+ end
+ end
+
+end
diff --git a/users/config/routes.rb b/users/config/routes.rb
index ccecfd5..69f9cf7 100644
--- a/users/config/routes.rb
+++ b/users/config/routes.rb
@@ -22,4 +22,6 @@ Rails.application.routes.draw do
get "/.well-known/host-meta" => 'webfinger#host_meta'
get "/webfinger" => 'webfinger#search'
+ get "/key/:login" => 'keys#show'
+
end
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/functional/keys_controller_test.rb b/users/test/functional/keys_controller_test.rb
new file mode 100644
index 0000000..b69cbc0
--- /dev/null
+++ b/users/test/functional/keys_controller_test.rb
@@ -0,0 +1,32 @@
+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
+ # 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
+ 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
+ # 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
diff --git a/users/test/integration/api/account_flow_test.rb b/users/test/integration/api/account_flow_test.rb
index e41befa..edd0859 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 "prevent changing login without changing password_verifier" 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 overwrite public key:
- put "http://api.lvh.me:3000/1/users/" + @user.id + '.json', :user => {:public_key => nil}, :format => :json
+ 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 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