tynn 1.0.0.rc2 → 1.0.0.rc3

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