apimaster 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. data/LICENSE +20 -0
  2. data/README.md +12 -0
  3. data/apimaster.gemspec +14 -0
  4. data/bin/apimaster +6 -0
  5. data/lib/apimaster.rb +21 -0
  6. data/lib/apimaster/application.rb +28 -0
  7. data/lib/apimaster/controllers/errors.rb +34 -0
  8. data/lib/apimaster/error.rb +79 -0
  9. data/lib/apimaster/generators/application.rb +112 -0
  10. data/lib/apimaster/generators/base.rb +206 -0
  11. data/lib/apimaster/generators/command.rb +697 -0
  12. data/lib/apimaster/generators/manifest.rb +51 -0
  13. data/lib/apimaster/generators/options.rb +162 -0
  14. data/lib/apimaster/generators/scripts.rb +64 -0
  15. data/lib/apimaster/generators/simple_logger.rb +44 -0
  16. data/lib/apimaster/generators/templates/Gemfile +21 -0
  17. data/lib/apimaster/generators/templates/LICENSE +20 -0
  18. data/lib/apimaster/generators/templates/README.md +10 -0
  19. data/lib/apimaster/generators/templates/Rakefile +19 -0
  20. data/lib/apimaster/generators/templates/TODO +4 -0
  21. data/lib/apimaster/generators/templates/app/controllers/index_controller.rb.erb +7 -0
  22. data/lib/apimaster/generators/templates/config.ru.erb +8 -0
  23. data/lib/apimaster/generators/templates/config/application.rb.erb +19 -0
  24. data/lib/apimaster/generators/templates/config/boot.rb.erb +17 -0
  25. data/lib/apimaster/generators/templates/config/initializer.rb.erb +13 -0
  26. data/lib/apimaster/generators/templates/config/patches.rb.erb +0 -0
  27. data/lib/apimaster/generators/templates/config/settings/app.yml.erb +3 -0
  28. data/lib/apimaster/generators/templates/config/settings/mongoid.yml.erb +66 -0
  29. data/lib/apimaster/generators/templates/config/settings/oauth.yml.erb +8 -0
  30. data/lib/apimaster/generators/templates/gitignore +10 -0
  31. data/lib/apimaster/generators/templates/lib/module.rb.erb +6 -0
  32. data/lib/apimaster/generators/templates/test/functional_test.rb.erb +2 -0
  33. data/lib/apimaster/generators/templates/test/test_helper.rb.erb +1 -0
  34. data/lib/apimaster/generators/templates/test/unit_test.rb.erb +2 -0
  35. data/lib/apimaster/generators/version.rb +3 -0
  36. data/lib/apimaster/helpers/headers.rb +30 -0
  37. data/lib/apimaster/helpers/request.rb +49 -0
  38. data/lib/apimaster/helpers/session.rb +36 -0
  39. data/lib/apimaster/mapper.rb +86 -0
  40. data/lib/apimaster/models/user.rb +33 -0
  41. data/lib/apimaster/models/user_mock.rb +13 -0
  42. data/lib/apimaster/setting.rb +68 -0
  43. metadata +45 -3
@@ -0,0 +1,13 @@
1
+
2
+ # Initialize environment
3
+ ROOT_PATH = File.expand_path(".")
4
+ ENV["RACK_ENV"] ||= "development"
5
+ Bundler.require(:default, ENV["RACK_ENV"].to_sym)
6
+
7
+ # Initialize settings
8
+ setting_files = "./config/settings/{app,oauth}.yml"
9
+ Apimaster::Setting.environment = ENV["RACK_ENV"]
10
+ Apimaster::Setting.load_file(setting_files)
11
+
12
+ # Database setting
13
+ # Mongoid.load!("./config/settings/mongoid.yml")
@@ -0,0 +1,3 @@
1
+ app:
2
+ base_url: "http://your-app.com"
3
+ site_url: "http://your-app.com"
@@ -0,0 +1,66 @@
1
+ development:
2
+ sessions:
3
+ default:
4
+ database: mongoid
5
+ hosts:
6
+ - localhost:27017
7
+
8
+ # Tell Mongoid which environment this configuration is for.
9
+ production:
10
+ # This starts the session configuration settings. You may have as
11
+ # many sessions as you like, but you must have at least 1 named
12
+ # 'default'.
13
+ sessions:
14
+ # Define the default session.
15
+ default:
16
+ # A session can have any number of hosts. Usually 1 for a single
17
+ # server setup, and at least 3 for a replica set. Hosts must be
18
+ # an array of host:port pairs. This session is single server.
19
+ hosts:
20
+ - flame.mongohq.com:27017
21
+ # Define the default database name.
22
+ database: mongoid
23
+ # Since this database points at a session connected to MongoHQ, we must
24
+ # provide the authentication details.
25
+ username: user
26
+ password: password
27
+ # This defines a secondary session at a replica set.
28
+ replica_set:
29
+ # This configuration is a 3 node replica set.
30
+ hosts:
31
+ - dedicated1.myapp.com:27017
32
+ - dedicated2.myapp.com:27017
33
+ - dedicated3.myapp.com:27017
34
+ database: mongoid
35
+ # We can set session specific options, like reads executing
36
+ # on secondary nodes, and defaulting the session to safe mode.
37
+ options:
38
+ consistency: :eventual
39
+ safe: true
40
+ # This defines a tertiary session at a Mongos fronted shard.
41
+ shard:
42
+ # This configuration is a Mongos shard server.
43
+ hosts:
44
+ - mongos.myapp.com:27017
45
+ database: mongoid
46
+ # This configuration shows an authenticated replica set via a uri.
47
+ another:
48
+ uri: mongodb://user:pass@59.1.22.1:27017,59.1.22.2:27017/mongoid
49
+ # Here we put the Mongoid specific configuration options. These are explained
50
+ # in more detail next.
51
+ options:
52
+ allow_dynamic_fields: false
53
+ identity_map_enabled: true
54
+ include_root_in_json: true
55
+ include_type_for_serialization: true
56
+ # Note this can also be true if you want to preload everything, but this is
57
+ # almost never necessary. Most of the time set this to false.
58
+ preload_models:
59
+ - Canvas
60
+ - Browser
61
+ - Firefox
62
+ scope_overwrite_exception: true
63
+ raise_not_found_error: false
64
+ skip_version_check: false
65
+ use_activesupport_time_zone: false
66
+ use_utc: true
@@ -0,0 +1,8 @@
1
+ oauth:
2
+ production:
3
+ oauth_domain: "open.admaster.com.cn"
4
+
5
+ development:
6
+ oauth_domain: "testopen.admasterapi.com"
7
+
8
+ test:
@@ -0,0 +1,10 @@
1
+ .DS_Store
2
+ *.db
3
+ public/*.*
4
+ coverage/
5
+ *.swp
6
+ .yardoc/
7
+ doc/
8
+ tmp/
9
+ *.rb~
10
+ tags
@@ -0,0 +1,6 @@
1
+ # encoding: utf-8
2
+ #
3
+ # Copyright (C) 2011-2012 AdMaster, Inc.
4
+
5
+ module <%= module_name %> end
6
+
@@ -0,0 +1,2 @@
1
+ require File.dirname(__FILE__) + '/test_helper'
2
+
@@ -0,0 +1,2 @@
1
+ require File.dirname(__FILE__) + '/test_helper'
2
+
@@ -0,0 +1,3 @@
1
+ module Apimaster::Generators
2
+ VERSION = "1.5.8"
3
+ end
@@ -0,0 +1,30 @@
1
+ # encoding: utf-8
2
+ #
3
+ # Copyright (C) 2011-2012 AdMaster, Inc.
4
+
5
+ module Apimaster::Helpers
6
+ module Headers
7
+
8
+ def header_pagination(pagination)
9
+ path = base_url + request.path_info
10
+ next_link = path + "?" + query_string_modifier(page: pagination.next_page)
11
+ last_link = path + "?" + query_string_modifier(page: pagination.page_count)
12
+ pagination_link = "<#{next_link}>; rel=\"next\", <#{last_link}>; rel=\"last\""
13
+ headers "Link" => pagination_link
14
+ end
15
+
16
+ def header_location(path)
17
+ headers "Location" => base_url + path
18
+ end
19
+
20
+ def header_link(path, rel)
21
+ headers "Link" => "<#{base_url+path}>; rel=\"#{rel}\""
22
+ end
23
+
24
+ private
25
+
26
+ def base_url
27
+ Apimaster::Setting.get('app.base_url')
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,49 @@
1
+ # encoding: utf-8
2
+ #
3
+ # Copyright (C) 2011-2012 AdMaster, Inc.
4
+ #
5
+ # @author: sunxiqiu@admaster.com.cn
6
+
7
+ module Apimaster::Helpers
8
+ module Request
9
+
10
+ # Convert a hash to a querystring for form population
11
+ def hash_to_query_string(hash)
12
+ hash.collect {|k,v| "#{k}=#{v}"}.join("&")
13
+ end
14
+
15
+ def query_string_modifier(hash)
16
+ hash_to_query_string(CGI::parse(request.query_string).merge(hash))
17
+ end
18
+
19
+ def posts
20
+ @posts ||= to_symbol_key_hash(request_json)
21
+ end
22
+
23
+ private
24
+
25
+ def to_symbol_key_hash(hash)
26
+ return hash unless hash.is_a? Hash
27
+ result = {}
28
+ hash.map do |key, val|
29
+ val = to_symbol_key_hash(val) if val.is_a? Hash
30
+ result[key.to_sym] = val
31
+ end
32
+ result
33
+ end
34
+
35
+ def request_json
36
+ begin
37
+ @request_json ||= parse_json
38
+ rescue JSON::ParserError => e
39
+ raise Apimaster::RequestError, "Problems parsing JSON"
40
+ end
41
+ end
42
+
43
+ def parse_json
44
+ body_data = request.body.read
45
+ body_data.empty? ? {} : JSON.parse(body_data)
46
+ end
47
+
48
+ end
49
+ end
@@ -0,0 +1,36 @@
1
+ # encoding: utf-8
2
+ #
3
+ # Copyright (C) 2011-2012 AdMaster, Inc.
4
+ #
5
+ # @author: sunxiqiu@admaster.com.cn
6
+
7
+ module Apimaster::Helpers
8
+ module Session
9
+
10
+ # Check logged in user is the owner
11
+ def is_owner? owner_id
12
+ !!current_user && current_user.id.to_i == owner_id.to_i
13
+ end
14
+
15
+ def authorize
16
+ raise Apimaster::UnauthorizedError.new :user unless current_user
17
+ end
18
+
19
+ # Return current_user record if logged in
20
+ def current_user
21
+ @current_user ||= auth_user
22
+ end
23
+
24
+ def auth_user
25
+ @access_token ||= params[:access_token] or header_token
26
+ (test? ? Apimaster::Models::UserMock : Apimaster::Models::User).auth @access_token
27
+ end
28
+
29
+ def header_token
30
+ keys = %w{HTTP_AUTHORIZATION X-HTTP_AUTHORIZATION X_HTTP_AUTHORIZATION}
31
+ authorization ||= keys.inject(nil) { |auth, key| auth || request.env[key] }
32
+ authorization.split[1] if authorization and authorization[/^token/i]
33
+ end
34
+
35
+ end
36
+ end
@@ -0,0 +1,86 @@
1
+ # encoding: utf-8
2
+ #
3
+ # Copyright (C) 2011-2012 AdMaster, Inc.
4
+
5
+ module Apimaster
6
+ class Mapper
7
+ # include Mongoid::Document
8
+
9
+ def post hash
10
+ from_hash hash
11
+ save
12
+ end
13
+
14
+ def put hash
15
+ from_hash hash
16
+ save
17
+ end
18
+
19
+ def patch hash
20
+ from_hash hash
21
+ save
22
+ end
23
+
24
+ def to_hash accessor = :all
25
+ record = {}
26
+ fields = self.class.find_attrs_in_options(:accessor, accessor)
27
+ fields.each do |field|
28
+ if self.respond_to?(field)
29
+ record[field] = self.send(field)
30
+ else
31
+ raise "Dataset #{self.class} has no method with the name of #{field}"
32
+ end
33
+ end
34
+ record
35
+ end
36
+
37
+ def from_hash(hash, method = :all)
38
+ data = {}
39
+ attrs = [:required, :optional]
40
+
41
+ attrs.each do |type|
42
+ fields = self.class.get_attrs(type, method)
43
+ fields.each do |field|
44
+ if hash.has_key?(field)
45
+ data[field] = hash[field]
46
+ elsif hash.has_key?(field.to_s)
47
+ data[field] = hash[field.to_s]
48
+ else
49
+ raise Apimaster::MissingFieldError.new(self.class.get_class_name, field) if type == :required
50
+ end
51
+ end
52
+ end
53
+
54
+ data.each do |key, val|
55
+ respond_setter key, val
56
+ end
57
+ end
58
+
59
+ def respond_setter key, val
60
+ name = (key.to_s + '=').to_sym
61
+ raise "#{self.class} lost of #{name}" unless self.respond_to?(name)
62
+ self.send name, val
63
+ end
64
+
65
+ class << self
66
+
67
+ OPTION_TYPES = [:accessor, :required, :optional]
68
+
69
+ @attr_options ||= {}
70
+
71
+ # attr_options :url, accessor: [:get, :list]
72
+ def attr_options name, options = {}
73
+ @attr_options[name] = options
74
+ end
75
+
76
+ # [:url, :name]
77
+ def find_attrs_in_options type, option = :all
78
+ raise "Unknown attribute options type: #{type}" unless OPTION_TYPES.include? type
79
+ @attr_options.select do |name, options|
80
+ type_options = options.is_a?(Hash) and options.key?(type) ? options[type] : nil
81
+ type_options.is_a?(Array) and (type_options.include?(option) or type_options.include(:all))
82
+ end.keys
83
+ end
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,33 @@
1
+ # encoding: utf-8
2
+ #
3
+ # Copyright (C) 2011-2012 AdMaster, Inc.
4
+
5
+ require 'net/http'
6
+
7
+ module Apimaster::Models
8
+ class User
9
+
10
+ attr_accessor :id
11
+ attr_accessor :email
12
+ attr_accessor :username
13
+
14
+ def initialize hash
15
+ hash.each do |key, val|
16
+ method_name = (key.to_s+'=').to_sym
17
+ self.send(method_name, val) if respond_to?(method_name)
18
+ end
19
+ end
20
+
21
+ def self.auth access_token
22
+ oauth_domain = Apimaster::Setting.get('oauth.oauth_domain')
23
+ json = Net::HTTP.get(oauth_domain, "/user?access_token=#{access_token}", 80)
24
+ user_hash = JSON.parse(json)
25
+
26
+ return nil unless user_hash.is_a?(Hash)
27
+ raise Apimaster::OauthError.new(user_hash["message"]) if user_hash.key?("message")
28
+
29
+ self.new user_hash
30
+ end
31
+
32
+ end
33
+ end
@@ -0,0 +1,13 @@
1
+ # encoding: utf-8
2
+ #
3
+ # Copyright (C) 2011-2012 AdMaster, Inc.
4
+
5
+ module Apimaster::Models
6
+ class UserMock
7
+
8
+ def self.auth access_token
9
+ User.new id: 1, email: "hello@admaster.com.cn", username: "hello"
10
+ end
11
+
12
+ end
13
+ end
@@ -0,0 +1,68 @@
1
+ # encoding: utf-8
2
+ #
3
+ # Copyright (C) 2011-2012 AdMaster, Inc.
4
+
5
+ module Apimaster
6
+
7
+ module Setting
8
+ class << self
9
+ @@hashes = {}
10
+
11
+ # environments: development, test and production.
12
+ ENVIRONMENTS = %w[test production development]
13
+
14
+ attr_accessor :environment
15
+
16
+ def set(key, value)
17
+ @@hashes[key] = value
18
+ end
19
+
20
+ def get(key, default = nil)
21
+ current = @@hashes
22
+ key.split('.').each do |k|
23
+ if current and current.is_a?(Hash)
24
+ current = current.has_key?(k) ? current[k] : default
25
+ end
26
+ end
27
+ current
28
+ end
29
+
30
+ # Loads the configuration from the YAML files whose +paths+ are passed as
31
+ # arguments, filtering the settings for the current environment. Note that
32
+ # these +paths+ can actually be globs.
33
+ def load_file(*paths)
34
+ paths.each do |pattern|
35
+ Dir.glob(pattern) do |file|
36
+ yaml = config_for_env(YAML.load_file(file)) || {}
37
+ yaml.each_pair do |key, value|
38
+ for_env = config_for_env(value)
39
+ set key, for_env unless value and for_env.nil? and respond_to? key
40
+ end
41
+ end
42
+ end
43
+ end
44
+
45
+ private
46
+
47
+ # Given a +hash+ with some application configuration it returns the
48
+ # settings applicable to the current environment. Note that this can only
49
+ # be done when all the keys of +hash+ are environment names included in the
50
+ # +environments+ setting (which is an Array of Strings). Also, the
51
+ # returned config is a indifferently accessible Hash, which means that you
52
+ # can get its values using Strings or Symbols as keys.
53
+ def config_for_env(hash)
54
+ if hash.respond_to? :keys and hash.keys.all? { |k| ENVIRONMENTS.include? k.to_s }
55
+ hash = hash[environment.to_s] || hash[environment.to_sym]
56
+ end
57
+
58
+ if hash.respond_to? :to_hash
59
+ indifferent_hash = Hash.new {|hash,key| hash[key.to_s] if Symbol === key }
60
+ indifferent_hash.merge hash.to_hash
61
+ else
62
+ hash
63
+ end
64
+ end
65
+
66
+ end
67
+ end
68
+ end