rhino_project_core 0.20.0.beta.18

Sign up to get free protection for your applications and to get access to all the features.
Files changed (117) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +28 -0
  3. data/Rakefile +34 -0
  4. data/app/assets/stripe_flow.png +0 -0
  5. data/app/controllers/concerns/rhino/authenticated.rb +18 -0
  6. data/app/controllers/concerns/rhino/error_handling.rb +58 -0
  7. data/app/controllers/concerns/rhino/paper_trail_whodunnit.rb +11 -0
  8. data/app/controllers/concerns/rhino/permit.rb +38 -0
  9. data/app/controllers/concerns/rhino/set_current_user.rb +13 -0
  10. data/app/controllers/rhino/account_controller.rb +34 -0
  11. data/app/controllers/rhino/active_model_extension_controller.rb +52 -0
  12. data/app/controllers/rhino/base_controller.rb +23 -0
  13. data/app/controllers/rhino/crud_controller.rb +57 -0
  14. data/app/controllers/rhino/simple_controller.rb +11 -0
  15. data/app/controllers/rhino/simple_stream_controller.rb +12 -0
  16. data/app/helpers/rhino/omniauth_helper.rb +67 -0
  17. data/app/helpers/rhino/policy_helper.rb +42 -0
  18. data/app/helpers/rhino/segment_helper.rb +62 -0
  19. data/app/models/rhino/account.rb +13 -0
  20. data/app/models/rhino/current.rb +7 -0
  21. data/app/models/rhino/user.rb +44 -0
  22. data/app/overrides/active_record/autosave_association_override.rb +18 -0
  23. data/app/overrides/active_record/delegated_type_override.rb +14 -0
  24. data/app/overrides/activestorage/direct_uploads_controller_override.rb +23 -0
  25. data/app/overrides/activestorage/redirect_controller_override.rb +21 -0
  26. data/app/overrides/activestorage/redirect_representation_controller_override.rb +21 -0
  27. data/app/overrides/devise_token_auth/confirmations_controller_override.rb +14 -0
  28. data/app/overrides/devise_token_auth/omniauth_callbacks_controller_override.rb +45 -0
  29. data/app/overrides/devise_token_auth/passwords_controller_override.rb +9 -0
  30. data/app/overrides/devise_token_auth/registrations_controller_override.rb +20 -0
  31. data/app/overrides/devise_token_auth/sessions_controller_override.rb +26 -0
  32. data/app/overrides/devise_token_auth/token_validations_controller_override.rb +18 -0
  33. data/app/policies/rhino/account_policy.rb +27 -0
  34. data/app/policies/rhino/active_storage_attachment_policy.rb +16 -0
  35. data/app/policies/rhino/admin_policy.rb +20 -0
  36. data/app/policies/rhino/base_policy.rb +72 -0
  37. data/app/policies/rhino/crud_policy.rb +109 -0
  38. data/app/policies/rhino/editor_policy.rb +12 -0
  39. data/app/policies/rhino/global_policy.rb +8 -0
  40. data/app/policies/rhino/resource_info_policy.rb +9 -0
  41. data/app/policies/rhino/user_policy.rb +20 -0
  42. data/app/policies/rhino/viewer_policy.rb +19 -0
  43. data/app/resources/rhino/info_graph.rb +41 -0
  44. data/app/resources/rhino/open_api_info.rb +108 -0
  45. data/config/routes.rb +19 -0
  46. data/db/migrate/20180101000000_devise_token_auth_create_users.rb +54 -0
  47. data/db/migrate/20180622142754_add_allow_change_password_to_users.rb +5 -0
  48. data/db/migrate/20191217010224_add_approved_to_users.rb +7 -0
  49. data/db/migrate/20200503182019_change_tokens_to_json_b.rb +9 -0
  50. data/lib/commands/rhino_command.rb +59 -0
  51. data/lib/generators/rhino/dev/setup/setup_generator.rb +175 -0
  52. data/lib/generators/rhino/dev/setup/templates/env.client.tt +4 -0
  53. data/lib/generators/rhino/dev/setup/templates/env.server.tt +35 -0
  54. data/lib/generators/rhino/dev/setup/templates/prepare-commit-msg +17 -0
  55. data/lib/generators/rhino/install/install_generator.rb +24 -0
  56. data/lib/generators/rhino/install/templates/account.rb +4 -0
  57. data/lib/generators/rhino/install/templates/rhino.rb +24 -0
  58. data/lib/generators/rhino/install/templates/user.rb +4 -0
  59. data/lib/generators/rhino/module/module_generator.rb +93 -0
  60. data/lib/generators/rhino/module/templates/engine.rb.tt +19 -0
  61. data/lib/generators/rhino/module/templates/install_generator.rb.tt +12 -0
  62. data/lib/generators/rhino/module/templates/module_tasks.rake.tt +17 -0
  63. data/lib/generators/rhino/policy/policy_generator.rb +33 -0
  64. data/lib/generators/rhino/policy/templates/policy.rb.tt +46 -0
  65. data/lib/generators/test_unit/rhino_policy_generator.rb +13 -0
  66. data/lib/generators/test_unit/templates/policy_test.rb.tt +57 -0
  67. data/lib/rhino/engine.rb +140 -0
  68. data/lib/rhino/omniauth/strategies/azure_o_auth2.rb +16 -0
  69. data/lib/rhino/resource/active_model_extension/backing_store/google_sheet.rb +89 -0
  70. data/lib/rhino/resource/active_model_extension/backing_store.rb +33 -0
  71. data/lib/rhino/resource/active_model_extension/describe.rb +38 -0
  72. data/lib/rhino/resource/active_model_extension/params.rb +70 -0
  73. data/lib/rhino/resource/active_model_extension/properties.rb +229 -0
  74. data/lib/rhino/resource/active_model_extension/reference.rb +50 -0
  75. data/lib/rhino/resource/active_model_extension/routing.rb +15 -0
  76. data/lib/rhino/resource/active_model_extension/serialization.rb +16 -0
  77. data/lib/rhino/resource/active_model_extension.rb +38 -0
  78. data/lib/rhino/resource/active_record_extension/describe.rb +44 -0
  79. data/lib/rhino/resource/active_record_extension/params.rb +213 -0
  80. data/lib/rhino/resource/active_record_extension/properties.rb +85 -0
  81. data/lib/rhino/resource/active_record_extension/properties_describe.rb +226 -0
  82. data/lib/rhino/resource/active_record_extension/reference.rb +50 -0
  83. data/lib/rhino/resource/active_record_extension/routing.rb +21 -0
  84. data/lib/rhino/resource/active_record_extension/search.rb +23 -0
  85. data/lib/rhino/resource/active_record_extension/serialization.rb +16 -0
  86. data/lib/rhino/resource/active_record_extension.rb +30 -0
  87. data/lib/rhino/resource/active_record_tree.rb +50 -0
  88. data/lib/rhino/resource/active_storage_extension.rb +41 -0
  89. data/lib/rhino/resource/describe.rb +19 -0
  90. data/lib/rhino/resource/owner.rb +172 -0
  91. data/lib/rhino/resource/params.rb +31 -0
  92. data/lib/rhino/resource/properties.rb +192 -0
  93. data/lib/rhino/resource/reference.rb +31 -0
  94. data/lib/rhino/resource/routing.rb +107 -0
  95. data/lib/rhino/resource/serialization.rb +13 -0
  96. data/lib/rhino/resource/sieves.rb +36 -0
  97. data/lib/rhino/resource.rb +54 -0
  98. data/lib/rhino/sieve/filter.rb +149 -0
  99. data/lib/rhino/sieve/helpers.rb +11 -0
  100. data/lib/rhino/sieve/limit.rb +20 -0
  101. data/lib/rhino/sieve/offset.rb +16 -0
  102. data/lib/rhino/sieve/order.rb +143 -0
  103. data/lib/rhino/sieve/search.rb +20 -0
  104. data/lib/rhino/sieve.rb +158 -0
  105. data/lib/rhino/test_case/controller.rb +134 -0
  106. data/lib/rhino/test_case/override.rb +19 -0
  107. data/lib/rhino/test_case/policy.rb +76 -0
  108. data/lib/rhino/test_case.rb +10 -0
  109. data/lib/rhino/version.rb +17 -0
  110. data/lib/rhino.rb +129 -0
  111. data/lib/tasks/rhino.rake +38 -0
  112. data/lib/tasks/rhino_dev.rake +17 -0
  113. data/lib/validators/country_validator.rb +11 -0
  114. data/lib/validators/email_validator.rb +8 -0
  115. data/lib/validators/ipv4_validator.rb +10 -0
  116. data/lib/validators/mac_address_validator.rb +9 -0
  117. metadata +178 -0
data/config/routes.rb ADDED
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ Rails.application.routes.draw do
4
+ scope Rhino.namespace do
5
+ mount_devise_token_auth_for 'User', at: "auth"
6
+
7
+ Rhino.resource_classes.each do |m|
8
+ if m.route_singular?
9
+ resource m.route_key, path: m.route_path, controller: m.controller_name, only: m.routes, rhino_resource: m.name, format: false
10
+ else
11
+ resources m.route_key, path: m.route_path, controller: m.controller_name, only: m.routes, rhino_resource: m.name, format: false
12
+ end
13
+ end
14
+ end
15
+
16
+ match "*#{Rhino.namespace}", to: 'rhino/base#not_found', via: :all, constraints: lambda { |request|
17
+ request.url[/\/rails\/active_storage\//].nil?
18
+ }
19
+ end
@@ -0,0 +1,54 @@
1
+ class DeviseTokenAuthCreateUsers < ActiveRecord::Migration[5.1]
2
+ def change
3
+ create_table(:users) do |t|
4
+ ## Required
5
+ t.string :provider, :null => false, :default => "email"
6
+ t.string :uid, :null => false, :default => ""
7
+
8
+ ## Database authenticatable
9
+ t.string :encrypted_password, :null => false, :default => ""
10
+
11
+ ## Recoverable
12
+ t.string :reset_password_token
13
+ t.datetime :reset_password_sent_at
14
+
15
+ ## Rememberable
16
+ t.datetime :remember_created_at
17
+
18
+ ## Trackable
19
+ t.integer :sign_in_count, :default => 0, :null => false
20
+ t.datetime :current_sign_in_at
21
+ t.datetime :last_sign_in_at
22
+ t.string :current_sign_in_ip
23
+ t.string :last_sign_in_ip
24
+
25
+ ## Confirmable
26
+ t.string :confirmation_token
27
+ t.datetime :confirmed_at
28
+ t.datetime :confirmation_sent_at
29
+ t.string :unconfirmed_email # Only if using reconfirmable
30
+
31
+ ## Lockable
32
+ # t.integer :failed_attempts, :default => 0, :null => false # Only if lock strategy is :failed_attempts
33
+ # t.string :unlock_token # Only if unlock strategy is :email or :both
34
+ # t.datetime :locked_at
35
+
36
+ ## User Info
37
+ t.string :name
38
+ t.string :nickname
39
+ t.string :image
40
+ t.string :email
41
+
42
+ ## Tokens
43
+ t.json :tokens
44
+
45
+ t.timestamps
46
+ end
47
+
48
+ add_index :users, :email, unique: true
49
+ add_index :users, [:uid, :provider], unique: true
50
+ add_index :users, :reset_password_token, unique: true
51
+ add_index :users, :confirmation_token, unique: true
52
+ # add_index :users, :unlock_token, unique: true
53
+ end
54
+ end
@@ -0,0 +1,5 @@
1
+ class AddAllowChangePasswordToUsers < ActiveRecord::Migration[5.2]
2
+ def change
3
+ add_column :users, :allow_password_change, :boolean, default: false, null: false
4
+ end
5
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ class AddApprovedToUsers < ActiveRecord::Migration[5.2]
4
+ def change
5
+ add_column :users, :approved, :boolean, default: false
6
+ end
7
+ end
@@ -0,0 +1,9 @@
1
+ class ChangeTokensToJsonB < ActiveRecord::Migration[5.2]
2
+ def up
3
+ change_column :users, :tokens, 'jsonb using tokens::jsonb'
4
+ end
5
+
6
+ def down
7
+ change_column :users, :tokens, 'json using tokens::json'
8
+ end
9
+ end
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "dotenv"
4
+ require "rails/command"
5
+
6
+ module Rails
7
+ module Command
8
+ class RhinoCommand < Base # :nodoc:
9
+ include Thor::Actions
10
+
11
+ no_commands do
12
+ def help
13
+ say "rails rhino::dummy [module] command # Run rails command in dummy application, defaults to rhino"
14
+ end
15
+ end
16
+
17
+ def dummy(*args)
18
+ rhino_command("test/dummy", nil, *args)
19
+ end
20
+
21
+ def test(*args)
22
+ rhino_command(nil, "test", *args)
23
+ end
24
+
25
+ def rails(*args)
26
+ rhino_command(nil, nil, *args)
27
+ end
28
+
29
+ def coverage(*args)
30
+ ENV["COVERAGE"] = "1"
31
+ test(*args)
32
+ end
33
+
34
+ protected
35
+ def rhino_command(extra_path, base_command, *args) # rubocop:todo Metrics/MethodLength
36
+ # Default to just rhino/rhino if no obvious module
37
+ module_name = if Dir.exist?("rhino/rhino_#{args[0]}")
38
+ args.shift
39
+ else
40
+ nil
41
+ end
42
+ module_base = ["rhino", module_name].compact.join("_")
43
+ module_path = ["rhino/#{module_base}", extra_path].compact.join("/")
44
+ db_name = "#{module_base}_dummy"
45
+
46
+ # Getting existing variables and re-use
47
+ ::Dotenv.load
48
+
49
+ inside(module_path) do
50
+ # Override DB_NAME so multiple can run in parallel
51
+ run(
52
+ "DB_NAME=#{db_name} BUNDLE_GEMFILE='#{__dir__}/../../../../Gemfile' bin/rails #{base_command} #{args.join(' ')}",
53
+ { abort_on_failure: true }
54
+ )
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,175 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rhino
4
+ module Generators
5
+ module Dev
6
+ # rubocop:disable Metrics/ClassLength
7
+ class SetupGenerator < ::Rails::Generators::Base
8
+ class_option :prompt, type: :boolean, default: true
9
+ class_option :server_port, type: :numeric
10
+ class_option :client_port, type: :numeric
11
+ class_option :db_host, type: :string
12
+ class_option :db_name, type: :string
13
+ class_option :db_port, type: :numeric
14
+ class_option :db_user, type: :string
15
+ class_option :db_password, type: :string
16
+ class_option :redis_port, type: :numeric
17
+ class_option :redis_database, type: :numeric
18
+
19
+ attr_reader :server_port,
20
+ :client_port,
21
+ :db_name,
22
+ :db_host,
23
+ :db_port,
24
+ :db_user,
25
+ :db_password,
26
+ :redis_host,
27
+ :redis_port,
28
+ :redis_database,
29
+ :dockerized
30
+
31
+ source_root File.expand_path("templates", __dir__)
32
+
33
+ def setup_env
34
+ say "Setting up local .env files"
35
+
36
+ collect_env_info
37
+
38
+ template "env.server", server_file(".env")
39
+ template "env.client", client_file(".env")
40
+ end
41
+
42
+ def install_hooks
43
+ say "Installing git hooks"
44
+ # Hooks need to be executable
45
+ copy_file "prepare-commit-msg",
46
+ project_file(".git/hooks/prepare-commit-msg"),
47
+ mode: :preserve
48
+ end
49
+
50
+ private
51
+ def project_dir
52
+ # Up one level from the server directory
53
+ Rails.root.parent
54
+ end
55
+
56
+ def server_extension
57
+ Rails.root.basename.to_s.match(/[-_]?server/)[0]
58
+ end
59
+
60
+ def server_port_default
61
+ options[:server_port] || ENV["PORT"] || 3000
62
+ end
63
+
64
+ def client_port_default
65
+ @server_port.to_i + 1
66
+ end
67
+
68
+ def db_name_default
69
+ db_name =
70
+ options[:db_name] || ENV["DB_NAME"] ||
71
+ File.basename(project_dir).sub(/[-_]?mono/, "")
72
+
73
+ return db_name if db_name.present?
74
+
75
+ File.basename(Rails.root.parent)
76
+ end
77
+
78
+ def db_host_default
79
+ options[:db_host] || ENV["DB_HOST"] || "localhost"
80
+ end
81
+
82
+ def db_port_default
83
+ options[:db_port] || ENV["DB_PORT"] || 5432
84
+ end
85
+
86
+ def db_user_default
87
+ options[:db_user] || ENV["DB_USERNAME"] || (dockerized ? "postgres" : "")
88
+ end
89
+
90
+ def db_password_default
91
+ options[:db_password] || ENV["DB_PASSWORD"] || (dockerized ? "password" : "")
92
+ end
93
+
94
+ def redis_host_default
95
+ options[:redis_host] || ENV["REDIS_HOST"] || "localhost"
96
+ end
97
+
98
+ def redis_port_default
99
+ options[:redis_port] || ENV["REDIS_PORT"] || 6379
100
+ end
101
+
102
+ def redis_database_default
103
+ options[:redis_database] || ENV["REDIS_DATABASE"] || 0
104
+ end
105
+
106
+ def dockerized_default
107
+ "yN"
108
+ end
109
+
110
+ def collect_env_info
111
+ collect_docker_info
112
+
113
+ @server_port = ask_prompt("Server Port?", server_port_default)
114
+ @client_port = ask_prompt("Client Port?", client_port_default)
115
+
116
+ collect_database_info
117
+ collect_redis_info
118
+ end
119
+
120
+ def collect_docker_info
121
+ @dockerized = %w[y Y].include?(ask_prompt("Run server on docker?", dockerized_default))
122
+
123
+ return unless dockerized
124
+
125
+ @db_host = "db"
126
+ @redis_host = "redis"
127
+ @redis_port = 6379
128
+
129
+ puts <<~HERE
130
+ The following docker configuration has been automatically set for you:
131
+ Database host: #{db_host}
132
+ Redis host: #{redis_host}
133
+ Redis port: #{redis_port}
134
+ HERE
135
+ end
136
+
137
+ def collect_database_info # rubocop:todo Metrics/AbcSize
138
+ @db_name = ask_prompt("Database?", db_name_default)
139
+ @db_host = ask_prompt("Database host?", db_host_default) unless dockerized
140
+ @db_port = ask_prompt("Database port?", db_port_default)
141
+ @db_user = ask_prompt("Database User?", db_user_default) until !dockerized || db_user.present?
142
+ @db_password = ask_prompt("Database Password?", db_password_default) until !dockerized || db_password.present?
143
+ end
144
+
145
+ def collect_redis_info
146
+ unless dockerized
147
+ @redis_host = ask_prompt("Redis host?", redis_host_default)
148
+ @redis_port = ask_prompt("Redis port?", redis_port_default)
149
+ end
150
+
151
+ @redis_database = ask_prompt("Redis database?", redis_database_default)
152
+ end
153
+
154
+ def project_file(file)
155
+ File.join(project_dir, file)
156
+ end
157
+
158
+ def client_file(file)
159
+ File.join(project_dir, "client", file)
160
+ end
161
+
162
+ def server_file(file)
163
+ File.join(project_dir, "server", file)
164
+ end
165
+
166
+ def ask_prompt(message, default)
167
+ return default unless options[:prompt]
168
+
169
+ ask(message, default:)
170
+ end
171
+ end
172
+ # rubocop:enable Metrics/ClassLength
173
+ end
174
+ end
175
+ end
@@ -0,0 +1,4 @@
1
+ PORT=<%= client_port %>
2
+
3
+ VITE_API_ROOT_PATH=http://localhost:<%= server_port %>
4
+ VITE_ROLLBAR_ACCESS_TOKEN=
@@ -0,0 +1,35 @@
1
+ PORT=<%= server_port %>
2
+
3
+ ROOT_URL=http://localhost:<%= server_port %>
4
+ FRONT_END_URL=http://localhost:<%= client_port %>
5
+
6
+ DB_NAME=<%= db_name %>
7
+ DB_HOST=<%= db_host %>
8
+ DB_PORT=<%= db_port %>
9
+ DB_USERNAME=<%= db_user %>
10
+ DB_PASSWORD=<%= db_password %>
11
+ REDIS_HOST=<%= redis_host %>
12
+ REDIS_PORT=<%= redis_port %>
13
+ REDIS_DATABASE=<%= redis_database %>
14
+
15
+ SECRET_KEY_BASE=0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
16
+
17
+ # Production only:
18
+ SENDGRID_API_KEY=<api-key>
19
+
20
+ #AWS_ACCESS_KEY=
21
+ #AWS_SECRET_KEY=
22
+ #AWS_S3_BUCKET=
23
+ #AWS_REGION=
24
+
25
+ #AZURE_STORAGE_KEY=AAAAAAAAAAAAAA
26
+ #AZURE_ACCOUNT_NAME="azure_acc_name"
27
+ #AZURE_CONTAINER="container-test"
28
+
29
+ #STRIPE_PUBLISHABLE_KEY=pk_...
30
+ #STRIPE_SECRET_KEY=sk_...
31
+
32
+ #AUTH_GOOGLE_OAUTH2_CLIENT_ID=
33
+ #AUTH_GOOGLE_OAUTH2_SECRET_KEY=
34
+
35
+ ROLLBAR_ACCESS_TOKEN=
@@ -0,0 +1,17 @@
1
+ #!/bin/bash
2
+
3
+ # This way you can customize which branches should be skipped when
4
+ # prepending commit message.
5
+ if [ -z "$BRANCHES_TO_SKIP" ]; then
6
+ BRANCHES_TO_SKIP=(main master develop test)
7
+ fi
8
+
9
+ BRANCH_NAME=$(git symbolic-ref --short HEAD)
10
+ BRANCH_NAME="${BRANCH_NAME##*/}"
11
+
12
+ BRANCH_EXCLUDED=$(printf "%s\n" "${BRANCHES_TO_SKIP[@]}" | grep -c "^$BRANCH_NAME$")
13
+ BRANCH_IN_COMMIT=$(grep -c "\[$BRANCH_NAME\]" $1)
14
+
15
+ if [ -n "$BRANCH_NAME" ] && ! [[ $BRANCH_EXCLUDED -eq 1 ]] && ! [[ $BRANCH_IN_COMMIT -ge 1 ]]; then
16
+ sed -i.bak -e "1s/^/[$BRANCH_NAME] /" $1
17
+ fi
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rhino
4
+ module Generators
5
+ class InstallGenerator < ::Rails::Generators::Base
6
+ source_root File.expand_path('templates', __dir__)
7
+
8
+ def install_user
9
+ say 'Installing user to app/models'
10
+ template 'user.rb', 'app/models/user.rb'
11
+ end
12
+
13
+ def install_account
14
+ say 'Installing account to app/models'
15
+ template 'account.rb', 'app/models/account.rb'
16
+ end
17
+
18
+ def install_initializer
19
+ say 'Installing initializer'
20
+ template 'rhino.rb', 'config/initializers/rhino.rb'
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Account < Rhino::Account
4
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ Rhino.setup do |config|
4
+ # ==> Owner configuration
5
+ # The auth owner class
6
+ # config.auth_owner = 'User'
7
+
8
+ # The base owner class
9
+ # config.base_owner = 'Organization'
10
+
11
+ # ==> Resource Configuration
12
+
13
+ # Include Rhino::Resource::ActiveRecordExtension by default
14
+ # config.auto_include_active_record = true
15
+
16
+ # The root path for the api ie '/api'
17
+ # config.namespace = :api
18
+
19
+ # Authentication
20
+ # config.allow_signup = true
21
+
22
+ # The list of resources exposed in the API
23
+ config.resources += ['User', 'Account']
24
+ end
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ class User < Rhino::User
4
+ end
@@ -0,0 +1,93 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rhino
4
+ module Generators
5
+ class ModuleGenerator < ::Rails::Generators::Base
6
+ attr_reader :module_name, :module_path
7
+
8
+ class_option :full, type: :boolean, default: false,
9
+ desc: 'Full plugin generation'
10
+
11
+ class_option :skip_plugin, type: :boolean, default: false,
12
+ desc: 'Skip plugin generation'
13
+
14
+ source_root File.expand_path('templates', __dir__)
15
+
16
+ def create_module
17
+ @module_name = ask('Module name?')
18
+ @module_name = "rhino_#{module_name}" unless module_name.starts_with?('rhino_')
19
+ @module_path = "rhino/#{module_name}"
20
+
21
+ return if options[:skip_plugin]
22
+
23
+ say "Creating #{module_name}"
24
+
25
+ plugin_command = "plugin new #{module_path} --skip-git"
26
+ plugin_command = "#{plugin_command} --full" if options[:full]
27
+ rails_command(plugin_command)
28
+ end
29
+
30
+ def remove_license
31
+ remove_file "#{module_path}/MIT-LICENSE"
32
+ end
33
+
34
+ def engine_registration
35
+ engine_file = "#{module_path}/lib/#{module_name}/engine.rb"
36
+
37
+ remove_file engine_file
38
+ template 'engine.rb', engine_file
39
+ end
40
+
41
+ def create_install_generator
42
+ generator_path = "#{module_path}/lib/generators/#{module_name}/install"
43
+ tasks_path = "#{module_path}/lib/tasks"
44
+
45
+ empty_directory "#{generator_path}/templates"
46
+ create_file("#{generator_path}/templates/.keep")
47
+
48
+ template 'install_generator.rb', "#{generator_path}/install_generator.rb"
49
+ template 'module_tasks.rake', "#{tasks_path}/#{module_name}.rake"
50
+
51
+ remove_file "#{tasks_path}/#{module_name}_tasks.rake"
52
+ end
53
+
54
+ def fix_gemspec
55
+ gemspec_file = "#{module_path}/#{module_name}.gemspec"
56
+
57
+ gsub_file gemspec_file, /spec.homepage.*/, 'spec.homepage = ""'
58
+ gsub_file gemspec_file, /spec.summary.*/, 'spec.summary = ""'
59
+ gsub_file gemspec_file, /spec.description.*/, 'spec.description = ""'
60
+ gsub_file gemspec_file, /spec.license.*/, 'spec.license = ""'
61
+ gsub_file gemspec_file, 'spec.files = Dir["{app,config,db,lib}/**/*", "MIT-LICENSE", "Rakefile", "README.md"]', 'spec.files = Dir["{app,config,db,lib}/**/*", "Rakefile", "README.md"]' # rubocop:disable Layout/LineLength
62
+ end
63
+
64
+ # Gross hack for now
65
+ DUMMY_SETUP_FILES = [
66
+ 'config/database.yml',
67
+ 'config/initializers/devise_token_auth.rb',
68
+ 'config/initializers/devise.rb',
69
+ 'app/models/user.rb',
70
+ 'db/migrate/20210111014230_devise_token_auth_create_users.rhino_engine.rb'
71
+ ].freeze
72
+
73
+ def dummy_setup
74
+ return unless options[:full]
75
+
76
+ rhino_dummy = Rails.root.join('rhino/rhino/test/dummy')
77
+ module_dummy = Rails.root.join("#{module_path}/test/dummy")
78
+
79
+ remove_file "#{module_dummy}/config/database.yml"
80
+
81
+ DUMMY_SETUP_FILES.each do |file|
82
+ copy_file "#{rhino_dummy}/#{file}", "#{module_dummy}/#{file}"
83
+ end
84
+ end
85
+
86
+ def rubocop
87
+ inside(module_path) do
88
+ run 'bundle exec rubocop -a', capture: true
89
+ end
90
+ end
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rhino/engine"
4
+
5
+ module <%= module_name.camelize %>
6
+ class Engine < ::Rails::Engine
7
+ config.autoload_paths << File.expand_path("../../lib", __dir__)
8
+
9
+ initializer "<%= module_name %>.register_module" do
10
+ config.after_initialize do
11
+ if true
12
+ Rhino.registered_modules[:<%= module_name %>] = {
13
+ version: <%= module_name.camelize %>::VERSION
14
+ }
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module <%= module_name.camelize %>
4
+ module Generators
5
+ class InstallGenerator < ::Rails::Generators::Base
6
+ source_root File.expand_path("templates", __dir__)
7
+
8
+ def install
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ namespace :<%= module_name %> do
4
+ # Prevent migration installation task from showing up twice.
5
+ if Rake::Task.task_defined?("<%= module_name %>_engine:install:migrations")
6
+ Rake::Task["<%= module_name %>_engine:install:migrations"].clear_comments
7
+ end
8
+
9
+ desc "Install <%= module_name %>"
10
+ task install: :environment do
11
+ if Rake::Task.task_defined?("<%= module_name %>_engine:install:migrations")
12
+ Rake::Task["<%= module_name %>_engine:install:migrations"].invoke
13
+ end
14
+
15
+ Rails::Command.invoke :generate, ["<%= module_name %>:install"]
16
+ end
17
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rhino
4
+ class PolicyGenerator < ::Rails::Generators::NamedBase
5
+ source_root File.expand_path("templates", __dir__)
6
+
7
+ class_option :parent, type: :string, default: "Rhino::ViewerPolicy", desc: "The parent class for the policy"
8
+
9
+ check_class_collision suffix: "Policy"
10
+
11
+ hook_for :test_framework, as: :rhino_policy
12
+
13
+ def create_policy_file
14
+ template "policy.rb", File.join("app/policies", class_path, "#{file_name}_policy.rb")
15
+ end
16
+
17
+ private
18
+ def parent_class_name
19
+ # FIXME: Does this really need to be top level namespaced?
20
+ return options[:parent] if options[:parent].starts_with?("::")
21
+
22
+ "::#{options[:parent]}"
23
+ end
24
+
25
+ def parent_scope_class_name
26
+ "#{parent_class_name}::Scope"
27
+ end
28
+
29
+ def file_name
30
+ @file_name ||= super.sub(/_policy\z/i, "")
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ <% module_namespacing do -%>
4
+ class <%= class_name %>Policy < <%= parent_class_name %>
5
+ # NOTE: Be explicit about which action you allow!
6
+ # def index?
7
+ # authorize_action(false)
8
+ # end
9
+
10
+ # def show?
11
+ # authorize_action(false)
12
+ # end
13
+
14
+ # def create?
15
+ # authorize_action(false)
16
+ # end
17
+
18
+ # def update?
19
+ # authorize_action(false)
20
+ # end
21
+
22
+ # def destroy?
23
+ # authorize_action(false)
24
+ # end
25
+
26
+ # def permitted_attributes_for_create
27
+ # super
28
+ # super - [:name] # Remove the name attribute from the permitted attributes for create
29
+ # end
30
+
31
+ # def permitted_attributes_for_show
32
+ # super
33
+ # end
34
+
35
+ # def permitted_attributes_for_update
36
+ # super
37
+ # end
38
+
39
+ class Scope < <%= parent_scope_class_name %>
40
+ # NOTE: Be explicit about which records you allow access to!
41
+ # def resolve
42
+ # scope.all
43
+ # end
44
+ end
45
+ end
46
+ <% end -%>