eco_apps 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/lib/eco_apps/acts_as_readonly.rb +73 -0
- data/lib/eco_apps/core_service.rb +48 -0
- data/lib/eco_apps/extensions/active_resource.rb +13 -0
- data/lib/eco_apps/files/app_config.yml +27 -0
- data/lib/eco_apps/utils/helpers.rb +46 -0
- data/lib/eco_apps/utils/idp_util.rb +16 -0
- data/lib/eco_apps.rb +44 -0
- data/lib/platform_config.yml +8 -0
- data/spec/spec.opts +4 -0
- data/spec/test_app/app/controllers/application_controller.rb +13 -0
- data/spec/test_app/app/helpers/application_helper.rb +3 -0
- data/spec/test_app/app/models/app.rb +8 -0
- data/spec/test_app/app/models/comment.rb +3 -0
- data/spec/test_app/app/models/comment_service.rb +3 -0
- data/spec/test_app/config/app_config.yml +28 -0
- data/spec/test_app/config/boot.rb +110 -0
- data/spec/test_app/config/database.yml +3 -0
- data/spec/test_app/config/environment.rb +12 -0
- data/spec/test_app/config/environments/development.rb +17 -0
- data/spec/test_app/config/environments/production.rb +28 -0
- data/spec/test_app/config/environments/test.rb +28 -0
- data/spec/test_app/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/test_app/config/initializers/inflections.rb +10 -0
- data/spec/test_app/config/initializers/mime_types.rb +5 -0
- data/spec/test_app/config/initializers/new_rails_defaults.rb +21 -0
- data/spec/test_app/config/initializers/session_store.rb +15 -0
- data/spec/test_app/config/routes.rb +43 -0
- data/spec/test_app/db/test.sqlite3 +0 -0
- data/spec/test_app/log/test.log +1596 -0
- data/spec/test_app/spec/controllers/helpers_spec.rb +37 -0
- data/spec/test_app/spec/models/active_resource_spec.rb +12 -0
- data/spec/test_app/spec/models/acts_as_readonly_spec.rb +28 -0
- data/spec/test_app/spec/models/core_service_spec.rb +35 -0
- data/spec/test_app/spec/spec_helper.rb +60 -0
- 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,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
|
data/spec/spec.opts
ADDED
@@ -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,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!
|