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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 26d89f9b3fbeb44e3217e8df7ae498dccf67153683c9ae28feace983ba68531d
4
- data.tar.gz: c5527c6ef4c1eb74a2f6a85cdb8fabd54133afa9203342005e0ba2715e4404dc
3
+ metadata.gz: fe2845048e277dc7fb21d3c93e50fd8dadbe7bbde5461a832217dfb704df5a34
4
+ data.tar.gz: 626ada7f57b9ba66807908c9374c4ce123cf311f0abd389a7211e6d0c6174849
5
5
  SHA512:
6
- metadata.gz: c31f5c0633b8c690f60d11b99f89faa4eb0d53c80a2c197888eafdf0a4d57307f2f6b75028d92aa4ec293fe3aaddc2c05b9ef958849cf4bb54f72e5bef996c0e
7
- data.tar.gz: bd4245fdd9e1f4f85a16735cb9dc1ea8ad1cbdb4c89522ff66518af82ab4a972fc674b2b68fabeaf42e02ff44a0b6a56e32734a838ef282f7d1d01bd9bb8789c
6
+ metadata.gz: 9610ea1cc8e3d868912b3a53632900b8588d7008534255679d0e8821f82672a6eb8287cfa06a7a1cc66d8d5d42b0714b5475e7dc38c4a697e3cd1420c1fdd127
7
+ data.tar.gz: 78cb840acb378734538c2aac586bdd219d3487c37a9a9a4ae977469139d0852a5295423117335be2030b262adf4e592004719406e3e4df4e99efaf4d179b4755
@@ -1,63 +1,63 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- mobile_workflow_cli (0.1.3)
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.12.2)
88
+ ffi (1.13.1)
89
89
  globalid (0.4.2)
90
90
  activesupport (>= 4.2.0)
91
- i18n (1.8.2)
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.0)
97
+ kaminari (1.2.1)
98
98
  activesupport (>= 4.1.0)
99
- kaminari-actionview (= 1.2.0)
100
- kaminari-activerecord (= 1.2.0)
101
- kaminari-core (= 1.2.0)
102
- kaminari-actionview (1.2.0)
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.0)
105
- kaminari-activerecord (1.2.0)
104
+ kaminari-core (= 1.2.1)
105
+ kaminari-activerecord (1.2.1)
106
106
  activerecord
107
- kaminari-core (= 1.2.0)
108
- kaminari-core (1.2.0)
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.3.0)
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.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.1)
190
+ websocket-driver (0.7.2)
191
191
  websocket-extensions (>= 0.1.0)
192
- websocket-extensions (0.1.4)
192
+ websocket-extensions (0.1.5)
193
193
  zeitwerk (2.3.0)
194
194
 
195
195
  PLATFORMS
@@ -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
@@ -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
- template 'Procfile', 'Procfile'
13
- template 'Procfile.dev', 'Procfile.dev'
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, aliases: "-H", default: false, desc: "Create Heroku app"
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
- build :procfiles
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
- deploy_heroku(admin_user, admin_password) if options[:heroku]
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
- //= link administrate/application.css
64
- //= link administrate/application.js
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
- module Admin
69
- class ApplicationController < Administrate::ApplicationController
70
- before_action :authenticate_admin
83
+ module Admin
84
+ class ApplicationController < Administrate::ApplicationController
85
+ before_action :authenticate_admin
71
86
 
72
- def authenticate_admin
73
- self.class.http_basic_authenticate_with(name: ENV["ADMIN_USER"], password: ENV["ADMIN_PASSWORD"])
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
- CODE
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
- properties_args = schema['properties'].keys.reject{|key| key == 'id'}.collect{|key| "#{key}:#{schema['properties'][key]['type']}" }.join(' ')
84
- generate(:model, "#{name.underscore} #{properties_args}")
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
- openapi_spec[:paths].each_pair do |url_path, path|
99
- controller_name = url_path.split('/').last.pluralize
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
- ADMIN_USER=#{admin_user}
135
- ADMIN_PASSWORD=#{admin_password}
136
- CODE
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
@@ -1,5 +1,5 @@
1
1
  module MobileWorkflowCli
2
- VERSION = "0.1.3"
2
+ VERSION = "0.1.4"
3
3
  RUBY_VERSION = '2.5.5'
4
4
  RAILS_VERSION = '6.0.0'
5
5
  end
@@ -3,45 +3,42 @@ git_source(:github) { |repo| "https://github.com/#{repo}.git" }
3
3
 
4
4
  ruby '2.6.6'
5
5
 
6
- # Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
7
- gem 'rails', '~> 6.0.3'
8
- # Use postgresql as the database for Active Record
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
- # Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder
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
- # Use Active Storage variant
26
- # gem 'image_processing', '~> 1.2'
15
+ # Authorisation / Authentication
16
+ gem 'cancancan', '~> 3.1'
27
17
 
28
18
  # Admin console
29
- gem "administrate"
30
-
31
- # Reduces boot times through caching; required in config/boot.rb
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
- group :development, :test do
35
- # Call 'byebug' anywhere in the code to stop execution and get a debugger console
36
- gem 'byebug', platforms: [:mri, :mingw, :x64_mingw]
37
- gem 'dotenv-rails'
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', '~> 3.2'
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,7 @@
1
+ class Ability
2
+ include CanCan::Ability
3
+
4
+ def initialize(user)
5
+ can :manage, :all
6
+ end
7
+ 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,2 @@
1
+ class ApplicationController < ActionController::Base
2
+ 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
@@ -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.3
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-05-16 00:00:00.000000000 Z
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