mobile_workflow_cli 0.1.3 → 0.1.4
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/Gemfile.lock +66 -66
- data/bin/mwf-delete +19 -0
- data/lib/mobile_workflow_cli.rb +5 -0
- data/lib/mobile_workflow_cli/app_builder.rb +90 -2
- data/lib/mobile_workflow_cli/app_cleaner.rb +24 -0
- data/lib/mobile_workflow_cli/app_generator.rb +47 -57
- data/lib/mobile_workflow_cli/aws_backend.rb +57 -0
- data/lib/mobile_workflow_cli/dokku_backend.rb +53 -0
- data/lib/mobile_workflow_cli/heroku_backend.rb +45 -0
- data/lib/mobile_workflow_cli/version.rb +1 -1
- data/templates/Gemfile.erb +25 -28
- data/templates/ability.rb +7 -0
- data/templates/api_controller.rb +32 -0
- data/templates/application_controller.rb +2 -0
- data/templates/controller.rb +39 -0
- data/templates/controller_generator.rb +18 -0
- data/templates/controller_spec.rb +41 -0
- data/templates/model.rb +56 -0
- data/templates/notifications_controller.rb +93 -0
- data/templates/storage.s3.yml +14 -0
- metadata +16 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fe2845048e277dc7fb21d3c93e50fd8dadbe7bbde5461a832217dfb704df5a34
|
4
|
+
data.tar.gz: 626ada7f57b9ba66807908c9374c4ce123cf311f0abd389a7211e6d0c6174849
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9610ea1cc8e3d868912b3a53632900b8588d7008534255679d0e8821f82672a6eb8287cfa06a7a1cc66d8d5d42b0714b5475e7dc38c4a697e3cd1420c1fdd127
|
7
|
+
data.tar.gz: 78cb840acb378734538c2aac586bdd219d3487c37a9a9a4ae977469139d0852a5295423117335be2030b262adf4e592004719406e3e4df4e99efaf4d179b4755
|
data/Gemfile.lock
CHANGED
@@ -1,63 +1,63 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
mobile_workflow_cli (0.1.
|
4
|
+
mobile_workflow_cli (0.1.4)
|
5
5
|
administrate
|
6
6
|
rails (>= 6.0.0)
|
7
7
|
|
8
8
|
GEM
|
9
9
|
remote: https://rubygems.org/
|
10
10
|
specs:
|
11
|
-
actioncable (6.0.3)
|
12
|
-
actionpack (= 6.0.3)
|
11
|
+
actioncable (6.0.3.1)
|
12
|
+
actionpack (= 6.0.3.1)
|
13
13
|
nio4r (~> 2.0)
|
14
14
|
websocket-driver (>= 0.6.1)
|
15
|
-
actionmailbox (6.0.3)
|
16
|
-
actionpack (= 6.0.3)
|
17
|
-
activejob (= 6.0.3)
|
18
|
-
activerecord (= 6.0.3)
|
19
|
-
activestorage (= 6.0.3)
|
20
|
-
activesupport (= 6.0.3)
|
15
|
+
actionmailbox (6.0.3.1)
|
16
|
+
actionpack (= 6.0.3.1)
|
17
|
+
activejob (= 6.0.3.1)
|
18
|
+
activerecord (= 6.0.3.1)
|
19
|
+
activestorage (= 6.0.3.1)
|
20
|
+
activesupport (= 6.0.3.1)
|
21
21
|
mail (>= 2.7.1)
|
22
|
-
actionmailer (6.0.3)
|
23
|
-
actionpack (= 6.0.3)
|
24
|
-
actionview (= 6.0.3)
|
25
|
-
activejob (= 6.0.3)
|
22
|
+
actionmailer (6.0.3.1)
|
23
|
+
actionpack (= 6.0.3.1)
|
24
|
+
actionview (= 6.0.3.1)
|
25
|
+
activejob (= 6.0.3.1)
|
26
26
|
mail (~> 2.5, >= 2.5.4)
|
27
27
|
rails-dom-testing (~> 2.0)
|
28
|
-
actionpack (6.0.3)
|
29
|
-
actionview (= 6.0.3)
|
30
|
-
activesupport (= 6.0.3)
|
28
|
+
actionpack (6.0.3.1)
|
29
|
+
actionview (= 6.0.3.1)
|
30
|
+
activesupport (= 6.0.3.1)
|
31
31
|
rack (~> 2.0, >= 2.0.8)
|
32
32
|
rack-test (>= 0.6.3)
|
33
33
|
rails-dom-testing (~> 2.0)
|
34
34
|
rails-html-sanitizer (~> 1.0, >= 1.2.0)
|
35
|
-
actiontext (6.0.3)
|
36
|
-
actionpack (= 6.0.3)
|
37
|
-
activerecord (= 6.0.3)
|
38
|
-
activestorage (= 6.0.3)
|
39
|
-
activesupport (= 6.0.3)
|
35
|
+
actiontext (6.0.3.1)
|
36
|
+
actionpack (= 6.0.3.1)
|
37
|
+
activerecord (= 6.0.3.1)
|
38
|
+
activestorage (= 6.0.3.1)
|
39
|
+
activesupport (= 6.0.3.1)
|
40
40
|
nokogiri (>= 1.8.5)
|
41
|
-
actionview (6.0.3)
|
42
|
-
activesupport (= 6.0.3)
|
41
|
+
actionview (6.0.3.1)
|
42
|
+
activesupport (= 6.0.3.1)
|
43
43
|
builder (~> 3.1)
|
44
44
|
erubi (~> 1.4)
|
45
45
|
rails-dom-testing (~> 2.0)
|
46
46
|
rails-html-sanitizer (~> 1.1, >= 1.2.0)
|
47
|
-
activejob (6.0.3)
|
48
|
-
activesupport (= 6.0.3)
|
47
|
+
activejob (6.0.3.1)
|
48
|
+
activesupport (= 6.0.3.1)
|
49
49
|
globalid (>= 0.3.6)
|
50
|
-
activemodel (6.0.3)
|
51
|
-
activesupport (= 6.0.3)
|
52
|
-
activerecord (6.0.3)
|
53
|
-
activemodel (= 6.0.3)
|
54
|
-
activesupport (= 6.0.3)
|
55
|
-
activestorage (6.0.3)
|
56
|
-
actionpack (= 6.0.3)
|
57
|
-
activejob (= 6.0.3)
|
58
|
-
activerecord (= 6.0.3)
|
50
|
+
activemodel (6.0.3.1)
|
51
|
+
activesupport (= 6.0.3.1)
|
52
|
+
activerecord (6.0.3.1)
|
53
|
+
activemodel (= 6.0.3.1)
|
54
|
+
activesupport (= 6.0.3.1)
|
55
|
+
activestorage (6.0.3.1)
|
56
|
+
actionpack (= 6.0.3.1)
|
57
|
+
activejob (= 6.0.3.1)
|
58
|
+
activerecord (= 6.0.3.1)
|
59
59
|
marcel (~> 0.3.1)
|
60
|
-
activesupport (6.0.3)
|
60
|
+
activesupport (6.0.3.1)
|
61
61
|
concurrent-ruby (~> 1.0, >= 1.0.2)
|
62
62
|
i18n (>= 0.7, < 2)
|
63
63
|
minitest (~> 5.1)
|
@@ -85,27 +85,27 @@ GEM
|
|
85
85
|
diff-lcs (1.3)
|
86
86
|
erubi (1.9.0)
|
87
87
|
execjs (2.7.0)
|
88
|
-
ffi (1.
|
88
|
+
ffi (1.13.1)
|
89
89
|
globalid (0.4.2)
|
90
90
|
activesupport (>= 4.2.0)
|
91
|
-
i18n (1.8.
|
91
|
+
i18n (1.8.3)
|
92
92
|
concurrent-ruby (~> 1.0)
|
93
93
|
jquery-rails (4.4.0)
|
94
94
|
rails-dom-testing (>= 1, < 3)
|
95
95
|
railties (>= 4.2.0)
|
96
96
|
thor (>= 0.14, < 2.0)
|
97
|
-
kaminari (1.2.
|
97
|
+
kaminari (1.2.1)
|
98
98
|
activesupport (>= 4.1.0)
|
99
|
-
kaminari-actionview (= 1.2.
|
100
|
-
kaminari-activerecord (= 1.2.
|
101
|
-
kaminari-core (= 1.2.
|
102
|
-
kaminari-actionview (1.2.
|
99
|
+
kaminari-actionview (= 1.2.1)
|
100
|
+
kaminari-activerecord (= 1.2.1)
|
101
|
+
kaminari-core (= 1.2.1)
|
102
|
+
kaminari-actionview (1.2.1)
|
103
103
|
actionview
|
104
|
-
kaminari-core (= 1.2.
|
105
|
-
kaminari-activerecord (1.2.
|
104
|
+
kaminari-core (= 1.2.1)
|
105
|
+
kaminari-activerecord (1.2.1)
|
106
106
|
activerecord
|
107
|
-
kaminari-core (= 1.2.
|
108
|
-
kaminari-core (1.2.
|
107
|
+
kaminari-core (= 1.2.1)
|
108
|
+
kaminari-core (1.2.1)
|
109
109
|
loofah (2.5.0)
|
110
110
|
crass (~> 1.0.2)
|
111
111
|
nokogiri (>= 1.5.9)
|
@@ -126,29 +126,29 @@ GEM
|
|
126
126
|
rack (2.2.2)
|
127
127
|
rack-test (1.1.0)
|
128
128
|
rack (>= 1.0, < 3)
|
129
|
-
rails (6.0.3)
|
130
|
-
actioncable (= 6.0.3)
|
131
|
-
actionmailbox (= 6.0.3)
|
132
|
-
actionmailer (= 6.0.3)
|
133
|
-
actionpack (= 6.0.3)
|
134
|
-
actiontext (= 6.0.3)
|
135
|
-
actionview (= 6.0.3)
|
136
|
-
activejob (= 6.0.3)
|
137
|
-
activemodel (= 6.0.3)
|
138
|
-
activerecord (= 6.0.3)
|
139
|
-
activestorage (= 6.0.3)
|
140
|
-
activesupport (= 6.0.3)
|
129
|
+
rails (6.0.3.1)
|
130
|
+
actioncable (= 6.0.3.1)
|
131
|
+
actionmailbox (= 6.0.3.1)
|
132
|
+
actionmailer (= 6.0.3.1)
|
133
|
+
actionpack (= 6.0.3.1)
|
134
|
+
actiontext (= 6.0.3.1)
|
135
|
+
actionview (= 6.0.3.1)
|
136
|
+
activejob (= 6.0.3.1)
|
137
|
+
activemodel (= 6.0.3.1)
|
138
|
+
activerecord (= 6.0.3.1)
|
139
|
+
activestorage (= 6.0.3.1)
|
140
|
+
activesupport (= 6.0.3.1)
|
141
141
|
bundler (>= 1.3.0)
|
142
|
-
railties (= 6.0.3)
|
142
|
+
railties (= 6.0.3.1)
|
143
143
|
sprockets-rails (>= 2.0.0)
|
144
144
|
rails-dom-testing (2.0.3)
|
145
145
|
activesupport (>= 4.2.0)
|
146
146
|
nokogiri (>= 1.6)
|
147
147
|
rails-html-sanitizer (1.3.0)
|
148
148
|
loofah (~> 2.3)
|
149
|
-
railties (6.0.3)
|
150
|
-
actionpack (= 6.0.3)
|
151
|
-
activesupport (= 6.0.3)
|
149
|
+
railties (6.0.3.1)
|
150
|
+
actionpack (= 6.0.3.1)
|
151
|
+
activesupport (= 6.0.3.1)
|
152
152
|
method_source
|
153
153
|
rake (>= 0.8.7)
|
154
154
|
thor (>= 0.20.3, < 2.0)
|
@@ -166,7 +166,7 @@ GEM
|
|
166
166
|
diff-lcs (>= 1.2.0, < 2.0)
|
167
167
|
rspec-support (~> 3.9.0)
|
168
168
|
rspec-support (3.9.3)
|
169
|
-
sassc (2.
|
169
|
+
sassc (2.4.0)
|
170
170
|
ffi (~> 1.9)
|
171
171
|
sassc-rails (2.1.2)
|
172
172
|
railties (>= 4.0.0)
|
@@ -175,7 +175,7 @@ GEM
|
|
175
175
|
sprockets-rails
|
176
176
|
tilt
|
177
177
|
selectize-rails (0.12.6)
|
178
|
-
sprockets (4.0.
|
178
|
+
sprockets (4.0.2)
|
179
179
|
concurrent-ruby (~> 1.0)
|
180
180
|
rack (> 1, < 3)
|
181
181
|
sprockets-rails (3.2.1)
|
@@ -187,9 +187,9 @@ GEM
|
|
187
187
|
tilt (2.0.10)
|
188
188
|
tzinfo (1.2.7)
|
189
189
|
thread_safe (~> 0.1)
|
190
|
-
websocket-driver (0.7.
|
190
|
+
websocket-driver (0.7.2)
|
191
191
|
websocket-extensions (>= 0.1.0)
|
192
|
-
websocket-extensions (0.1.
|
192
|
+
websocket-extensions (0.1.5)
|
193
193
|
zeitwerk (2.3.0)
|
194
194
|
|
195
195
|
PLATFORMS
|
data/bin/mwf-delete
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'pathname'
|
3
|
+
require 'byebug'
|
4
|
+
|
5
|
+
source_path = (Pathname.new(__FILE__).dirname + '../lib').expand_path
|
6
|
+
$LOAD_PATH << source_path
|
7
|
+
|
8
|
+
require 'mobile_workflow_cli'
|
9
|
+
|
10
|
+
if ARGV.empty?
|
11
|
+
puts "USAGE: mwf-delete <directory>"
|
12
|
+
puts "See --help for more info"
|
13
|
+
exit 0
|
14
|
+
elsif ['-v', '--version'].include? ARGV[0]
|
15
|
+
puts MobileWorkflowCli::VERSION
|
16
|
+
exit 0
|
17
|
+
end
|
18
|
+
|
19
|
+
MobileWorkflowCli::AppCleaner.start
|
data/lib/mobile_workflow_cli.rb
CHANGED
@@ -2,6 +2,11 @@ require "mobile_workflow_cli/version"
|
|
2
2
|
|
3
3
|
require "mobile_workflow_cli/app_generator"
|
4
4
|
require "mobile_workflow_cli/app_builder"
|
5
|
+
require "mobile_workflow_cli/app_cleaner"
|
6
|
+
|
7
|
+
require "mobile_workflow_cli/aws_backend"
|
8
|
+
require "mobile_workflow_cli/heroku_backend"
|
9
|
+
require "mobile_workflow_cli/dokku_backend"
|
5
10
|
|
6
11
|
module MobileWorkflowCli
|
7
12
|
class Error < StandardError; end
|
@@ -9,8 +9,96 @@ module MobileWorkflowCli
|
|
9
9
|
end
|
10
10
|
|
11
11
|
def procfiles
|
12
|
-
|
13
|
-
|
12
|
+
copy_file 'Procfile', 'Procfile'
|
13
|
+
copy_file 'Procfile.dev', 'Procfile.dev'
|
14
|
+
end
|
15
|
+
|
16
|
+
def rspec_generator
|
17
|
+
generate 'rspec:install'
|
18
|
+
end
|
19
|
+
|
20
|
+
def controller_generator
|
21
|
+
copy_file 'controller_generator.rb', 'lib/generators/mobile_workflow/controller_generator.rb'
|
22
|
+
copy_file 'controller.rb', 'lib/generators/mobile_workflow/templates/controller.rb'
|
23
|
+
copy_file 'controller_spec.rb', 'lib/generators/mobile_workflow/templates/controller_spec.rb'
|
24
|
+
end
|
25
|
+
|
26
|
+
def ability_generator
|
27
|
+
copy_file 'ability.rb', 'app/models/ability.rb'
|
28
|
+
end
|
29
|
+
|
30
|
+
def application_controller
|
31
|
+
copy_file 'application_controller.rb', 'app/controllers/application_controller.rb'
|
32
|
+
end
|
33
|
+
|
34
|
+
def api_controller
|
35
|
+
copy_file 'api_controller.rb', 'app/controllers/api_controller.rb'
|
36
|
+
end
|
37
|
+
|
38
|
+
def model_template
|
39
|
+
copy_file 'model.rb', 'lib/templates/active_record/model/model.rb'
|
40
|
+
end
|
41
|
+
|
42
|
+
def active_storage
|
43
|
+
rails_command 'active_storage:install'
|
44
|
+
copy_file 'storage.s3.yml', 'config/storage.yml'
|
45
|
+
gsub_file 'config/environments/production.rb', 'config.active_storage.service = :local', 'config.active_storage.service = :amazon'
|
46
|
+
end
|
47
|
+
|
48
|
+
def notifications_controller
|
49
|
+
copy_file 'notifications_controller.rb', 'app/controllers/notifications_controller.rb'
|
50
|
+
route 'resources :notifications, only: :create'
|
51
|
+
end
|
52
|
+
|
53
|
+
def s3_backend(region)
|
54
|
+
@region = region
|
55
|
+
aws_backend.create
|
56
|
+
say "AWS Access ID: #{aws_backend.access_id}"
|
57
|
+
say "AWS Secret Key: #{aws_backend.secret_key}"
|
58
|
+
|
59
|
+
open('.env', 'a') { |f|
|
60
|
+
f.puts "AWS_ACCESS_ID=#{aws_backend.access_id}"
|
61
|
+
f.puts "AWS_SECRET_KEY=#{aws_backend.secret_key}"
|
62
|
+
f.puts "AWS_REGION=#{aws_backend.region}"
|
63
|
+
f.puts "AWS_BUCKET_NAME=#{aws_backend.bucket_name}"
|
64
|
+
}
|
65
|
+
|
66
|
+
if options[:heroku]
|
67
|
+
heroku_backend.sync_dotenv
|
68
|
+
aws_backend.create_topic_subscription(heroku_backend.notifications_endpoint)
|
69
|
+
elsif options[:dokku]
|
70
|
+
dokku_backend.sync_dotenv
|
71
|
+
aws_backend.create_topic_subscription(dokku_backend.notifications_endpoint)
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
|
76
|
+
def heroku
|
77
|
+
heroku_backend.create
|
78
|
+
heroku_backend.configure_activestorage if options[:s3_storage]
|
79
|
+
heroku_backend.deploy
|
80
|
+
heroku_backend.sync_dotenv
|
81
|
+
end
|
82
|
+
|
83
|
+
def dokku(dokku_host)
|
84
|
+
@dokku_host = dokku_host
|
85
|
+
dokku_backend.create
|
86
|
+
dokku_backend.configure_activestorage if options[:s3_storage]
|
87
|
+
dokku_backend.deploy
|
88
|
+
dokku_backend.sync_dotenv
|
89
|
+
end
|
90
|
+
|
91
|
+
private
|
92
|
+
def aws_backend
|
93
|
+
@aws_backend ||= AwsBackend.new(app_name: app_name, region: @region)
|
94
|
+
end
|
95
|
+
|
96
|
+
def dokku_backend
|
97
|
+
@dokku_backend ||= DokkuBackend.new(app_name: app_name, dokku_host: @dokku_host)
|
98
|
+
end
|
99
|
+
|
100
|
+
def heroku_backend
|
101
|
+
@heroku_backend ||= HerokuBackend.new(app_name: app_name)
|
14
102
|
end
|
15
103
|
end
|
16
104
|
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'rails/generators'
|
2
|
+
require 'rails/generators/rails/app/app_generator'
|
3
|
+
require 'json'
|
4
|
+
require 'active_support/core_ext/hash/indifferent_access'
|
5
|
+
|
6
|
+
module MobileWorkflowCli
|
7
|
+
class AppCleaner < Thor
|
8
|
+
class_option :version, type: :boolean, aliases: "-v", desc: "Show version number and quit"
|
9
|
+
class_option :help, type: :boolean, aliases: '-h', desc: "Show this help message and quit"
|
10
|
+
|
11
|
+
class_option :deploy_heroku, type: :boolean, aliases: "-H", default: false, desc: "Create Heroku app"
|
12
|
+
class_option :s3_storage, type: :boolean, default: false, desc: "Create an s3 backend for image upload and storage"
|
13
|
+
class_option :aws_region, type: :string, default: 'us-east-1', desc: "Specify a region to create AWS resources in"
|
14
|
+
|
15
|
+
desc "clean APP_NAME", "clean the app"
|
16
|
+
def clean(app_name)
|
17
|
+
`rm -rf #{app_name}`
|
18
|
+
AwsBackend.new(app_name: app_name, region: options[:aws_region]).destroy
|
19
|
+
HerokuBackend.new(app_name: app_name).destroy
|
20
|
+
end
|
21
|
+
|
22
|
+
|
23
|
+
end
|
24
|
+
end
|
@@ -5,16 +5,20 @@ require 'active_support/core_ext/hash/indifferent_access'
|
|
5
5
|
|
6
6
|
module MobileWorkflowCli
|
7
7
|
class AppGenerator < Rails::Generators::AppGenerator
|
8
|
-
hide!
|
9
|
-
|
10
|
-
class_option :database, type: :string, aliases: "-d", default: "postgresql", desc: "Configure for selected database (options: #{DATABASES.join("/")})"
|
8
|
+
hide!
|
11
9
|
class_option :skip_test, type: :boolean, default: true, desc: "Skip Test Unit"
|
12
10
|
class_option :force, type: :boolean, default: true, desc: "Force overwrite"
|
13
11
|
|
14
12
|
class_option :version, type: :boolean, aliases: "-v", desc: "Show version number and quit"
|
15
13
|
class_option :help, type: :boolean, aliases: '-h', desc: "Show this help message and quit"
|
16
14
|
|
17
|
-
class_option :heroku, type: :boolean,
|
15
|
+
class_option :heroku, type: :boolean, default: false, desc: "Create Heroku app"
|
16
|
+
|
17
|
+
class_option :dokku, type: :boolean, default: false, desc: "Create Dokku app"
|
18
|
+
class_option :dokku_host, type: :string, desc: "Specify the Dokku host machine e.g. 18.131.127.164"
|
19
|
+
|
20
|
+
class_option :s3_storage, type: :boolean, default: false, desc: "Create an s3 backend for image upload and storage"
|
21
|
+
class_option :aws_region, type: :string, default: 'us-east-1', desc: "Specify a region to create AWS resources in"
|
18
22
|
|
19
23
|
def self.banner
|
20
24
|
"mwf <directory> <OpenAPI Spec file path> [options]"
|
@@ -22,15 +26,24 @@ module MobileWorkflowCli
|
|
22
26
|
|
23
27
|
def finish_template
|
24
28
|
run "spring stop"
|
25
|
-
|
29
|
+
|
26
30
|
super
|
27
31
|
after_bundle do
|
32
|
+
build :application_controller
|
33
|
+
build :api_controller
|
34
|
+
build :notifications_controller if options[:s3_storage]
|
35
|
+
build :model_template
|
36
|
+
build :procfiles
|
37
|
+
build :rspec_generator
|
38
|
+
build :controller_generator
|
39
|
+
build :ability_generator
|
40
|
+
build :active_storage if options[:s3_storage]
|
41
|
+
|
28
42
|
open_api_spec = read_openapi_spec
|
29
43
|
generate_models(open_api_spec)
|
30
44
|
setup_db
|
31
45
|
|
32
46
|
generate_administrate
|
33
|
-
generate_base_api_controller(open_api_spec)
|
34
47
|
generate_controllers_and_routes(open_api_spec)
|
35
48
|
|
36
49
|
admin_user = 'admin'
|
@@ -38,7 +51,9 @@ module MobileWorkflowCli
|
|
38
51
|
generate_dot_env(admin_user, admin_password)
|
39
52
|
initial_git_commit
|
40
53
|
|
41
|
-
|
54
|
+
build :heroku if options[:heroku]
|
55
|
+
build :dokku, options[:dokku_host] if options[:dokku]
|
56
|
+
build :s3_backend, options[:aws_region] if options[:s3_storage]
|
42
57
|
end
|
43
58
|
end
|
44
59
|
|
@@ -60,61 +75,43 @@ module MobileWorkflowCli
|
|
60
75
|
def generate_administrate
|
61
76
|
generate 'administrate:install'
|
62
77
|
file 'app/assets/config/manifest.js', <<-CODE
|
63
|
-
|
64
|
-
|
78
|
+
//= link administrate/application.css
|
79
|
+
//= link administrate/application.js
|
65
80
|
CODE
|
66
81
|
|
67
82
|
file 'app/controllers/admin/application_controller.rb', <<-CODE
|
68
|
-
|
69
|
-
|
70
|
-
|
83
|
+
module Admin
|
84
|
+
class ApplicationController < Administrate::ApplicationController
|
85
|
+
before_action :authenticate_admin
|
71
86
|
|
72
|
-
|
73
|
-
|
74
|
-
end
|
75
|
-
end
|
87
|
+
def authenticate_admin
|
88
|
+
self.class.http_basic_authenticate_with(name: ENV["ADMIN_USER"], password: ENV["ADMIN_PASSWORD"])
|
76
89
|
end
|
77
|
-
|
90
|
+
end
|
91
|
+
end
|
92
|
+
CODE
|
78
93
|
end
|
79
94
|
|
80
95
|
def generate_models(openapi_spec)
|
81
96
|
say "Generating models"
|
82
97
|
openapi_spec[:components][:schemas].each_pair do |name, schema|
|
83
|
-
|
84
|
-
|
98
|
+
next if ["answer", "attachment"].include? name # Don't generate schemas for MW schemas
|
99
|
+
|
100
|
+
generated_properties_args = schema["properties"].keys.collect{|key| "#{key}:string" }.join(" ")
|
101
|
+
if yes? "Use generated schema #{name}(#{generated_properties_args})[yn]?"
|
102
|
+
generate(:model, "#{name.underscore} #{generated_properties_args}")
|
103
|
+
else
|
104
|
+
properties_args = ask "Specify schema for #{name}: (e.g. text:string image:attachment region:reference)"
|
105
|
+
generate(:model, "#{name.underscore} #{properties_args}")
|
106
|
+
end
|
85
107
|
end
|
86
108
|
end
|
87
109
|
|
88
|
-
def generate_base_api_controller(openapi_spec)
|
89
|
-
file 'app/controllers/api_controller.rb', <<-CODE
|
90
|
-
class ApiController < ActionController::API
|
91
|
-
end
|
92
|
-
CODE
|
93
|
-
end
|
94
|
-
|
95
110
|
def generate_controllers_and_routes(openapi_spec)
|
96
111
|
say "Generating controllers"
|
97
|
-
controller_names = []
|
98
|
-
|
99
|
-
|
100
|
-
model = path[:get][:responses]["200"][:content]['application/json'][:schema][:items]['$ref'].split('/').last
|
101
|
-
file "app/controllers/#{controller_name}_controller.rb", <<-CODE
|
102
|
-
class #{controller_name.titleize}Controller < ApiController
|
103
|
-
def index
|
104
|
-
render json: #{model}.where(filter_params)
|
105
|
-
end
|
106
|
-
|
107
|
-
private
|
108
|
-
def filter_params
|
109
|
-
params.permit() # Add any filter properties here
|
110
|
-
end
|
111
|
-
end
|
112
|
-
CODE
|
113
|
-
controller_names << controller_name
|
114
|
-
end
|
115
|
-
controller_names.each {|n| route "resources :#{n}, only: :index" }
|
116
|
-
|
117
|
-
# Root route
|
112
|
+
controller_names = openapi_spec[:paths].keys.collect{|url_path| url_path.split('/').last.pluralize }
|
113
|
+
controller_names.each {|n| generate "mobile_workflow:controller #{n.singularize}" }
|
114
|
+
controller_names.each {|n| route "resources :#{n}, only: [:index, :show, :create]" }
|
118
115
|
route "root to: 'admin/#{controller_names.first}#index'"
|
119
116
|
end
|
120
117
|
|
@@ -131,16 +128,9 @@ module MobileWorkflowCli
|
|
131
128
|
|
132
129
|
def generate_dot_env(admin_user, admin_password)
|
133
130
|
file '.env', <<-CODE
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
end
|
138
|
-
|
139
|
-
def deploy_heroku(admin_user, admin_password)
|
140
|
-
heroku_output = `heroku create`
|
141
|
-
`git push heroku master`
|
142
|
-
`heroku config:set ADMIN_USER=#{admin_user} ADMIN_PASSWORD=#{admin_password}`
|
143
|
-
say "Server created: #{heroku_output}"
|
131
|
+
ADMIN_USER=#{admin_user}
|
132
|
+
ADMIN_PASSWORD=#{admin_password}
|
133
|
+
CODE
|
144
134
|
end
|
145
135
|
end
|
146
136
|
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
class AwsBackend
|
2
|
+
|
3
|
+
attr_accessor :access_id, :secret_key, :region, :bucket_name
|
4
|
+
|
5
|
+
def initialize(app_name:, region:)
|
6
|
+
@app_name = app_name
|
7
|
+
@aws_name = @app_name.gsub("_", "-")
|
8
|
+
@region = region
|
9
|
+
end
|
10
|
+
|
11
|
+
def bucket_name
|
12
|
+
@aws_name
|
13
|
+
end
|
14
|
+
|
15
|
+
def create
|
16
|
+
aws_command "aws s3api create-bucket --bucket #{@aws_name} --acl private --region #{@region} --create-bucket-configuration LocationConstraint=#{@region}"
|
17
|
+
@topic_arn = aws_command("aws sns create-topic --name #{@aws_name} --region #{@region}")["TopicArn"]
|
18
|
+
aws_command "aws iam create-user --user-name #{@aws_name}"
|
19
|
+
aws_command "aws iam put-user-policy --user-name #{@aws_name} --policy-name s3 --policy-document '{\"Version\":\"2012-10-17\",\"Statement\":[{\"Effect\":\"Allow\",\"Action\":[\"s3:PutObject\",\"s3:PutObjectAcl\",\"s3:GetObject\", \"s3:DeleteObject\"],\"Resource\":[\"arn:aws:s3:::#{@aws_name}/*\"]}, {\"Effect\": \"Allow\", \"Action\": \"s3:ListBucket\", \"Resource\": \"arn:aws:s3:::#{@aws_name}\"}]}'"
|
20
|
+
aws_command "aws iam put-user-policy --user-name #{@aws_name} --policy-name sns --policy-document '{\"Version\":\"2012-10-17\",\"Statement\":[{\"Effect\":\"Allow\",\"Action\":[\"sns:ConfirmSubscription\"],\"Resource\":[\"#{@topic_arn}\"]}]}'"
|
21
|
+
aws_command "aws sns set-topic-attributes --topic-arn #{@topic_arn} --region #{@region} --attribute-name Policy --attribute-value '{\"Version\": \"2012-10-17\", \"Id\": \"s3\", \"Statement\": [{\"Sid\": \"#{@aws_name}-s3-sid\", \"Effect\": \"Allow\", \"Principal\": {\"AWS\": \"*\"}, \"Action\": \"SNS:Publish\", \"Resource\": \"#{@topic_arn}\", \"Condition\": {\"ArnEquals\": {\"aws:SourceArn\": \"arn:aws:s3:::#{@aws_name}\"}}}]}'"
|
22
|
+
aws_command "aws s3api put-bucket-notification-configuration --bucket #{@aws_name} --notification-configuration '{\"TopicConfigurations\": [{\"TopicArn\": \"#{@topic_arn}\", \"Events\": [\"s3:ObjectCreated:*\"]}]}'"
|
23
|
+
aws_credentials_json = aws_command("aws iam create-access-key --user-name #{@aws_name}")["AccessKey"]
|
24
|
+
@access_id, @secret_key = aws_credentials_json["AccessKeyId"], aws_credentials_json["SecretAccessKey"]
|
25
|
+
|
26
|
+
return @access_id, @secret_key
|
27
|
+
end
|
28
|
+
|
29
|
+
def create_topic_subscription(endpoint)
|
30
|
+
aws_command "aws sns subscribe --topic-arn #{@topic_arn} --region #{@region} --protocol https --notification-endpoint #{endpoint}"
|
31
|
+
end
|
32
|
+
|
33
|
+
def destroy
|
34
|
+
aws_command "aws s3api delete-bucket --bucket #{@aws_name} --region #{@region}"
|
35
|
+
|
36
|
+
aws_command("aws sns list-topics")["Topics"].each do |topic|
|
37
|
+
topic_arn = topic["TopicArn"]
|
38
|
+
aws_command "aws sns delete-topic --topic-arn '#{topic_arn}'" if topic_arn.end_with?(@aws_name)
|
39
|
+
end
|
40
|
+
|
41
|
+
aws_command "aws iam delete-user-policy --user-name #{@aws_name} --policy-name s3"
|
42
|
+
aws_command "aws iam delete-user-policy --user-name #{@aws_name} --policy-name sns"
|
43
|
+
aws_command("aws iam list-access-keys --user-name #{@aws_name}")["AccessKeyMetadata"].each do |accessKeyMetadata|
|
44
|
+
aws_command "aws iam delete-access-key --user-name #{@aws_name} --access-key #{accessKeyMetadata["AccessKeyId"]}"
|
45
|
+
end
|
46
|
+
aws_command "aws iam delete-user --user-name #{@aws_name}"
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
def aws_command(command)
|
51
|
+
puts "Running: #{command}"
|
52
|
+
output = `#{command}`
|
53
|
+
puts "Output: #{output}" unless output.blank?
|
54
|
+
return !output.blank? ? JSON.parse(output) : nil
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
class DokkuBackend
|
2
|
+
def initialize(dokku_host:, app_name:)
|
3
|
+
@dokku_host = dokku_host
|
4
|
+
@dokku_app_name = app_name.gsub("_", "-")
|
5
|
+
end
|
6
|
+
|
7
|
+
def create
|
8
|
+
remote_command "dokku apps:create #{@dokku_app_name}"
|
9
|
+
remote_command "dokku postgres:create #{@dokku_app_name}"
|
10
|
+
remote_command "dokku postgres:link #{@dokku_app_name} #{@dokku_app_name}"
|
11
|
+
|
12
|
+
local_command "git remote add dokku dokku@#{@dokku_host}:#{@dokku_app_name}"
|
13
|
+
end
|
14
|
+
|
15
|
+
def configure_activestorage
|
16
|
+
|
17
|
+
end
|
18
|
+
|
19
|
+
def deploy
|
20
|
+
local_command "git push dokku master"
|
21
|
+
end
|
22
|
+
|
23
|
+
def sync_dotenv
|
24
|
+
env = File.read(".env").split.join(" ")
|
25
|
+
puts "Setting env: #{env}"
|
26
|
+
local_command "dokku config:set #{env}"
|
27
|
+
end
|
28
|
+
|
29
|
+
def destroy
|
30
|
+
remote_command "dokku apps:destroy #{@dokku_app_name}"
|
31
|
+
end
|
32
|
+
|
33
|
+
def dokku_app_host
|
34
|
+
remote_command "dokku url #{@dokku_app_name}"
|
35
|
+
end
|
36
|
+
|
37
|
+
def notifications_endpoint
|
38
|
+
"https://#{dokku_app_host}/notifications"
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
def remote_command(command)
|
43
|
+
command = "ssh -t ubuntu@#{@dokku_host} '#{command}'"
|
44
|
+
local_command(command)
|
45
|
+
end
|
46
|
+
|
47
|
+
def local_command(command)
|
48
|
+
puts "Running: #{command}"
|
49
|
+
output = `#{command}`
|
50
|
+
puts "Output: #{output}" unless output.blank?
|
51
|
+
return output
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
class HerokuBackend
|
2
|
+
def initialize(app_name:)
|
3
|
+
@heroku_app_name = app_name.gsub("_", "-")
|
4
|
+
end
|
5
|
+
|
6
|
+
def create
|
7
|
+
heroku_command "heroku create #{@heroku_app_name}"
|
8
|
+
heroku_command "git push --set-upstream heroku master"
|
9
|
+
end
|
10
|
+
|
11
|
+
def configure_activestorage
|
12
|
+
heroku_command "heroku buildpacks:add -i 1 https://github.com/heroku/heroku-buildpack-activestorage-preview --app #{@heroku_app_name}"
|
13
|
+
heroku_command "heroku labs:enable runtime-dyno-metadata --app #{@heroku_app_name}" # Gives access to heroku variables which can be used to construct URLs
|
14
|
+
|
15
|
+
# Force recompile after buildpacks change
|
16
|
+
heroku_command "git commit --allow-empty -m 'empty commit'"
|
17
|
+
deploy
|
18
|
+
end
|
19
|
+
|
20
|
+
def deploy
|
21
|
+
heroku_command "git push"
|
22
|
+
end
|
23
|
+
|
24
|
+
def sync_dotenv
|
25
|
+
env = File.read(".env").split.join(" ")
|
26
|
+
puts "Setting env: #{env}"
|
27
|
+
heroku_command "heroku config:set #{env} --app #{@heroku_app_name}"
|
28
|
+
end
|
29
|
+
|
30
|
+
def destroy
|
31
|
+
heroku_command "heroku destroy #{@heroku_app_name} --confirm #{@heroku_app_name}"
|
32
|
+
end
|
33
|
+
|
34
|
+
def notifications_endpoint
|
35
|
+
"https://#{@heroku_app_name}.herokuapp.com/notifications"
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
def heroku_command(command)
|
40
|
+
puts "Running: #{command}"
|
41
|
+
output = `#{command}`
|
42
|
+
puts "Output: #{output}" unless output.blank?
|
43
|
+
return output
|
44
|
+
end
|
45
|
+
end
|
data/templates/Gemfile.erb
CHANGED
@@ -3,45 +3,42 @@ git_source(:github) { |repo| "https://github.com/#{repo}.git" }
|
|
3
3
|
|
4
4
|
ruby '2.6.6'
|
5
5
|
|
6
|
-
#
|
7
|
-
gem 'rails', '~> 6.0.
|
8
|
-
|
9
|
-
gem 'pg', '>= 0.18', '< 2.0'
|
10
|
-
# Use Puma as the app server
|
6
|
+
# Core Gems
|
7
|
+
gem 'rails', '~> 6.0.2', '>= 6.0.2.2'
|
8
|
+
|
11
9
|
gem 'puma', '~> 4.1'
|
12
|
-
# Use SCSS for stylesheets
|
13
10
|
gem 'sass-rails', '>= 6'
|
14
|
-
# Transpile app-like JavaScript. Read more: https://github.com/rails/webpacker
|
15
11
|
gem 'webpacker', '~> 4.0'
|
16
|
-
# Turbolinks makes navigating your web application faster. Read more: https://github.com/turbolinks/turbolinks
|
17
12
|
gem 'turbolinks', '~> 5'
|
18
|
-
|
19
|
-
gem 'jbuilder', '~> 2.7'
|
20
|
-
# Use Redis adapter to run Action Cable in production
|
21
|
-
# gem 'redis', '~> 4.0'
|
22
|
-
# Use Active Model has_secure_password
|
23
|
-
# gem 'bcrypt', '~> 3.1.7'
|
13
|
+
gem 'bootsnap', '>= 1.4.2', require: false
|
24
14
|
|
25
|
-
#
|
26
|
-
|
15
|
+
# Authorisation / Authentication
|
16
|
+
gem 'cancancan', '~> 3.1'
|
27
17
|
|
28
18
|
# Admin console
|
29
|
-
gem
|
30
|
-
|
31
|
-
|
32
|
-
gem 'bootsnap', '>= 1.4.2', require: false
|
19
|
+
gem 'administrate', '~> 0.13.0'
|
20
|
+
gem 'administrate-field-active_storage'
|
21
|
+
gem 'administrate-field-enum'
|
33
22
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
end
|
23
|
+
# Backend storage for S3
|
24
|
+
gem "image_processing"
|
25
|
+
gem 'aws-sdk-s3', '~> 1.60', '>= 1.60.1'
|
26
|
+
gem 'aws-sdk-sns', '~> 1.23'
|
39
27
|
|
40
28
|
group :development do
|
41
|
-
# Access an interactive console on exception pages or by calling 'console' anywhere in the code.
|
42
29
|
gem 'web-console', '>= 3.3.0'
|
43
|
-
gem 'listen', '
|
44
|
-
# Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring
|
30
|
+
gem 'listen', '>= 3.0.5', '< 3.2'
|
45
31
|
gem 'spring'
|
46
32
|
gem 'spring-watcher-listen', '~> 2.0.0'
|
47
33
|
end
|
34
|
+
|
35
|
+
group :development, :test do
|
36
|
+
gem 'sqlite3'
|
37
|
+
gem 'rspec-rails', '~> 4.0.0'
|
38
|
+
gem 'byebug', platforms: [:mri, :mingw, :x64_mingw]
|
39
|
+
gem 'dotenv-rails'
|
40
|
+
end
|
41
|
+
|
42
|
+
group :production do
|
43
|
+
gem 'pg', '>= 0.18', '< 2.0'
|
44
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
class ApiController < ActionController::API
|
2
|
+
def current_user
|
3
|
+
nil
|
4
|
+
end
|
5
|
+
|
6
|
+
def binary_urls(object)
|
7
|
+
return unless params["binaries"]
|
8
|
+
|
9
|
+
params["binaries"].collect do |binary|
|
10
|
+
property = binary["identifier"].split('/')[0] # i.e. image/jpg --> image, video/mp4 --> video
|
11
|
+
|
12
|
+
{
|
13
|
+
"identifier" => binary["identifier"],
|
14
|
+
"url" => presigned_url("#{object.class.name.underscore}/#{object.id}/#{property}"),
|
15
|
+
"method" => "PUT"
|
16
|
+
}
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
def presigned_url(key)
|
22
|
+
presigner.presigned_url(:put_object, bucket: ENV['AWS_BUCKET_NAME'], key: key, metadata: {})
|
23
|
+
end
|
24
|
+
|
25
|
+
def presigner
|
26
|
+
Aws::S3::Presigner.new(client: s3_client)
|
27
|
+
end
|
28
|
+
|
29
|
+
def s3_client
|
30
|
+
Aws::S3::Client.new(region: ENV['AWS_REGION'], access_key_id: ENV['AWS_ACCESS_ID'], secret_access_key: ENV['AWS_SECRET_KEY'])
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
class <%= controller_class_name %>Controller < ApiController
|
2
|
+
before_action :rewrite_payload, only: :create
|
3
|
+
|
4
|
+
load_and_authorize_resource
|
5
|
+
|
6
|
+
def index
|
7
|
+
render json: @<%= controller_class_name.underscore %>.collect(&:list_item_as_json)
|
8
|
+
end
|
9
|
+
|
10
|
+
def show
|
11
|
+
render json: @<%= controller_class_name.singularize.underscore %>.display_as_json
|
12
|
+
end
|
13
|
+
|
14
|
+
def create
|
15
|
+
if @<%= controller_class_name.singularize.underscore %>.save
|
16
|
+
render json: { binary_urls: binary_urls(@<%= controller_class_name.singularize.underscore %>), response: @<%= controller_class_name.singularize.underscore %> }, status: :created
|
17
|
+
else
|
18
|
+
head :unprocessable_entity
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
def rewrite_payload
|
24
|
+
Rails.logger.debug "Pre-rewrite params: #{params}"
|
25
|
+
|
26
|
+
# Use this method to make any changes to parameters
|
27
|
+
|
28
|
+
# Example to get properties from question
|
29
|
+
# params[:payload][:name] = params.dig(:payload, :name, :answer)
|
30
|
+
|
31
|
+
# Example to get properties from previous list
|
32
|
+
# passport_id = params.dig(:payload, :choose_passport, :selected, :id)
|
33
|
+
end
|
34
|
+
|
35
|
+
def <%= controller_class_name.singularize.underscore %>_params
|
36
|
+
# Permit any fields you want to save
|
37
|
+
params.require(:payload).permit(:name)
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module MobileWorkflow
|
2
|
+
module Generators
|
3
|
+
# Custom scaffolding generator
|
4
|
+
class ControllerGenerator < Rails::Generators::NamedBase
|
5
|
+
include Rails::Generators::ResourceHelpers
|
6
|
+
|
7
|
+
def self.source_root
|
8
|
+
Rails.root
|
9
|
+
end
|
10
|
+
|
11
|
+
def copy_controller_and_spec_files
|
12
|
+
template "lib/generators/mobile_workflow/templates/controller.rb", File.join("app/controllers", "#{controller_file_name}_controller.rb")
|
13
|
+
template "lib/generators/mobile_workflow/templates/controller_spec.rb", File.join("spec/controllers", "#{controller_file_name}_controller_spec.rb")
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rails_helper'
|
4
|
+
require 'json'
|
5
|
+
|
6
|
+
RSpec.describe <%= controller_class_name %>Controller do
|
7
|
+
let(:params) { {} }
|
8
|
+
let(:json_response) { JSON.parse(response.body, symbolize_names: true) }
|
9
|
+
|
10
|
+
describe 'GET #index' do
|
11
|
+
let!(:<%= controller_class_name.singularize.underscore %>) { <%= controller_class_name.singularize %>.create }
|
12
|
+
before(:each) { get :index, params: params }
|
13
|
+
|
14
|
+
context 'ok' do
|
15
|
+
it { expect(json_response[0][:id]).to eq <%= controller_class_name.singularize.underscore %>.id }
|
16
|
+
it { expect(response.status).to eq 200 }
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
describe 'GET #show' do
|
21
|
+
let(:<%= controller_class_name.singularize.underscore %>) { <%= controller_class_name.singularize %>.create }
|
22
|
+
let(:params) { { id: <%= controller_class_name.singularize.underscore %>.id } }
|
23
|
+
before(:each) { get :show, params: params }
|
24
|
+
|
25
|
+
context 'ok' do
|
26
|
+
it { expect(response.status).to eq 200 }
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe 'POST #create' do
|
31
|
+
let(:payload_params) { {text: 'OK'} }
|
32
|
+
let(:params) { { payload: payload_params, binaries: [{identifier: 'record', mimetype: 'video/mp4'}] } }
|
33
|
+
before(:each) { post :create, params: params }
|
34
|
+
|
35
|
+
context 'ok' do
|
36
|
+
it { expect(<%= controller_class_name.singularize %>.count).to eq 1 }
|
37
|
+
it { expect(response.status).to eq 201 }
|
38
|
+
it { expect(json_response[:binary_urls]).to_not be_nil }
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
data/templates/model.rb
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
<% module_namespacing do -%>
|
2
|
+
class <%= class_name %> < <%= parent_class_name.classify %>
|
3
|
+
# Enable if you need to generate attachment URLs
|
4
|
+
# include Rails.application.routes.url_helpers
|
5
|
+
|
6
|
+
<% attributes.select(&:reference?).each do |attribute| -%>
|
7
|
+
belongs_to :<%= attribute.name %><%= ', polymorphic: true' if attribute.polymorphic? %>
|
8
|
+
<% end -%>
|
9
|
+
<% attributes.select(&:attachment?).each do |attribute| -%>
|
10
|
+
has_one_attached :<%= attribute.name %>
|
11
|
+
<% end -%>
|
12
|
+
<% attributes.select(&:attachments?).each do |attribute| -%>
|
13
|
+
has_many_attached :<%= attribute.name %>
|
14
|
+
<% end -%>
|
15
|
+
|
16
|
+
def list_item_as_json
|
17
|
+
{
|
18
|
+
id: id,
|
19
|
+
text: text,
|
20
|
+
# detailText: nil,
|
21
|
+
# sfSymbolName: nil,
|
22
|
+
# imageURL: preview_url(image, height: 100, width: 100)
|
23
|
+
}
|
24
|
+
end
|
25
|
+
|
26
|
+
def display_as_json
|
27
|
+
[
|
28
|
+
{label: "ID", text: text, mimeType: 'text/plain'},
|
29
|
+
{label: "Text", text: text, mimeType: 'text/plain'}
|
30
|
+
]
|
31
|
+
end
|
32
|
+
|
33
|
+
# private
|
34
|
+
# include Rails.application.routes.url_helpers # for attachment URLs
|
35
|
+
# def preview_url(attachment, height:, width:, options: { resize_to_fill: [height, width]} )
|
36
|
+
# return nil unless attachment.attached?
|
37
|
+
#
|
38
|
+
# if attachment.image?
|
39
|
+
# Rails.application.routes.url_helpers.rails_representation_url(attachment.variant(combine_options: options), host: attachment_host)
|
40
|
+
# elsif attachment.previewable?
|
41
|
+
# Rails.application.routes.url_helpers.rails_representation_url(attachment.preview(options), host: attachment_host)
|
42
|
+
# else
|
43
|
+
# return nil
|
44
|
+
# end
|
45
|
+
# end
|
46
|
+
#
|
47
|
+
# def attachment_url(attachment)
|
48
|
+
# Rails.application.routes.url_helpers.rails_blob_url(attachment, host: attachment_host)
|
49
|
+
# end
|
50
|
+
#
|
51
|
+
# def attachment_host
|
52
|
+
# "https://#{ENV['HEROKU_APP_NAME']}.herokuapp.com"
|
53
|
+
# end
|
54
|
+
|
55
|
+
end
|
56
|
+
<% end -%>
|
@@ -0,0 +1,93 @@
|
|
1
|
+
class NotificationsController < ApiController
|
2
|
+
before_action :verify_request_authenticity
|
3
|
+
|
4
|
+
def create
|
5
|
+
Rails.logger.info("Message body: #{message_body}")
|
6
|
+
|
7
|
+
case message_body['Type']
|
8
|
+
when 'SubscriptionConfirmation'
|
9
|
+
confirm_subscription ? (head :ok) : (head :bad_request)
|
10
|
+
else
|
11
|
+
@object = find_object
|
12
|
+
@object.send("#{attribute_name}=",active_record_blob)
|
13
|
+
if @object.save
|
14
|
+
head :ok
|
15
|
+
else
|
16
|
+
Rails.logger.warn "Error saving object: #{@object} #{object.errors.full_messages}"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
def verify_request_authenticity
|
23
|
+
head :unauthorized if raw_post.blank?
|
24
|
+
|
25
|
+
#head :unauthorized if raw_post.blank? || !message_verifier.authentic?(raw_post) # Not working
|
26
|
+
end
|
27
|
+
|
28
|
+
def active_record_blob
|
29
|
+
s3_object = s3_bucket.object(object_key)
|
30
|
+
checksum_base64 = checksum_base64(object_key, s3_object)
|
31
|
+
ActiveStorage::Blob.create! key: s3_object.key, filename: s3_object.key, byte_size: s3_object.size, checksum: checksum_base64, content_type: s3_object.content_type
|
32
|
+
end
|
33
|
+
|
34
|
+
def checksum_base64(object_key, s3_object)
|
35
|
+
path = Tempfile.new(object_key).path
|
36
|
+
s3_object.download_file(path)
|
37
|
+
file = File.new(path)
|
38
|
+
Digest::MD5.file(file).base64digest
|
39
|
+
end
|
40
|
+
|
41
|
+
def find_object
|
42
|
+
object_class_name, object_id = key_identifiers
|
43
|
+
object_class_name.camelcase.constantize.find(object_id.to_i)
|
44
|
+
end
|
45
|
+
|
46
|
+
def attribute_name
|
47
|
+
key_identifiers[2]
|
48
|
+
end
|
49
|
+
|
50
|
+
def key_identifiers
|
51
|
+
object_class_name, object_id, attribute_name = object_key.split("/")
|
52
|
+
return object_class_name, object_id, attribute_name
|
53
|
+
end
|
54
|
+
|
55
|
+
def object_key
|
56
|
+
@object_key ||= message['Records'][0]['s3']['object']['key']
|
57
|
+
end
|
58
|
+
|
59
|
+
def message
|
60
|
+
message = JSON.parse(message_body['Message'])
|
61
|
+
end
|
62
|
+
|
63
|
+
def message_body
|
64
|
+
@message_body ||= JSON.parse(raw_post)
|
65
|
+
end
|
66
|
+
|
67
|
+
def raw_post
|
68
|
+
@raw_post ||= request.raw_post
|
69
|
+
end
|
70
|
+
|
71
|
+
def message_verifier
|
72
|
+
@message_verifier ||= Aws::SNS::MessageVerifier.new
|
73
|
+
end
|
74
|
+
|
75
|
+
def confirm_subscription
|
76
|
+
sns_client.confirm_subscription(
|
77
|
+
topic_arn: message_body['TopicArn'],
|
78
|
+
token: message_body['Token']
|
79
|
+
)
|
80
|
+
return true
|
81
|
+
rescue Aws::SNS::Errors::ServiceError => e
|
82
|
+
Rails.logger.warn(e.message)
|
83
|
+
return false
|
84
|
+
end
|
85
|
+
|
86
|
+
def s3_bucket
|
87
|
+
Aws::S3::Resource.new(region: ENV['AWS_REGION'], access_key_id: ENV['AWS_ACCESS_ID'], secret_access_key: ENV['AWS_SECRET_KEY']).bucket(ENV['AWS_BUCKET_NAME'])
|
88
|
+
end
|
89
|
+
|
90
|
+
def sns_client
|
91
|
+
Aws::SNS::Client.new(region: ENV['AWS_REGION'], access_key_id: ENV['AWS_ACCESS_ID'], secret_access_key: ENV['AWS_SECRET_KEY'])
|
92
|
+
end
|
93
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
test:
|
2
|
+
service: Disk
|
3
|
+
root: <%= Rails.root.join("tmp/storage") %>
|
4
|
+
|
5
|
+
local:
|
6
|
+
service: Disk
|
7
|
+
root: <%= Rails.root.join("storage") %>
|
8
|
+
|
9
|
+
amazon:
|
10
|
+
service: S3
|
11
|
+
access_key_id: <%= ENV['AWS_ACCESS_ID'] %>
|
12
|
+
secret_access_key: <%= ENV['AWS_SECRET_KEY'] %>
|
13
|
+
region: <%= ENV['AWS_REGION'] %>
|
14
|
+
bucket: <%= ENV['AWS_BUCKET_NAME'] %>
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mobile_workflow_cli
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Matt Brooke-Smith
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-06-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: administrate
|
@@ -71,10 +71,15 @@ files:
|
|
71
71
|
- Rakefile
|
72
72
|
- USAGE
|
73
73
|
- bin/mwf
|
74
|
+
- bin/mwf-delete
|
74
75
|
- bin/setup
|
75
76
|
- lib/mobile_workflow_cli.rb
|
76
77
|
- lib/mobile_workflow_cli/app_builder.rb
|
78
|
+
- lib/mobile_workflow_cli/app_cleaner.rb
|
77
79
|
- lib/mobile_workflow_cli/app_generator.rb
|
80
|
+
- lib/mobile_workflow_cli/aws_backend.rb
|
81
|
+
- lib/mobile_workflow_cli/dokku_backend.rb
|
82
|
+
- lib/mobile_workflow_cli/heroku_backend.rb
|
78
83
|
- lib/mobile_workflow_cli/version.rb
|
79
84
|
- mobile_workflow_cli.gemspec
|
80
85
|
- spec/mobile_workflow_cli_spec.rb
|
@@ -83,6 +88,15 @@ files:
|
|
83
88
|
- templates/Procfile
|
84
89
|
- templates/Procfile.dev
|
85
90
|
- templates/README.md.erb
|
91
|
+
- templates/ability.rb
|
92
|
+
- templates/api_controller.rb
|
93
|
+
- templates/application_controller.rb
|
94
|
+
- templates/controller.rb
|
95
|
+
- templates/controller_generator.rb
|
96
|
+
- templates/controller_spec.rb
|
97
|
+
- templates/model.rb
|
98
|
+
- templates/notifications_controller.rb
|
99
|
+
- templates/storage.s3.yml
|
86
100
|
homepage: https://github.com/FutureWorkshops/MobileWorkflowCli
|
87
101
|
licenses:
|
88
102
|
- MIT
|