eco_apps 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (35) hide show
  1. data/lib/eco_apps/acts_as_readonly.rb +73 -0
  2. data/lib/eco_apps/core_service.rb +48 -0
  3. data/lib/eco_apps/extensions/active_resource.rb +13 -0
  4. data/lib/eco_apps/files/app_config.yml +27 -0
  5. data/lib/eco_apps/utils/helpers.rb +46 -0
  6. data/lib/eco_apps/utils/idp_util.rb +16 -0
  7. data/lib/eco_apps.rb +44 -0
  8. data/lib/platform_config.yml +8 -0
  9. data/spec/spec.opts +4 -0
  10. data/spec/test_app/app/controllers/application_controller.rb +13 -0
  11. data/spec/test_app/app/helpers/application_helper.rb +3 -0
  12. data/spec/test_app/app/models/app.rb +8 -0
  13. data/spec/test_app/app/models/comment.rb +3 -0
  14. data/spec/test_app/app/models/comment_service.rb +3 -0
  15. data/spec/test_app/config/app_config.yml +28 -0
  16. data/spec/test_app/config/boot.rb +110 -0
  17. data/spec/test_app/config/database.yml +3 -0
  18. data/spec/test_app/config/environment.rb +12 -0
  19. data/spec/test_app/config/environments/development.rb +17 -0
  20. data/spec/test_app/config/environments/production.rb +28 -0
  21. data/spec/test_app/config/environments/test.rb +28 -0
  22. data/spec/test_app/config/initializers/backtrace_silencers.rb +7 -0
  23. data/spec/test_app/config/initializers/inflections.rb +10 -0
  24. data/spec/test_app/config/initializers/mime_types.rb +5 -0
  25. data/spec/test_app/config/initializers/new_rails_defaults.rb +21 -0
  26. data/spec/test_app/config/initializers/session_store.rb +15 -0
  27. data/spec/test_app/config/routes.rb +43 -0
  28. data/spec/test_app/db/test.sqlite3 +0 -0
  29. data/spec/test_app/log/test.log +1596 -0
  30. data/spec/test_app/spec/controllers/helpers_spec.rb +37 -0
  31. data/spec/test_app/spec/models/active_resource_spec.rb +12 -0
  32. data/spec/test_app/spec/models/acts_as_readonly_spec.rb +28 -0
  33. data/spec/test_app/spec/models/core_service_spec.rb +35 -0
  34. data/spec/test_app/spec/spec_helper.rb +60 -0
  35. metadata +105 -0
@@ -0,0 +1,73 @@
1
+ module Idapted
2
+ module ActsAsReadonly
3
+ def self.included(base)
4
+ base.extend(ClassMethods)
5
+ end
6
+
7
+ module ClassMethods
8
+ def acts_as_readonly(name, options = {})
9
+ cattr_accessor :app_name, :rails_origin_table_name
10
+ self.app_name = name
11
+
12
+ unless Rails.env == "test"
13
+ config = YAML.load(options[:database]||CoreService.app(name).database)
14
+ connection = (config[Rails.env] || config["production"] || config)
15
+ establish_connection connection #activate readonly connection
16
+
17
+ db_name = self.connection.current_database
18
+ prefix = table_name.include?(db_name) ? "" : db_name + "."
19
+ tbl = (options[:table_name]||table_name).to_s
20
+
21
+ self.rails_origin_table_name = tbl
22
+ set_table_name(prefix + tbl)
23
+ else
24
+ generate_table(self.table_name)
25
+ end
26
+
27
+ unless options[:readonly] == false or Rails.env == "test"
28
+ include Idapted::ActsAsReadonly::InstanceMethods
29
+ extend Idapted::ActsAsReadonly::SingletonMethods
30
+ end
31
+ end
32
+ alias_method :acts_as_remote, :acts_as_readonly
33
+
34
+ private
35
+ def generate_table(table_name)
36
+ begin
37
+ self.connection.drop_table(self.table_name) if self.connection.table_exists?(self.table_name)
38
+ self.connection.create_table(self.table_name, :force => true){|f|
39
+ if (config = APP_CONFIG["readonly_for_test"].try("[]", table_name)).present?
40
+ config.each{|key, value|
41
+ f.send(key, *(value.is_a?(Array) ? value.join(",") : value.gsub(" ","").split(",")))
42
+ }
43
+ end
44
+ f.timestamps
45
+ }
46
+ rescue Exception => e
47
+ puts "#{e.message} error occured in #{table_name}"
48
+ end
49
+ end
50
+ end
51
+
52
+ module SingletonMethods
53
+ def delete_all(conditions = nil)
54
+ raise ActiveRecord::ReadOnlyRecord
55
+ end
56
+
57
+ def table_exists?
58
+ connection.table_exists?(self.rails_origin_table_name)
59
+ end
60
+ end
61
+
62
+ module InstanceMethods
63
+ def readonly?
64
+ true
65
+ end
66
+
67
+ def destroy
68
+ raise ActiveRecord::ReadOnlyRecord
69
+ end
70
+ end
71
+ end
72
+ end
73
+
@@ -0,0 +1,48 @@
1
+ class CoreService < ActiveResource::Base
2
+ self.site = MASTER_APP_URL
3
+
4
+ class << self
5
+ def reset_config
6
+ options = {
7
+ :name => APP_CONFIG["name"],
8
+ :url => APP_CONFIG["url"],
9
+ :api => APP_CONFIG["api"],
10
+ :database => YAML.load_file(Rails.root.join("config/database.yml"))}
11
+
12
+ if in_master_app?
13
+ app = App.find_or_create_by_name(options[:name])
14
+ app.update_attributes(options)
15
+ else
16
+ begin
17
+ self.post(:reset_config, :app => options)
18
+ rescue ActiveResource::ForbiddenAccess
19
+ raise 'Access denied by master app! Please make sure ip address is contained by intranet_ip which is set in GEM_DIR/eco_apps/lib/platform_config.yml'
20
+ rescue Exception
21
+ raise "master_app_url '#{MASTER_APP_URL}' is unreachable! Please change it in GEM_DIR/eco_apps/lib/platform_config.yml or APP_ROOT/config/app_config.yml and make sure the master app starts at this address."
22
+ end
23
+ end
24
+ end
25
+
26
+ def app(app_name)
27
+ app_name = app_name.to_s
28
+ if in_master_app?
29
+ obj = App.find_by_name(app_name)
30
+ else
31
+ unless Rails.env == "production" or APP_CONFIG[Rails.env].blank? or
32
+ (local = APP_CONFIG[Rails.env][app_name]).blank?
33
+ return self.new(:name => local["name"], :url => local["url"],
34
+ :api => YAML.dump(local["api"]), :database => (local["database"].blank? ? nil : YAML.dump(local["database"])))
35
+ end
36
+ obj = CoreService.find(app_name)
37
+ end
38
+
39
+ return obj if (!obj.blank? and obj.attributes["error"].blank?)
40
+ raise("#{app_name} doesn't exist")
41
+ end
42
+
43
+ def in_master_app?
44
+ Object.const_defined?("IN_ECO_APPS_MASTER") and IN_ECO_APPS_MASTER
45
+ end
46
+ end
47
+
48
+ end
@@ -0,0 +1,13 @@
1
+ module ActiveResource
2
+ class Base
3
+ class << self
4
+ alias_method :set_site, :site=
5
+
6
+ def site=(site)
7
+ site = CoreService.app(site.to_s).url if site.is_a?(Symbol)
8
+ set_site(site)
9
+ end
10
+ end
11
+ end
12
+ end
13
+
@@ -0,0 +1,27 @@
1
+ # Configuration of app
2
+ name: # set app's name here
3
+ # url: url of app
4
+
5
+ # Specify api url
6
+ # api:
7
+ # url:
8
+ # dog_info: dogs/:id
9
+
10
+ # mock settings for other app (basically used in development environment)
11
+ # development:
12
+ # pet: #other app's name
13
+ # url: http://localhost:3001
14
+ # database:
15
+ # adapter: mysql
16
+ # encoding: utf8
17
+ # database: pet_development
18
+ # host: localhost
19
+ # user: root
20
+ # password:
21
+ # other app's settings
22
+
23
+ # columns needed for readonly models in test
24
+ # readonly_for_test:
25
+ # orders:
26
+ # integer: dog_id, user_id
27
+ # string: description
@@ -0,0 +1,46 @@
1
+ module Idapted
2
+ module Helpers
3
+ def self.included(base)
4
+ base.send(:include, InstanceMethods)
5
+ base.helper_method :url_of
6
+ base.extend SingletonMethods
7
+ end
8
+
9
+ module InstanceMethods
10
+
11
+ def url_of(app_name, url_key, options={})
12
+ app = CoreService.app(app_name.to_s)
13
+ app_url = YAML.load(app.url)
14
+ app_url = app_url[Rails.env] if app_url.is_a?(Hash)
15
+
16
+ api = YAML.load(app.api)
17
+ begin
18
+ url = api["url"][url_key.to_s] || ""
19
+ options.each{|k,v| url = url.gsub(":#{k}", v.to_s)}
20
+ params = options[:params]
21
+ params = params.map{|t| "#{t.first}=#{t.last}"}.join("&") if params.instance_of?(Hash)
22
+ [app_url.gsub(/\/$/,""), url.gsub(/^\//,"")].join("/") + (params.blank? ? "" : "?#{params}")
23
+ rescue Exception => e
24
+ raise "#{url_key} of #{app_name} seems not configured correctly in #{app_name}'s site_config.yml"
25
+ end
26
+ end
27
+
28
+ def authenticate_ip_address
29
+ INTRANET_IP.each do |ip|
30
+ return if ip.contains?(request.remote_ip)
31
+ end
32
+ respond_to do |format|
33
+ format.html{ render :text => "Access Denied!" }
34
+ format.xml{ render :xml => {:info => "Access Denied!"}.to_xml, :status => :forbidden}
35
+ end
36
+ end
37
+ end
38
+
39
+ module SingletonMethods
40
+ def ip_limited_access(options = {})
41
+ before_filter(:authenticate_ip_address, options) if Rails.env == "production"
42
+ end
43
+ end
44
+ end
45
+ end
46
+
@@ -0,0 +1,16 @@
1
+ module Idp
2
+ class Util
3
+ class << self
4
+ def copy(src, dest, force = true)
5
+ if not force and File.exist?(dest)
6
+ return false
7
+ else
8
+ FileUtils.mkdir_p(dest) unless File.exist?(dest)
9
+ FileUtils.remove_dir(dest, true)
10
+ FileUtils.cp_r(src, dest)
11
+ return true
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
data/lib/eco_apps.rb ADDED
@@ -0,0 +1,44 @@
1
+ require 'eco_apps/utils/idp_util'
2
+
3
+ def files(name)
4
+ File.join(File.dirname(__FILE__),"eco_apps/files", name)
5
+ end
6
+
7
+ if Object.const_defined?("Rails")
8
+
9
+ Idp::Util.copy(files("app_config.yml"), config_file = Rails.root.join("config/app_config.yml").to_s, false)
10
+
11
+ APP_CONFIG = YAML.load_file(File.join(File.dirname(__FILE__), "platform_config.yml")).merge(YAML.load_file(config_file))
12
+
13
+ if APP_CONFIG["name"].blank?
14
+ raise "Please set app's name in APP_ROOT/config/app_config.yml"
15
+ end
16
+
17
+ if (master_app_url = APP_CONFIG["master_app_url"]).blank?
18
+ raise 'Please set master_app_url in GEM_DIR/eco_apps/lib/platform_config.yml or APP_ROOT/config/app_config.yml'
19
+ end
20
+
21
+ MASTER_APP_URL = (master_app_url.is_a?(Hash) ? master_app_url[Rails.env] : master_app_url)
22
+ if not MASTER_APP_URL =~ Regexp.new("http://")
23
+ raise 'master_app_url must begin with http://'
24
+ end
25
+
26
+ if Rails.env == "production"
27
+ require 'netaddr'
28
+ raise "intranet_ip is not identified!" if (ips = APP_CONFIG["intranet_ip"]).blank?
29
+ INTRANET_IP = [ips].flatten.map{|ip|NetAddr::CIDR.create(ip)}
30
+ end
31
+
32
+ require 'eco_apps/core_service'
33
+ require 'eco_apps/acts_as_readonly'
34
+
35
+ require 'eco_apps/extensions/active_resource'
36
+
37
+ require 'eco_apps/utils/helpers'
38
+
39
+ ActionController::Base.send(:include, Idapted::Helpers)
40
+ ActiveRecord::Base.send(:include, Idapted::ActsAsReadonly)
41
+
42
+ CoreService.reset_config unless Rails.env == "test"
43
+
44
+ end
@@ -0,0 +1,8 @@
1
+ # Configuration of platform
2
+ master_app_url:
3
+ development: http://dev.lan
4
+ production: http://production.lan
5
+ test: http://test.lan
6
+ intranet_ip:
7
+ - 192.168.0.1/24
8
+ - 192.168.1.1/24
data/spec/spec.opts ADDED
@@ -0,0 +1,4 @@
1
+ --colour
2
+ --format progress
3
+ --loadby mtime
4
+ --reverse
@@ -0,0 +1,13 @@
1
+ # Filters added to this controller apply to all controllers in the application.
2
+ # Likewise, all the methods added will be available for all controllers.
3
+
4
+ class ApplicationController < ActionController::Base
5
+ helper :all # include all helpers, all the time
6
+ protect_from_forgery # See ActionController::RequestForgeryProtection for details
7
+
8
+ # Scrub sensitive parameters from your log
9
+ # filter_parameter_logging :password
10
+ def test
11
+ render :text => "test"
12
+ end
13
+ end
@@ -0,0 +1,3 @@
1
+ # Methods added to this helper will be available to all templates in the application.
2
+ module ApplicationHelper
3
+ end
@@ -0,0 +1,8 @@
1
+ class App < ActiveRecord::Base
2
+ unless self.table_exists?
3
+ self.connection.create_table :apps do |t|
4
+ t.string :name, :url
5
+ t.text :database, :api
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,3 @@
1
+ class Comment < ActiveRecord::Base
2
+ acts_as_readonly :article
3
+ end
@@ -0,0 +1,3 @@
1
+ class CommentService < ActiveResource::Base
2
+ self.site = :article
3
+ end
@@ -0,0 +1,28 @@
1
+ # Configuration of app
2
+ name: test_app
3
+ url: http://www.example.com/test_app
4
+ master_app_url: http://www.example.com/master
5
+
6
+ test:
7
+ article:
8
+ url: http://www.example.com/article
9
+ api:
10
+ url:
11
+ comment_list: comments/recent
12
+ development:
13
+ article:
14
+ url: http://www.example.com/article
15
+ api:
16
+ url:
17
+ comments: articles/:article_id/comments
18
+ database:
19
+ adapter: mysql
20
+ database: article_development
21
+ username: root
22
+ password: root
23
+ host: localhost
24
+
25
+ # columns needed for readonly models in test
26
+ readonly_for_test:
27
+ comments:
28
+ string: title
@@ -0,0 +1,110 @@
1
+ # Don't change this file!
2
+ # Configure your app in config/environment.rb and config/environments/*.rb
3
+
4
+ RAILS_ROOT = "#{File.dirname(__FILE__)}/.." unless defined?(RAILS_ROOT)
5
+
6
+ module Rails
7
+ class << self
8
+ def boot!
9
+ unless booted?
10
+ preinitialize
11
+ pick_boot.run
12
+ end
13
+ end
14
+
15
+ def booted?
16
+ defined? Rails::Initializer
17
+ end
18
+
19
+ def pick_boot
20
+ (vendor_rails? ? VendorBoot : GemBoot).new
21
+ end
22
+
23
+ def vendor_rails?
24
+ File.exist?("#{RAILS_ROOT}/vendor/rails")
25
+ end
26
+
27
+ def preinitialize
28
+ load(preinitializer_path) if File.exist?(preinitializer_path)
29
+ end
30
+
31
+ def preinitializer_path
32
+ "#{RAILS_ROOT}/config/preinitializer.rb"
33
+ end
34
+ end
35
+
36
+ class Boot
37
+ def run
38
+ load_initializer
39
+ Rails::Initializer.run(:set_load_path)
40
+ end
41
+ end
42
+
43
+ class VendorBoot < Boot
44
+ def load_initializer
45
+ require "#{RAILS_ROOT}/vendor/rails/railties/lib/initializer"
46
+ Rails::Initializer.run(:install_gem_spec_stubs)
47
+ Rails::GemDependency.add_frozen_gem_path
48
+ end
49
+ end
50
+
51
+ class GemBoot < Boot
52
+ def load_initializer
53
+ self.class.load_rubygems
54
+ load_rails_gem
55
+ require 'initializer'
56
+ end
57
+
58
+ def load_rails_gem
59
+ if version = self.class.gem_version
60
+ gem 'rails', version
61
+ else
62
+ gem 'rails'
63
+ end
64
+ rescue Gem::LoadError => load_error
65
+ $stderr.puts %(Missing the Rails #{version} gem. Please `gem install -v=#{version} rails`, update your RAILS_GEM_VERSION setting in config/environment.rb for the Rails version you do have installed, or comment out RAILS_GEM_VERSION to use the latest version installed.)
66
+ exit 1
67
+ end
68
+
69
+ class << self
70
+ def rubygems_version
71
+ Gem::RubyGemsVersion rescue nil
72
+ end
73
+
74
+ def gem_version
75
+ if defined? RAILS_GEM_VERSION
76
+ RAILS_GEM_VERSION
77
+ elsif ENV.include?('RAILS_GEM_VERSION')
78
+ ENV['RAILS_GEM_VERSION']
79
+ else
80
+ parse_gem_version(read_environment_rb)
81
+ end
82
+ end
83
+
84
+ def load_rubygems
85
+ min_version = '1.3.2'
86
+ require 'rubygems'
87
+ unless rubygems_version >= min_version
88
+ $stderr.puts %Q(Rails requires RubyGems >= #{min_version} (you have #{rubygems_version}). Please `gem update --system` and try again.)
89
+ exit 1
90
+ end
91
+
92
+ rescue LoadError
93
+ $stderr.puts %Q(Rails requires RubyGems >= #{min_version}. Please install RubyGems and try again: http://rubygems.rubyforge.org)
94
+ exit 1
95
+ end
96
+
97
+ def parse_gem_version(text)
98
+ $1 if text =~ /^[^#]*RAILS_GEM_VERSION\s*=\s*["']([!~<>=]*\s*[\d.]+)["']/
99
+ end
100
+
101
+ private
102
+ def read_environment_rb
103
+ File.read("#{RAILS_ROOT}/config/environment.rb")
104
+ end
105
+ end
106
+ end
107
+ end
108
+
109
+ # All that for this:
110
+ Rails.boot!