weapon 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: dd05b8383fdf6a56aee99e98e7c4e6aadfd800e4
4
- data.tar.gz: caf2a88d30150d5b98fd8824fdb5af1b90ba5e90
3
+ metadata.gz: 8621ad57230f376e88746ffb2ca40f8957f7d483
4
+ data.tar.gz: 969cb6e67bdc34eec0263004c0887896edc189f8
5
5
  SHA512:
6
- metadata.gz: 40ed25df93a88f72b4f1f14ae96a59de044d39fd23563b7943c8aa05dcaf9accaf2117b58bfb18529d2db826ebf522674417e504038ec5f6a322771f04fed121
7
- data.tar.gz: 026e9afc4441a43fbef02c8ca2c9f73de6c12866b5a034927420daf0ff1ca680f265e658f538d1cd203f2586040d938059380e25e5034b49ded79ca06eb86f3a
6
+ metadata.gz: 5641986317808d41699ffa477bd7e34c5edbeaedb5cd8dd5524f3f3649ab3f923fabd85c6a62bff9cc1a79b3c7d3ce7359162d6d0e20f3b15ec8ae03703f276d
7
+ data.tar.gz: 015e1e722924516d70c47c74aaeaa305f33e3a087993daf3cdd7ebe5edb4fa473f4984d0c694d8423105b62682df12bd2f5765d01b6ebd701ce0d101e86ac0af
@@ -1,36 +1,54 @@
1
1
 
2
2
  class Weapon::ActiveadminGenerator < Rails::Generators::NamedBase # :nodoc:
3
- desc 'This generator creates a example email setting and add exception_notification for production'
4
-
5
- def create_example_email
6
- application(nil, env: "production") do
7
- config.action_mailer.raise_delivery_errors = true
8
- config.action_mailer.default_url_options = {:host => '120.25.61.54:8100'}
9
- config.action_mailer.delivery_method = :smtp
10
- config.action_mailer.smtp_settings = {
11
- :address => "smtp.163.com",
12
- :port => 25,
13
- :user_name => "ledcloud@163.com",
14
- :password => "ffgexobhlolfjhij",
15
- :enable_starttls_auto => true,
16
- :authentication => "plain",
17
- :domain => "163.com"
18
- }
19
- end
20
- end
3
+ desc 'This generator creates activeadmin files'
21
4
 
22
- def add_exception_notify
23
- gem_group :production do
24
- gem "rspec-rails"
25
- end
5
+ class_option :only, type: :string, desc: 'only generate model for listed model'
6
+ class_option :except, type: :string, desc: 'when generate model, exclude listed model'
7
+
8
+ def generate_activeadmin
9
+
10
+ prefix = 'app/admin'
11
+
12
+ if args[0].nil? || args[0] == "all"
13
+ names = Dir["app/models/*.rb"].map {|x| File.basename(x, '.rb')}
14
+
15
+ if options[:only]
16
+ names = names & options[:only].split(',')
17
+ end
18
+
19
+ if options[:except]
20
+ names = names - options[:except].split(',')
21
+ end
22
+
23
+ names.each do |name|
24
+ next unless name.camelize.constantize.respond_to? 'column_names'
25
+ column_names = name.camelize.constantize.column_names
26
+ infos = column_names.map {|column| "expose :#{column}"}
27
+ end
28
+ else
29
+ name = args[0]
30
+ return unless name.camelize.constantize.respond_to? 'column_names'
31
+ column_names = name.camelize.constantize.column_names
32
+
33
+ if options[:only]
34
+ column_names = column_names & options[:only].split(',')
35
+ end
36
+
37
+ if options[:except]
38
+ column_names = column_names - options[:except].split(',')
39
+ end
40
+
41
+ ap column_names
42
+ a = Magicfile.new
43
+ infos = ['xx']
44
+ a.append_string_lines(infos)
45
+ a.to_file "#{prefix}/name.rb"
26
46
 
27
- application(nil, env: "production") do
28
- config.middleware.use ExceptionNotification::Rack,
29
- :email => {
30
- :email_prefix => "[weapon] ",
31
- :sender_address => "weapon <ledcloud@163.com>",
32
- :exception_recipients => %w{dilin.life@gmail.com}
33
- }
34
47
  end
48
+
49
+
50
+
35
51
  end
52
+
53
+
36
54
  end
@@ -1,20 +1,19 @@
1
1
  require 'magicfile'
2
2
  require 'fileutils'
3
-
3
+ require 'thor'
4
4
 
5
5
  class Weapon::GrapeGenerator < Rails::Generators::Base # :nodoc:
6
- desc 'This generator creates grape entity for model'
6
+ desc 'This generator creates basic grape files for models'
7
+ include Thor::Actions
7
8
 
8
- def generate_grape_entity
9
+ source_root File.expand_path("../templates", __FILE__)
10
+ class_option :only, type: :string, desc: 'only generate api for listed model'
11
+ class_option :except, type: :string, desc: 'when generate api, exclude listed model'
9
12
 
10
- prefix_dirs = Dir.glob('app/api/*/')
11
- if prefix_dirs.count == 0
12
- prefix = 'app/api/v1'
13
- elsif prefix_dirs.count == 1
14
- prefix = prefix_dirs[0]
15
- else
16
- prefix = ask('there are multi directory in app/api directory, please input path like app/api/v1')
17
- end
13
+ def generate_grape_files
14
+
15
+ prefix = 'app/api/v1'
16
+ FileUtils.mkdir_p prefix
18
17
 
19
18
  if args[0].nil? || args[0] == "all"
20
19
  names = Dir["app/models/*.rb"].map {|x| File.basename(x, '.rb')}
@@ -22,28 +21,44 @@ class Weapon::GrapeGenerator < Rails::Generators::Base # :nodoc:
22
21
  names = args
23
22
  end
24
23
 
25
- ap names
26
-
27
- names.each do |name|
28
- entity_dir = File.join(prefix, "entities")
29
- entity_path = File.join(entity_dir, "#{name}.rb")
30
-
31
- ap "dir is #{entity_dir}"
32
- ap "path is #{entity_path}"
24
+ if options[:only]
25
+ names = names & options[:only].split(',')
26
+ end
33
27
 
34
- next unless name.camelize.constantize.respond_to? 'column_names'
35
- column_names = name.camelize.constantize.column_names
36
- infos = column_names.map {|column| "expose :#{column}"}
28
+ if options[:except]
29
+ names = names - options[:except].split(',')
30
+ end
37
31
 
38
- FileUtils.mkdir_p entity_dir
32
+ module_array = prefix.split('/')[1..-1]
33
+ names.each do |name|
39
34
  a = Magicfile.new
40
- module_array = prefix.split('/')[1..-1].append('entities')
41
35
  a.append_modules(module_array)
42
- a.append_class(name.camelize, 'Grape::Entity')
36
+ a.append_class(name.camelize.pluralize, 'Grape::API')
37
+ infos = ["version 'v1', using: :path", "format :json", "default_format: json"]
43
38
  a.append_string_lines(infos)
44
- a.to_file entity_path
39
+ a.to_file "#{prefix}/#{name.pluralize}.rb"
45
40
  end
46
41
 
42
+ b = Magicfile.new
43
+ b.append_modules(module_array)
44
+ b.append_class('Root', 'Grape::API')
45
+ infos = ["helpers Api::V1::Helpers", "version 'v1', using: :path", "cascade false", "format :json", "default_format :json\n", "use Api::V1::Auth::Middleware\n"]
46
+ infos += names.map {|x| "mount Api::V1::#{x.camelize.pluralize}"}
47
+ infos += ["\n", "before do", " header 'Access-Control-Allow-Origin'", "end\n"]
48
+ b.append_string_lines(infos)
49
+ b.to_file "#{prefix}/root.rb"
50
+
51
+ copy_file 'dispatch.rb', "app/api/dispatch.rb"
52
+ copy_file 'errors.rb', "#{prefix}/errors.rb"
53
+ copy_file 'helpers.rb', "#{prefix}/helpers.rb"
54
+ copy_file 'named_params.rb', "#{prefix}/named_params.rb"
55
+ FileUtils.mkdir_p "#{prefix}/auth"
56
+ copy_file 'auth/utils.rb', "#{prefix}/auth/utils.rb"
57
+ copy_file 'auth/middleware.rb', "#{prefix}/auth/middleware.rb"
58
+ copy_file 'auth/authenticator.rb', "#{prefix}/auth/authenticator.rb"
59
+
60
+ route "mount Api::Dispatch => '/api'"
61
+
47
62
  end
48
63
 
49
64
  end
@@ -0,0 +1,86 @@
1
+ module Api
2
+ module V1
3
+ module Auth
4
+ class Authenticator
5
+
6
+ def initialize(request, params)
7
+ @request = request
8
+ @params = params
9
+ end
10
+
11
+
12
+ def authenticate!
13
+ check_user!
14
+ check_tonce!
15
+ check_signature!
16
+ user
17
+ end
18
+
19
+ def user
20
+ @user ||= User.where(access_key: @params[:access_key]).first
21
+ end
22
+
23
+ def check_user!
24
+ raise InvalidAccessKeyError, @params[:access_key] unless user
25
+ raise ExpiredAccessKeyError, @params[:access_key] if user.auth_expired?
26
+ end
27
+
28
+ def check_signature!
29
+ Rails.logger.warn "payload is #{payload}"
30
+ Rails.logger.warn "uploaded signature is #{@params[:signature]}"
31
+ Rails.logger.warn "generated signature is #{Utils.hmac_signature(user.secret_key, payload)}"
32
+ if @params[:signature] != Utils.hmac_signature(user.secret_key, payload)
33
+ Rails.logger.warn "Api v1 auth failed: signature doesn't match. token: #{user.access_key} payload: #{payload}"
34
+ raise Api::V1::IncorrectSignatureError, @params[:signature]
35
+ end
36
+ end
37
+
38
+ def check_tonce!
39
+ key = "api:v1:tonce:#{user.access_key}:#{tonce}"
40
+ if Utils.cache.read(key)
41
+ Rails.logger.warn "API v1 auth failed: used tonce.access_key: #{user.access_key} payload: #{payload} tonce: #{tonce}"
42
+ raise Api::V1::TonceUsedError.new(user.access_key, tonce)
43
+ end
44
+ Utils.cache.write key, tonce, 61 # forget after 61 seconds
45
+
46
+ now = Time.now.to_i
47
+ if tonce < now-30 || tonce > now+30# within 30 seconds
48
+ Rails.logger.warn "Api v1 auth failed: invalid tonce. access_key: #{user.access_key} payload: #{payload} tonce: #{tonce} current timestamp: #{now}"
49
+ raise Api::V1::InvalidTonceError.new(tonce, now)
50
+ end
51
+ end
52
+
53
+ def tonce
54
+ @tonce ||= @params[:tonce].to_i
55
+ end
56
+
57
+ def payload
58
+ "#{canonical_verb}|#{Api::V1::Root::PREFIX}#{canonical_uri}|#{canonical_query}"
59
+ end
60
+
61
+ def canonical_verb
62
+ @request.request_method
63
+ end
64
+
65
+ def canonical_uri
66
+ @request.path_info
67
+ end
68
+
69
+ def canonical_query
70
+ hash = @params.select {|k,v| !%w(route_info signature format).include?(k) }
71
+ ap hash
72
+ URI.unescape(hash.to_param)
73
+ end
74
+
75
+ def endpoint
76
+ @request.env['api.endpoint']
77
+ end
78
+
79
+ def route_scopes
80
+ endpoint.options[:route_options][:scopes]
81
+ end
82
+
83
+ end
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,35 @@
1
+ module Api
2
+ module V1
3
+ module Auth
4
+ class Middleware < ::Grape::Middleware::Base
5
+
6
+ def before
7
+ #raise AuthorizationError
8
+ if provided?
9
+ auth = Api::V1::Auth::Authenticator.new(request, params)
10
+ ap "do auth"
11
+ @env['user'] = auth.authenticate!
12
+ end
13
+ end
14
+
15
+ def provided?
16
+ ap params
17
+ ap params["access_key"]
18
+ ap params["tonce"]
19
+ ap params["signature"]
20
+ params["access_key"] && params["tonce"] && params["signature"]
21
+ end
22
+
23
+ def request
24
+ @request ||= ::Grape::Request.new(env)
25
+ end
26
+
27
+ def params
28
+ @params ||= request.params
29
+ end
30
+
31
+ end
32
+ end
33
+
34
+ end
35
+ end
@@ -0,0 +1,28 @@
1
+ module Api
2
+ module V1
3
+ module Auth
4
+ module Utils
5
+ class <<self
6
+
7
+ def cache
8
+ # Simply use rack-attack cache wrapper
9
+ @cache ||= Rack::Attack::Cache.new
10
+ end
11
+
12
+ def urlsafe_string_40
13
+ # 30 is picked so generated string length is 40
14
+ SecureRandom.urlsafe_base64(30).tr('_-', 'xx')
15
+ end
16
+
17
+ alias :generate_access_key :urlsafe_string_40
18
+ alias :generate_secret_key :urlsafe_string_40
19
+
20
+ def hmac_signature(secret_key, payload)
21
+ OpenSSL::HMAC.hexdigest 'SHA256', secret_key, payload
22
+ end
23
+
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,13 @@
1
+
2
+ module Api
3
+ class Dispatch < Grape::API
4
+
5
+ mount Api::V1::Root
6
+
7
+ format :json
8
+ default_format :json
9
+
10
+ content_type :json, "application/json;charset=utf-8"
11
+
12
+ end
13
+ end
@@ -0,0 +1,81 @@
1
+ module Api
2
+ module V1
3
+
4
+ module ExceptionHandlers
5
+
6
+ def self.included(base)
7
+ base.instance_eval do
8
+ rescue_from Grape::Exceptions::ValidationErrors do |e|
9
+ Rack::Response.new({
10
+ success: false,
11
+ message: e.message,
12
+ data: {}
13
+ }.to_json, e.status)
14
+ end
15
+ end
16
+ end
17
+
18
+ end
19
+
20
+ class Error < Grape::Exceptions::Base
21
+ attr :code, :text
22
+
23
+ # code: api error code defined by Peatio, errors originated from
24
+ # subclasses of Error have code start from 2000.
25
+ # text: human readable error message
26
+ # status: http status code
27
+ def initialize(opts={})
28
+ @text = opts[:text] || ''
29
+
30
+ @status = 200
31
+ @message = {success: false, message: @text, data: {}}
32
+ end
33
+ end
34
+
35
+ class AuthorizationError < Error
36
+ def initialize
37
+ super code: 2001, text: 'Authorization failed', status: 401
38
+ end
39
+ end
40
+
41
+
42
+
43
+ class IncorrectSignatureError < Error
44
+ def initialize(signature)
45
+ super code: 2005, text: "Signature #{signature} is incorrect.", status: 401
46
+ end
47
+ end
48
+
49
+ class TonceUsedError < Error
50
+ def initialize(access_key, tonce)
51
+ super code: 2006, text: "The tonce #{tonce} has already been used by access key #{access_key}.", status: 401
52
+ end
53
+ end
54
+
55
+ class InvalidTonceError < Error
56
+ def initialize(tonce, now)
57
+ super code: 2007, text: "The tonce #{tonce} is invalid, current timestamp is #{now}.", status: 401
58
+ end
59
+ end
60
+
61
+ class InvalidAccessKeyError < Error
62
+ def initialize(access_key)
63
+ super code: 2008, text: "The access key #{access_key} does not exist.", status: 401
64
+ end
65
+ end
66
+
67
+ class DisabledAccessKeyError < Error
68
+ def initialize(access_key)
69
+ super code: 2009, text: "The access key #{access_key} is disabled.", status: 401
70
+ end
71
+ end
72
+
73
+ class ExpiredAccessKeyError < Error
74
+ def initialize(access_key)
75
+ super code: 2010, text: "The access key #{access_key} has expired.", status: 401
76
+ end
77
+ end
78
+
79
+
80
+ end
81
+ end
@@ -0,0 +1,24 @@
1
+ module Api
2
+ module V1
3
+ module Helpers
4
+ def render_success(data = {}, msg = nil)
5
+ status 200
6
+ { success: true, message: msg.to_s, data: data }
7
+ end
8
+
9
+ def render_fail(msg = nil, data = {})
10
+ status 200
11
+ { success: false, message: msg.to_s, data: data }
12
+ end
13
+
14
+ def authenticate!
15
+ current_user or raise AuthorizationError
16
+ end
17
+
18
+ def current_user
19
+ @user ||= env['user']
20
+ end
21
+
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,14 @@
1
+ module Api
2
+ module V1
3
+ module NamedParams
4
+ extend ::Grape::API::Helpers
5
+
6
+ params :auth do
7
+ requires :access_key, type: String, desc: "Access key."
8
+ requires :tonce, type: Integer, desc: "Tonce is an integer represents the milliseconds elapsed since Unix epoch."
9
+ requires :signature, type: String, desc: "The signature of your request payload, generated using your secret key."
10
+ end
11
+
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,55 @@
1
+ require 'magicfile'
2
+ require 'fileutils'
3
+
4
+
5
+ class Weapon::GrapeEntityGenerator < Rails::Generators::Base # :nodoc:
6
+ desc 'This generator creates grape entity for model'
7
+
8
+ class_option :only, type: :string, desc: 'only generate api for listed model'
9
+ class_option :except, type: :string, desc: 'when generate api, exclude listed model'
10
+
11
+ def generate_grape_entity
12
+
13
+ prefix_dirs = Dir.glob('app/api/*/')
14
+ if prefix_dirs.count == 0
15
+ prefix = 'app/api/v1'
16
+ elsif prefix_dirs.count == 1
17
+ prefix = prefix_dirs[0]
18
+ else
19
+ prefix = ask('there are multi directory in app/api directory, please input path like app/api/v1')
20
+ end
21
+
22
+ if args[0].nil? || args[0] == "all"
23
+ names = Dir["app/models/*.rb"].map {|x| File.basename(x, '.rb')}
24
+ else
25
+ names = args
26
+ end
27
+
28
+ if options[:only]
29
+ names = names & options[:only].split(',')
30
+ end
31
+
32
+ if options[:except]
33
+ names = names - options[:except].split(',')
34
+ end
35
+
36
+ names.each do |name|
37
+ entity_dir = File.join(prefix, "entities")
38
+ entity_path = File.join(entity_dir, "#{name}.rb")
39
+
40
+ next unless name.camelize.constantize.respond_to? 'column_names'
41
+ column_names = name.camelize.constantize.column_names
42
+ infos = column_names.map {|column| "expose :#{column}"}
43
+
44
+ FileUtils.mkdir_p entity_dir
45
+ a = Magicfile.new
46
+ module_array = prefix.split('/')[1..-1].append('entities')
47
+ a.append_modules(module_array)
48
+ a.append_class(name.camelize, 'Grape::Entity')
49
+ a.append_string_lines(infos)
50
+ a.to_file entity_path
51
+ end
52
+
53
+ end
54
+
55
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: weapon
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - seaify
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-01-26 00:00:00.000000000 Z
11
+ date: 2016-01-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -92,6 +92,14 @@ files:
92
92
  - lib/generators/weapon/activeadmin/activeadmin_generator.rb
93
93
  - lib/generators/weapon/email/email_generator.rb
94
94
  - lib/generators/weapon/grape/grape_generator.rb
95
+ - lib/generators/weapon/grape/templates/auth/authenticator.rb
96
+ - lib/generators/weapon/grape/templates/auth/middleware.rb
97
+ - lib/generators/weapon/grape/templates/auth/utils.rb
98
+ - lib/generators/weapon/grape/templates/dispatch.rb
99
+ - lib/generators/weapon/grape/templates/errors.rb
100
+ - lib/generators/weapon/grape/templates/helpers.rb
101
+ - lib/generators/weapon/grape/templates/named_params.rb
102
+ - lib/generators/weapon/grape_entity/grape_entity_generator.rb
95
103
  - lib/generators/weapon/i18n/i18n_generator.rb
96
104
  - lib/support/create_gem/basic.bin
97
105
  - lib/support/create_gem/basic.gemspec