weapon 0.1.2 → 0.1.3
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.
- 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
|