weapon 0.1.2 → 0.1.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/support/mina_unicorn/deploy.rb +8 -25
- data/lib/support/mina_unicorn/deploy_production.rb +8 -0
- data/lib/support/mina_unicorn/deploy_staging.rb +10 -0
- data/lib/support/mina_unicorn/unicorn-nginx.conf +1 -1
- data/lib/support/mina_unicorn/unicorn_production.rb +28 -0
- data/lib/support/mina_unicorn/unicorn_staging.rb +28 -0
- data/lib/weapon.rb +40 -24
- metadata +8 -30
- data/lib/generators/weapon/activeadmin/activeadmin_generator.rb +0 -54
- data/lib/generators/weapon/email/email_generator.rb +0 -40
- data/lib/generators/weapon/grape/grape_generator.rb +0 -64
- data/lib/generators/weapon/grape/templates/auth/authenticator.rb +0 -86
- data/lib/generators/weapon/grape/templates/auth/middleware.rb +0 -35
- data/lib/generators/weapon/grape/templates/auth/utils.rb +0 -28
- data/lib/generators/weapon/grape/templates/dispatch.rb +0 -13
- data/lib/generators/weapon/grape/templates/errors.rb +0 -81
- data/lib/generators/weapon/grape/templates/helpers.rb +0 -24
- data/lib/generators/weapon/grape/templates/named_params.rb +0 -14
- data/lib/generators/weapon/grape_entity/grape_entity_generator.rb +0 -55
- data/lib/generators/weapon/i18n/i18n_generator.rb +0 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4b6b5520a327f18f9e318546d2b70fce70cd86bb
|
4
|
+
data.tar.gz: f42c3be68c2451b00595b1f828c6bc761a404006
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 817954fee8cfe14108ec4a8f72a5280acbfd5fbd7b242b2a4c8208acd73d086921dbcaaf76510061fcb6dca0e8f2bee4b4a89b8433d6049229c669ddf4e2d737
|
7
|
+
data.tar.gz: bcffdafb303f7369d2a186088facc448ddf46777ebb9613cadb96a0e69de2fe697c1f444896e7b4a188237194aa60e5233737fd163d0aac2dfaf8af6ca5e2e1c
|
@@ -1,28 +1,15 @@
|
|
1
|
+
set :default_stage, 'staging'
|
2
|
+
|
3
|
+
require 'mina/multistage'
|
1
4
|
require 'mina/bundler'
|
2
5
|
require 'mina/rails'
|
3
6
|
require 'mina/git'
|
4
|
-
|
5
|
-
require 'mina/rvm' # for rvm support. (http://rvm.io)
|
7
|
+
require 'mina/rbenv'
|
6
8
|
require 'mina/unicorn'
|
7
9
|
|
8
|
-
# Basic settings:
|
9
|
-
# domain - The hostname to SSH to.
|
10
|
-
# deploy_to - Path to deploy into.
|
11
|
-
# repository - Git repo to clone from. (needed by mina/git)
|
12
|
-
# branch - Branch name to deploy. (needed by mina/git)
|
13
|
-
|
14
|
-
set :user, 'user_name_fore_replace'
|
15
|
-
set :domain, 'domain_name_for_replace'
|
16
|
-
set :deploy_to, 'deploy_path_for_replace'
|
17
|
-
set :repository, 'repo_path_for_replace'
|
18
|
-
set :branch, 'master'
|
19
|
-
|
20
|
-
# For system-wide RVM install.
|
21
|
-
# set :rvm_path, '/usr/local/rvm/bin/rvm'
|
22
|
-
|
23
10
|
# Manually create these paths in shared/ (eg: shared/config/database.yml) in your server.
|
24
11
|
# They will be linked in the 'deploy:link_shared_paths' step.
|
25
|
-
set :shared_paths, ['config/database.yml', 'config/secrets.yml', 'log']
|
12
|
+
set :shared_paths, ['config/database.yml', 'config/secrets.yml', 'config/application.yml', 'log', 'tmp', 'public/uploads']
|
26
13
|
|
27
14
|
# Optional settings:
|
28
15
|
# set :user, 'foobar' # Username in the server to SSH to.
|
@@ -32,12 +19,7 @@ set :shared_paths, ['config/database.yml', 'config/secrets.yml', 'log']
|
|
32
19
|
# This task is the environment that is loaded for most commands, such as
|
33
20
|
# `mina deploy` or `mina rake`.
|
34
21
|
task :environment do
|
35
|
-
|
36
|
-
# Be sure to commit your .ruby-version or .rbenv-version to your repository.
|
37
|
-
# invoke :'rbenv:load'
|
38
|
-
|
39
|
-
# For those using RVM, use this to load an RVM version@gemset.
|
40
|
-
invoke :'rvm:use[ruby-2.0.0-p643@default]'
|
22
|
+
invoke :'rbenv:load'
|
41
23
|
end
|
42
24
|
|
43
25
|
# Put any custom mkdir's in here for when `mina setup` is ran.
|
@@ -56,9 +38,10 @@ task :setup => :environment do
|
|
56
38
|
queue! %[mkdir -p "#{deploy_to}/#{shared_path}/tmp/pids"]
|
57
39
|
queue! %[chmod g+rx,u+rwx "#{deploy_to}/#{shared_path}/tmp/pids"]
|
58
40
|
|
41
|
+
queue! %[touch "#{deploy_to}/#{shared_path}/config/application.yml"]
|
59
42
|
queue! %[touch "#{deploy_to}/#{shared_path}/config/database.yml"]
|
60
43
|
queue! %[touch "#{deploy_to}/#{shared_path}/config/secrets.yml"]
|
61
|
-
queue %[echo "-----> Be sure to edit '#{deploy_to}/#{shared_path}/config/database.yml' and 'secrets.yml'."]
|
44
|
+
queue %[echo "-----> Be sure to edit '#{deploy_to}/#{shared_path}/config/application.yml' and 'database.yml' and 'secrets.yml'."]
|
62
45
|
|
63
46
|
queue %[
|
64
47
|
repo_host=`echo $repo | sed -e 's/.*@//g' -e 's/:.*//g'` &&
|
@@ -0,0 +1,8 @@
|
|
1
|
+
set :unicorn_config, -> { "#{deploy_to}/#{current_path}/config/unicorn/production.rb" }
|
2
|
+
set :branch, 'master'
|
3
|
+
set :rails_env, 'master'
|
4
|
+
|
5
|
+
set :domain, 'domain_for_replace'
|
6
|
+
set :deploy_to, 'deploy_directory_for_replace'
|
7
|
+
set :repository, 'repo_path_for_replace'
|
8
|
+
set :user, 'username_for_replace'
|
@@ -0,0 +1,10 @@
|
|
1
|
+
set :branch, 'staging'
|
2
|
+
set :unicorn_config, -> { "#{deploy_to}/#{current_path}/config/unicorn/staging.rb" }
|
3
|
+
set :unicorn_pid, -> { "#{deploy_to}/#{current_path}/tmp/pids/unicorn-staging.pid" }
|
4
|
+
set :rails_env, 'staging'
|
5
|
+
|
6
|
+
#set variables
|
7
|
+
set :domain, 'domain_for_replace'
|
8
|
+
set :deploy_to, 'deploy_directory_for_replace_staging'
|
9
|
+
set :repository, 'repo_path_for_replace'
|
10
|
+
set :user, 'username_for_replace'
|
@@ -0,0 +1,28 @@
|
|
1
|
+
app_path = File.expand_path( File.join(File.dirname(__FILE__), '..', '..'))
|
2
|
+
|
3
|
+
worker_processes 4
|
4
|
+
preload_app true
|
5
|
+
timeout 180
|
6
|
+
listen '/tmp/unicorn.sock'
|
7
|
+
pid "#{app_path}/tmp/pids/unicorn.pid"
|
8
|
+
user 'username_for_replace', 'username_for_replace'
|
9
|
+
stderr_path "log/unicorn_err.log"
|
10
|
+
stdout_path "log/unicorn.log"
|
11
|
+
|
12
|
+
before_fork do |server, worker|
|
13
|
+
old_pid = "#{server.config[:pid]}.oldbin"
|
14
|
+
if File.exists?(old_pid) && server.pid != old_pid
|
15
|
+
begin
|
16
|
+
Process.kill("QUIT", File.read(old_pid).to_i)
|
17
|
+
rescue Errno::ENOENT, Errno::ESRCH
|
18
|
+
# someone else did our job for us
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
after_fork do |server, worker|
|
24
|
+
end
|
25
|
+
|
26
|
+
before_exec do |server|
|
27
|
+
ENV["BUNDLE_GEMFILE"] = "#{app_path}/Gemfile"
|
28
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
app_path = File.expand_path( File.join(File.dirname(__FILE__), '..', '..'))
|
2
|
+
|
3
|
+
worker_processes 1
|
4
|
+
preload_app true
|
5
|
+
timeout 180
|
6
|
+
listen '/tmp/unicorn-staging.sock'
|
7
|
+
pid "#{app_path}/tmp/pids/unicorn-staging.pid"
|
8
|
+
user 'username_for_replace', 'username_for_replace'
|
9
|
+
stderr_path "log/unicorn-stagingerr.log"
|
10
|
+
stdout_path "log/unicorn-stagingout.log"
|
11
|
+
|
12
|
+
before_fork do |server, worker|
|
13
|
+
old_pid = "#{server.config[:pid]}.oldbin"
|
14
|
+
if File.exists?(old_pid) && server.pid != old_pid
|
15
|
+
begin
|
16
|
+
Process.kill("QUIT", File.read(old_pid).to_i)
|
17
|
+
rescue Errno::ENOENT, Errno::ESRCH
|
18
|
+
# someone else did our job for us
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
after_fork do |server, worker|
|
24
|
+
end
|
25
|
+
|
26
|
+
before_exec do |server|
|
27
|
+
ENV["BUNDLE_GEMFILE"] = "#{app_path}/Gemfile"
|
28
|
+
end
|
data/lib/weapon.rb
CHANGED
@@ -37,46 +37,62 @@ class Weapon < Thor
|
|
37
37
|
def setup_mina_unicorn
|
38
38
|
makesure_in_git
|
39
39
|
|
40
|
+
gem 'mina-multistage', require: false
|
40
41
|
gem 'mina-unicorn', require: false
|
41
42
|
gem 'unicorn'
|
42
43
|
run "bundle"
|
43
|
-
|
44
|
-
|
45
|
-
copy_file 'support/mina_unicorn/unicorn.rb', 'config/unicorn.rb'
|
46
|
-
gsub_file "config/unicorn.rb", "app_name_for_replace", app_name
|
44
|
+
FileUtils.mkdir_p "config/deploy"
|
45
|
+
FileUtils.mkdir_p "config/unicorn"
|
47
46
|
|
47
|
+
copy_file 'support/mina_unicorn/deploy.rb', 'config/deploy.rb'
|
48
|
+
copy_file 'support/mina_unicorn/unicorn_production.rb', 'config/unicorn/production.rb'
|
49
|
+
copy_file 'support/mina_unicorn/unicorn_staging.rb', 'config/unicorn/staging.rb'
|
50
|
+
copy_file 'support/mina_unicorn/deploy_production.rb', 'config/deploy/production.rb'
|
51
|
+
copy_file 'support/mina_unicorn/deploy_staging.rb', 'config/deploy/staging.rb'
|
48
52
|
copy_file 'support/mina_unicorn/unicorn-nginx.conf', 'unicorn-nginx.conf'
|
49
|
-
gsub_file "config/unicorn.rb", "app_name_for_replace", app_name
|
50
|
-
|
51
|
-
domain_name = ask("input your domain name, used as nginx conf file's server_name, like www.example.com: ")
|
52
|
-
gsub_file "unicorn-nginx.conf", "app_name_for_replace", app_name
|
53
|
-
gsub_file "unicorn-nginx.conf", "domain_name_for_replace", domain_name
|
54
53
|
|
55
54
|
puts "setup mina deploy"
|
56
|
-
copy_file 'support/mina_unicorn/deploy.rb', 'config/deploy.rb'
|
57
55
|
|
58
|
-
|
56
|
+
app_name = `pwd`.split('/')[-1].strip()
|
57
|
+
username, domain = ask("input your username && host like seaify@1.2.3.4: ").split('@')
|
58
|
+
deploy_directory = "/home/#{username}/#{app_name}"
|
59
|
+
repo_path = `git config --get remote.origin.url`.strip()
|
59
60
|
|
60
|
-
|
61
|
-
|
61
|
+
%w(app_name username domain deploy_directory repo_path).each do |key|
|
62
|
+
ap key
|
63
|
+
gsub_file "config/deploy/production.rb", "#{key}_for_replace", eval(key)
|
64
|
+
gsub_file "config/deploy/staging.rb", "#{key}_for_replace", eval(key)
|
62
65
|
|
63
|
-
|
64
|
-
|
66
|
+
gsub_file "config/unicorn/production.rb", "#{key}_for_replace", eval(key)
|
67
|
+
gsub_file "config/unicorn/staging.rb", "#{key}_for_replace", eval(key)
|
65
68
|
|
66
|
-
|
67
|
-
|
68
|
-
gsub_file "config/deploy.rb", "deploy_path_for_replace", directory
|
69
|
+
gsub_file "unicorn-nginx.conf", "#{key}_for_replace", eval(key)
|
70
|
+
gsub_file "config/deploy.rb", "#{key}_for_replace", eval(key)
|
69
71
|
|
70
|
-
|
71
|
-
repository = ask("input your git remote url to pull from, default #{default_repo} ")
|
72
|
-
gsub_file "config/deploy.rb", "repo_path_for_replace", (repository != "")?repository: default_repo
|
72
|
+
end
|
73
73
|
|
74
|
-
setup_dir_command = 'ssh ' + username + '@' + domain + " -t 'mkdir -p " +
|
74
|
+
setup_dir_command = 'ssh ' + username + '@' + domain + " -t 'mkdir -p " + deploy_directory + ';chown -R ' + username + ' ' + deploy_directory + "'"
|
75
75
|
run setup_dir_command
|
76
|
+
setup_staging_dir_command = 'ssh ' + username + '@' + domain + " -t 'mkdir -p " + deploy_directory + '_staging;chown -R ' + username + ' ' + deploy_directory + "_staging'"
|
77
|
+
run setup_staging_dir_command
|
78
|
+
|
79
|
+
|
80
|
+
run 'scp config/database.yml ' + username + '@' + domain + ':' + deploy_directory + '/shared/config/'
|
81
|
+
run 'scp config/application.yml ' + username + '@' + domain + ':' + deploy_directory + '/shared/config/'
|
82
|
+
run 'scp config/secrets.yml ' + username + '@' + domain + ':' + deploy_directory + '/shared/config/'
|
83
|
+
|
84
|
+
run 'scp config/database.yml ' + username + '@' + domain + ':' + deploy_directory + '_staging/shared/config/'
|
85
|
+
run 'scp config/application.yml ' + username + '@' + domain + ':' + deploy_directory + '_staging/shared/config/'
|
86
|
+
run 'scp config/secrets.yml ' + username + '@' + domain + ':' + deploy_directory + '_staging/shared/config/'
|
87
|
+
|
88
|
+
run 'scp unicorn-nginx.conf ' + username + '@' + domain + ':' + "/etc/nginx/sites-enabled/#{app_name}.conf"
|
89
|
+
=begin
|
90
|
+
run "git clone https://github.com/sstephenson/rbenv.git ~/.rbenv"
|
91
|
+
run "echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.zshrc"
|
92
|
+
run "echo 'eval "$(rbenv init -)"' >> ~/.zshrc"
|
93
|
+
=end
|
76
94
|
|
77
95
|
run 'mina setup'
|
78
|
-
run 'scp config/database.yml ' + username + '@' + domain + ':' + directory + '/shared/config/'
|
79
|
-
run 'scp unicorn-nginx.conf ' + username + '@' + domain + ':' + '/etc/nginx/sites-enabled/#{app_name}.conf'
|
80
96
|
run 'mina deploy'
|
81
97
|
puts "remember to restart nginx server"
|
82
98
|
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.
|
4
|
+
version: 0.1.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
|
-
-
|
7
|
+
- Chuck.lei
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-05-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -66,20 +66,6 @@ dependencies:
|
|
66
66
|
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '1.6'
|
69
|
-
- !ruby/object:Gem::Dependency
|
70
|
-
name: magicfile
|
71
|
-
requirement: !ruby/object:Gem::Requirement
|
72
|
-
requirements:
|
73
|
-
- - "~>"
|
74
|
-
- !ruby/object:Gem::Version
|
75
|
-
version: 0.0.3
|
76
|
-
type: :runtime
|
77
|
-
prerelease: false
|
78
|
-
version_requirements: !ruby/object:Gem::Requirement
|
79
|
-
requirements:
|
80
|
-
- - "~>"
|
81
|
-
- !ruby/object:Gem::Version
|
82
|
-
version: 0.0.3
|
83
69
|
description: provide mina deploy, github setup, slack exception notify, i18n scaffold,
|
84
70
|
rails-settings-ui, guard custom
|
85
71
|
email: dilin.life@gmail.com
|
@@ -89,18 +75,6 @@ extensions: []
|
|
89
75
|
extra_rdoc_files: []
|
90
76
|
files:
|
91
77
|
- bin/weapon
|
92
|
-
- lib/generators/weapon/activeadmin/activeadmin_generator.rb
|
93
|
-
- lib/generators/weapon/email/email_generator.rb
|
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
|
103
|
-
- lib/generators/weapon/i18n/i18n_generator.rb
|
104
78
|
- lib/support/create_gem/basic.bin
|
105
79
|
- lib/support/create_gem/basic.gemspec
|
106
80
|
- lib/support/create_gem/basic.rb
|
@@ -114,8 +88,12 @@ files:
|
|
114
88
|
- lib/support/custom_i18n/zh-CN.yml
|
115
89
|
- lib/support/exception_slack_notify/exception_notification.rb
|
116
90
|
- lib/support/mina_unicorn/deploy.rb
|
91
|
+
- lib/support/mina_unicorn/deploy_production.rb
|
92
|
+
- lib/support/mina_unicorn/deploy_staging.rb
|
117
93
|
- lib/support/mina_unicorn/unicorn-nginx.conf
|
118
94
|
- lib/support/mina_unicorn/unicorn.rb
|
95
|
+
- lib/support/mina_unicorn/unicorn_production.rb
|
96
|
+
- lib/support/mina_unicorn/unicorn_staging.rb
|
119
97
|
- lib/support/rails_settings_ui/rails_settings_ui.rb
|
120
98
|
- lib/support/rails_settings_ui/setting.rb
|
121
99
|
- lib/weapon.rb
|
@@ -139,7 +117,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
139
117
|
version: '0'
|
140
118
|
requirements: []
|
141
119
|
rubyforge_project:
|
142
|
-
rubygems_version: 2.4.
|
120
|
+
rubygems_version: 2.4.5
|
143
121
|
signing_key:
|
144
122
|
specification_version: 4
|
145
123
|
summary: weapon for rails application!
|
@@ -1,54 +0,0 @@
|
|
1
|
-
|
2
|
-
class Weapon::ActiveadminGenerator < Rails::Generators::NamedBase # :nodoc:
|
3
|
-
desc 'This generator creates activeadmin files'
|
4
|
-
|
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"
|
46
|
-
|
47
|
-
end
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
end
|
52
|
-
|
53
|
-
|
54
|
-
end
|
@@ -1,40 +0,0 @@
|
|
1
|
-
|
2
|
-
class Weapon::EmailGenerator < Rails::Generators::Base # :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
|
-
%(
|
8
|
-
config.action_mailer.raise_delivery_errors = true
|
9
|
-
config.action_mailer.default_url_options = {:host => 'http://www.example.com'}
|
10
|
-
config.action_mailer.delivery_method = :smtp
|
11
|
-
config.action_mailer.smtp_settings = {
|
12
|
-
:address => "smtp.163.com",
|
13
|
-
:port => 25,
|
14
|
-
:user_name => "weapontest@163.com",
|
15
|
-
:password => "abcdef1234",
|
16
|
-
:enable_starttls_auto => true,
|
17
|
-
:authentication => "plain",
|
18
|
-
:domain => "163.com"
|
19
|
-
}
|
20
|
-
)
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
def add_exception_notify
|
25
|
-
gem_group :production do
|
26
|
-
gem "exception_notification"
|
27
|
-
end
|
28
|
-
|
29
|
-
application(nil, env: "production") do
|
30
|
-
%(
|
31
|
-
config.middleware.use ExceptionNotification::Rack,
|
32
|
-
:email => {
|
33
|
-
:email_prefix => "[weapon] ",
|
34
|
-
:sender_address => "weapon <ledcloud@163.com>",
|
35
|
-
:exception_recipients => %w{dilin.life@gmail.com}
|
36
|
-
}
|
37
|
-
)
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
@@ -1,64 +0,0 @@
|
|
1
|
-
require 'magicfile'
|
2
|
-
require 'fileutils'
|
3
|
-
require 'thor'
|
4
|
-
|
5
|
-
class Weapon::GrapeGenerator < Rails::Generators::Base # :nodoc:
|
6
|
-
desc 'This generator creates basic grape files for models'
|
7
|
-
include Thor::Actions
|
8
|
-
|
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'
|
12
|
-
|
13
|
-
def generate_grape_files
|
14
|
-
|
15
|
-
prefix = 'app/api/v1'
|
16
|
-
FileUtils.mkdir_p prefix
|
17
|
-
|
18
|
-
if args[0].nil? || args[0] == "all"
|
19
|
-
names = Dir["app/models/*.rb"].map {|x| File.basename(x, '.rb')}
|
20
|
-
else
|
21
|
-
names = args
|
22
|
-
end
|
23
|
-
|
24
|
-
if options[:only]
|
25
|
-
names = names & options[:only].split(',')
|
26
|
-
end
|
27
|
-
|
28
|
-
if options[:except]
|
29
|
-
names = names - options[:except].split(',')
|
30
|
-
end
|
31
|
-
|
32
|
-
module_array = prefix.split('/')[1..-1]
|
33
|
-
names.each do |name|
|
34
|
-
a = Magicfile.new
|
35
|
-
a.append_modules(module_array)
|
36
|
-
a.append_class(name.camelize.pluralize, 'Grape::API')
|
37
|
-
infos = ["version 'v1', using: :path", "format :json", "default_format: json"]
|
38
|
-
a.append_string_lines(infos)
|
39
|
-
a.to_file "#{prefix}/#{name.pluralize}.rb"
|
40
|
-
end
|
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
|
-
|
62
|
-
end
|
63
|
-
|
64
|
-
end
|
@@ -1,86 +0,0 @@
|
|
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
|
@@ -1,35 +0,0 @@
|
|
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
|
@@ -1,28 +0,0 @@
|
|
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
|
@@ -1,81 +0,0 @@
|
|
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
|
@@ -1,24 +0,0 @@
|
|
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
|
@@ -1,14 +0,0 @@
|
|
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
|
@@ -1,55 +0,0 @@
|
|
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
|