From e0be49a97dc0cfb55a4e2b9502aeb04750a86816 Mon Sep 17 00:00:00 2001 From: elijah Date: Tue, 17 Jun 2014 01:51:03 -0700 Subject: support for optional gems in Gemfile (engines/ and config/customization/gems/) --- Gemfile | 36 +++++++++++++++++++---- config/defaults.yml | 5 +++- lib/gemfile_tools.rb | 83 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 118 insertions(+), 6 deletions(-) create mode 100644 lib/gemfile_tools.rb diff --git a/Gemfile b/Gemfile index ae11e0e..79e6e45 100644 --- a/Gemfile +++ b/Gemfile @@ -1,5 +1,7 @@ source 'https://rubygems.org' +require File.expand_path('../lib/gemfile_tools.rb', __FILE__) + gem "rails", "~> 3.2.18" gem "couchrest", "~> 1.1.3" gem "couchrest_model", "~> 2.0.0" @@ -10,9 +12,6 @@ gem "json" gem "ruby-srp", "~> 0.2.1" gem "rails_warden" -gem 'leap_web_help', :path => 'engines/support' -gem 'leap_web_billing', :path => 'engines/billing' - gem 'http_accept_language' # To use debugger @@ -45,7 +44,7 @@ group :test do gem 'poltergeist' # headless js gem 'launchy' # save_and_open_page gem 'phantomjs-binaries' # binaries specific to the os - + # moching and stubbing gem 'mocha', '~> 0.13.0', :require => false gem 'minitest-stub-const' # why? @@ -53,7 +52,7 @@ group :test do # generating test data gem 'factory_girl_rails' # test data factories gem 'faker' # names and numbers for test data - + # billing tests gem 'fake_braintree', require: false end @@ -81,3 +80,30 @@ end # unreleased so far ... but leap_web_certs need it gem 'certificate_authority', :git => 'https://github.com/cchandler/certificate_authority.git' + +# +# include optional gems and engines +# + +group :test do + enabled_engines('test').each do |gem_name, gem_dir| + gem gem_name, :path => gem_dir + end +end + +group :development do + enabled_engines('development').each do |gem_name, gem_dir| + gem gem_name, :path => gem_dir + end +end + +group :production do + enabled_engines('production').each do |gem_name, gem_dir| + gem gem_name, :path => gem_dir + end +end + +custom_gems.each do |gem_name, gem_dir| + gem gem_name, :path => gem_dir +end + diff --git a/config/defaults.yml b/config/defaults.yml index 1c7e694..0614d1e 100644 --- a/config/defaults.yml +++ b/config/defaults.yml @@ -34,7 +34,7 @@ common: &common token_expires_after: 60 # handles that will be blocked from being used as logins or email aliases # in addition to the ones in /etc/passwd and http://tools.ietf.org/html/rfc2142 - handle_blacklist: [certmaster, ssladmin, arin-admin, administrator, www-data, maildrop] + handle_blacklist: ['certmaster', 'ssladmin', 'arin-admin', 'administrator', 'www-data', 'maildrop', 'postmaster', 'admin', 'contact', 'info'] # handles that will be allowed despite being in /etc/passwd or rfc2142 handle_whitelist: [] # actions enabled in the account settings @@ -46,6 +46,9 @@ common: &common available_locales: - :en minimum_client_version: "0.5" + engines: + - support + - billing service_levels: &service_levels service_levels: diff --git a/lib/gemfile_tools.rb b/lib/gemfile_tools.rb new file mode 100644 index 0000000..2cdc42e --- /dev/null +++ b/lib/gemfile_tools.rb @@ -0,0 +1,83 @@ +# +# Utilities for use in Gemfile, in order to support +# enabling and disabling gems, and including custom gems +# in the deployment. +# +# Dynamic code in Gemfile is incompatible with +# `bundle install --deployment` because dynamic code might +# produce new Gemfile.lock. For this reason, this app must +# be deployed with `bundle install --path vendor/bundle` instead. +# + +require 'yaml' + +# +# custom gems are gems placed in config/customization/gems. +# this are added at deploy time by the platform. +# The Gemfile.lock is then rebuilt to take these into account. +# +def custom_gems + custom_gem_dir = File.expand_path('../../config/customization/gems', __FILE__) + Dir["#{custom_gem_dir}/*"].collect{|gem_dir| + resolve_gem_directory(gem_dir) + }.compact +end + +# +# returns an array of [engine_name, engine_path] from Rails.root/engines/* that are +# enabled. Uses the 'engines' key from config.yml to determine if engine is enabled +# +def enabled_engines(environment) + if local_config[environment] + if local_config[environment][:engines] + local_config[environment][:engines].collect {|engine_dir| + full_dir_path = File.join(File.expand_path("../../engines", __FILE__), engine_dir) + resolve_gem_directory(full_dir_path) + }.compact + else + [] + end + else + [] + end +end + +# +# local_config can be accessed as an indifferent hash of +# the merger of config/default.yml and config/config.yml +# +def local_config + @local_config ||= begin + # a quick and dirty indifferent hash (note: does not affect children): + empty_hash = {} + empty_hash.default_proc = proc{|h, k| h.key?(k.to_s) ? h[k.to_s] : nil} + ["defaults.yml", "config.yml"].inject(empty_hash.dup) {|config, file| + filepath = File.join(File.expand_path("../../config", __FILE__), file) + if File.exists?(filepath) + new_config = YAML.load_file(filepath) + ['development', 'test','production'].each do |env| + config[env] ||= empty_hash.dup + config[env].merge!(new_config[env]) + end + end + config + } + end +end + +# +# return [gem_name, relative_gem_path] for gem at the specific directory +# or nil if not actually a gem directory +# +def resolve_gem_directory(gem_dir) + if Dir.exists?(gem_dir) + gemspec = Dir["#{gem_dir}/*.gemspec"] + if gemspec.any? + gem_name = File.basename(gemspec.first).sub(/\.gemspec$/,'') + [gem_name, gem_dir] + end + else + puts "Warning: no gem at `#{gem_dir}`" + nil + end +end -- cgit v1.2.3 From 280a46b5c4958cb183427028a8e66059856d46aa Mon Sep 17 00:00:00 2001 From: elijah Date: Tue, 17 Jun 2014 01:57:15 -0700 Subject: if identity fails to be created, destroy the user. also, pass through identity errors to user and add identity class hook. --- app/models/account.rb | 15 ++++++++++++--- app/models/identity.rb | 1 + 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/app/models/account.rb b/app/models/account.rb index 32ed445..bee540e 100644 --- a/app/models/account.rb +++ b/app/models/account.rb @@ -18,9 +18,18 @@ class Account def self.create(attrs) @user = User.create(attrs) if @user.persisted? - identity = @user.identity - identity.user_id = @user.id - identity.save + @identity = @user.identity + @identity.user_id = @user.id + @identity.save + @identity.errors.each do |attr, msg| + @user.errors.add(attr, msg) + end + end + rescue StandardError => ex + @user.errors.add(:base, ex.to_s) + ensure + if @user.persisted? && (@identity.nil? || !@identity.persisted?) + @user.destroy end return @user end diff --git a/app/models/identity.rb b/app/models/identity.rb index 2f6241c..e7b5785 100644 --- a/app/models/identity.rb +++ b/app/models/identity.rb @@ -163,4 +163,5 @@ class Identity < CouchRest::Model::Base end end + ActiveSupport.run_load_hooks(:identity, self) end -- cgit v1.2.3 From 240fd8f1efe9e76540787a17a13dcaf345c7933e Mon Sep 17 00:00:00 2001 From: elijah Date: Tue, 17 Jun 2014 13:12:27 -0700 Subject: Gemfile: fix problem when config is missing environments --- lib/gemfile_tools.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/gemfile_tools.rb b/lib/gemfile_tools.rb index 2cdc42e..50798cb 100644 --- a/lib/gemfile_tools.rb +++ b/lib/gemfile_tools.rb @@ -57,7 +57,9 @@ def local_config new_config = YAML.load_file(filepath) ['development', 'test','production'].each do |env| config[env] ||= empty_hash.dup - config[env].merge!(new_config[env]) + if new_config[env] + config[env].merge!(new_config[env]) + end end end config -- cgit v1.2.3 From 03b56bc0d94558ad7ff8b82e17314511a40ed16a Mon Sep 17 00:00:00 2001 From: elijah Date: Mon, 23 Jun 2014 13:52:00 -0700 Subject: Account.create - do a User.new instead of User.create, so that we can report the errors on the object if not saved. --- app/models/account.rb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app/models/account.rb b/app/models/account.rb index bee540e..67fec58 100644 --- a/app/models/account.rb +++ b/app/models/account.rb @@ -16,7 +16,8 @@ class Account # Returns the user record so it can be used in views. def self.create(attrs) - @user = User.create(attrs) + @user = User.new(attrs) + @user.save if @user.persisted? @identity = @user.identity @identity.user_id = @user.id @@ -28,7 +29,7 @@ class Account rescue StandardError => ex @user.errors.add(:base, ex.to_s) ensure - if @user.persisted? && (@identity.nil? || !@identity.persisted?) + if @user && @user.persisted? && (@identity.nil? || !@identity.persisted?) @user.destroy end return @user -- cgit v1.2.3 From 7672b23d0459b61d6b55f0ad7dd30ae4f719c55b Mon Sep 17 00:00:00 2001 From: elijah Date: Mon, 23 Jun 2014 14:23:53 -0700 Subject: added debugging note to DEVELOP.md --- DEVELOP.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/DEVELOP.md b/DEVELOP.md index 0bc2031..64c8771 100644 --- a/DEVELOP.md +++ b/DEVELOP.md @@ -70,3 +70,18 @@ For example: login_as @user visit robot_path(@robot, :locale => nil) end + +## Debugging + +Sometimes bugs only show up when deployed to the live production server. Debugging can be tricky, +because the open source mod_passenger does not support debugger. You can't just run +`rails server` because HSTS records for your site will make most browsers require TLS. + +One solution is to temporarily modify the apache config to proxypass the TLS requests to rails: + + + ProxyPass / http://127.0.0.1:3000/ + ProxyPassReverse / http://127.0.0.1:3000/ + ProxyPreserveHost on + .... + \ No newline at end of file -- cgit v1.2.3 From 91c2ba1054b9daf25b922e5922d88bfe1098fd3d Mon Sep 17 00:00:00 2001 From: elijah Date: Wed, 25 Jun 2014 13:38:27 -0700 Subject: android app now supports signup, so change text that said otherwise. --- config/locales/home.en.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/locales/home.en.yml b/config/locales/home.en.yml index c3cdfb1..d1e74eb 100644 --- a/config/locales/home.en.yml +++ b/config/locales/home.en.yml @@ -4,5 +4,5 @@ en: download_bitmask: "Download Bitmask" login_info: "Log in to change your account settings, create support tickets, and manage payments." - signup_info: "Get a user account via this website. We recommend registering via the Bitmask application instead unless you are only using Bitmask for Android." + signup_info: "Create a new user account. For higher security, we recommend you create your account via the Bitmask application instead." support_info: "Can't login? Create a new support ticket anonymously." -- cgit v1.2.3 From 470bc1e35f22c1fe5813a1754e52b3fbc2bb951b Mon Sep 17 00:00:00 2001 From: Azul Date: Tue, 1 Jul 2014 09:21:25 +0200 Subject: Version 0.5.3 This release enables using custom gems in the leap platform customization. It also fixes cornercases during the account creation and documents debugging in production. * android app now supports signup, so change text that said otherwise. * added debugging note to DEVELOP.md * Account.create - do a User.new instead of User.create, so that we can report the errors on the object if not saved. Pull request #172 from elijh/feature/customgem * Gemfile: fix problem when config is missing environments * support for optional gems in Gemfile (engines/ and * config/customization/gems/) Pull request #171 from elijh/feature/identityfail * if identity fails to be created, destroy the user. also, pass through identity errors to user and add identity class hook. --- lib/leap_web/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/leap_web/version.rb b/lib/leap_web/version.rb index 56df918..9ff7c46 100644 --- a/lib/leap_web/version.rb +++ b/lib/leap_web/version.rb @@ -1,3 +1,3 @@ module LeapWeb - VERSION = "0.5.2" unless defined?(LeapWeb::VERSION) + VERSION = "0.5.3" unless defined?(LeapWeb::VERSION) end -- cgit v1.2.3