hanami 0.0.0 → 0.7.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +214 -0
- data/FEATURES.md +156 -0
- data/LICENSE.md +22 -0
- data/README.md +80 -15
- data/bin/hanami +5 -0
- data/hanami.gemspec +27 -12
- data/lib/hanami.rb +78 -2
- data/lib/hanami/action/csrf_protection.rb +167 -0
- data/lib/hanami/action/routing_helpers.rb +40 -0
- data/lib/hanami/application.rb +244 -0
- data/lib/hanami/application_name.rb +101 -0
- data/lib/hanami/cli.rb +119 -0
- data/lib/hanami/cli_sub_commands/assets.rb +29 -0
- data/lib/hanami/cli_sub_commands/db.rb +124 -0
- data/lib/hanami/cli_sub_commands/destroy.rb +102 -0
- data/lib/hanami/cli_sub_commands/generate.rb +127 -0
- data/lib/hanami/commands/assets/precompile.rb +35 -0
- data/lib/hanami/commands/console.rb +90 -0
- data/lib/hanami/commands/db/abstract.rb +19 -0
- data/lib/hanami/commands/db/apply.rb +14 -0
- data/lib/hanami/commands/db/console.rb +50 -0
- data/lib/hanami/commands/db/create.rb +14 -0
- data/lib/hanami/commands/db/drop.rb +14 -0
- data/lib/hanami/commands/db/migrate.rb +19 -0
- data/lib/hanami/commands/db/prepare.rb +14 -0
- data/lib/hanami/commands/db/version.rb +14 -0
- data/lib/hanami/commands/generate/abstract.rb +63 -0
- data/lib/hanami/commands/generate/action.rb +262 -0
- data/lib/hanami/commands/generate/app.rb +116 -0
- data/lib/hanami/commands/generate/mailer.rb +118 -0
- data/lib/hanami/commands/generate/migration.rb +63 -0
- data/lib/hanami/commands/generate/model.rb +96 -0
- data/lib/hanami/commands/new/abstract.rb +128 -0
- data/lib/hanami/commands/new/app.rb +116 -0
- data/lib/hanami/commands/new/container.rb +102 -0
- data/lib/hanami/commands/routes.rb +41 -0
- data/lib/hanami/commands/server.rb +79 -0
- data/lib/hanami/config/configure.rb +17 -0
- data/lib/hanami/config/cookies.rb +68 -0
- data/lib/hanami/config/framework_configuration.rb +42 -0
- data/lib/hanami/config/load_paths.rb +27 -0
- data/lib/hanami/config/mapper.rb +36 -0
- data/lib/hanami/config/mapping.rb +12 -0
- data/lib/hanami/config/routes.rb +16 -0
- data/lib/hanami/config/security.rb +58 -0
- data/lib/hanami/config/sessions.rb +97 -0
- data/lib/hanami/configuration.rb +1728 -0
- data/lib/hanami/container.rb +59 -0
- data/lib/hanami/environment.rb +485 -0
- data/lib/hanami/frameworks.rb +14 -0
- data/lib/hanami/generators/action/action.rb.tt +8 -0
- data/lib/hanami/generators/action/action_spec.minitest.tt +12 -0
- data/lib/hanami/generators/action/action_spec.rspec.tt +11 -0
- data/lib/hanami/generators/action/action_without_view.rb.tt +9 -0
- data/lib/hanami/generators/action/template.tt +0 -0
- data/lib/hanami/generators/action/view.rb.tt +5 -0
- data/lib/hanami/generators/action/view_spec.minitest.tt +13 -0
- data/lib/hanami/generators/action/view_spec.rspec.tt +12 -0
- data/lib/hanami/generators/app/.gitkeep.tt +1 -0
- data/lib/hanami/generators/app/application.rb.tt +273 -0
- data/lib/hanami/generators/app/config/initializers/.gitkeep +0 -0
- data/lib/hanami/generators/app/config/routes.rb.tt +2 -0
- data/lib/hanami/generators/app/favicon.ico +0 -0
- data/lib/hanami/generators/app/templates/application.html.erb.tt +10 -0
- data/lib/hanami/generators/app/views/application_layout.rb.tt +7 -0
- data/lib/hanami/generators/application/app/.env.development.tt +4 -0
- data/lib/hanami/generators/application/app/.env.test.tt +4 -0
- data/lib/hanami/generators/application/app/.env.tt +1 -0
- data/lib/hanami/generators/application/app/.gitignore +0 -0
- data/lib/hanami/generators/application/app/.gitkeep +1 -0
- data/lib/hanami/generators/application/app/Gemfile.tt +37 -0
- data/lib/hanami/generators/application/app/Rakefile.minitest.tt +11 -0
- data/lib/hanami/generators/application/app/Rakefile.rspec.tt +6 -0
- data/lib/hanami/generators/application/app/apps/.gitkeep.tt +1 -0
- data/lib/hanami/generators/application/app/capybara.rb.rspec.tt +8 -0
- data/lib/hanami/generators/application/app/config.ru.tt +3 -0
- data/lib/hanami/generators/application/app/config/application.rb.tt +270 -0
- data/lib/hanami/generators/application/app/config/environment.rb.tt +5 -0
- data/lib/hanami/generators/application/app/config/initializers/.gitkeep +0 -0
- data/lib/hanami/generators/application/app/config/routes.rb.tt +2 -0
- data/lib/hanami/generators/application/app/db/.gitkeep +1 -0
- data/lib/hanami/generators/application/app/favicon.ico +0 -0
- data/lib/hanami/generators/application/app/features_helper.rb.minitest.tt +11 -0
- data/lib/hanami/generators/application/app/features_helper.rb.rspec.tt +12 -0
- data/lib/hanami/generators/application/app/gitignore.tt +2 -0
- data/lib/hanami/generators/application/app/gitignore_with_db.tt +4 -0
- data/lib/hanami/generators/application/app/hanamirc.tt +3 -0
- data/lib/hanami/generators/application/app/lib/app_name.rb.tt +59 -0
- data/lib/hanami/generators/application/app/lib/chirp/entities/.gitkeep +1 -0
- data/lib/hanami/generators/application/app/lib/chirp/repositories/.gitkeep +1 -0
- data/lib/hanami/generators/application/app/lib/config/mapping.rb.tt +7 -0
- data/lib/hanami/generators/application/app/rspec.rspec.tt +2 -0
- data/lib/hanami/generators/application/app/schema.sql.tt +0 -0
- data/lib/hanami/generators/application/app/spec_helper.rb.minitest.tt +7 -0
- data/lib/hanami/generators/application/app/spec_helper.rb.rspec.tt +104 -0
- data/lib/hanami/generators/application/app/templates/application.html.erb.tt +10 -0
- data/lib/hanami/generators/application/app/views/application_layout.rb.tt +7 -0
- data/lib/hanami/generators/application/container/.env.development.tt +3 -0
- data/lib/hanami/generators/application/container/.env.test.tt +3 -0
- data/lib/hanami/generators/application/container/.env.tt +1 -0
- data/lib/hanami/generators/application/container/.gitignore +0 -0
- data/lib/hanami/generators/application/container/.gitkeep +1 -0
- data/lib/hanami/generators/application/container/Gemfile.tt +36 -0
- data/lib/hanami/generators/application/container/Rakefile.minitest.tt +11 -0
- data/lib/hanami/generators/application/container/Rakefile.rspec.tt +6 -0
- data/lib/hanami/generators/application/container/capybara.rb.rspec.tt +8 -0
- data/lib/hanami/generators/application/container/config.ru.tt +3 -0
- data/lib/hanami/generators/application/container/config/environment.rb.tt +7 -0
- data/lib/hanami/generators/application/container/config/initializers/.gitkeep +0 -0
- data/lib/hanami/generators/application/container/db/.gitkeep +1 -0
- data/lib/hanami/generators/application/container/features_helper.rb.minitest.tt +11 -0
- data/lib/hanami/generators/application/container/features_helper.rb.rspec.tt +12 -0
- data/lib/hanami/generators/application/container/gitignore.tt +2 -0
- data/lib/hanami/generators/application/container/gitignore_with_db.tt +4 -0
- data/lib/hanami/generators/application/container/hanamirc.tt +3 -0
- data/lib/hanami/generators/application/container/lib/app_name.rb.tt +60 -0
- data/lib/hanami/generators/application/container/lib/chirp/entities/.gitkeep +1 -0
- data/lib/hanami/generators/application/container/lib/chirp/mailers/.gitkeep +0 -0
- data/lib/hanami/generators/application/container/lib/chirp/mailers/templates/.gitkeep +0 -0
- data/lib/hanami/generators/application/container/lib/chirp/repositories/.gitkeep +1 -0
- data/lib/hanami/generators/application/container/lib/config/mapping.rb.tt +7 -0
- data/lib/hanami/generators/application/container/rspec.rspec.tt +2 -0
- data/lib/hanami/generators/application/container/schema.sql.tt +0 -0
- data/lib/hanami/generators/application/container/spec_helper.rb.minitest.tt +7 -0
- data/lib/hanami/generators/application/container/spec_helper.rb.rspec.tt +104 -0
- data/lib/hanami/generators/database_config.rb +99 -0
- data/lib/hanami/generators/generatable.rb +51 -0
- data/lib/hanami/generators/generator.rb +35 -0
- data/lib/hanami/generators/mailer/mailer.rb.tt +7 -0
- data/lib/hanami/generators/mailer/mailer_spec.rb.tt +7 -0
- data/lib/hanami/generators/mailer/template.html.tt +0 -0
- data/lib/hanami/generators/mailer/template.txt.tt +0 -0
- data/lib/hanami/generators/migration/migration.rb.tt +4 -0
- data/lib/hanami/generators/model/entity.rb.tt +3 -0
- data/lib/hanami/generators/model/entity_spec.minitest.tt +5 -0
- data/lib/hanami/generators/model/entity_spec.rspec.tt +3 -0
- data/lib/hanami/generators/model/repository.rb.tt +3 -0
- data/lib/hanami/generators/model/repository_spec.minitest.tt +5 -0
- data/lib/hanami/generators/model/repository_spec.rspec.tt +3 -0
- data/lib/hanami/generators/test_framework.rb +42 -0
- data/lib/hanami/hanamirc.rb +152 -0
- data/lib/hanami/loader.rb +258 -0
- data/lib/hanami/mailer/glue.rb +68 -0
- data/lib/hanami/middleware.rb +143 -0
- data/lib/hanami/rake_helper.rb +68 -0
- data/lib/hanami/rake_tasks.rb +2 -0
- data/lib/hanami/rendering_policy.rb +77 -0
- data/lib/hanami/repositories/car_repository.rb +3 -0
- data/lib/hanami/repositories/name_repository.rb +3 -0
- data/lib/hanami/root.rb +7 -0
- data/lib/hanami/routes.rb +151 -0
- data/lib/hanami/routing/default.rb +25 -0
- data/lib/hanami/setup.rb +3 -0
- data/lib/hanami/static.rb +77 -0
- data/lib/hanami/templates/default.html.erb +9 -0
- data/lib/hanami/templates/welcome.html.erb +52 -0
- data/lib/hanami/version.rb +4 -1
- data/lib/hanami/views/default.rb +34 -0
- data/lib/hanami/views/default_template_finder.rb +20 -0
- data/lib/hanami/views/null_view.rb +17 -0
- data/lib/hanami/welcome.rb +40 -0
- metadata +357 -16
- data/.gitignore +0 -9
- data/Gemfile +0 -4
- data/Rakefile +0 -2
- data/bin/console +0 -14
- data/bin/setup +0 -8
data/bin/hanami
ADDED
data/hanami.gemspec
CHANGED
|
@@ -4,20 +4,35 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
|
4
4
|
require 'hanami/version'
|
|
5
5
|
|
|
6
6
|
Gem::Specification.new do |spec|
|
|
7
|
-
spec.name =
|
|
7
|
+
spec.name = 'hanami'
|
|
8
8
|
spec.version = Hanami::VERSION
|
|
9
|
-
spec.authors = [
|
|
10
|
-
spec.email = [
|
|
11
|
-
|
|
12
|
-
spec.summary = %q{The web, with simplicity}
|
|
9
|
+
spec.authors = ['Luca Guidi', 'Trung Lê', 'Alfonso Uceda Pompa']
|
|
10
|
+
spec.email = ['me@lucaguidi.com', 'trung.le@ruby-journal.com', 'uceda73@gmail.com']
|
|
11
|
+
spec.summary = %q{The web, with simplicity.}
|
|
13
12
|
spec.description = %q{Hanami is a web framework for Ruby}
|
|
14
|
-
spec.homepage =
|
|
13
|
+
spec.homepage = 'http://hanamirb.org'
|
|
14
|
+
spec.license = 'MIT'
|
|
15
|
+
|
|
16
|
+
spec.files = `git ls-files -z -- lib/* bin/* LICENSE.md README.md CHANGELOG.md FEATURES.md hanami.gemspec`.split("\x0")
|
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test)/})
|
|
19
|
+
spec.require_paths = ['lib']
|
|
20
|
+
spec.required_ruby_version = '>= 2.0.0'
|
|
15
21
|
|
|
16
|
-
spec.
|
|
17
|
-
spec.
|
|
18
|
-
spec.
|
|
19
|
-
spec.
|
|
22
|
+
spec.add_dependency 'hanami-utils', '~> 0.7'
|
|
23
|
+
spec.add_dependency 'hanami-router', '~> 0.6'
|
|
24
|
+
spec.add_dependency 'hanami-controller', '~> 0.6'
|
|
25
|
+
spec.add_dependency 'hanami-view', '~> 0.6'
|
|
26
|
+
spec.add_dependency 'hanami-helpers', '~> 0.3'
|
|
27
|
+
spec.add_dependency 'hanami-mailer', '~> 0.2'
|
|
28
|
+
spec.add_dependency 'hanami-assets', '~> 0.2'
|
|
29
|
+
spec.add_dependency 'shotgun', '~> 0.9'
|
|
30
|
+
spec.add_dependency 'dotenv', '~> 2.0'
|
|
31
|
+
spec.add_dependency 'thor', '~> 0.19'
|
|
32
|
+
spec.add_dependency 'bundler', '~> 1.6'
|
|
20
33
|
|
|
21
|
-
spec.add_development_dependency
|
|
22
|
-
spec.add_development_dependency
|
|
34
|
+
spec.add_development_dependency 'minispec-metadata', '~> 3.2.1'
|
|
35
|
+
spec.add_development_dependency 'minitest', '~> 5'
|
|
36
|
+
spec.add_development_dependency 'rack-test', '~> 0.6'
|
|
37
|
+
spec.add_development_dependency 'rake', '~> 10'
|
|
23
38
|
end
|
data/lib/hanami.rb
CHANGED
|
@@ -1,5 +1,81 @@
|
|
|
1
|
-
require
|
|
1
|
+
require 'hanami/version'
|
|
2
|
+
require 'hanami/application'
|
|
3
|
+
require 'hanami/container'
|
|
4
|
+
require 'hanami/environment'
|
|
2
5
|
|
|
6
|
+
# A complete web framework for Ruby
|
|
7
|
+
#
|
|
8
|
+
# @since 0.1.0
|
|
9
|
+
#
|
|
10
|
+
# @see http://hanamirb.org
|
|
3
11
|
module Hanami
|
|
4
|
-
|
|
12
|
+
DEFAULT_PUBLIC_DIRECTORY = 'public'.freeze
|
|
13
|
+
|
|
14
|
+
# Return root of the project (top level directory).
|
|
15
|
+
#
|
|
16
|
+
# @return [Pathname] root path
|
|
17
|
+
#
|
|
18
|
+
# @since 0.3.2
|
|
19
|
+
#
|
|
20
|
+
# @example
|
|
21
|
+
# Hanami.root # => #<Pathname:/Users/luca/Code/bookshelf>
|
|
22
|
+
def self.root
|
|
23
|
+
environment.root
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def self.public_directory
|
|
27
|
+
root.join(DEFAULT_PUBLIC_DIRECTORY)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# Return the current environment
|
|
31
|
+
#
|
|
32
|
+
# @return [String] the current environment
|
|
33
|
+
#
|
|
34
|
+
# @since 0.3.1
|
|
35
|
+
#
|
|
36
|
+
# @see Hanami::Environment#environment
|
|
37
|
+
#
|
|
38
|
+
# @example
|
|
39
|
+
# Hanami.env => "development"
|
|
40
|
+
def self.env
|
|
41
|
+
environment.environment
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# Check to see if specified environment(s) matches the current environment.
|
|
45
|
+
#
|
|
46
|
+
# If multiple names are given, it returns true, if at least one of them
|
|
47
|
+
# matches the current environment.
|
|
48
|
+
#
|
|
49
|
+
# @return [TrueClass,FalseClass] the result of the check
|
|
50
|
+
#
|
|
51
|
+
# @since 0.3.1
|
|
52
|
+
#
|
|
53
|
+
# @see Hanami.env
|
|
54
|
+
#
|
|
55
|
+
# @example Single name
|
|
56
|
+
# puts ENV['HANAMI_ENV'] # => "development"
|
|
57
|
+
#
|
|
58
|
+
# Hanami.env?(:development) # => true
|
|
59
|
+
# Hanami.env?('development') # => true
|
|
60
|
+
#
|
|
61
|
+
# Hanami.env?(:production) # => false
|
|
62
|
+
#
|
|
63
|
+
# @example Multiple names
|
|
64
|
+
# puts ENV['HANAMI_ENV'] # => "development"
|
|
65
|
+
#
|
|
66
|
+
# Hanami.env?(:development, :test) # => true
|
|
67
|
+
# Hanami.env?(:production, :staging) # => false
|
|
68
|
+
def self.env?(*names)
|
|
69
|
+
environment.environment?(*names)
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# Return environment
|
|
73
|
+
#
|
|
74
|
+
# @return [Hanami::Environment] environment
|
|
75
|
+
#
|
|
76
|
+
# @api private
|
|
77
|
+
# @since 0.3.2
|
|
78
|
+
def self.environment
|
|
79
|
+
Environment.new
|
|
80
|
+
end
|
|
5
81
|
end
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
require 'securerandom'
|
|
2
|
+
|
|
3
|
+
module Hanami
|
|
4
|
+
module Action
|
|
5
|
+
# Invalid CSRF Token
|
|
6
|
+
#
|
|
7
|
+
# @since 0.4.0
|
|
8
|
+
class InvalidCSRFTokenError < ::StandardError
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
# CSRF Protection
|
|
12
|
+
#
|
|
13
|
+
# This security mechanism is enabled automatically if sessions are turned on.
|
|
14
|
+
#
|
|
15
|
+
# It stores a "challenge" token in session. For each "state changing request"
|
|
16
|
+
# (eg. <tt>POST</tt>, <tt>PATCH</tt> etc..), we should send a special param:
|
|
17
|
+
# <tt>_csrf_token</tt>.
|
|
18
|
+
#
|
|
19
|
+
# If the param matches with the challenge token, the flow can continue.
|
|
20
|
+
# Otherwise the application detects an attack attempt, it reset the session
|
|
21
|
+
# and <tt>Hanami::Action::InvalidCSRFTokenError</tt> is raised.
|
|
22
|
+
#
|
|
23
|
+
# We can specify a custom handling strategy, by overriding <tt>#handle_invalid_csrf_token</tt>.
|
|
24
|
+
#
|
|
25
|
+
# Form helper (<tt>#form_for</tt>) automatically sets a hidden field with the
|
|
26
|
+
# correct token. A special view method (<tt>#csrf_token</tt>) is available in
|
|
27
|
+
# case the form markup is manually crafted.
|
|
28
|
+
#
|
|
29
|
+
# We can disable this check on action basis, by overriding <tt>#verify_csrf_token?</tt>.
|
|
30
|
+
#
|
|
31
|
+
# @since 0.4.0
|
|
32
|
+
#
|
|
33
|
+
# @see https://www.owasp.org/index.php/Cross-Site_Request_Forgery_%28CSRF%29
|
|
34
|
+
# @see https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)_Prevention_Cheat_Sheet
|
|
35
|
+
#
|
|
36
|
+
# @example Custom Handling
|
|
37
|
+
# module Web::Controllers::Books
|
|
38
|
+
# class Create
|
|
39
|
+
# include Web::Action
|
|
40
|
+
#
|
|
41
|
+
# def call(params)
|
|
42
|
+
# # ...
|
|
43
|
+
# end
|
|
44
|
+
#
|
|
45
|
+
# private
|
|
46
|
+
#
|
|
47
|
+
# def handle_invalid_csrf_token
|
|
48
|
+
# Web::Logger.warn "CSRF attack: expected #{ session[:_csrf_token] }, was #{ params[:_csrf_token] }"
|
|
49
|
+
# # manual handling
|
|
50
|
+
# end
|
|
51
|
+
# end
|
|
52
|
+
# end
|
|
53
|
+
#
|
|
54
|
+
# @example Bypass Security Check
|
|
55
|
+
# module Web::Controllers::Books
|
|
56
|
+
# class Create
|
|
57
|
+
# include Web::Action
|
|
58
|
+
#
|
|
59
|
+
# def call(params)
|
|
60
|
+
# # ...
|
|
61
|
+
# end
|
|
62
|
+
#
|
|
63
|
+
# private
|
|
64
|
+
#
|
|
65
|
+
# def verify_csrf_token?
|
|
66
|
+
# false
|
|
67
|
+
# end
|
|
68
|
+
# end
|
|
69
|
+
# end
|
|
70
|
+
module CSRFProtection
|
|
71
|
+
# Session and params key for CSRF token.
|
|
72
|
+
#
|
|
73
|
+
# This key is shared with <tt>hanami-controller</tt> and <tt>hanami-helpers</tt>
|
|
74
|
+
#
|
|
75
|
+
# @since 0.4.0
|
|
76
|
+
# @api private
|
|
77
|
+
CSRF_TOKEN = :_csrf_token
|
|
78
|
+
|
|
79
|
+
# Idempotent HTTP methods
|
|
80
|
+
#
|
|
81
|
+
# By default, the check isn't performed if the request method is included
|
|
82
|
+
# in this list.
|
|
83
|
+
#
|
|
84
|
+
# @since 0.4.0
|
|
85
|
+
# @api private
|
|
86
|
+
IDEMPOTENT_HTTP_METHODS = Hash[
|
|
87
|
+
'GET' => true,
|
|
88
|
+
'HEAD' => true,
|
|
89
|
+
'TRACE' => true,
|
|
90
|
+
'OPTIONS' => true
|
|
91
|
+
].freeze
|
|
92
|
+
|
|
93
|
+
# @since 0.4.0
|
|
94
|
+
# @api private
|
|
95
|
+
def self.included(action)
|
|
96
|
+
action.class_eval do
|
|
97
|
+
before :set_csrf_token, :verify_csrf_token
|
|
98
|
+
end unless Hanami.env?(:test)
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
private
|
|
102
|
+
# Set CSRF Token in session
|
|
103
|
+
#
|
|
104
|
+
# @since 0.4.0
|
|
105
|
+
# @api private
|
|
106
|
+
def set_csrf_token
|
|
107
|
+
session[CSRF_TOKEN] ||= generate_csrf_token
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
# Verify if CSRF token from params, matches the one stored in session.
|
|
111
|
+
# If not, it raises an error.
|
|
112
|
+
#
|
|
113
|
+
# Don't override this method.
|
|
114
|
+
#
|
|
115
|
+
# To bypass the security check, please override <tt>#verify_csrf_token?</tt>.
|
|
116
|
+
# For custom handling of an attack, please override <tt>#handle_invalid_csrf_token</tt>.
|
|
117
|
+
#
|
|
118
|
+
# @since 0.4.0
|
|
119
|
+
# @api private
|
|
120
|
+
def verify_csrf_token
|
|
121
|
+
handle_invalid_csrf_token if invalid_csrf_token?
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
# Verify if CSRF token from params, matches the one stored in session.
|
|
125
|
+
#
|
|
126
|
+
# Don't override this method.
|
|
127
|
+
#
|
|
128
|
+
# @since 0.4.0
|
|
129
|
+
# @api private
|
|
130
|
+
def invalid_csrf_token?
|
|
131
|
+
verify_csrf_token? &&
|
|
132
|
+
! ::Rack::Utils.secure_compare(session[CSRF_TOKEN], params[CSRF_TOKEN])
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
# Generates a random CSRF Token
|
|
136
|
+
#
|
|
137
|
+
# @since 0.4.0
|
|
138
|
+
# @api private
|
|
139
|
+
def generate_csrf_token
|
|
140
|
+
SecureRandom.hex(32)
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
# Decide if perform the check or not.
|
|
144
|
+
#
|
|
145
|
+
# Override and return <tt>false</tt> if you want to bypass security check.
|
|
146
|
+
#
|
|
147
|
+
# @since 0.4.0
|
|
148
|
+
def verify_csrf_token?
|
|
149
|
+
!IDEMPOTENT_HTTP_METHODS[request_method]
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
# Handle CSRF attack.
|
|
153
|
+
#
|
|
154
|
+
# The default policy resets the session and raises an exception.
|
|
155
|
+
#
|
|
156
|
+
# Override this method, for custom handling.
|
|
157
|
+
#
|
|
158
|
+
# @raise [Hanami::Action::InvalidCSRFTokenError]
|
|
159
|
+
#
|
|
160
|
+
# @since 0.4.0
|
|
161
|
+
def handle_invalid_csrf_token
|
|
162
|
+
session.clear
|
|
163
|
+
raise InvalidCSRFTokenError.new
|
|
164
|
+
end
|
|
165
|
+
end
|
|
166
|
+
end
|
|
167
|
+
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
require 'hanami/utils/string'
|
|
2
|
+
|
|
3
|
+
module Hanami
|
|
4
|
+
module Action
|
|
5
|
+
# Routing helper for full stack Hanami web applications.
|
|
6
|
+
#
|
|
7
|
+
# For a given application called <tt>Web::Application</tt>, at runtime
|
|
8
|
+
# Hanami creates a routes factory called <tt>Web::Routes</tt>.
|
|
9
|
+
#
|
|
10
|
+
# Included by default in every controller.
|
|
11
|
+
#
|
|
12
|
+
# @since 0.3.2
|
|
13
|
+
#
|
|
14
|
+
# @example Usage in controller
|
|
15
|
+
# require 'hanami'
|
|
16
|
+
#
|
|
17
|
+
# module Web::Controllers::Protected
|
|
18
|
+
# class Index
|
|
19
|
+
# include Web::Action
|
|
20
|
+
#
|
|
21
|
+
# def call(params)
|
|
22
|
+
# redirect_to routes.root_path
|
|
23
|
+
# end
|
|
24
|
+
# end
|
|
25
|
+
# end
|
|
26
|
+
module RoutingHelpers
|
|
27
|
+
def self.included(base)
|
|
28
|
+
factory = "#{ Utils::String.new(base).namespace }::Routes"
|
|
29
|
+
|
|
30
|
+
base.class_eval <<-END_EVAL, __FILE__, __LINE__
|
|
31
|
+
private
|
|
32
|
+
|
|
33
|
+
def routes
|
|
34
|
+
#{ factory }
|
|
35
|
+
end
|
|
36
|
+
END_EVAL
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
require 'hanami/utils/class_attribute'
|
|
2
|
+
require 'hanami/frameworks'
|
|
3
|
+
require 'hanami/configuration'
|
|
4
|
+
require 'hanami/loader'
|
|
5
|
+
require 'hanami/logger'
|
|
6
|
+
require 'hanami/rendering_policy'
|
|
7
|
+
require 'hanami/middleware'
|
|
8
|
+
|
|
9
|
+
module Hanami
|
|
10
|
+
# A full stack Hanami application
|
|
11
|
+
#
|
|
12
|
+
# @since 0.1.0
|
|
13
|
+
#
|
|
14
|
+
# @example
|
|
15
|
+
# require 'hanami'
|
|
16
|
+
#
|
|
17
|
+
# module Bookshelf
|
|
18
|
+
# class Application < Hanami::Application
|
|
19
|
+
# end
|
|
20
|
+
# end
|
|
21
|
+
class Application
|
|
22
|
+
# Override Ruby's Class#inherited
|
|
23
|
+
#
|
|
24
|
+
# @since 0.2.0
|
|
25
|
+
# @api private
|
|
26
|
+
#
|
|
27
|
+
# @see http://www.ruby-doc.org/core/Class.html#method-i-inherited
|
|
28
|
+
def self.inherited(base)
|
|
29
|
+
super
|
|
30
|
+
|
|
31
|
+
base.class_eval do
|
|
32
|
+
include Hanami::Utils::ClassAttribute
|
|
33
|
+
|
|
34
|
+
class_attribute :configuration
|
|
35
|
+
self.configuration = Configuration.new
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
synchronize do
|
|
39
|
+
applications.add(base)
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# Registry of Hanami applications in the current Ruby process
|
|
44
|
+
#
|
|
45
|
+
# @return [Set] a set of all the registered applications
|
|
46
|
+
#
|
|
47
|
+
# @since 0.2.0
|
|
48
|
+
# @api private
|
|
49
|
+
def self.applications
|
|
50
|
+
synchronize do
|
|
51
|
+
@@applications ||= Set.new
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# Configure the application.
|
|
56
|
+
# It yields the given block in the context of the configuration
|
|
57
|
+
#
|
|
58
|
+
# @param environment [Symbol,nil] the configuration environment name
|
|
59
|
+
# @param blk [Proc] the configuration block
|
|
60
|
+
#
|
|
61
|
+
# @since 0.1.0
|
|
62
|
+
#
|
|
63
|
+
# @see Hanami::Configuration
|
|
64
|
+
#
|
|
65
|
+
# @example
|
|
66
|
+
# require 'hanami'
|
|
67
|
+
#
|
|
68
|
+
# module Bookshelf
|
|
69
|
+
# Application < Hanami::Application
|
|
70
|
+
# configure do
|
|
71
|
+
# # ...
|
|
72
|
+
# end
|
|
73
|
+
# end
|
|
74
|
+
# end
|
|
75
|
+
def self.configure(environment = nil, &blk)
|
|
76
|
+
configuration.configure(environment, &blk)
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
# Return the routes for this application
|
|
80
|
+
#
|
|
81
|
+
# @return [Hanami::Router] a route set
|
|
82
|
+
#
|
|
83
|
+
# @since 0.1.0
|
|
84
|
+
#
|
|
85
|
+
# @see Hanami::Configuration#routes
|
|
86
|
+
attr_reader :routes
|
|
87
|
+
|
|
88
|
+
# Set the routes for this application
|
|
89
|
+
#
|
|
90
|
+
# @param [Hanami::Router]
|
|
91
|
+
#
|
|
92
|
+
# @since 0.1.0
|
|
93
|
+
# @api private
|
|
94
|
+
attr_writer :routes
|
|
95
|
+
|
|
96
|
+
# Rendering policy
|
|
97
|
+
#
|
|
98
|
+
# @param [Hanami::RenderingPolicy]
|
|
99
|
+
#
|
|
100
|
+
# @since 0.2.0
|
|
101
|
+
# @api private
|
|
102
|
+
attr_accessor :renderer
|
|
103
|
+
|
|
104
|
+
# Initialize and load a new instance of the application
|
|
105
|
+
#
|
|
106
|
+
# @return [Hanami::Application] a new instance of the application
|
|
107
|
+
#
|
|
108
|
+
# @since 0.1.0
|
|
109
|
+
def initialize(options = {})
|
|
110
|
+
self.class.configuration.path_prefix options[:path_prefix]
|
|
111
|
+
self.class.load!(self)
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
# Eager load the application configuration, by activating the framework
|
|
115
|
+
# duplication mechanisms.
|
|
116
|
+
#
|
|
117
|
+
# @param application [Hanami::Application, Class<Hanami::Application>]
|
|
118
|
+
# @return void
|
|
119
|
+
#
|
|
120
|
+
# @since 0.1.1
|
|
121
|
+
#
|
|
122
|
+
# @example
|
|
123
|
+
# require 'hanami'
|
|
124
|
+
#
|
|
125
|
+
# module OneFile
|
|
126
|
+
# class Application < Hanami::Application
|
|
127
|
+
# configure do
|
|
128
|
+
# routes do
|
|
129
|
+
# get '/', to: 'dashboard#index'
|
|
130
|
+
# end
|
|
131
|
+
# end
|
|
132
|
+
#
|
|
133
|
+
# load!
|
|
134
|
+
# end
|
|
135
|
+
#
|
|
136
|
+
# module Controllers::Dashboard
|
|
137
|
+
# class Index
|
|
138
|
+
# include OneFile::Action
|
|
139
|
+
#
|
|
140
|
+
# def call(params)
|
|
141
|
+
# self.body = 'Hello!'
|
|
142
|
+
# end
|
|
143
|
+
# end
|
|
144
|
+
# end
|
|
145
|
+
# end
|
|
146
|
+
def self.load!(application = self)
|
|
147
|
+
Hanami::Loader.new(application).load!
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
# Preload all the registered applications, by yielding their configurations
|
|
151
|
+
# and preparing the frameworks.
|
|
152
|
+
#
|
|
153
|
+
# This is useful for testing suites, where we want to make Hanami frameworks
|
|
154
|
+
# ready, but not preload applications code.
|
|
155
|
+
#
|
|
156
|
+
# This allows to test components such as views or actions in isolation and
|
|
157
|
+
# to have faster boot times.
|
|
158
|
+
#
|
|
159
|
+
# @return [void]
|
|
160
|
+
#
|
|
161
|
+
# @since 0.2.0
|
|
162
|
+
def self.preload!
|
|
163
|
+
synchronize do
|
|
164
|
+
applications.each(&:load!)
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
nil
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
# Full preload for all the registered applications.
|
|
171
|
+
#
|
|
172
|
+
# This is useful in console where we want all the application code available.
|
|
173
|
+
#
|
|
174
|
+
# @return [void]
|
|
175
|
+
#
|
|
176
|
+
# @since 0.2.1
|
|
177
|
+
# @api private
|
|
178
|
+
def self.preload_applications!
|
|
179
|
+
synchronize do
|
|
180
|
+
applications.each { |app| app.new }
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
nil
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
# Return the configuration for this application
|
|
187
|
+
#
|
|
188
|
+
# @since 0.1.0
|
|
189
|
+
# @api private
|
|
190
|
+
#
|
|
191
|
+
# @see Hanami::Application.configuration
|
|
192
|
+
def configuration
|
|
193
|
+
self.class.configuration
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
# Return the application name
|
|
197
|
+
#
|
|
198
|
+
# @since 0.2.0
|
|
199
|
+
# @api private
|
|
200
|
+
def name
|
|
201
|
+
self.class.name
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
# Process a request.
|
|
205
|
+
# This method makes Hanami applications compatible with the Rack protocol.
|
|
206
|
+
#
|
|
207
|
+
# @param env [Hash] a Rack env
|
|
208
|
+
#
|
|
209
|
+
# @return [Array] a serialized Rack response
|
|
210
|
+
#
|
|
211
|
+
# @since 0.1.0
|
|
212
|
+
#
|
|
213
|
+
# @see http://rack.github.io
|
|
214
|
+
# @see Hanami::RenderingPolicy#render
|
|
215
|
+
# @see Hanami::Application#middleware
|
|
216
|
+
def call(env)
|
|
217
|
+
renderer.render(env, middleware.call(env))
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
# Rack middleware stack
|
|
221
|
+
#
|
|
222
|
+
# @return [Hanami::Middleware] the middleware stack
|
|
223
|
+
#
|
|
224
|
+
# @since 0.1.0
|
|
225
|
+
# @api private
|
|
226
|
+
#
|
|
227
|
+
# @see Hanami::Middleware
|
|
228
|
+
def middleware
|
|
229
|
+
@middleware ||= configuration.middleware
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
private
|
|
233
|
+
|
|
234
|
+
# Yields the given block in a critical section
|
|
235
|
+
#
|
|
236
|
+
# @since 0.2.0
|
|
237
|
+
# @api private
|
|
238
|
+
def self.synchronize
|
|
239
|
+
Mutex.new.synchronize do
|
|
240
|
+
yield
|
|
241
|
+
end
|
|
242
|
+
end
|
|
243
|
+
end
|
|
244
|
+
end
|