tynn 0.0.4 → 1.0.0.rc1

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.
Files changed (49) hide show
  1. checksums.yaml +4 -4
  2. data/lib/tynn/all_methods.rb +17 -0
  3. data/lib/tynn/environment.rb +12 -8
  4. data/lib/tynn/matchers.rb +37 -19
  5. data/lib/tynn/request.rb +4 -0
  6. data/lib/tynn/response.rb +151 -0
  7. data/lib/tynn/secure_headers.rb +28 -4
  8. data/lib/tynn/session.rb +74 -3
  9. data/lib/tynn/ssl.rb +2 -2
  10. data/lib/tynn/static.rb +26 -0
  11. data/lib/tynn/test.rb +37 -2
  12. data/lib/tynn/version.rb +7 -2
  13. data/lib/tynn.rb +88 -8
  14. data/test/all_methods_test.rb +16 -0
  15. data/test/core_test.rb +0 -86
  16. data/test/matchers_test.rb +11 -8
  17. data/test/middleware_test.rb +79 -0
  18. data/test/protection_test.rb +37 -0
  19. data/test/session_test.rb +1 -6
  20. metadata +45 -52
  21. data/.gems +0 -10
  22. data/docs/bin/build +0 -38
  23. data/docs/guides/security.md +0 -1
  24. data/docs/index.md +0 -89
  25. data/docs/layout.html +0 -61
  26. data/docs/public/.gitignore +0 -1
  27. data/docs/public/css/styles.css +0 -111
  28. data/docs/public/guides/.gitignore +0 -2
  29. data/docs/syro/syro.rb +0 -112
  30. data/examples/composition.ru +0 -40
  31. data/examples/hello.ru +0 -9
  32. data/examples/protection.ru +0 -18
  33. data/examples/render.ru +0 -13
  34. data/examples/views/home.erb +0 -1
  35. data/examples/views/layout.erb +0 -5
  36. data/lib/tynn/csrf.rb +0 -48
  37. data/lib/tynn/options.rb +0 -9
  38. data/makefile +0 -15
  39. data/test/csrf_test.rb +0 -98
  40. data/test/options_test.rb +0 -16
  41. data/test/views/custom_layout.erb +0 -1
  42. data/test/views/custom_layout.mote +0 -1
  43. data/test/views/layout.erb +0 -1
  44. data/test/views/layout.mote +0 -1
  45. data/test/views/partial.erb +0 -1
  46. data/test/views/partial.mote +0 -1
  47. data/test/views/view.erb +0 -1
  48. data/test/views/view.mote +0 -1
  49. data/tynn.gemspec +0 -24
@@ -1,111 +0,0 @@
1
- html {
2
- font-family: "Roboto";
3
- }
4
-
5
- body {
6
- color: rgba(0, 0, 0, 0.87);
7
- font-size: 16px;
8
- font-weight: 400;
9
- margin: 0;
10
- padding: 0;
11
- }
12
-
13
- .container {
14
- padding-top: 64px;
15
- min-width: 960px;
16
- }
17
-
18
- header {
19
- background: #2196F3;
20
- box-shadow: 0 0 5px rgba(0, 0, 0, 0.5);
21
- height: 64px;
22
- position: fixed;
23
- top: 0;
24
- width: 100%;
25
- text-align: right;
26
- }
27
-
28
- h1 {
29
- color: rgba(0, 0, 0, 0.54);
30
- font-size: 34px;
31
- font-weight: 400;
32
- }
33
-
34
- h2 {
35
- font-size: 24px;
36
- font-weight: 400;
37
- }
38
-
39
- h3 {
40
- font-size: 16px;
41
- font-weight: 500;
42
- }
43
-
44
- .wrap {
45
- width: 960px;
46
- margin-left: auto;
47
- margin-right: auto;
48
- padding-left: 20px;
49
- padding-right: 20px;
50
- }
51
-
52
- header a {
53
- color: white;
54
- line-height: 64px;
55
- text-decoration: none;
56
- }
57
-
58
- .nav-home {
59
- float: left;
60
- font-size: 24px;
61
- letter-spacing: 2px;
62
- }
63
-
64
- .nav-github {
65
- font-size: 32px;
66
- }
67
-
68
- .content {
69
- padding-top: 20px;
70
- }
71
-
72
- .nav-docs {
73
- float: left;
74
- width: 21.875%;
75
- }
76
-
77
- .nav-docs-section {
78
- border-top: 1px solid rgba(0, 0, 0, 0.12);
79
- padding: 12px 0;
80
- }
81
-
82
- .nav-docs-section:first-child {
83
- padding-top: 0;
84
- border-top: 0;
85
- }
86
-
87
- .nav-docs ul {
88
- list-style: none;
89
- padding: 0;
90
- }
91
-
92
- .nav-docs ul a {
93
- color: rgba(0, 0, 0, 0.87);
94
- font-size: 14px;
95
- line-height: 24px;
96
- text-decoration: none;
97
- }
98
-
99
- .nav-docs ul a:hover {
100
- color: #FF4081;
101
- }
102
-
103
- .nav-docs ul ul {
104
- padding-left: 20px;
105
- }
106
-
107
- .inner-content {
108
- float: right;
109
- line-height: 24px;
110
- width: 67.7083%;
111
- }
@@ -1,2 +0,0 @@
1
- *
2
- !.gitignore
data/docs/syro/syro.rb DELETED
@@ -1,112 +0,0 @@
1
- class Syro::Response
2
- ##
3
- # :method: []
4
- #
5
- # Returns the response header corresponding to `key`.
6
- #
7
- # res["Content-Type"] # => "text/html"
8
- # res["Content-Length"] # => "42"
9
-
10
- ##
11
- # :method: []=
12
- # :call-seq: []=(value)
13
- #
14
- # Sets the given `value` with the header corresponding to `key`.
15
- #
16
- # res["Content-Type"] = "application/json"
17
- # res["Content-Type"] # => "application/json"
18
-
19
- ##
20
- # :method: body
21
- #
22
- # Returns the body of the response.
23
- #
24
- # res.body
25
- # # => []
26
- #
27
- # res.write("there is")
28
- # res.write("no try")
29
- #
30
- # res.body
31
- # # => ["there is", "no try"]
32
-
33
- ##
34
- # :method: finish
35
- #
36
- # Returns an array with three elements: the status, headers and body.
37
- # If the status is not set, the status is set to 404 if empty body,
38
- # otherwise the status is set to 200 and updates the `Content-Type`
39
- # header to `text/html`.
40
- #
41
- # res.status = 200
42
- # res.finish
43
- # # => [200, {}, []]
44
- #
45
- # res.status = nil
46
- # res.finish
47
- # # => [404, {}, []]
48
- #
49
- # res.status = nil
50
- # res.write("yo!")
51
- # res.finish
52
- # # => [200, { "Content-Type" => "text/html" }, ["yo!"]]
53
-
54
- ##
55
- # :method: headers
56
- #
57
- # Returns a hash with the response headers.
58
- #
59
- # res.headers
60
- # # => { "Content-Type" => "text/html", "Content-Length" => "42" }
61
-
62
- ##
63
- # :method: redirect
64
- # :call-seq: redirect(path, 302)
65
- #
66
- # Sets the `Location` header to `path` and updates the status to
67
- # `status`. By default, `status` is `302`.
68
- #
69
- # res.redirect("/path")
70
- #
71
- # res["Location"] # => "/path"
72
- # res.status # => 302
73
- #
74
- # res.redirect("http://tynn.ru", 303)
75
- #
76
- # res["Location"] # => "http://tynn.ru"
77
- # res.status # => 303
78
-
79
- ##
80
- # :method: status
81
- #
82
- # Returns the status of the response.
83
- #
84
- # res.status # => 200
85
- #
86
-
87
- ##
88
- # :method: status=
89
- # :call-seq: status=(status)
90
- #
91
- # Sets the status of the response.
92
- #
93
- # res.status = 200
94
- #
95
-
96
- ##
97
- # :method: write
98
- # :call-seq: write(str)
99
- #
100
- # Appends `str` to `body` and updates the `Content-Length` header.
101
- #
102
- # res.body # => []
103
- #
104
- # res.write("foo")
105
- # res.write("bar")
106
- #
107
- # res.body
108
- # # => ["foo", "bar"]
109
- #
110
- # res["Content-Length"]
111
- # # => 6
112
- end
@@ -1,40 +0,0 @@
1
- require_relative "../lib/tynn"
2
-
3
- class Users < Tynn
4
- end
5
-
6
- Users.define do
7
- on(:id) do |id|
8
- get do
9
- res.write("GET /users/#{ id }")
10
- end
11
-
12
- put do
13
- res.write("PUT /users/#{ id }")
14
- end
15
-
16
- patch do
17
- res.write("PATCH /users/#{ id }")
18
- end
19
-
20
- delete do
21
- res.write("DELETE /users/#{ id }")
22
- end
23
- end
24
-
25
- get do
26
- res.write("GET /users")
27
- end
28
-
29
- post do
30
- res.write("POST /users")
31
- end
32
- end
33
-
34
- Tynn.define do
35
- on("users") do
36
- run(Users)
37
- end
38
- end
39
-
40
- run(Tynn)
data/examples/hello.ru DELETED
@@ -1,9 +0,0 @@
1
- require_relative "../lib/tynn"
2
-
3
- Tynn.define do
4
- root do
5
- res.write("hello")
6
- end
7
- end
8
-
9
- run(Tynn)
@@ -1,18 +0,0 @@
1
- require_relative "../lib/tynn"
2
- require_relative "../lib/tynn/environment"
3
- require_relative "../lib/tynn/protection"
4
- require_relative "../lib/tynn/session"
5
-
6
- Tynn.helpers(Tynn::Environment)
7
-
8
- Tynn.helpers(Tynn::Protection, ssl: Tynn.production?)
9
-
10
- Tynn.helpers(Tynn::Session, secret: SecureRandom.hex(64))
11
-
12
- Tynn.define do
13
- root do
14
- res.write("use protection")
15
- end
16
- end
17
-
18
- run(Tynn)
data/examples/render.ru DELETED
@@ -1,13 +0,0 @@
1
- require "erb"
2
- require_relative "../lib/tynn"
3
- require_relative "../lib/tynn/render"
4
-
5
- Tynn.helpers(Tynn::Render, views: File.expand_path("views", __dir__))
6
-
7
- Tynn.define do
8
- root do
9
- render("home", title: "Thanks for using Tynn!")
10
- end
11
- end
12
-
13
- run(Tynn)
@@ -1 +0,0 @@
1
- <%= title %>
@@ -1,5 +0,0 @@
1
- <h1>Tynn</h1>
2
-
3
- <p>
4
- <%= content %>
5
- </p>
data/lib/tynn/csrf.rb DELETED
@@ -1,48 +0,0 @@
1
- module Tynn::CSRF
2
- def csrf
3
- @csrf ||= Tynn::CSRF::Helper.new(self)
4
- end
5
-
6
- class Helper
7
- CSRF_HEADER = "HTTP_X_CSRF_TOKEN".freeze
8
-
9
- def initialize(app)
10
- @app = app
11
- @req = app.req
12
- end
13
-
14
- def token
15
- return session[:csrf_token] ||= SecureRandom.base64(32)
16
- end
17
-
18
- def reset!
19
- session.delete(:csrf_token)
20
- end
21
-
22
- def safe?
23
- return @req.get? || @req.head? || verify_token
24
- end
25
-
26
- def unsafe?
27
- return !safe?
28
- end
29
-
30
- def form_tag
31
- return %Q(<input type="hidden" name="csrf_token" value="#{ token }">)
32
- end
33
-
34
- def meta_tag
35
- return %Q(<meta name="csrf_token" content="#{ token }">)
36
- end
37
-
38
- private
39
-
40
- def verify_token
41
- return @req[:csrf_token] == token || @req.env[CSRF_HEADER] == token
42
- end
43
-
44
- def session
45
- return @app.session
46
- end
47
- end
48
- end
data/lib/tynn/options.rb DELETED
@@ -1,9 +0,0 @@
1
- module Tynn::Options
2
- def options
3
- if root? && req.options?
4
- yield
5
-
6
- halt(res.finish)
7
- end
8
- end
9
- end
data/makefile DELETED
@@ -1,15 +0,0 @@
1
- default: test
2
-
3
- docs:
4
- @./docs/bin/build
5
-
6
- install:
7
- @cat .gems | xargs gem install
8
-
9
- server:
10
- ruby -run -e httpd ./docs/public -p 4000
11
-
12
- test:
13
- @cutest -r ./test/helper.rb ./test/*_test.rb
14
-
15
- .PHONY: test
data/test/csrf_test.rb DELETED
@@ -1,98 +0,0 @@
1
- require "securerandom"
2
- require_relative "../lib/tynn/csrf"
3
- require_relative "../lib/tynn/session"
4
-
5
- setup do
6
- Tynn.helpers(Tynn::CSRF)
7
- Tynn.helpers(Tynn::Session, secret: SecureRandom.hex(64))
8
-
9
- Tynn::Test.new
10
- end
11
-
12
- test "get should be safe" do |app|
13
- Tynn.define do
14
- get do
15
- res.write(csrf.safe?)
16
- end
17
- end
18
-
19
- app.get("/")
20
-
21
- assert_equal "true", app.res.body
22
- end
23
-
24
- test "head should be safe" do |app|
25
- Tynn.define do
26
- on req.head? do
27
- res.write(csrf.safe?)
28
- end
29
- end
30
-
31
- app.head("/")
32
-
33
- assert_equal "true", app.res.body
34
- end
35
-
36
- test "invalid csrf token" do |app|
37
- Tynn.define do
38
- post do
39
- res.write(csrf.unsafe?)
40
- end
41
- end
42
-
43
- app.post("/")
44
-
45
- assert_equal "true", app.res.body
46
- end
47
-
48
- test "valid csrf token" do |app|
49
- token = SecureRandom.hex(64)
50
-
51
- Tynn.define do
52
- post do
53
- session[:csrf_token] = token
54
-
55
- res.write(csrf.safe?)
56
- end
57
- end
58
-
59
- app.post("/", csrf_token: token)
60
-
61
- assert_equal "true", app.res.body
62
- end
63
-
64
- test "resets token" do |app|
65
- token = SecureRandom.hex(64)
66
-
67
- Tynn.define do
68
- post do
69
- session[:csrf_token] = token
70
-
71
- if csrf.unsafe?
72
- csrf.reset!
73
- end
74
-
75
- res.write(csrf.token)
76
- end
77
- end
78
-
79
- app.post("/", csrf_token: "nonsense")
80
-
81
- assert token != app.res.body
82
- end
83
-
84
- test "http header" do |app|
85
- token = SecureRandom.hex(64)
86
-
87
- Tynn.define do
88
- post do
89
- session[:csrf_token] = token
90
-
91
- res.write(csrf.safe?)
92
- end
93
- end
94
-
95
- app.post("/", {}, "HTTP_X_CSRF_TOKEN" => token)
96
-
97
- assert_equal "true", app.res.body
98
- end
data/test/options_test.rb DELETED
@@ -1,16 +0,0 @@
1
- require_relative "../lib/tynn/options"
2
-
3
- test "options" do
4
- Tynn.helpers(Tynn::Options)
5
-
6
- Tynn.define do
7
- options do
8
- res.write ""
9
- end
10
- end
11
-
12
- app = Tynn::Test.new
13
- app.options("/")
14
-
15
- assert_equal 200, app.res.status
16
- end
@@ -1 +0,0 @@
1
- custom / <%= content %>
@@ -1 +0,0 @@
1
- custom / {{! content }}
@@ -1 +0,0 @@
1
- <%= content %>
@@ -1 +0,0 @@
1
- {{! content }}
@@ -1 +0,0 @@
1
- <%= name %>
@@ -1 +0,0 @@
1
- {{ name }}
data/test/views/view.erb DELETED
@@ -1 +0,0 @@
1
- <%= title %> / <%= partial("partial", name: name) %>
data/test/views/view.mote DELETED
@@ -1 +0,0 @@
1
- {{ title }} / {{! app.partial("partial", name: name) }}
data/tynn.gemspec DELETED
@@ -1,24 +0,0 @@
1
- require_relative "lib/tynn/version"
2
-
3
- Gem::Specification.new do |s|
4
- s.name = "tynn"
5
- s.version = Tynn::VERSION
6
- s.summary = "Simple library to create Rack applications"
7
- s.description = s.summary
8
- s.authors = ["Francesco Rodríguez"]
9
- s.email = ["frodsan@protonmail.ch"]
10
- s.homepage = "https://github.com/harmoni/tynn"
11
- s.license = "MIT"
12
-
13
- s.files = `git ls-files`.split("\n")
14
-
15
- s.add_dependency "rack", "~> 1.6"
16
- s.add_dependency "seteable", "1.1.0"
17
- s.add_dependency "syro", "~> 1.0"
18
-
19
- s.add_development_dependency "cutest", "1.2.2"
20
- s.add_development_dependency "erubis", "~> 2.7"
21
- s.add_development_dependency "hmote", "1.4.0"
22
- s.add_development_dependency "rack-test", "0.6.3"
23
- s.add_development_dependency "tilt", "~> 2.0"
24
- end