eucalypt 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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