hanami 1.3.5 → 2.0.0.alpha1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (147) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +51 -41
  3. data/FEATURES.md +2 -12
  4. data/LICENSE.md +1 -1
  5. data/README.md +5 -8
  6. data/bin/hanami +6 -4
  7. data/hanami.gemspec +24 -28
  8. data/lib/hanami/application.rb +44 -176
  9. data/lib/hanami/boot.rb +6 -0
  10. data/lib/hanami/cli/commands/command.rb +21 -29
  11. data/lib/hanami/cli/commands/server.rb +63 -14
  12. data/lib/hanami/cli/commands.rb +5 -42
  13. data/lib/hanami/configuration/cookies.rb +24 -0
  14. data/lib/hanami/configuration/middleware.rb +8 -28
  15. data/lib/hanami/configuration/security.rb +141 -0
  16. data/lib/hanami/configuration/sessions.rb +50 -0
  17. data/lib/hanami/configuration.rb +181 -191
  18. data/lib/hanami/container.rb +107 -0
  19. data/lib/hanami/frameworks.rb +24 -18
  20. data/lib/hanami/routes.rb +17 -205
  21. data/lib/hanami/server.rb +5 -69
  22. data/lib/hanami/version.rb +3 -1
  23. data/lib/hanami.rb +39 -243
  24. metadata +36 -233
  25. data/lib/hanami/action/csrf_protection.rb +0 -211
  26. data/lib/hanami/action/routing_helpers.rb +0 -40
  27. data/lib/hanami/app.rb +0 -96
  28. data/lib/hanami/application_configuration.rb +0 -1495
  29. data/lib/hanami/application_name.rb +0 -108
  30. data/lib/hanami/application_namespace.rb +0 -14
  31. data/lib/hanami/assets/asset.rb +0 -72
  32. data/lib/hanami/assets/static.rb +0 -102
  33. data/lib/hanami/cli/commands/assets/precompile.rb +0 -42
  34. data/lib/hanami/cli/commands/assets.rb +0 -16
  35. data/lib/hanami/cli/commands/console.rb +0 -95
  36. data/lib/hanami/cli/commands/db/apply.rb +0 -32
  37. data/lib/hanami/cli/commands/db/console.rb +0 -44
  38. data/lib/hanami/cli/commands/db/create.rb +0 -32
  39. data/lib/hanami/cli/commands/db/drop.rb +0 -32
  40. data/lib/hanami/cli/commands/db/migrate.rb +0 -39
  41. data/lib/hanami/cli/commands/db/prepare.rb +0 -32
  42. data/lib/hanami/cli/commands/db/rollback.rb +0 -59
  43. data/lib/hanami/cli/commands/db/version.rb +0 -32
  44. data/lib/hanami/cli/commands/db.rb +0 -32
  45. data/lib/hanami/cli/commands/destroy/action.rb +0 -137
  46. data/lib/hanami/cli/commands/destroy/app.rb +0 -159
  47. data/lib/hanami/cli/commands/destroy/mailer.rb +0 -74
  48. data/lib/hanami/cli/commands/destroy/migration.rb +0 -51
  49. data/lib/hanami/cli/commands/destroy/model.rb +0 -84
  50. data/lib/hanami/cli/commands/destroy.rb +0 -26
  51. data/lib/hanami/cli/commands/generate/action/action.erb +0 -7
  52. data/lib/hanami/cli/commands/generate/action/action_spec.minitest.erb +0 -11
  53. data/lib/hanami/cli/commands/generate/action/action_spec.rspec.erb +0 -9
  54. data/lib/hanami/cli/commands/generate/action/action_without_view.erb +0 -7
  55. data/lib/hanami/cli/commands/generate/action/view.erb +0 -7
  56. data/lib/hanami/cli/commands/generate/action/view_spec.minitest.erb +0 -12
  57. data/lib/hanami/cli/commands/generate/action/view_spec.rspec.erb +0 -10
  58. data/lib/hanami/cli/commands/generate/action.rb +0 -321
  59. data/lib/hanami/cli/commands/generate/app/application.erb +0 -313
  60. data/lib/hanami/cli/commands/generate/app/favicon.ico +0 -0
  61. data/lib/hanami/cli/commands/generate/app/gitkeep.erb +0 -0
  62. data/lib/hanami/cli/commands/generate/app/layout.erb +0 -7
  63. data/lib/hanami/cli/commands/generate/app/layout_spec.minitest.erb +0 -10
  64. data/lib/hanami/cli/commands/generate/app/layout_spec.rspec.erb +0 -10
  65. data/lib/hanami/cli/commands/generate/app/routes.erb +0 -5
  66. data/lib/hanami/cli/commands/generate/app/template.erb.erb +0 -10
  67. data/lib/hanami/cli/commands/generate/app/template.haml.erb +0 -7
  68. data/lib/hanami/cli/commands/generate/app/template.slim.erb +0 -8
  69. data/lib/hanami/cli/commands/generate/app.rb +0 -243
  70. data/lib/hanami/cli/commands/generate/mailer/mailer.erb +0 -9
  71. data/lib/hanami/cli/commands/generate/mailer/mailer_spec.minitest.erb +0 -7
  72. data/lib/hanami/cli/commands/generate/mailer/mailer_spec.rspec.erb +0 -5
  73. data/lib/hanami/cli/commands/generate/mailer.rb +0 -104
  74. data/lib/hanami/cli/commands/generate/migration/migration.erb +0 -4
  75. data/lib/hanami/cli/commands/generate/migration.rb +0 -41
  76. data/lib/hanami/cli/commands/generate/model/entity.erb +0 -2
  77. data/lib/hanami/cli/commands/generate/model/entity_spec.minitest.erb +0 -5
  78. data/lib/hanami/cli/commands/generate/model/entity_spec.rspec.erb +0 -3
  79. data/lib/hanami/cli/commands/generate/model/migration.erb +0 -10
  80. data/lib/hanami/cli/commands/generate/model/repository.erb +0 -5
  81. data/lib/hanami/cli/commands/generate/model/repository_spec.minitest.erb +0 -5
  82. data/lib/hanami/cli/commands/generate/model/repository_spec.rspec.erb +0 -3
  83. data/lib/hanami/cli/commands/generate/model.rb +0 -125
  84. data/lib/hanami/cli/commands/generate/secret.rb +0 -48
  85. data/lib/hanami/cli/commands/generate.rb +0 -28
  86. data/lib/hanami/cli/commands/new/.env.development.erb +0 -3
  87. data/lib/hanami/cli/commands/new/.env.test.erb +0 -3
  88. data/lib/hanami/cli/commands/new/.gitkeep.erb +0 -0
  89. data/lib/hanami/cli/commands/new/Gemfile.erb +0 -57
  90. data/lib/hanami/cli/commands/new/README.md.erb +0 -33
  91. data/lib/hanami/cli/commands/new/config/boot.erb +0 -2
  92. data/lib/hanami/cli/commands/new/config/environment.erb +0 -49
  93. data/lib/hanami/cli/commands/new/config.ru.erb +0 -3
  94. data/lib/hanami/cli/commands/new/gitignore.erb +0 -4
  95. data/lib/hanami/cli/commands/new/gitignore_with_sqlite.erb +0 -5
  96. data/lib/hanami/cli/commands/new/hanamirc.erb +0 -3
  97. data/lib/hanami/cli/commands/new/lib/project.erb +0 -2
  98. data/lib/hanami/cli/commands/new/minitest/Rakefile.erb +0 -12
  99. data/lib/hanami/cli/commands/new/minitest/features_helper.erb +0 -11
  100. data/lib/hanami/cli/commands/new/minitest/spec_helper.erb +0 -7
  101. data/lib/hanami/cli/commands/new/rspec/Rakefile.erb +0 -9
  102. data/lib/hanami/cli/commands/new/rspec/capybara.erb +0 -8
  103. data/lib/hanami/cli/commands/new/rspec/features_helper.erb +0 -12
  104. data/lib/hanami/cli/commands/new/rspec/rspec.erb +0 -2
  105. data/lib/hanami/cli/commands/new/rspec/spec_helper.erb +0 -103
  106. data/lib/hanami/cli/commands/new/schema.sql.erb +0 -0
  107. data/lib/hanami/cli/commands/new.rb +0 -578
  108. data/lib/hanami/cli/commands/project.rb +0 -421
  109. data/lib/hanami/cli/commands/routes.rb +0 -21
  110. data/lib/hanami/cli/commands/templates.rb +0 -31
  111. data/lib/hanami/cli/commands/version.rb +0 -19
  112. data/lib/hanami/common_logger.rb +0 -109
  113. data/lib/hanami/components/app/assets.rb +0 -59
  114. data/lib/hanami/components/app/controller.rb +0 -74
  115. data/lib/hanami/components/app/routes.rb +0 -59
  116. data/lib/hanami/components/app/view.rb +0 -44
  117. data/lib/hanami/components/component.rb +0 -182
  118. data/lib/hanami/components/components.rb +0 -479
  119. data/lib/hanami/components/routes_inspector.rb +0 -72
  120. data/lib/hanami/components.rb +0 -156
  121. data/lib/hanami/config/cookies.rb +0 -69
  122. data/lib/hanami/config/framework_configuration.rb +0 -43
  123. data/lib/hanami/config/load_paths.rb +0 -46
  124. data/lib/hanami/config/mapper.rb +0 -47
  125. data/lib/hanami/config/routes.rb +0 -20
  126. data/lib/hanami/config/security.rb +0 -110
  127. data/lib/hanami/config/sessions.rb +0 -119
  128. data/lib/hanami/configuration/app.rb +0 -21
  129. data/lib/hanami/early_hints.rb +0 -129
  130. data/lib/hanami/env.rb +0 -69
  131. data/lib/hanami/environment.rb +0 -541
  132. data/lib/hanami/environment_application_configurations.rb +0 -37
  133. data/lib/hanami/hanamirc.rb +0 -169
  134. data/lib/hanami/mailer/glue.rb +0 -27
  135. data/lib/hanami/middleware_stack.rb +0 -172
  136. data/lib/hanami/rake_helper.rb +0 -78
  137. data/lib/hanami/rake_tasks.rb +0 -3
  138. data/lib/hanami/rendering_policy.rb +0 -94
  139. data/lib/hanami/routing/default.rb +0 -32
  140. data/lib/hanami/setup.rb +0 -3
  141. data/lib/hanami/static.rb +0 -63
  142. data/lib/hanami/templates/default.html.erb +0 -30
  143. data/lib/hanami/templates/welcome.html.erb +0 -52
  144. data/lib/hanami/views/default.rb +0 -37
  145. data/lib/hanami/views/default_template_finder.rb +0 -22
  146. data/lib/hanami/views/null_view.rb +0 -15
  147. data/lib/hanami/welcome.rb +0 -41
@@ -1,35 +1,84 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Hanami
4
+ # Hanami CLI
5
+ #
6
+ # @since 1.1.0
2
7
  class CLI
3
8
  module Commands
4
9
  # @since 1.1.0
5
10
  # @api private
6
11
  class Server < Command
7
- requires 'code_reloading'
8
-
9
12
  desc "Start Hanami server (only for development)"
10
13
 
11
- option :server, desc: "Force a server engine (eg, webrick, puma, thin, etc..)"
12
- option :host, desc: "The host address to bind to"
13
- option :port, desc: "The port to run the server on", aliases: ["-p"]
14
- option :debug, desc: "Turn on debug output"
15
- option :warn, desc: "Turn on warnings"
16
- option :daemonize, desc: "Daemonize the server"
17
- option :pid, desc: "Path to write a pid file after daemonize"
18
- option :code_reloading, desc: "Code reloading", type: :boolean, default: true
14
+ option :server, desc: "Force a server engine (eg, webrick, puma, thin, etc..)"
15
+ option :host, desc: "The host address to bind to"
16
+ option :port, desc: "The port to run the server on", aliases: ["-p"]
17
+ option :debug, desc: "Turn on debug output", type: :boolean
18
+ option :warn, desc: "Turn on warnings", type: :boolean
19
+ option :daemonize, desc: "Daemonize the server", type: :boolean
20
+ option :pid, desc: "Path to write a pid file after daemonize"
19
21
 
20
22
  example [
21
23
  " # Basic usage (it uses the bundled server engine)",
22
24
  "--server=webrick # Force `webrick` server engine",
23
25
  "--host=0.0.0.0 # Bind to a host",
24
- "--port=2306 # Bind to a port",
25
- "--no-code-reloading # Disable code reloading"
26
+ "--port=2306 # Bind to a port"
26
27
  ]
27
28
 
28
29
  # @since 1.1.0
29
30
  # @api private
30
- def call(*)
31
+ def call(**args)
32
+ require "hanami"
33
+ require "hanami/container"
31
34
  require "hanami/server"
32
- Hanami::Server.new.start
35
+
36
+ options = parse_arguments(args)
37
+ Hanami::Server.new(options).start
38
+ end
39
+
40
+ private
41
+
42
+ DEFAULT_CONFIG = "config.ru"
43
+ private_constant :DEFAULT_CONFIG
44
+
45
+ DEFAULT_HOST = "0.0.0.0"
46
+ private_constant :DEFAULT_HOST
47
+
48
+ DEFAULT_PORT = "2300"
49
+ private_constant :DEFAULT_PORT
50
+
51
+ OPTIONAL_SETTINGS = %i[
52
+ server
53
+ debug
54
+ warn
55
+ daemonize
56
+ pid
57
+ ].freeze
58
+
59
+ def parse_arguments(args)
60
+ Hanami::Container.start(:env)
61
+
62
+ {
63
+ config: DEFAULT_CONFIG,
64
+ Host: host(args),
65
+ Port: port(args),
66
+ AccessLog: []
67
+ }.merge(
68
+ args.slice(*OPTIONAL_SETTINGS)
69
+ )
70
+ end
71
+
72
+ def host(args)
73
+ args.fetch(:host) do
74
+ ENV.fetch("HANAMI_HOST", DEFAULT_HOST)
75
+ end
76
+ end
77
+
78
+ def port(args)
79
+ args.fetch(:port) do
80
+ ENV.fetch("HANAMI_PORT", DEFAULT_PORT)
81
+ end
33
82
  end
34
83
  end
35
84
  end
@@ -1,5 +1,6 @@
1
- require 'dry/cli'
2
- require 'ostruct'
1
+ # frozen_string_literal: true
2
+
3
+ require "hanami/cli"
3
4
 
4
5
  module Hanami
5
6
  # Hanami CLI
@@ -23,7 +24,7 @@ module Hanami
23
24
  # module CLI
24
25
  # module Commands
25
26
  # class Generate < Hanami::CLI::Command
26
- # desc "Generate Webpack config"
27
+ # desc "Generate Webpack configuration"
27
28
  #
28
29
  # def call(*)
29
30
  # # ...
@@ -54,48 +55,10 @@ module Hanami
54
55
  # @since 1.1.0
55
56
  # @api private
56
57
  module Commands
57
- extend Dry::CLI::Registry
58
-
59
- # CLI command context
60
- #
61
- # @since 1.1.0
62
- # @api private
63
- class Context < OpenStruct
64
- # @since 1.1.0
65
- # @api private
66
- def initialize(data)
67
- data = data.each_with_object({}) do |(k, v), result|
68
- v = Utils::String.new(v) if v.is_a?(::String)
69
- result[k] = v
70
- end
71
-
72
- super(data)
73
- freeze
74
- end
75
-
76
- # @since 1.1.0
77
- # @api private
78
- def with(data)
79
- self.class.new(to_h.merge(data))
80
- end
81
-
82
- # @since 1.1.0
83
- # @api private
84
- def binding
85
- super
86
- end
87
- end
58
+ extend Hanami::CLI::Registry
88
59
 
89
60
  require "hanami/cli/commands/command"
90
- require "hanami/cli/commands/assets"
91
- require "hanami/cli/commands/console"
92
- require "hanami/cli/commands/db"
93
- require "hanami/cli/commands/destroy"
94
- require "hanami/cli/commands/generate"
95
- require "hanami/cli/commands/new"
96
- require "hanami/cli/commands/routes"
97
61
  require "hanami/cli/commands/server"
98
- require "hanami/cli/commands/version"
99
62
  end
100
63
  end
101
64
  end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Hanami
4
+ class Configuration
5
+ # Hanami configuration for HTTP cookies
6
+ #
7
+ # @since 2.0.0
8
+ class Cookies
9
+ def self.null
10
+ { null: true }
11
+ end
12
+
13
+ attr_reader :options
14
+
15
+ def initialize(options)
16
+ @options = options
17
+ end
18
+
19
+ def enabled?
20
+ options != self.class.null
21
+ end
22
+ end
23
+ end
24
+ end
@@ -1,40 +1,20 @@
1
- require "concurrent"
1
+ # frozen_string_literal: true
2
2
 
3
3
  module Hanami
4
- # @api private
5
4
  class Configuration
6
- # Middleware configuration
7
- # @since 1.2.0
5
+ # Hanami application configured Rack middleware
6
+ #
7
+ # @since 2.0.0
8
8
  class Middleware
9
- # @api private
10
- # @since 1.2.0
11
9
  def initialize
12
- @middleware = Concurrent::Array.new
10
+ @stack = []
13
11
  end
14
12
 
15
- # Use a Rack middleware
16
- #
17
- # @param middleware [#call] a Rack middleware
18
- # @param args [Array<Object>] an optional set of options
19
- # @param blk [Proc] an optional block to pass to the middleware
20
- #
21
- # @since 1.2.0
22
- #
23
- # @example
24
- # # config/environment.rb
25
- # # ...
26
- # Hanami.configure do
27
- # middleware.use MyRackMiddleware
28
- # end
29
- def use(middleware, *args, &blk)
30
- @middleware.push([middleware, args, blk])
13
+ def use(middleware, *args)
14
+ stack.push([middleware, *args])
31
15
  end
32
16
 
33
- # @api private
34
- # @since 1.2.0
35
- def each(&blk)
36
- @middleware.each(&blk)
37
- end
17
+ attr_reader :stack
38
18
  end
39
19
  end
40
20
  end
@@ -0,0 +1,141 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "concurrent/hash"
4
+ require "hanami/utils/string"
5
+
6
+ module Hanami
7
+ class Configuration
8
+ # Hanami configuration security settings
9
+ #
10
+ # @since 2.0.0
11
+ class Security
12
+ def initialize
13
+ @settings = Concurrent::Hash.new
14
+ settings[:x_frame_options] = Setting.new(HEADER_X_FRAME_OPTIONS, DEFAULT_X_FRAME_OPTIONS)
15
+ settings[:x_content_type_options] = Setting.new(HEADER_X_CONTENT_TYPE_OPTIONS, DEFAULT_X_CONTENT_TYPE_OPTIONS)
16
+ settings[:x_xss_protection] = Setting.new(HEADER_X_XSS_PROTECTION, DEFAULT_X_XSS_PROTECTION)
17
+ settings[:content_security_policy] = ContentSecurityPolicy.new(HEADER_CONTENT_SECURITY_POLICY, DEFAULT_CONTENT_SECURITY_POLICY.dup)
18
+ end
19
+
20
+ def x_frame_options=(value)
21
+ settings[:x_frame_options].value = value
22
+ end
23
+
24
+ def x_frame_options
25
+ settings.fetch(:x_frame_options)
26
+ end
27
+
28
+ def x_content_type_options=(value)
29
+ settings[:x_content_type_options].value = value
30
+ end
31
+
32
+ def x_content_type_options
33
+ settings.fetch(:x_content_type_options)
34
+ end
35
+
36
+ def x_xss_protection=(value)
37
+ settings[:x_xss_protection].value = value
38
+ end
39
+
40
+ def x_xss_protection
41
+ settings.fetch(:x_xss_protection)
42
+ end
43
+
44
+ def content_security_policy=(options)
45
+ settings[:content_security_policy].value = options
46
+ end
47
+
48
+ def content_security_policy
49
+ settings.fetch(:content_security_policy)
50
+ end
51
+
52
+ def to_hash
53
+ settings.each_with_object({}) do |(_, v), result|
54
+ next if v.value.nil?
55
+
56
+ result[v.header] = v.value
57
+ end
58
+ end
59
+
60
+ private
61
+
62
+ # X-Frame-Options
63
+ HEADER_X_FRAME_OPTIONS = "X-Frame-Options"
64
+ private_constant :HEADER_X_FRAME_OPTIONS
65
+
66
+ DEFAULT_X_FRAME_OPTIONS = "DENY"
67
+ private_constant :DEFAULT_X_FRAME_OPTIONS
68
+
69
+ # X-Content-Type-Optionx
70
+ HEADER_X_CONTENT_TYPE_OPTIONS = "X-Content-Type-Options"
71
+ private_constant :HEADER_X_CONTENT_TYPE_OPTIONS
72
+
73
+ DEFAULT_X_CONTENT_TYPE_OPTIONS = "nosniff"
74
+ private_constant :DEFAULT_X_CONTENT_TYPE_OPTIONS
75
+
76
+ # X-XSS-Protection
77
+ HEADER_X_XSS_PROTECTION = "X-XSS-Protection"
78
+ private_constant :HEADER_X_XSS_PROTECTION
79
+
80
+ DEFAULT_X_XSS_PROTECTION = "1; mode=block"
81
+ private_constant :DEFAULT_X_XSS_PROTECTION
82
+
83
+ # Content-Security-Policy
84
+ HEADER_CONTENT_SECURITY_POLICY = "Content-Security-Policy"
85
+ private_constant :HEADER_CONTENT_SECURITY_POLICY
86
+
87
+ DEFAULT_CONTENT_SECURITY_POLICY = {
88
+ form_action: "'self'",
89
+ frame_ancestors: "'self'",
90
+ base_uri: "'self'",
91
+ default_src: "'none'",
92
+ script_src: "'self'",
93
+ connect_src: "'self'",
94
+ img_src: "'self' https: data:",
95
+ style_src: "'self' 'unsafe-inline' https:",
96
+ font_src: "'self'",
97
+ object_src: "'none'",
98
+ plugin_types: "application/pdf",
99
+ child_src: "'self'",
100
+ frame_src: "'self'",
101
+ media_src: "'self'"
102
+ }.freeze
103
+ private_constant :DEFAULT_CONTENT_SECURITY_POLICY
104
+
105
+ # Security setting
106
+ #
107
+ # @api private
108
+ # @since 2.0.0
109
+ class Setting
110
+ attr_accessor :header, :value
111
+
112
+ def initialize(header, value)
113
+ @header = header.freeze
114
+ @value = value
115
+ end
116
+ end
117
+
118
+ # Content security policy settings
119
+ #
120
+ # @api private
121
+ # @since 2.0.0
122
+ class ContentSecurityPolicy < Setting
123
+ def value
124
+ @value.map do |k, v|
125
+ "#{Utils::String.dasherize(k)} #{v}" unless v.nil?
126
+ end.compact.join("; ")
127
+ end
128
+
129
+ def [](key)
130
+ @value[key]
131
+ end
132
+
133
+ def []=(key, value)
134
+ @value[key] = value
135
+ end
136
+ end
137
+
138
+ attr_reader :settings
139
+ end
140
+ end
141
+ end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "hanami/utils/string"
4
+ require "hanami/utils/class"
5
+
6
+ module Hanami
7
+ class Configuration
8
+ # Hanami configuration for HTTP sessions
9
+ #
10
+ # @since 2.0.0
11
+ class Sessions
12
+ def self.null
13
+ NULL_STORAGE
14
+ end
15
+
16
+ attr_reader :storage, :options
17
+
18
+ def initialize(*args)
19
+ storage, options, = Array(args.dup).flatten
20
+
21
+ @storage = storage
22
+ @options = options || {}
23
+ end
24
+
25
+ def enabled?
26
+ storage != NULL_STORAGE
27
+ end
28
+
29
+ def middleware
30
+ [[storage_middleware, options]]
31
+ end
32
+
33
+ private
34
+
35
+ NULL_STORAGE = :null
36
+ private_constant :NULL_STORAGE
37
+
38
+ def storage_middleware
39
+ require_storage
40
+
41
+ name = Utils::String.classify(storage)
42
+ Utils::Class.load!(name, Rack::Session)
43
+ end
44
+
45
+ def require_storage
46
+ require "rack/session/#{storage}"
47
+ end
48
+ end
49
+ end
50
+ end