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.
@@ -0,0 +1,32 @@
1
+ require_relative "../lib/tynn/force_ssl"
2
+
3
+ setup do
4
+ Tynn::Test.new
5
+ end
6
+
7
+ test "redirects to https" do |app|
8
+ Tynn.helpers(Tynn::ForceSSL)
9
+
10
+ Tynn.define do
11
+ end
12
+
13
+ app.get("/")
14
+
15
+ assert_equal 301, app.res.status
16
+ assert_equal "https://example.org/", app.res.location
17
+ end
18
+
19
+ test "https request" do |app|
20
+ Tynn.helpers(Tynn::ForceSSL)
21
+
22
+ Tynn.define do
23
+ root do
24
+ res.write("secure")
25
+ end
26
+ end
27
+
28
+ app.get("/", {}, "HTTPS" => "on")
29
+
30
+ assert_equal 200, app.res.status
31
+ assert_equal "secure", app.res.body
32
+ end
@@ -0,0 +1,78 @@
1
+ require_relative "../lib/tynn/hmote"
2
+
3
+ setup do
4
+ Tynn.helpers(Tynn::HMote, views: File.expand_path("./test/views"))
5
+
6
+ Tynn::Test.new
7
+ end
8
+
9
+ test "partial" do |app|
10
+ Tynn.define do
11
+ on "partial" do
12
+ res.write(partial("partial", name: "mote"))
13
+ end
14
+ end
15
+
16
+ app.get("/partial")
17
+
18
+ assert_equal "mote", app.res.body.strip
19
+ end
20
+
21
+ test "view" do |app|
22
+ Tynn.define do
23
+ on "view" do
24
+ res.write(view("view", title: "tynn", name: "mote"))
25
+ end
26
+ end
27
+
28
+ app.get("/view")
29
+
30
+ assert_equal "tynn / mote", app.res.body.strip
31
+ end
32
+
33
+ test "render" do |app|
34
+ Tynn.define do
35
+ on "render" do
36
+ render("view", title: "tynn", name: "mote")
37
+ end
38
+ end
39
+
40
+ app.get("/render")
41
+
42
+ assert_equal 200, app.res.status
43
+ assert_equal "text/html", app.res.headers["Content-Type"]
44
+ assert_equal "tynn / mote", app.res.body.strip
45
+ end
46
+
47
+ test "404" do |app|
48
+ Tynn.define do
49
+ on "404" do
50
+ res.status = 404
51
+
52
+ render("view", title: "tynn", name: "mote")
53
+ end
54
+ end
55
+
56
+ app.get("/404")
57
+
58
+ assert_equal 404, app.res.status
59
+ assert_equal "text/html", app.res.headers["Content-Type"]
60
+ assert_equal "tynn / mote", app.res.body.strip
61
+ end
62
+
63
+ test "custom layout" do
64
+ class App < Tynn
65
+ set(:layout, "custom_layout")
66
+ end
67
+
68
+ App.define do
69
+ root do
70
+ render("view", title: "tynn", name: "mote")
71
+ end
72
+ end
73
+
74
+ app = Tynn::Test.new(App)
75
+ app.get("/")
76
+
77
+ assert_equal "custom / tynn / mote", app.res.body.strip
78
+ end
data/test/hsts_test.rb ADDED
@@ -0,0 +1,29 @@
1
+ require_relative "../lib/tynn/hsts"
2
+
3
+ test "hsts header" do |app|
4
+ Tynn.helpers(Tynn::HSTS)
5
+
6
+ Tynn.define do
7
+ end
8
+
9
+ app = Tynn::Test.new
10
+ app.get("/", {})
11
+
12
+ header = app.res.headers["Strict-Transport-Security"]
13
+
14
+ assert_equal "max-age=15552000; includeSubdomains", header
15
+ end
16
+
17
+ test "hsts header options" do |app|
18
+ Tynn.helpers(Tynn::HSTS, expires: 1, subdomains: false, preload: true)
19
+
20
+ Tynn.define do
21
+ end
22
+
23
+ app = Tynn::Test.new
24
+ app.get("/", {})
25
+
26
+ header = app.res.headers["Strict-Transport-Security"]
27
+
28
+ assert_equal "max-age=1; preload", header
29
+ end
@@ -1,18 +1,6 @@
1
1
  require_relative "../lib/tynn/protection"
2
2
  require_relative "../lib/tynn/session"
3
3
 
4
- test "includes secure headers" do
5
- Tynn.helpers(Tynn::Protection)
6
-
7
- assert Tynn.include?(Tynn::SecureHeaders)
8
- end
9
-
10
- test "includes ssl helper if ssl is true" do
11
- Tynn.helpers(Tynn::Protection, ssl: true)
12
-
13
- assert Tynn.include?(Tynn::SSL)
14
- end
15
-
16
4
  test "supports hsts options" do
17
5
  hsts = { expires: 100, subdomains: false, preload: true }
18
6
 
@@ -46,21 +34,3 @@ test "adds secure flag to session cookie" do
46
34
 
47
35
  assert(/;\s*secure\s*(;|$)/i === session)
48
36
  end
49
-
50
- test "if session uses secure flag" do
51
- Tynn.helpers(Tynn::Protection, ssl: true)
52
- Tynn.helpers(Tynn::Session, secret: "_this_must_be_random_", secure: true)
53
-
54
- Tynn.define do
55
- root do
56
- session[:foo] = "foo"
57
- end
58
- end
59
-
60
- app = Tynn::Test.new
61
- app.get("/", {}, "HTTPS" => "on")
62
-
63
- session, _ = app.res.headers["Set-Cookie"].split("\n")
64
-
65
- assert(/;\s*secure\s*(;|$)/i === session)
66
- end
data/test/render_test.rb CHANGED
@@ -1,4 +1,4 @@
1
- require "erb"
1
+ require "erubis"
2
2
  require_relative "../lib/tynn/render"
3
3
 
4
4
  setup do
@@ -77,3 +77,16 @@ test "custom layout" do
77
77
 
78
78
  assert_equal "custom / tynn / erb", app.res.body.strip
79
79
  end
80
+
81
+ test "escapes by default" do
82
+ Tynn.define do
83
+ root do
84
+ res.write(partial("partial", name: "<a></a>"))
85
+ end
86
+ end
87
+
88
+ app = Tynn::Test.new
89
+ app.get("/")
90
+
91
+ assert_equal "&lt;a&gt;&lt;/a&gt;", app.res.body.strip
92
+ end
@@ -12,9 +12,16 @@ test "secure headers" do
12
12
  app = Tynn::Test.new
13
13
  app.get("/")
14
14
 
15
+ secure_headers = {
16
+ "X-Content-Type-Options" => "nosniff",
17
+ "X-Frame-Options" => "SAMEORIGIN",
18
+ "X-Permitted-Cross-Domain-Policies" => "none",
19
+ "X-XSS-Protection" => "1; mode=block"
20
+ }
21
+
15
22
  headers = app.res.headers
16
23
 
17
- Tynn::SecureHeaders::HEADERS.each do |header, value|
24
+ secure_headers.each do |header, value|
18
25
  assert_equal(value, headers[header])
19
26
  end
20
27
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tynn
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0.rc2
4
+ version: 1.0.0.rc3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Francesco Rodríguez
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-10-21 00:00:00.000000000 Z
11
+ date: 2015-10-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rack
@@ -24,20 +24,6 @@ dependencies:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: '1.6'
27
- - !ruby/object:Gem::Dependency
28
- name: seteable
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - "~>"
32
- - !ruby/object:Gem::Version
33
- version: '1.1'
34
- type: :runtime
35
- prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - "~>"
39
- - !ruby/object:Gem::Version
40
- version: '1.1'
41
27
  - !ruby/object:Gem::Dependency
42
28
  name: syro
43
29
  requirement: !ruby/object:Gem::Requirement
@@ -134,7 +120,9 @@ files:
134
120
  - lib/tynn.rb
135
121
  - lib/tynn/all_methods.rb
136
122
  - lib/tynn/environment.rb
137
- - lib/tynn/erubis.rb
123
+ - lib/tynn/force_ssl.rb
124
+ - lib/tynn/hmote.rb
125
+ - lib/tynn/hsts.rb
138
126
  - lib/tynn/json.rb
139
127
  - lib/tynn/matchers.rb
140
128
  - lib/tynn/not_found.rb
@@ -144,15 +132,18 @@ files:
144
132
  - lib/tynn/response.rb
145
133
  - lib/tynn/secure_headers.rb
146
134
  - lib/tynn/session.rb
147
- - lib/tynn/ssl.rb
135
+ - lib/tynn/settings.rb
148
136
  - lib/tynn/static.rb
149
137
  - lib/tynn/test.rb
150
138
  - lib/tynn/version.rb
151
139
  - test/all_methods_test.rb
152
140
  - test/core_test.rb
141
+ - test/default_headers_test.rb
153
142
  - test/environment_test.rb
154
- - test/erubis_test.rb
143
+ - test/force_ssl_test.rb
155
144
  - test/helper.rb
145
+ - test/hmote_test.rb
146
+ - test/hsts_test.rb
156
147
  - test/json_test.rb
157
148
  - test/matchers_test.rb
158
149
  - test/middleware_test.rb
@@ -161,7 +152,6 @@ files:
161
152
  - test/render_test.rb
162
153
  - test/secure_headers_test.rb
163
154
  - test/session_test.rb
164
- - test/ssl_test.rb
165
155
  - test/static_test.rb
166
156
  homepage: https://github.com/frodsan/tynn
167
157
  licenses:
@@ -190,9 +180,12 @@ summary: Thin library to create web applications
190
180
  test_files:
191
181
  - test/all_methods_test.rb
192
182
  - test/core_test.rb
183
+ - test/default_headers_test.rb
193
184
  - test/environment_test.rb
194
- - test/erubis_test.rb
185
+ - test/force_ssl_test.rb
195
186
  - test/helper.rb
187
+ - test/hmote_test.rb
188
+ - test/hsts_test.rb
196
189
  - test/json_test.rb
197
190
  - test/matchers_test.rb
198
191
  - test/middleware_test.rb
@@ -201,5 +194,5 @@ test_files:
201
194
  - test/render_test.rb
202
195
  - test/secure_headers_test.rb
203
196
  - test/session_test.rb
204
- - test/ssl_test.rb
205
197
  - test/static_test.rb
198
+ has_rdoc:
data/lib/tynn/erubis.rb DELETED
@@ -1,17 +0,0 @@
1
- require "erubis"
2
- require_relative "render"
3
-
4
- class Tynn
5
- module Erubis
6
- def self.setup(app, options = {}) # :nodoc:
7
- options = options.dup
8
-
9
- options[:options] ||= {}
10
- options[:options] = {
11
- escape_html: true
12
- }.merge!(options[:options])
13
-
14
- app.helpers(Tynn::Render, options)
15
- end
16
- end
17
- end
data/lib/tynn/ssl.rb DELETED
@@ -1,73 +0,0 @@
1
- class Tynn
2
- module SSL
3
- def self.setup(app, hsts: {}) # :nodoc:
4
- app.use(Tynn::SSL::Middleware, hsts: hsts)
5
- end
6
-
7
- class Middleware # :nodoc:
8
- def initialize(app, hsts: {})
9
- @app = app
10
- @hsts_header = build_hsts_header(hsts)
11
- end
12
-
13
- def call(env)
14
- request = Rack::Request.new(env)
15
-
16
- unless request.ssl?
17
- return [301, redirect_headers(request), []]
18
- end
19
-
20
- result = @app.call(env)
21
-
22
- set_hsts_header(result[1])
23
- set_cookies_as_secure(result[1])
24
-
25
- return result
26
- end
27
-
28
- private
29
-
30
- HSTS_HEADER = "Strict-Transport-Security".freeze
31
- HSTS_EXPIRE = 15_552_000 # 180 days
32
-
33
- def build_hsts_header(options)
34
- header = sprintf("max-age=%i", options.fetch(:expires, HSTS_EXPIRE))
35
- header << "; includeSubdomains" if options.fetch(:subdomains, true)
36
- header << "; preload" if options[:preload]
37
-
38
- return header
39
- end
40
-
41
- def redirect_headers(request)
42
- return {
43
- "Content-Type" => "text/html",
44
- "Location" => https_location(request)
45
- }
46
- end
47
-
48
- HTTPS_LOCATION = "https://%s%s".freeze
49
-
50
- def https_location(request)
51
- return sprintf(HTTPS_LOCATION, request.host, request.fullpath)
52
- end
53
-
54
- def set_hsts_header(headers)
55
- headers[HSTS_HEADER] = @hsts_header
56
- end
57
-
58
- COOKIE_HEADER = "Set-Cookie".freeze
59
- COOKIE_SEPARATOR = "\n".freeze
60
- COOKIE_REGEXP = /;\s*secure\s*(;|$)/i
61
-
62
- def set_cookies_as_secure(headers)
63
- return unless cookies = headers[COOKIE_HEADER]
64
-
65
- cookies = cookies.split(COOKIE_SEPARATOR).map do |cookie|
66
- (cookie !~ COOKIE_REGEXP) ? "#{ cookie }; secure" : cookie
67
- end
68
-
69
- headers[COOKIE_HEADER] = cookies.join(COOKIE_SEPARATOR)
70
- end
71
- end
72
- end
73
- end
data/test/erubis_test.rb DELETED
@@ -1,20 +0,0 @@
1
- require_relative "../lib/tynn/erubis"
2
-
3
- setup do
4
- Tynn.helpers(Tynn::Erubis, views: File.expand_path("./test/views"))
5
-
6
- Tynn::Test.new
7
- end
8
-
9
- test "escapes" do |app|
10
- Tynn.define do
11
- root do
12
- res.write(partial("partial", name: "<a></a>"))
13
- end
14
- end
15
-
16
- app = Tynn::Test.new
17
- app.get("/")
18
-
19
- assert_equal "&lt;a&gt;&lt;/a&gt;", app.res.body.strip
20
- end
data/test/ssl_test.rb DELETED
@@ -1,82 +0,0 @@
1
- require_relative "../lib/tynn/ssl"
2
-
3
- setup do
4
- Tynn::Test.new
5
- end
6
-
7
- test "redirects to https" do |app|
8
- Tynn.helpers(Tynn::SSL)
9
-
10
- Tynn.define do
11
- end
12
-
13
- app.get("/")
14
-
15
- assert_equal 301, app.res.status
16
- assert_equal "https://example.org/", app.res.location
17
- end
18
-
19
- test "https request" do |app|
20
- Tynn.helpers(Tynn::SSL)
21
-
22
- Tynn.define do
23
- root do
24
- res.write("secure")
25
- end
26
- end
27
-
28
- app.get("/", {}, "HTTPS" => "on")
29
-
30
- assert_equal "secure", app.res.body
31
- end
32
-
33
- test "hsts header" do |app|
34
- Tynn.helpers(Tynn::SSL)
35
-
36
- Tynn.define do
37
- end
38
-
39
- app = Tynn::Test.new
40
- app.get("/", {}, "HTTPS" => "on")
41
-
42
- header = app.res.headers["Strict-Transport-Security"]
43
-
44
- assert_equal "max-age=15552000; includeSubdomains", header
45
- end
46
-
47
- test "hsts header options" do |app|
48
- Tynn.helpers(Tynn::SSL, hsts: {
49
- expires: 1,
50
- subdomains: false,
51
- preload: true
52
- })
53
-
54
- Tynn.define do
55
- end
56
-
57
- app = Tynn::Test.new
58
- app.get("/", {}, "HTTPS" => "on")
59
-
60
- header = app.res.headers["Strict-Transport-Security"]
61
-
62
- assert_equal "max-age=1; preload", header
63
- end
64
-
65
- test "secure cookies" do |app|
66
- Tynn.helpers(Tynn::SSL)
67
-
68
- Tynn.define do
69
- get do
70
- res.set_cookie("first", "cookie")
71
- res.set_cookie("other", "cookie")
72
- end
73
- end
74
-
75
- app = Tynn::Test.new
76
- app.get("/", {}, "HTTPS" => "on")
77
-
78
- first, other = app.res.headers["Set-Cookie"].split("\n")
79
-
80
- assert_equal "first=cookie; secure", first
81
- assert_equal "other=cookie; secure", other
82
- end