diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/extensions/couchrest.rb | 95 | ||||
-rw-r--r-- | lib/extensions/simple_form.rb | 28 | ||||
-rw-r--r-- | lib/leap_web.rb | 4 | ||||
-rw-r--r-- | lib/tasks/leap_web_core_tasks.rake | 25 | ||||
-rw-r--r-- | lib/tasks/leap_web_users_tasks.rake | 10 | ||||
-rw-r--r-- | lib/tasks/test.rake | 19 | ||||
-rw-r--r-- | lib/warden/session_serializer.rb | 13 | ||||
-rw-r--r-- | lib/warden/strategies/secure_remote_password.rb | 81 | ||||
-rw-r--r-- | lib/webfinger.rb | 6 | ||||
-rw-r--r-- | lib/webfinger/host_meta_presenter.rb | 30 | ||||
-rw-r--r-- | lib/webfinger/user_presenter.rb | 35 |
11 files changed, 329 insertions, 17 deletions
diff --git a/lib/extensions/couchrest.rb b/lib/extensions/couchrest.rb new file mode 100644 index 0000000..95f5d92 --- /dev/null +++ b/lib/extensions/couchrest.rb @@ -0,0 +1,95 @@ +module CouchRest + module Model + module Designs + + class View + + # so we can called Ticket.method.descending or Ticket.method.ascending + def ascending + self + end + end + + class DesignMapper + def load_views(dir) + Dir.glob("#{dir}/*.js") do |js| + name = File.basename(js, '.js') + file = File.open(js, 'r') + view name.to_sym, + :map => file.read, + :reduce => "function(key, values, rereduce) { return sum(values); }" + end + end + end + end + + module Connection + + module ClassMethods + + def use_database(db) + @database = prepare_database(db) + rescue RestClient::Exception, + Errno::EHOSTUNREACH, + Errno::ECONNREFUSED => e + message = "Could not connect to couch database #{db} due to #{e.to_s}" + Rails.logger.warn message + raise e.class.new(message) if APP_CONFIG[:reraise_errors] + end + end + + end + + module Utils + module Migrate + def self.load_all_models_with_engines + self.load_all_models_without_engines + return unless defined?(Rails) + Dir[Rails.root + 'engines/*/app/models/**/*.rb'].each do |path| + require path + end + end + + 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 + + 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 + config.action_dispatch.rescue_responses.merge!( + 'CouchRest::Model::DocumentNotFound' => :not_found, + 'RestClient::ResourceNotFound' => :not_found + ) + end +end diff --git a/lib/extensions/simple_form.rb b/lib/extensions/simple_form.rb new file mode 100644 index 0000000..f28e18f --- /dev/null +++ b/lib/extensions/simple_form.rb @@ -0,0 +1,28 @@ +module WrappedButton + def wrapped_button(*args, &block) + template.content_tag :div, :class => "form-actions" do + options = args.extract_options! + options[:class] = ['btn-primary', options[:class]].compact + args.unshift :loading + args << options + if cancel = options.delete(:cancel) + cancel_link = template.link_to I18n.t('simple_form.buttons.cancel'), + cancel, class: :btn + button(*args, &block) + ' ' + cancel_link + else + button(*args, &block) + end + end + end +end +SimpleForm::FormBuilder.send :include, WrappedButton + +module LoadingButton + def loading_button(*args, &block) + options = args.extract_options! + options[:"data-loading-text"] = I18n.t('simple_form.buttons.loading') + args << options + button_button(*args, &block) + end +end +SimpleForm::FormBuilder.send :include, LoadingButton diff --git a/lib/leap_web.rb b/lib/leap_web.rb deleted file mode 100644 index 9495fc6..0000000 --- a/lib/leap_web.rb +++ /dev/null @@ -1,4 +0,0 @@ -require 'leap_web_core' -require 'leap_web_certs' -require 'leap_web_users' -# do we want billing and help here? diff --git a/lib/tasks/leap_web_core_tasks.rake b/lib/tasks/leap_web_core_tasks.rake new file mode 100644 index 0000000..ec6abac --- /dev/null +++ b/lib/tasks/leap_web_core_tasks.rake @@ -0,0 +1,25 @@ +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/tasks/leap_web_users_tasks.rake b/lib/tasks/leap_web_users_tasks.rake new file mode 100644 index 0000000..62bcbe9 --- /dev/null +++ b/lib/tasks/leap_web_users_tasks.rake @@ -0,0 +1,10 @@ +# desc "Explaining what the task does" +# task :leap_web_users do +# # Task goes here +# end + +# recommended that for our setup, we should have this triggered from a cron job in puppet rather than using whenever gem +desc "Send one month warning messages" +task :leap_web_users do + User.send_one_month_warnings +end diff --git a/lib/tasks/test.rake b/lib/tasks/test.rake index 3c87b45..d96b625 100644 --- a/lib/tasks/test.rake +++ b/lib/tasks/test.rake @@ -1,18 +1,11 @@ namespace :test do - Rails::SubTestTask.new(:units => "test:prepare") do |t| - t.libs << "test" - t.pattern = '*/test/unit/**/*_test.rb' - end - - Rails::SubTestTask.new(:functionals => "test:prepare") do |t| - t.libs << "test" - t.pattern = '*/test/functional/**/*_test.rb' - end - - Rails::SubTestTask.new(:integration => "test:prepare") do |t| - t.libs << "test" - t.pattern = '*/test/integration/**/*_test.rb' + [:units, :functionals, :integration].each do |type| + Rails::SubTestTask.new(type => "test:prepare") do |t| + t.libs << "test" + subdir = type.to_s.singularize + t.pattern = "engines/*/test/#{subdir}/**/*_test.rb" + end end end diff --git a/lib/warden/session_serializer.rb b/lib/warden/session_serializer.rb new file mode 100644 index 0000000..81d7076 --- /dev/null +++ b/lib/warden/session_serializer.rb @@ -0,0 +1,13 @@ +module Warden + # Setup Session Serialization + class SessionSerializer + def serialize(record) + [record.class.name, record.id] + end + + def deserialize(keys) + klass, id = keys + klass.constantize.find(id) + end + end +end diff --git a/lib/warden/strategies/secure_remote_password.rb b/lib/warden/strategies/secure_remote_password.rb new file mode 100644 index 0000000..2c334c6 --- /dev/null +++ b/lib/warden/strategies/secure_remote_password.rb @@ -0,0 +1,81 @@ +module Warden + module Strategies + class SecureRemotePassword < Warden::Strategies::Base + + def valid? + handshake? || authentication? + end + + def authenticate! + if authentication? + validate! + else # handshake + initialize! + end + end + + protected + + def handshake? + params['A'] && params['login'] + end + + def authentication? + params['client_auth'] && session[:handshake] + end + + def validate! + if client = validate + success!(User.find_by_login(client.username)) + else + Rails.logger.warn "Login attempt failed." + Rails.logger.debug debug_info + Rails.logger.debug "Received: #{params['client_auth']}" + session.delete(:handshake) + fail!(:base => "invalid_user_pass") + end + end + + def validate + session[:handshake].authenticate(params['client_auth']) + end + + def initialize! + if user = User.find_by_login(id) + client = SRP::Client.new user.username, + :verifier => user.verifier, + :salt => user.salt + session[:handshake] = SRP::Session.new(client, params['A']) + custom! json_response(session[:handshake]) + else + fail! :base => 'invalid_user_pass' + end + rescue SRP::InvalidEphemeral + fail!(:base => "invalid_ephemeral") + end + + def json_response(object) + [ 200, + {"Content-Type" => "application/json; charset=utf-8"}, + [object.to_json] + ] + end + + def id + params["id"] || params["login"] + end + + protected + + def debug_info + JSON.pretty_generate(session[:handshake].internal_state) + end + + end + end + Warden::Strategies.add :secure_remote_password, + Warden::Strategies::SecureRemotePassword + +end + + diff --git a/lib/webfinger.rb b/lib/webfinger.rb new file mode 100644 index 0000000..dd49b41 --- /dev/null +++ b/lib/webfinger.rb @@ -0,0 +1,6 @@ +module Webfinger + + autoload :HostMetaPresenter, 'webfinger/host_meta_presenter' + autoload :UserPresenter, 'webfinger/user_presenter' + +end diff --git a/lib/webfinger/host_meta_presenter.rb b/lib/webfinger/host_meta_presenter.rb new file mode 100644 index 0000000..84ab7a9 --- /dev/null +++ b/lib/webfinger/host_meta_presenter.rb @@ -0,0 +1,30 @@ +require 'uri' + +class Webfinger::HostMetaPresenter + def initialize(request) + @request = request + end + + def to_json(options = {}) + { + subject: subject, + links: links + }.to_json(options) + end + + def subject + url = URI.parse(@request.url) + url.path = '' + url.to_s + end + + def links + { lrdd: { type: 'application/xrd+xml', template: webfinger_template } } + end + + protected + + def webfinger_template(path = 'webfinger', query_param='q') + "#{subject}/#{path}?#{query_param}={uri}" + end +end diff --git a/lib/webfinger/user_presenter.rb b/lib/webfinger/user_presenter.rb new file mode 100644 index 0000000..329f477 --- /dev/null +++ b/lib/webfinger/user_presenter.rb @@ -0,0 +1,35 @@ +class Webfinger::UserPresenter + include Rails.application.routes.url_helpers + attr_accessor :user + + def initialize(user, request) + @user = user + @request = request + end + + def to_json(options = {}) + { + subject: subject, + links: links + }.to_json(options) + end + + def subject + "acct:#{@user.email_address}" + end + + def links + links = {} + links[:public_key] = { type: 'PGP', href: key } if key + return links + end + + protected + + def key + if @user.public_key.present? + Base64.encode64(@user.public_key.to_s) + end + end + +end |