eucalypt 0.1.0

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.
Files changed (160) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +3 -0
  3. data/LICENSE +21 -0
  4. data/README.md +26 -0
  5. data/Rakefile +2 -0
  6. data/bin/eucalypt +3 -0
  7. data/eucalypt.gemspec +39 -0
  8. data/lib/eucalypt/app.rb +6 -0
  9. data/lib/eucalypt/controller.rb +10 -0
  10. data/lib/eucalypt/errors.rb +109 -0
  11. data/lib/eucalypt/eucalypt-blog/helpers.rb +106 -0
  12. data/lib/eucalypt/eucalypt-blog/namespaces/blog/__base__.rb +22 -0
  13. data/lib/eucalypt/eucalypt-blog/namespaces/blog/__require__.rb +1 -0
  14. data/lib/eucalypt/eucalypt-blog/namespaces/blog/cli/blog.rb +65 -0
  15. data/lib/eucalypt/eucalypt-blog/namespaces/blog/generators/article.rb +28 -0
  16. data/lib/eucalypt/eucalypt-blog/namespaces/blog/generators/controller.rb +14 -0
  17. data/lib/eucalypt/eucalypt-blog/namespaces/blog/generators/helper.rb +12 -0
  18. data/lib/eucalypt/eucalypt-blog/namespaces/blog/generators/list.rb +74 -0
  19. data/lib/eucalypt/eucalypt-blog/namespaces/blog/generators/views.rb +20 -0
  20. data/lib/eucalypt/eucalypt-blog/namespaces/blog/templates/controller/controller.tt +33 -0
  21. data/lib/eucalypt/eucalypt-blog/namespaces/blog/templates/controller/controller_spec.tt +43 -0
  22. data/lib/eucalypt/eucalypt-blog/namespaces/blog/templates/helper/helper.tt +5 -0
  23. data/lib/eucalypt/eucalypt-blog/namespaces/blog/templates/helper/helper_spec.tt +9 -0
  24. data/lib/eucalypt/eucalypt-blog/namespaces/blog/templates/views/article.erb +1 -0
  25. data/lib/eucalypt/eucalypt-blog/namespaces/blog/templates/views/article_layout.erb +10 -0
  26. data/lib/eucalypt/eucalypt-blog/namespaces/blog/templates/views/article_md.tt +9 -0
  27. data/lib/eucalypt/eucalypt-blog/namespaces/blog/templates/views/articles.erb +1 -0
  28. data/lib/eucalypt/eucalypt-blog/namespaces/blog/templates/views/articles_layout.erb +10 -0
  29. data/lib/eucalypt/eucalypt-blog/namespaces/blog/templates/views/search.erb +1 -0
  30. data/lib/eucalypt/eucalypt-blog/namespaces/blog-article/cli/article.rb +120 -0
  31. data/lib/eucalypt/eucalypt-blog/namespaces/blog-article-edit/cli/edit-datetime.rb +113 -0
  32. data/lib/eucalypt/eucalypt-blog/namespaces/blog-article-edit/cli/edit-urltitle.rb +75 -0
  33. data/lib/eucalypt/eucalypt-core/cli/__base__.rb +11 -0
  34. data/lib/eucalypt/eucalypt-core/cli/console.rb +15 -0
  35. data/lib/eucalypt/eucalypt-core/cli/core.rb +6 -0
  36. data/lib/eucalypt/eucalypt-core/cli/help.rb +11 -0
  37. data/lib/eucalypt/eucalypt-core/cli/init.rb +71 -0
  38. data/lib/eucalypt/eucalypt-core/cli/launch.rb +33 -0
  39. data/lib/eucalypt/eucalypt-core/cli/test.rb +16 -0
  40. data/lib/eucalypt/eucalypt-core/cli/version.rb +11 -0
  41. data/lib/eucalypt/eucalypt-core/templates/Gemfile.tt +35 -0
  42. data/lib/eucalypt/eucalypt-core/templates/eucalypt/.gitignore +48 -0
  43. data/lib/eucalypt/eucalypt-core/templates/eucalypt/.travis.yml +8 -0
  44. data/lib/eucalypt/eucalypt-core/templates/eucalypt/Procfile +1 -0
  45. data/lib/eucalypt/eucalypt-core/templates/eucalypt/Rakefile +7 -0
  46. data/lib/eucalypt/eucalypt-core/templates/eucalypt/app/assets/fonts/.empty_directory +0 -0
  47. data/lib/eucalypt/eucalypt-core/templates/eucalypt/app/assets/images/.empty_directory +0 -0
  48. data/lib/eucalypt/eucalypt-core/templates/eucalypt/app/assets/scripts/application.js +17 -0
  49. data/lib/eucalypt/eucalypt-core/templates/eucalypt/app/assets/stylesheets/__partials__.scss +16 -0
  50. data/lib/eucalypt/eucalypt-core/templates/eucalypt/app/assets/stylesheets/application.scss +17 -0
  51. data/lib/eucalypt/eucalypt-core/templates/eucalypt/app/assets/stylesheets/partials/_mixins.scss +54 -0
  52. data/lib/eucalypt/eucalypt-core/templates/eucalypt/app/controllers/application_controller.rb +7 -0
  53. data/lib/eucalypt/eucalypt-core/templates/eucalypt/app/helpers/application_helper.rb +3 -0
  54. data/lib/eucalypt/eucalypt-core/templates/eucalypt/app/models/.empty_directory +0 -0
  55. data/lib/eucalypt/eucalypt-core/templates/eucalypt/app/static/.empty_directory +0 -0
  56. data/lib/eucalypt/eucalypt-core/templates/eucalypt/app/static/readme.yml +34 -0
  57. data/lib/eucalypt/eucalypt-core/templates/eucalypt/app/views/index.erb +0 -0
  58. data/lib/eucalypt/eucalypt-core/templates/eucalypt/app/views/layouts/main.erb +9 -0
  59. data/lib/eucalypt/eucalypt-core/templates/eucalypt/app/views/partials/.empty_directory +0 -0
  60. data/lib/eucalypt/eucalypt-core/templates/eucalypt/app.rb +42 -0
  61. data/lib/eucalypt/eucalypt-core/templates/eucalypt/config/active_record.rb +6 -0
  62. data/lib/eucalypt/eucalypt-core/templates/eucalypt/config/asset_pipeline.rb +15 -0
  63. data/lib/eucalypt/eucalypt-core/templates/eucalypt/config/database.yml +16 -0
  64. data/lib/eucalypt/eucalypt-core/templates/eucalypt/config/initializers/.empty_directory +0 -0
  65. data/lib/eucalypt/eucalypt-core/templates/eucalypt/config/logging.rb +27 -0
  66. data/lib/eucalypt/eucalypt-core/templates/eucalypt/config/manifest.rb +15 -0
  67. data/lib/eucalypt/eucalypt-core/templates/eucalypt/config.ru +10 -0
  68. data/lib/eucalypt/eucalypt-core/templates/eucalypt/log/.empty_directory +0 -0
  69. data/lib/eucalypt/eucalypt-core/templates/eucalypt/spec/controllers/application_controller_spec.rb +9 -0
  70. data/lib/eucalypt/eucalypt-core/templates/eucalypt/spec/helpers/application_helper_spec.rb +9 -0
  71. data/lib/eucalypt/eucalypt-core/templates/eucalypt/spec/models/.empty_directory +0 -0
  72. data/lib/eucalypt/eucalypt-core/templates/eucalypt/spec/spec_helper.rb +18 -0
  73. data/lib/eucalypt/eucalypt-destroy/helpers.rb +77 -0
  74. data/lib/eucalypt/eucalypt-destroy/namespaces/destroy/cli/destroy-controller.rb +16 -0
  75. data/lib/eucalypt/eucalypt-destroy/namespaces/destroy/cli/destroy-helper.rb +16 -0
  76. data/lib/eucalypt/eucalypt-destroy/namespaces/destroy/cli/destroy-model.rb +16 -0
  77. data/lib/eucalypt/eucalypt-destroy/namespaces/destroy/cli/destroy-scaffold.rb +63 -0
  78. data/lib/eucalypt/eucalypt-destroy/namespaces/destroy/cli/destroy.rb +21 -0
  79. data/lib/eucalypt/eucalypt-generate/.gitkeep +0 -0
  80. data/lib/eucalypt/eucalypt-generate/namespaces/generate/cli/generate-scaffold.rb +62 -0
  81. data/lib/eucalypt/eucalypt-generate/namespaces/generate/cli/generate.rb +24 -0
  82. data/lib/eucalypt/eucalypt-generate/namespaces/generate-controller/cli/generate-controller.rb +29 -0
  83. data/lib/eucalypt/eucalypt-generate/namespaces/generate-controller/generators/controller.rb +45 -0
  84. data/lib/eucalypt/eucalypt-generate/namespaces/generate-controller/templates/controller/controller.tt +3 -0
  85. data/lib/eucalypt/eucalypt-generate/namespaces/generate-controller/templates/controller/policy_rest_controller.tt +71 -0
  86. data/lib/eucalypt/eucalypt-generate/namespaces/generate-controller/templates/controller/rest_controller.tt +28 -0
  87. data/lib/eucalypt/eucalypt-generate/namespaces/generate-controller/templates/controller_spec.tt +9 -0
  88. data/lib/eucalypt/eucalypt-generate/namespaces/generate-helper/cli/generate-helper.rb +23 -0
  89. data/lib/eucalypt/eucalypt-generate/namespaces/generate-helper/generators/helper.rb +24 -0
  90. data/lib/eucalypt/eucalypt-generate/namespaces/generate-helper/templates/helper.tt +3 -0
  91. data/lib/eucalypt/eucalypt-generate/namespaces/generate-helper/templates/helper_spec.tt +9 -0
  92. data/lib/eucalypt/eucalypt-generate/namespaces/generate-model/cli/generate-model.rb +26 -0
  93. data/lib/eucalypt/eucalypt-generate/namespaces/generate-model/generators/model.rb +25 -0
  94. data/lib/eucalypt/eucalypt-generate/namespaces/generate-model/templates/model.tt +3 -0
  95. data/lib/eucalypt/eucalypt-generate/namespaces/generate-model/templates/model_spec.tt +8 -0
  96. data/lib/eucalypt/eucalypt-migration/helpers.rb +93 -0
  97. data/lib/eucalypt/eucalypt-migration/migration_base.tt +4 -0
  98. data/lib/eucalypt/eucalypt-migration/namespaces/migration/cli/migration.rb +39 -0
  99. data/lib/eucalypt/eucalypt-migration/namespaces/migration-add/cli/add-column.rb +25 -0
  100. data/lib/eucalypt/eucalypt-migration/namespaces/migration-add/cli/add-index.rb +25 -0
  101. data/lib/eucalypt/eucalypt-migration/namespaces/migration-add/cli/add.rb +18 -0
  102. data/lib/eucalypt/eucalypt-migration/namespaces/migration-add/generators/column.rb +46 -0
  103. data/lib/eucalypt/eucalypt-migration/namespaces/migration-add/generators/index.rb +52 -0
  104. data/lib/eucalypt/eucalypt-migration/namespaces/migration-blank/cli/blank.rb +22 -0
  105. data/lib/eucalypt/eucalypt-migration/namespaces/migration-blank/generators/blank.rb +28 -0
  106. data/lib/eucalypt/eucalypt-migration/namespaces/migration-change/cli/change-column.rb +23 -0
  107. data/lib/eucalypt/eucalypt-migration/namespaces/migration-change/cli/change.rb +17 -0
  108. data/lib/eucalypt/eucalypt-migration/namespaces/migration-change/generators/column.rb +46 -0
  109. data/lib/eucalypt/eucalypt-migration/namespaces/migration-create/cli/create-table.rb +25 -0
  110. data/lib/eucalypt/eucalypt-migration/namespaces/migration-create/cli/create.rb +17 -0
  111. data/lib/eucalypt/eucalypt-migration/namespaces/migration-create/generators/table.rb +53 -0
  112. data/lib/eucalypt/eucalypt-migration/namespaces/migration-drop/cli/drop-column.rb +22 -0
  113. data/lib/eucalypt/eucalypt-migration/namespaces/migration-drop/cli/drop-index.rb +23 -0
  114. data/lib/eucalypt/eucalypt-migration/namespaces/migration-drop/cli/drop-table.rb +22 -0
  115. data/lib/eucalypt/eucalypt-migration/namespaces/migration-drop/cli/drop.rb +19 -0
  116. data/lib/eucalypt/eucalypt-migration/namespaces/migration-drop/generators/column.rb +38 -0
  117. data/lib/eucalypt/eucalypt-migration/namespaces/migration-drop/generators/index.rb +48 -0
  118. data/lib/eucalypt/eucalypt-migration/namespaces/migration-drop/generators/table.rb +37 -0
  119. data/lib/eucalypt/eucalypt-migration/namespaces/migration-rename/cli/rename-column.rb +22 -0
  120. data/lib/eucalypt/eucalypt-migration/namespaces/migration-rename/cli/rename-index.rb +22 -0
  121. data/lib/eucalypt/eucalypt-migration/namespaces/migration-rename/cli/rename-table.rb +24 -0
  122. data/lib/eucalypt/eucalypt-migration/namespaces/migration-rename/cli/rename.rb +19 -0
  123. data/lib/eucalypt/eucalypt-migration/namespaces/migration-rename/generators/column.rb +39 -0
  124. data/lib/eucalypt/eucalypt-migration/namespaces/migration-rename/generators/index.rb +39 -0
  125. data/lib/eucalypt/eucalypt-migration/namespaces/migration-rename/generators/table.rb +38 -0
  126. data/lib/eucalypt/eucalypt-security/helpers.rb +22 -0
  127. data/lib/eucalypt/eucalypt-security/namespaces/security/cli/security.rb +31 -0
  128. data/lib/eucalypt/eucalypt-security/namespaces/security-policy/cli/security-policy.rb +91 -0
  129. data/lib/eucalypt/eucalypt-security/namespaces/security-policy/generators/policy.rb +31 -0
  130. data/lib/eucalypt/eucalypt-security/namespaces/security-policy/templates/create_policy_roles_migration.tt +11 -0
  131. data/lib/eucalypt/eucalypt-security/namespaces/security-policy/templates/policy.tt +16 -0
  132. data/lib/eucalypt/eucalypt-security/namespaces/security-policy-permission/cli/security-policy-permission.rb +62 -0
  133. data/lib/eucalypt/eucalypt-security/namespaces/security-policy-permission/generators/policy-permission.rb +28 -0
  134. data/lib/eucalypt/eucalypt-security/namespaces/security-policy-permission/templates/add_permission_to_policy_migration.tt +5 -0
  135. data/lib/eucalypt/eucalypt-security/namespaces/security-policy-role/cli/security-policy-role.rb +66 -0
  136. data/lib/eucalypt/eucalypt-security/namespaces/security-pundit/cli/security-pundit.rb +79 -0
  137. data/lib/eucalypt/eucalypt-security/namespaces/security-pundit/generators/role.rb +24 -0
  138. data/lib/eucalypt/eucalypt-security/namespaces/security-pundit/templates/create_roles_migration.tt +7 -0
  139. data/lib/eucalypt/eucalypt-security/namespaces/security-pundit/templates/pundit.tt +4 -0
  140. data/lib/eucalypt/eucalypt-security/namespaces/security-warden/cli/security-warden.rb +61 -0
  141. data/lib/eucalypt/eucalypt-security/namespaces/security-warden/generators/auth_controller.rb +34 -0
  142. data/lib/eucalypt/eucalypt-security/namespaces/security-warden/generators/user.rb +37 -0
  143. data/lib/eucalypt/eucalypt-security/namespaces/security-warden/templates/auth_controller.tt +25 -0
  144. data/lib/eucalypt/eucalypt-security/namespaces/security-warden/templates/auth_login.tt +1 -0
  145. data/lib/eucalypt/eucalypt-security/namespaces/security-warden/templates/create_users_table_migration.tt +9 -0
  146. data/lib/eucalypt/eucalypt-security/namespaces/security-warden/templates/user.tt +16 -0
  147. data/lib/eucalypt/eucalypt-security/namespaces/security-warden/templates/warden.tt +35 -0
  148. data/lib/eucalypt/eucalypt-security/namespaces/security-warden/user_confirm.rb +38 -0
  149. data/lib/eucalypt/helpers/colorize.rb +27 -0
  150. data/lib/eucalypt/helpers/gemfile.rb +48 -0
  151. data/lib/eucalypt/helpers/inflect.rb +79 -0
  152. data/lib/eucalypt/helpers/messages.rb +31 -0
  153. data/lib/eucalypt/helpers/migration.rb +85 -0
  154. data/lib/eucalypt/helpers/numeric.rb +10 -0
  155. data/lib/eucalypt/helpers.rb +6 -0
  156. data/lib/eucalypt/list.rb +39 -0
  157. data/lib/eucalypt/static.rb +48 -0
  158. data/lib/eucalypt/version.rb +3 -0
  159. data/lib/eucalypt.rb +19 -0
  160. metadata +373 -0
@@ -0,0 +1,22 @@
1
+ require 'active_support'
2
+ require 'active_support/core_ext'
3
+ require 'thor'
4
+ require 'eucalypt/helpers'
5
+ require 'eucalypt/eucalypt-generate/namespaces/generate/cli/generate'
6
+
7
+ module Eucalypt
8
+ class Security < Thor
9
+ module Helpers
10
+ include Eucalypt::Helpers
11
+ include Eucalypt::Helpers::Messages
12
+ using Colorize
13
+
14
+ def create_config_file(type, directory)
15
+ config_relative = File.join 'config', "#{type}.rb"
16
+ config_file = File.join(directory, config_relative)
17
+ Out.warning "#{type.to_s.capitalize} config file #{config_relative.colorize(:bold)} already exists." if File.file? config_file
18
+ template "#{type}.tt", config_file
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,31 @@
1
+ require 'eucalypt/errors'
2
+ require 'eucalypt/eucalypt-security/namespaces/security-warden/cli/security-warden'
3
+ require 'eucalypt/eucalypt-security/namespaces/security-pundit/cli/security-pundit'
4
+ require 'eucalypt/eucalypt-security/namespaces/security-policy/cli/security-policy'
5
+ require 'eucalypt/helpers'
6
+
7
+ module Eucalypt
8
+ class Security < Thor
9
+ include Thor::Actions
10
+ include Eucalypt::Helpers
11
+ using Colorize
12
+
13
+ class << self
14
+ require 'eucalypt/list'
15
+ include Eucalypt::List
16
+ def banner(task, namespace = false, subcommand = true)
17
+ basename + ' ' + task.formatted_usage(self, true, subcommand).split(':').join(' ')
18
+ end
19
+ end
20
+
21
+ register(Eucalypt::SecurityWarden, 'warden', 'warden [COMMAND]', 'Configure Warden authentication'.colorize(:grey))
22
+ register(Eucalypt::SecurityPundit, 'pundit', 'pundit [COMMAND]', 'Configure Pundit authorization'.colorize(:grey))
23
+ register(Eucalypt::SecurityPolicy, 'policy', 'policy [COMMAND]', 'Pundit policy commands'.colorize(:grey))
24
+ end
25
+
26
+ class CLI < Thor
27
+ include Eucalypt::Helpers
28
+ using Colorize
29
+ register(Security, 'security', 'security [COMMAND]', 'Manage authentication and authorization'.colorize(:grey))
30
+ end
31
+ end
@@ -0,0 +1,91 @@
1
+ require 'thor'
2
+ require 'eucalypt/errors'
3
+ require 'eucalypt/helpers'
4
+ require 'eucalypt/eucalypt-security/namespaces/security-policy/generators/policy'
5
+ require 'eucalypt/eucalypt-security/namespaces/security-policy-permission/cli/security-policy-permission'
6
+ require 'eucalypt/eucalypt-security/namespaces/security-policy-role/cli/security-policy-role'
7
+
8
+ module Eucalypt
9
+ class SecurityPolicy < Thor
10
+ include Thor::Actions
11
+ include Eucalypt::Helpers
12
+ using Colorize
13
+
14
+ method_option :permissions, type: :array, aliases: '-p', default: [], desc: "Permissions to generate along with the policy"
15
+ desc "generate [NAME]", "Create a new Pundit policy".colorize(:grey)
16
+ def generate(name)
17
+ directory = File.expand_path('.')
18
+ if Eucalypt.app? directory
19
+ # Check for authorization gems
20
+ return unless Gemfile.check(%w[pundit], 'eucalypt security pundit setup', directory)
21
+
22
+ # Check for user model
23
+ unless File.exist? File.join(directory, 'app', 'models', 'user.rb')
24
+ Eucalypt::Error.no_user_model
25
+ return
26
+ end
27
+
28
+ # Check for role model
29
+ unless File.exist? File.join(directory, 'app', 'models', 'role.rb')
30
+ Eucalypt::Error.no_role_model
31
+ return
32
+ end
33
+
34
+ policy = Inflect.new(:policy, name)
35
+
36
+ policy_generator = Eucalypt::Generators::Policy.new
37
+ policy_generator.destination_root = directory
38
+
39
+ # Generate policy file
40
+ policy_generator.generate(name: name)
41
+
42
+ # Create policy roles table
43
+ policy_generator.generate_policy_roles_migration(policy: policy.resource)
44
+
45
+ # Create policy role model
46
+ Dir.chdir(directory) do
47
+ Eucalypt::CLI.start(['generate', 'model', "#{policy.resource}_role", '--no-spec', '--no-table'])
48
+ end
49
+
50
+ # Add validation to role model
51
+ role_model_file = File.join directory, 'app', 'models', "#{policy.resource}_role.rb"
52
+ File.open(role_model_file) do |f|
53
+ insert = " validates :permission, uniqueness: true"
54
+ inject_into_class(role_model_file, "#{policy.resource}_role".camelize, "#{insert}\n") unless f.read.include? insert
55
+ end
56
+
57
+ # Add policy column to user roles table
58
+ Dir.chdir(directory) do
59
+ args = %w[migration add column]
60
+ args << 'roles'
61
+ args << policy.resource
62
+ args << 'string'
63
+ args << %w[-o default:default]
64
+ args.flatten!
65
+ Eucalypt::CLI.start(args)
66
+ end
67
+
68
+ # Generate permissions
69
+ options[:permissions].each do |permission|
70
+ Eucalypt::CLI.start(['security', 'policy', 'permission', 'generate', policy.resource, permission])
71
+ end
72
+ else
73
+ Eucalypt::Error.wrong_directory
74
+ end
75
+ end
76
+
77
+ #def destroy()
78
+ #end
79
+
80
+ class << self
81
+ require 'eucalypt/list'
82
+ include Eucalypt::List
83
+ def banner(task, namespace = false, subcommand = true)
84
+ "#{basename} security #{task.formatted_usage(self, true, subcommand).split(':').join(' ')}"
85
+ end
86
+ end
87
+
88
+ register(Eucalypt::SecurityPolicyPermission, 'permission', 'permission [COMMAND]', 'Pundit policy permission commands'.colorize(:grey))
89
+ register(Eucalypt::SecurityPolicyRole, 'role', 'role [COMMAND]', 'Pundit policy role commands'.colorize(:grey))
90
+ end
91
+ end
@@ -0,0 +1,31 @@
1
+ require 'active_support'
2
+ require 'active_support/core_ext'
3
+ require 'thor'
4
+ require 'eucalypt/helpers'
5
+
6
+ module Eucalypt
7
+ module Generators
8
+ class Policy < Thor::Group
9
+ include Thor::Actions
10
+ include Eucalypt::Helpers
11
+
12
+ def self.source_root
13
+ File.join File.dirname(__dir__), 'templates'
14
+ end
15
+
16
+ def generate(name:)
17
+ policy = Inflect.new(:policy, name)
18
+ config = {class_name: policy.class_name, resource: policy.resource, constant: policy.constant}
19
+ template('policy.tt', policy.file_path, config)
20
+ end
21
+
22
+ def generate_policy_roles_migration(policy:)
23
+ sleep 1
24
+ migration = Eucalypt::Helpers::Migration[title: "create_#{policy}_roles", template: 'create_policy_roles_migration.tt']
25
+ return unless migration.create_anyway? if migration.exists?
26
+ config = {migration_title: migration.title.camelize, policy: policy}
27
+ template migration.template, migration.file_path, config
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,11 @@
1
+ class <%= config[:migration_title] %> < ActiveRecord::Migration[<%= ActiveRecord::Migration.current_version %>]
2
+ def change
3
+ create_table :<%= config[:policy] %>_roles do |t|
4
+ t.string :permission, null: false
5
+ t.boolean :admin, default: true
6
+ t.boolean :default, default: false
7
+ end
8
+
9
+ add_index :<%= config[:policy] %>_roles, :permission, unique: true
10
+ end
11
+ end
@@ -0,0 +1,16 @@
1
+ class <%= config[:class_name] %>
2
+ attr_reader :user, :<%= config[:resource] %>
3
+
4
+ def initialize(user, <%= config[:resource] %>)
5
+ @user = user
6
+ @<%= config[:resource] %> = <%= config[:resource] %>
7
+ end
8
+
9
+ if ActiveRecord::Base.connection.table_exists?(:<%= config[:resource] %>_roles)
10
+ <%= config[:constant] %>Role.pluck(:permission).each do |permission|
11
+ define_method("#{permission}?") do
12
+ <%= config[:constant] %>Role.find_by(permission: permission).send(user.role.<%= config[:resource] %>)
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,62 @@
1
+ require 'thor'
2
+ require 'eucalypt/errors'
3
+ require 'eucalypt/helpers'
4
+ require 'eucalypt/eucalypt-security/namespaces/security-policy-permission/generators/policy-permission'
5
+
6
+ module Eucalypt
7
+ class SecurityPolicyPermission < Thor
8
+ include Thor::Actions
9
+ include Eucalypt::Helpers
10
+ using Colorize
11
+
12
+ desc "generate [POLICY] [PERMISSION]", "Create a new Pundit policy permission".colorize(:grey)
13
+ def generate(name, permission)
14
+ directory = File.expand_path('.')
15
+ if Eucalypt.app? directory
16
+ # Check for authorization gems
17
+ return unless Gemfile.check(%w[pundit], 'eucalypt security pundit setup', directory)
18
+
19
+ # Check for user model
20
+ unless File.exist? File.join(directory, 'app', 'models', 'user.rb')
21
+ Eucalypt::Error.no_user_model
22
+ return
23
+ end
24
+
25
+ # Check for role model
26
+ unless File.exist? File.join(directory, 'app', 'models', 'role.rb')
27
+ Eucalypt::Error.no_role_model
28
+ return
29
+ end
30
+
31
+ policy = Inflect.new(:policy, name)
32
+
33
+ # Check for policy file and policy role model
34
+ policy_file = File.join(directory, 'app', 'policies', policy.file_name)
35
+ policy_role_model = File.join(directory, 'app', 'models', "#{policy.resource}_role.rb")
36
+ unless File.exist?(policy_file) && File.exist?(policy_role_model)
37
+ Eucalypt::Error.no_policy(policy.resource)
38
+ return
39
+ end
40
+
41
+ policy_permission = Eucalypt::Generators::PolicyPermission.new
42
+ policy_permission.destination_root = directory
43
+
44
+ # Add permission record to policy role table
45
+ policy_permission.generate(policy_name: policy.resource, permission: Inflect.resource_keep_inflection(permission))
46
+ else
47
+ Eucalypt::Error.wrong_directory
48
+ end
49
+ end
50
+
51
+ # def destroy()
52
+ # end
53
+
54
+ class << self
55
+ require 'eucalypt/list'
56
+ include Eucalypt::List
57
+ def banner(task, namespace = false, subcommand = true)
58
+ "#{basename} security policy #{task.formatted_usage(self, true, subcommand).split(':').join(' ')}"
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,28 @@
1
+ require 'active_support'
2
+ require 'active_support/core_ext'
3
+ require 'thor'
4
+ require 'eucalypt/helpers'
5
+
6
+ module Eucalypt
7
+ module Generators
8
+ class PolicyPermission < Thor::Group
9
+ include Thor::Actions
10
+ include Eucalypt::Helpers
11
+
12
+ def self.source_root
13
+ File.join File.dirname(__dir__), 'templates'
14
+ end
15
+
16
+ def generate(policy_name:, permission:)
17
+ sleep 1
18
+ migration = Eucalypt::Helpers::Migration[
19
+ title: "add_#{permission}_permission_to_#{policy_name}_policy",
20
+ template: 'add_permission_to_policy_migration.tt'
21
+ ]
22
+ return unless migration.create_anyway? if migration.exists?
23
+ config = {migration_title: migration.title.camelize, policy_name: policy_name, permission: permission}
24
+ template migration.template, migration.file_path, config
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,5 @@
1
+ class <%= config[:migration_title] %> < ActiveRecord::Migration[<%= ActiveRecord::Migration.current_version %>]
2
+ def change
3
+ <%= config[:policy_name].camelize %>Role.create permission: '<%= config[:permission] %>'
4
+ end
5
+ end
@@ -0,0 +1,66 @@
1
+ require 'thor'
2
+ require 'eucalypt/errors'
3
+ require 'eucalypt/helpers'
4
+
5
+ module Eucalypt
6
+ class SecurityPolicyRole < Thor
7
+ include Thor::Actions
8
+ include Eucalypt::Helpers
9
+ using Colorize
10
+
11
+ desc "generate [POLICY] [ROLE]", "Create a new Pundit policy role".colorize(:grey)
12
+ def generate(name, role)
13
+ directory = File.expand_path('.')
14
+ if Eucalypt.app? directory
15
+ # Check for authorization gems
16
+ return unless Gemfile.check(%w[pundit], 'eucalypt security pundit setup', directory)
17
+
18
+ # Check for user model
19
+ unless File.exist? File.join(directory, 'app', 'models', 'user.rb')
20
+ Eucalypt::Error.no_user_model
21
+ return
22
+ end
23
+
24
+ # Check for role model
25
+ unless File.exist? File.join(directory, 'app', 'models', 'role.rb')
26
+ Eucalypt::Error.no_role_model
27
+ return
28
+ end
29
+
30
+ policy = Inflect.new(:policy, name)
31
+
32
+ # Check for policy file and policy role model
33
+ policy_file = File.join(directory, 'app', 'policies', policy.file_name)
34
+ policy_role_model = File.join(directory, 'app', 'models', "#{policy.resource}_role.rb")
35
+ unless File.exist?(policy_file) && File.exist?(policy_role_model)
36
+ Eucalypt::Error.no_policy(policy.resource)
37
+ return
38
+ end
39
+
40
+ # Add role column to policy roles table
41
+ Dir.chdir(directory) do
42
+ args = %w[migration add column]
43
+ args << "#{policy.resource}_roles"
44
+ args << Inflect.resource(role)
45
+ args << 'boolean'
46
+ args << %w[-o default:false]
47
+ args.flatten!
48
+ Eucalypt::CLI.start(args)
49
+ end
50
+ else
51
+ Eucalypt::Error.wrong_directory
52
+ end
53
+ end
54
+
55
+ # def destroy()
56
+ # end
57
+
58
+ class << self
59
+ require 'eucalypt/list'
60
+ include Eucalypt::List
61
+ def banner(task, namespace = false, subcommand = true)
62
+ "#{basename} security policy #{task.formatted_usage(self, true, subcommand).split(':').join(' ')}"
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,79 @@
1
+ require 'thor'
2
+ require 'eucalypt/helpers'
3
+ require 'eucalypt/eucalypt-security/helpers'
4
+ require 'eucalypt/eucalypt-security/namespaces/security-pundit/generators/role'
5
+
6
+ module Eucalypt
7
+ class SecurityPundit < Thor
8
+ include Thor::Actions
9
+ include Eucalypt::Helpers
10
+ include Eucalypt::Helpers::Messages
11
+ include Eucalypt::Helpers::Gemfile
12
+ include Eucalypt::Security::Helpers
13
+ using Colorize
14
+
15
+ def self.source_root
16
+ File.join File.dirname(__dir__), 'templates'
17
+ end
18
+
19
+ desc "setup", "Set up Pundit authorization".colorize(:grey)
20
+ def setup
21
+ directory = File.expand_path('.')
22
+ if Eucalypt.app? directory
23
+ # Check if user model exists
24
+ user_model_file = File.join(directory, 'app', 'models', 'user.rb')
25
+ unless File.file? user_model_file
26
+ Eucalypt::Error.no_user_model
27
+ return
28
+ end
29
+
30
+ Out.setup "Setting up Pundit authorization..."
31
+
32
+ # Add Pundit to Gemfile
33
+ gemfile_add('Authorization', {pundit: '~> 2.0'}, directory)
34
+
35
+ # Create Pundit config file
36
+ create_config_file(:pundit, directory)
37
+
38
+ # Create roles migration
39
+ Eucalypt::Generators::Role.new.generate_roles_migration
40
+
41
+ # Create Role model
42
+ role_model_file = File.join(directory, 'app', 'models', 'role.rb')
43
+ Out.warning "Role model already exists." if File.file? role_model_file
44
+ Dir.chdir(directory) do
45
+ Eucalypt::CLI.start(%w[generate model role --no-spec --no-table])
46
+ end
47
+
48
+ # Add belongs_to to Role model
49
+ File.open(role_model_file) do |f|
50
+ insert = " belongs_to :user"
51
+ inject_into_class(role_model_file, 'Role', "#{insert}\n") unless f.read.include? insert
52
+ end
53
+
54
+ # Add relationship to User model
55
+ File.open(user_model_file) do |f|
56
+ contents = f.read
57
+ insert = " has_one :role, dependent: :destroy\n"
58
+ inject_into_file(user_model_file, insert, before: / include BCrypt/) unless contents.include? insert
59
+ insert = " after_save :create_role\n\n"
60
+ inject_into_file(user_model_file, insert, before: / include BCrypt/) unless contents.include? insert
61
+ insert = "\n private\n\n def create_role\n self.role = Role.new\n end\n"
62
+ inject_into_file(user_model_file, insert, before: /^end/) unless contents.include? insert
63
+ end
64
+
65
+ Out.info "Ensure you run `#{'rake db:migrate'.colorize(:bold)}` to create the necessary tables for Pundit."
66
+ else
67
+ Eucalypt::Error.wrong_directory
68
+ end
69
+ end
70
+
71
+ class << self
72
+ require 'eucalypt/list'
73
+ include Eucalypt::List
74
+ def banner(task, namespace = false, subcommand = true)
75
+ "#{basename} security #{task.formatted_usage(self, true, subcommand).split(':').join(' ')}"
76
+ end
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,24 @@
1
+ require 'active_support'
2
+ require 'active_support/core_ext'
3
+ require 'thor'
4
+ require 'eucalypt/helpers'
5
+
6
+ module Eucalypt
7
+ module Generators
8
+ class Role < Thor::Group
9
+ include Thor::Actions
10
+ include Eucalypt::Helpers
11
+
12
+ def self.source_root
13
+ File.join File.dirname(__dir__), 'templates'
14
+ end
15
+
16
+ def generate_roles_migration
17
+ sleep 1
18
+ migration = Eucalypt::Helpers::Migration[title: "create_roles", template: 'create_roles_migration.tt']
19
+ return unless migration.create_anyway? if migration.exists?
20
+ template migration.template, migration.file_path
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,7 @@
1
+ class CreateRoles < ActiveRecord::Migration[<%= ActiveRecord::Migration.current_version %>]
2
+ def change
3
+ create_table :roles do |t|
4
+ t.references :user, foreign_key: true
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,4 @@
1
+ class ApplicationController < Sinatra::Base
2
+ # Include Pundit for authorization
3
+ include Pundit
4
+ end
@@ -0,0 +1,61 @@
1
+ require 'thor'
2
+ require 'eucalypt/helpers'
3
+ require 'eucalypt/eucalypt-security/helpers'
4
+ require 'eucalypt/eucalypt-security/namespaces/security-warden/generators/user'
5
+ require 'eucalypt/eucalypt-security/namespaces/security-warden/generators/auth_controller'
6
+
7
+ module Eucalypt
8
+ class SecurityWarden < Thor
9
+ include Thor::Actions
10
+ include Eucalypt::Helpers
11
+ include Eucalypt::Helpers::Messages
12
+ include Eucalypt::Helpers::Gemfile
13
+ include Eucalypt::Security::Helpers
14
+ using Colorize
15
+
16
+ def self.source_root
17
+ File.join File.dirname(__dir__), 'templates'
18
+ end
19
+
20
+ option :controller, type: :boolean, default: true, desc: "Include an authentication controller"
21
+ desc "setup", "Set up Warden authentication".colorize(:grey)
22
+ def setup
23
+ directory = File.expand_path('.')
24
+ if Eucalypt.app? directory
25
+ Out.setup "Setting up Warden authentication..."
26
+
27
+ # Add Warden and BCrypt to Gemfile
28
+ gemfile_add('Authentication and encryption', {warden: '~> 1.2', bcrypt: '~> 3.1'}, directory)
29
+
30
+ # Create Warden config file
31
+ create_config_file(:warden, directory)
32
+
33
+ user = Eucalypt::Generators::User.new
34
+
35
+ # Create user migration
36
+ user.generate_migration
37
+
38
+ # Create user model
39
+ user.generate_model(directory)
40
+
41
+ if options[:controller]
42
+ auth_controller = Eucalypt::Generators::AuthController.new
43
+ auth_controller.destination_root = directory
44
+ auth_controller.generate
45
+ end
46
+
47
+ Out.info "Ensure you run `#{'rake db:migrate'.colorize(:bold)}` to create the necessary tables for Warden."
48
+ else
49
+ Eucalypt::Error.wrong_directory
50
+ end
51
+ end
52
+
53
+ class << self
54
+ require 'eucalypt/list'
55
+ include Eucalypt::List
56
+ def banner(task, namespace = false, subcommand = true)
57
+ "#{basename} security #{task.formatted_usage(self, true, subcommand).split(':').join(' ')}"
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,34 @@
1
+ require 'active_support'
2
+ require 'active_support/core_ext'
3
+ require 'thor'
4
+ require 'eucalypt/helpers'
5
+
6
+ module Eucalypt
7
+ module Generators
8
+ class AuthController < Thor::Group
9
+ include Thor::Actions
10
+ include Eucalypt::Helpers
11
+ using String::Builder
12
+
13
+ def self.source_root
14
+ File.join File.dirname(__dir__), 'templates'
15
+ end
16
+
17
+ def generate
18
+ template 'auth_controller.tt', File.join('app', 'controllers', 'authentication_controller.rb')
19
+
20
+ config = {}
21
+ config[:data] = String.build do |s|
22
+ s << "<%=\n"
23
+ s << " form_for :user, '/auth/login' do\n"
24
+ s << " text_field :username\n"
25
+ s << " password_field :password\n"
26
+ s << " submit 'Login'\n"
27
+ s << " end\n"
28
+ s << "%>"
29
+ end
30
+ template 'auth_login.tt', File.join('app', 'views', 'authentication', 'login.erb'), config
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,37 @@
1
+ require 'active_support'
2
+ require 'active_support/core_ext'
3
+ require 'thor'
4
+ require 'eucalypt/helpers'
5
+ require 'active_record'
6
+
7
+ module Eucalypt
8
+ module Generators
9
+ class User < Thor::Group
10
+ include Thor::Actions
11
+ include Eucalypt::Helpers
12
+ include Eucalypt::Helpers::Messages
13
+
14
+ def self.source_root
15
+ File.join File.dirname(__dir__), 'templates'
16
+ end
17
+
18
+ def generate_migration
19
+ sleep 1
20
+ migration = Eucalypt::Helpers::Migration[title: 'create_users', template: 'create_users_table_migration.tt']
21
+ return unless migration.create_anyway? if migration.exists?
22
+ template migration.template, migration.file_path
23
+ end
24
+
25
+ def generate_model(directory)
26
+ model_file = File.join(directory, 'app', 'models', 'user.rb')
27
+
28
+ if File.file? model_file
29
+ Out.warning 'User model already exists.'
30
+ return
31
+ end
32
+
33
+ template 'user.tt', model_file
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,25 @@
1
+ class AuthenticationController < Eucalypt::Controller(route: '/auth')
2
+ helpers AuthenticationHelper if defined? AuthenticationHelper
3
+
4
+ get '/login' do
5
+ redirect '/' if current_user
6
+ erb :'authentication/login', layout: false
7
+ end
8
+
9
+ post '/login' do
10
+ redirect '/' if current_user
11
+ authenticate
12
+ redirect session[:return_to] || '/'
13
+ end
14
+
15
+ get '/logout' do
16
+ env['warden'].logout
17
+ redirect to '/login'
18
+ end
19
+
20
+ post '/invalid' do
21
+ session[:return_to] = env['warden.options'][:attempted_path]
22
+ status 403 # Unauthenticated
23
+ redirect to '/login'
24
+ end
25
+ end
@@ -0,0 +1,9 @@
1
+ class CreateUsers < ActiveRecord::Migration[<%= ActiveRecord::Migration.current_version %>]
2
+ def change
3
+ create_table :users do |t|
4
+ t.string :username, null: false
5
+ t.string :encrypted_password, null: false
6
+ t.timestamps
7
+ end
8
+ end
9
+ end