tynn 1.0.0.rc2 → 1.0.0.rc3

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.
@@ -1,45 +1,44 @@
1
1
  class Tynn
2
- # Adds security related HTTP headers.
2
+ # Public: Adds security related HTTP headers.
3
3
  #
4
- # ```
5
- # require "tynn"
6
- # require "tynn/secure_headers"
4
+ # Examples
7
5
  #
8
- # Tynn.helpers(Tynn::SecureHeaders)
9
- # ```
6
+ # require "tynn"
7
+ # require "tynn/secure_headers"
8
+ #
9
+ # Tynn.helpers(Tynn::SecureHeaders)
10
10
  #
11
11
  # This helper applies the following headers:
12
12
  #
13
- # * **X-Content-Type-Options:** Prevents IE and Chrome from
14
- # [content type sniffing][mime-sniffing].
13
+ # *X-Content-Type-Options:* <tt>"nosniff"</tt>
14
+ #
15
+ # Prevents IE and Chrome from
16
+ # {content type sniffing}[https://msdn.microsoft.com/library/gg622941(v=vs.85).aspx]
17
+ #
18
+ # *X-Frame-Options:* <tt>"SAMEORIGIN"</tt>
19
+ #
20
+ # Provides {Clickjacking}[https://www.owasp.org/index.php/Clickjacking]
21
+ # protection.
15
22
  #
16
- # * **X-Frame-Options (XFO):** Provides [Clickjacking][clickjacking]
17
- # protection. Check the [X-Frame-Options draft][x-frame-options] for
18
- # more information.
23
+ # *X-Permitted-Cross-Domain-Policies:* <tt>"none"</tt>
19
24
  #
20
- # * **X-Permitted-Cross-Domain-Policies:** Restricts Adobe Flash Player's
21
- # access to data. Check this [article][pcdp] for more information.
25
+ # Restricts Adobe Flash Player's access to data.
22
26
  #
23
- # * **X-XSS-Protection:** Enables the [XSS][xss] protection filter built
24
- # into IE, Chrome and Safari. This filter is usually enabled by default,
25
- # the use of this header is to re-enable it if it was disabled by the user.
27
+ # *X-XSS-Protection:* <tt>"1; mode=block"</tt>
26
28
  #
27
- # [clickjacking]: https://www.owasp.org/index.php/Clickjacking
28
- # [mime-sniffing]: https://msdn.microsoft.com/library/gg622941(v=vs.85).aspx
29
- # [pcdp]: https://www.adobe.com/devnet/adobe-media-server/articles/cross-domain-xml-for-streaming.html
30
- # [x-frame-options]: https://tools.ietf.org/html/draft-ietf-websec-x-frame-options-02
31
- # [xss]: https://www.owasp.org/index.php/Cross-site_Scripting_(XSS)
29
+ # Enables the XSS protection filter built into IE, Chrome and Safari.
30
+ # This filter is usually enabled by default, the use of this header
31
+ # is to re-enable it if it was disabled by the user.
32
32
  #
33
33
  module SecureHeaders
34
- HEADERS = {
35
- "X-Content-Type-Options" => "nosniff",
36
- "X-Frame-Options" => "SAMEORIGIN",
37
- "X-Permitted-Cross-Domain-Policies" => "none",
38
- "X-XSS-Protection" => "1; mode=block"
39
- } # :nodoc:
40
-
41
- def default_headers # :nodoc:
42
- return super.merge(HEADERS)
34
+ # Internal: Sets the default HTTP secure headers.
35
+ def self.setup(app)
36
+ app.settings[:default_headers].update(
37
+ "X-Content-Type-Options" => "nosniff",
38
+ "X-Frame-Options" => "SAMEORIGIN",
39
+ "X-Permitted-Cross-Domain-Policies" => "none",
40
+ "X-XSS-Protection" => "1; mode=block"
41
+ )
43
42
  end
44
43
  end
45
44
  end
data/lib/tynn/session.rb CHANGED
@@ -1,87 +1,85 @@
1
1
  class Tynn
2
- # Adds simple cookie based session management. If a secret token is
3
- # given, it signs the cookie data to ensure that it cannot be altered
4
- # by unauthorized means.
2
+ # Public: Adds simple cookie based session management. You can pass a secret
3
+ # token to sign the cookie data, thus unauthorized means can't alter it.
5
4
  #
6
- # ```
7
- # require "tynn"
8
- # require "tynn/session"
5
+ # Examples
9
6
  #
10
- # Tynn.helpers(Tynn::Session, secret: "__change_me__")
7
+ # require "tynn"
8
+ # require "tynn/session"
11
9
  #
12
- # Tynn.define do
13
- # root do
14
- # res.write(sprintf("hei %s", session[:username]))
15
- # end
10
+ # Tynn.helpers(Tynn::Session, secret: "__change_me__")
11
+ #
12
+ # Tynn.define do
13
+ # root do
14
+ # res.write(sprintf("hei %s", session[:username]))
15
+ # end
16
16
  #
17
- # on(:username) do |username|
18
- # session[:username] = username
17
+ # on(:username) do |username|
18
+ # session[:username] = username
19
+ # end
19
20
  # end
20
- # end
21
- # ```
22
21
  #
23
22
  # The following command generates a cryptographically secure secret ready
24
23
  # to use:
25
24
  #
26
- # ```
27
- # $ ruby -r securerandom -e "puts SecureRandom.hex(64)"
28
- # ```
25
+ # $ ruby -r securerandom -e "puts SecureRandom.hex(64)"
29
26
  #
30
27
  # It's important to keep the token secret. Knowing the token allows an
31
28
  # attacker to tamper the data. So, it's recommended to load the token
32
29
  # from the environment.
33
30
  #
34
- # ```
35
- # Tynn.helpers(Tynn::Session, secret: ENV["SESSION_SECRET"])
36
- # ```
37
- #
38
- # Under the hood, Tynn::Session uses the [Rack::Session::Cookie][rack-session]
39
- # middleware. Thus, supports all the options available for this middleware.
40
- #
41
- # * `:key` - the name of the cookie. Defaults to `"rack.session"`.
42
- # * `:expire_after` - sets the lifespan of the cookie. If `nil`,
43
- # the cookie will be deleted after the user close the browser.
44
- # Defaults to `nil`.
45
- # * `:httponly` - if `true`, sets the [HttpOnly][cookie-httponly] attribute.
46
- # This mitigates the risk of client side scripting accessing the cookie.
47
- # Defaults to `true`.
48
- # * `:secure` - if `true`, sets the [Secure][cookie-secure] attribute.
49
- # This tells the browser to only transmit the cookie over HTTPS. Defaults
50
- # to `false`.
51
- #
52
- # ```
53
- # Tynn.helpers(
54
- # Tynn::Session,
55
- # key: "app",
56
- # secret: ENV["SESSION_SECRET"],
57
- # expire_after: 36_000, # seconds
58
- # httponly: true,
59
- # secure: true
60
- # )
61
- # ```
62
- #
63
- # [cookie-httponly]: https://www.owasp.org/index.php/Session_Management_Cheat_Sheet#HttpOnly_Attribute
64
- # [cookie-secure]: https://www.owasp.org/index.php/Session_Management_Cheat_Sheet#Secure_Attribute
65
- # [rack-session]: http://www.rubydoc.info/gems/rack/Rack/Session/Cookie
31
+ # Examples
32
+ #
33
+ # Tynn.helpers(Tynn::Session, secret: ENV["SESSION_SECRET"])
34
+ #
35
+ # Under the hood, Tynn::Session uses the +Rack::Session::Cookie+ middleware.
36
+ # Thus, supports all the options available for this middleware:
37
+ #
38
+ # key - The name of the cookie. Defaults to <tt>"rack.session"</tt>.
39
+ #
40
+ # httponly - If +true+, sets the +HttpOnly+ flag. This mitigates the
41
+ # risk of client side scripting accessing the cookie. Defaults
42
+ # to +true+.
43
+ #
44
+ # secure - If +true+, sets the +Secure+ flag. This tells the browser
45
+ # to only transmit the cookie over HTTPS. Defaults to `false`.
46
+ #
47
+ # expire_after - The lifespan of the cookie. If +nil+, the session cookie
48
+ # is temporary and is no retained after the browser is
49
+ # closed. Defaults to +nil+.
50
+ #
51
+ # Examples
52
+ #
53
+ # Tynn.helpers(
54
+ # Tynn::Session,
55
+ # key: "app",
56
+ # secret: ENV["SESSION_SECRET"],
57
+ # expire_after: 36_000, # seconds
58
+ # httponly: true,
59
+ # secure: true
60
+ # )
66
61
  #
67
62
  module Session
68
- RACK_SESSION = "rack.session".freeze # :nodoc:
63
+ # Internal: Configures Rack::Session::Cookie middleware.
64
+ def self.setup(app, options = {})
65
+ defaults = { secure: app.settings[:ssl] }
69
66
 
70
- def self.setup(app, options = {}) # :nodoc:
71
- app.use(Rack::Session::Cookie, options)
67
+ app.use(Rack::Session::Cookie, defaults.merge(options))
72
68
  end
73
69
 
74
- # Returns the session hash.
75
- #
76
- # ```
77
- # session # => {}
78
- #
79
- # session[:foo] = "foo"
80
- # session[:foo] # => "foo"
81
- # ```
82
- #
83
- def session
84
- return env[RACK_SESSION]
70
+ module InstanceMethods
71
+ # Public: Returns the session hash.
72
+ #
73
+ # Examples
74
+ #
75
+ # session # => {}
76
+ #
77
+ # session[:foo] = "foo"
78
+ # session[:foo] # => "foo"
79
+ #
80
+ def session
81
+ return env["rack.session".freeze]
82
+ end
85
83
  end
86
84
  end
87
85
  end
@@ -0,0 +1,28 @@
1
+ class Tynn
2
+ module Settings # :nodoc: all
3
+ def self.deepclone(hash)
4
+ default_proc, hash.default_proc = hash.default_proc, nil
5
+
6
+ return Marshal.load(Marshal.dump(hash))
7
+ ensure
8
+ hash.default_proc = default_proc
9
+ end
10
+
11
+ module InstanceMethods # :nodoc: all
12
+ def settings
13
+ return self.class.settings
14
+ end
15
+ end
16
+
17
+ module ClassMethods # :nodoc: all
18
+ def inherited(subclass)
19
+ subclass.settings.replace(Tynn::Settings.deepclone(settings))
20
+ subclass.settings.default_proc = proc { |h, k| h[k] = settings[k] }
21
+ end
22
+
23
+ def settings
24
+ return @settings ||= {}
25
+ end
26
+ end
27
+ end
28
+ end
data/lib/tynn/static.rb CHANGED
@@ -1,33 +1,36 @@
1
1
  class Tynn
2
- # Adds support for static files (javascript files, images, stylesheets, etc).
2
+ # Public: Adds support for static files (javascript files, images,
3
+ # stylesheets, etc).
3
4
  #
4
- # ```
5
- # require "tynn"
6
- # require "tynn/static"
5
+ # Examples
7
6
  #
8
- # Tynn.helpers(Tynn::Static, ["/js", "/css"])
9
- # ```
7
+ # require "tynn"
8
+ # require "tynn/static"
10
9
  #
11
- # By default, serve all requests beginning with the given paths from the folder
12
- # `public` in the current directory (e.g. `public/js/*`, `public/css/*`). You
13
- # can change the default by passing the `:root` option.
10
+ # Tynn.helpers(Tynn::Static, ["/js", "/css"])
14
11
  #
15
- # ```
16
- # Tynn.helpers(Tynn::Static, ["/js", "/css"], root: "assets")
17
- # ```
12
+ # By default, serves all requests beginning with the given paths from
13
+ # the folder +public+ in the current directory (e.g. +public/js/*+,
14
+ # +public/css/*+). You can change the default by passing the +:root+
15
+ # option.
18
16
  #
19
- # Under the hood, it uses the [Rack::Static][rack-static] middleware.
20
- # Thus, supports all the options available for this middleware.
17
+ # Examples
21
18
  #
22
- # ```
23
- # Tynn.helpers(Tynn::Static, ["/js", "/css"], index: "index.html")
24
- # ```
19
+ # Tynn.helpers(Tynn::Static, ["/js", "/css"], root: "assets")
25
20
  #
26
- # [rack-static]: http://www.rubydoc.info/gems/rack/Rack/Static
21
+ # Under the hood, it uses the +Rack::Static+ middleware. Thus,
22
+ # supports all the options available by the middleware. Check
23
+ # {Rack::Static}[http://www.rubydoc.info/gems/rack/Rack/Static]
24
+ # for more information.
25
+ #
26
+ # Examples
27
+ #
28
+ # Tynn.helpers(Tynn::Static, ["/js", "/css"], index: "index.html")
27
29
  #
28
30
  module Static
29
- def self.setup(app, urls, options = {}) # :nodoc:
30
- options = options.dup
31
+ # Internal: Configures Rack::Static middleware.
32
+ def self.setup(app, urls, opts = {})
33
+ options = opts.dup
31
34
 
32
35
  options[:urls] ||= urls
33
36
  options[:root] ||= File.expand_path("public", Dir.pwd)
data/lib/tynn/test.rb CHANGED
@@ -1,50 +1,49 @@
1
1
  require "rack/test"
2
2
 
3
3
  class Tynn
4
- # A simple helper class that uses [rack-test][rack-test] to simulate requests
5
- # to your application.
4
+ # Public: A simple helper class to simulate requests to your application.
6
5
  #
7
- # ```
8
- # require "tynn"
9
- # require "tynn/test"
6
+ # Examples
10
7
  #
11
- # Tynn.define do
12
- # root do
13
- # res.write("hei")
14
- # end
15
- # end
8
+ # require "tynn"
9
+ # require "tynn/test"
16
10
  #
17
- # app = Tynn::Test.new
18
- # app.get("/")
11
+ # Tynn.define do
12
+ # root do
13
+ # res.write("hei")
14
+ # end
15
+ # end
19
16
  #
20
- # 200 == app.res.status # => true
21
- # "hei" == app.res.body # => true
22
- # ```
17
+ # app = Tynn::Test.new
18
+ # app.get("/")
23
19
  #
24
- # **NOTE:** Tynn doesn't ship with [rack-test][rack-test]. In order to
25
- # use this plugin, you need to install it first.
20
+ # 200 == app.res.status # => true
21
+ # "hei" == app.res.body # => true
26
22
  #
27
- # [rack-test]: http://rubygems.org/gems/rack-test
23
+ # In order to use this plugin, you need to install
24
+ # {rack-test}[https://rubygems.org/gems/rack-test].
28
25
  #
29
26
  class Test
30
27
  include Rack::Test::Methods
31
28
 
32
- # Instantiates a new Tynn::Test object with the given `application` to test.
29
+ # Internal: Returns the application class that handles the
30
+ # mock requests. Required by Rack::Test::Methods.
31
+ attr_reader :app
32
+
33
+ # Public: Initializes a new Tynn::Test object.
33
34
  #
34
- # ```
35
- # class API < Tynn
36
- # end
35
+ # app - The application class to test (default: Tynn).
37
36
  #
38
- # app = Tynn::Test.new(API)
39
- # app.get("/json")
40
- # ```
37
+ # Examples
41
38
  #
42
- def initialize(application = Tynn)
43
- @app = application
44
- end
45
-
46
- def app # :nodoc:
47
- return @app
39
+ # class API < Tynn
40
+ # end
41
+ #
42
+ # app = Tynn::Test.new(API)
43
+ # app.get("/json")
44
+ #
45
+ def initialize(app = Tynn)
46
+ @app = app
48
47
  end
49
48
 
50
49
  alias_method :res, :last_response
data/lib/tynn/version.rb CHANGED
@@ -3,6 +3,6 @@ class Tynn # :nodoc: all
3
3
  MAJOR_VERSION = 1,
4
4
  MINOR_VERSION = 0,
5
5
  PATCH_VERSION = 0,
6
- PRE_VERSION = "rc2"
6
+ PRE_VERSION = "rc3"
7
7
  ].compact.join(".")
8
8
  end
@@ -0,0 +1,14 @@
1
+ test "default headers" do
2
+ Tynn.set(:default_headers, "Content-Type" => "text/plain")
3
+
4
+ Tynn.define do
5
+ root do
6
+ res.write("hei")
7
+ end
8
+ end
9
+
10
+ app = Tynn::Test.new(Tynn)
11
+ app.get("/")
12
+
13
+ assert_equal "text/plain", app.res.headers["Content-Type"]
14
+ end
@@ -1,31 +1,27 @@
1
1
  require_relative "../lib/tynn/environment"
2
2
 
3
- test "default" do
4
- Tynn.helpers(Tynn::Environment)
5
-
6
- assert_equal(:development, Tynn.environment)
7
- end
8
-
9
- test "helpers" do
10
- Tynn.helpers(Tynn::Environment)
11
-
12
- assert Tynn.development?
13
- assert !Tynn.test?
14
- assert !Tynn.production?
15
- end
16
-
17
3
  test "use RACK_ENV by default" do
18
- ENV["RACK_ENV"] = "production"
4
+ begin
5
+ old, ENV["RACK_ENV"] = ENV["RACK_ENV"], "production"
6
+
7
+ Tynn.helpers(Tynn::Environment)
19
8
 
20
- Tynn.helpers(Tynn::Environment)
9
+ assert_equal(:production, Tynn.environment)
21
10
 
22
- assert_equal(:production, Tynn.environment)
11
+ assert !Tynn.development?
12
+ assert !Tynn.test?
13
+ assert Tynn.production?
23
14
 
24
- ENV.delete("RACK_ENV")
15
+ ensure
16
+ ENV["RACK_ENV"] = old
17
+ end
25
18
  end
26
19
 
27
20
  test "use custom value" do
28
21
  Tynn.helpers(Tynn::Environment, env: "development")
29
22
 
30
23
  assert_equal(:development, Tynn.environment)
24
+ assert Tynn.development?
25
+ assert !Tynn.test?
26
+ assert !Tynn.production?
31
27
  end