putsreq 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (233) hide show
  1. checksums.yaml +7 -0
  2. data/.codeclimate.yml +7 -0
  3. data/.coffeelint.json +5 -0
  4. data/.gitignore +20 -0
  5. data/.hound.yml +14 -0
  6. data/.jshintrc +3 -0
  7. data/.rspec +3 -0
  8. data/.rubocop.yml +110 -0
  9. data/.ruby-version +1 -0
  10. data/.travis.yml +18 -0
  11. data/Gemfile +91 -0
  12. data/Gemfile.lock +270 -0
  13. data/LICENSE +5 -0
  14. data/Procfile +1 -0
  15. data/README.md +147 -0
  16. data/Rakefile +8 -0
  17. data/app/assets/javascripts/application.js +27 -0
  18. data/app/assets/javascripts/buckets.js.coffee +68 -0
  19. data/app/assets/javascripts/initializers.js.coffee +8 -0
  20. data/app/assets/stylesheets/application.css +15 -0
  21. data/app/assets/stylesheets/base.css +68 -0
  22. data/app/assets/stylesheets/buckets.css.scss +91 -0
  23. data/app/assets/stylesheets/helpers.css +154 -0
  24. data/app/controllers/application_controller.rb +35 -0
  25. data/app/controllers/buckets_controller.rb +88 -0
  26. data/app/controllers/concerns/.keep +0 -0
  27. data/app/controllers/home_controller.rb +18 -0
  28. data/app/helpers/application_helper.rb +14 -0
  29. data/app/interactors/create_request.rb +15 -0
  30. data/app/interactors/create_response.rb +11 -0
  31. data/app/interactors/eval_response_builder.rb +55 -0
  32. data/app/interactors/filter_headers.rb +28 -0
  33. data/app/interactors/forward_request.rb +39 -0
  34. data/app/interactors/notify_count.rb +15 -0
  35. data/app/interactors/record_request.rb +5 -0
  36. data/app/mailers/.keep +0 -0
  37. data/app/models/.keep +0 -0
  38. data/app/models/bucket.rb +99 -0
  39. data/app/models/concerns/.keep +0 -0
  40. data/app/models/request.rb +36 -0
  41. data/app/models/response.rb +22 -0
  42. data/app/models/user.rb +42 -0
  43. data/app/views/buckets/_buttons.html.erb +4 -0
  44. data/app/views/buckets/_form.html.erb +33 -0
  45. data/app/views/buckets/_readonly_buttons.html.erb +1 -0
  46. data/app/views/buckets/_requests.html.erb +45 -0
  47. data/app/views/buckets/show.html.erb +58 -0
  48. data/app/views/home/index.html.erb +45 -0
  49. data/app/views/layouts/_header.html.erb +18 -0
  50. data/app/views/layouts/application.html.erb +28 -0
  51. data/app/views/layouts/devise.html.erb +22 -0
  52. data/app/views/shared/_flash.html.erb +10 -0
  53. data/app/views/users/confirmations/new.html.erb +12 -0
  54. data/app/views/users/mailer/confirmation_instructions.html.erb +5 -0
  55. data/app/views/users/mailer/reset_password_instructions.html.erb +8 -0
  56. data/app/views/users/mailer/unlock_instructions.html.erb +7 -0
  57. data/app/views/users/passwords/edit.html.erb +32 -0
  58. data/app/views/users/passwords/new.html.erb +23 -0
  59. data/app/views/users/registrations/edit.html.erb +59 -0
  60. data/app/views/users/registrations/new.html.erb +46 -0
  61. data/app/views/users/sessions/new.html.erb +38 -0
  62. data/app/views/users/shared/_links.erb +25 -0
  63. data/app/views/users/unlocks/new.html.erb +12 -0
  64. data/bin/bundle +3 -0
  65. data/bin/putsreq +71 -0
  66. data/bin/rails +4 -0
  67. data/bin/rake +4 -0
  68. data/bin/rspec +16 -0
  69. data/config.ru +4 -0
  70. data/config/application.rb +42 -0
  71. data/config/boot.rb +4 -0
  72. data/config/environment.rb +5 -0
  73. data/config/environments/development.rb +33 -0
  74. data/config/environments/production.rb +82 -0
  75. data/config/environments/test.rb +36 -0
  76. data/config/initializers/backtrace_silencers.rb +7 -0
  77. data/config/initializers/devise.rb +256 -0
  78. data/config/initializers/filter_parameter_logging.rb +4 -0
  79. data/config/initializers/inflections.rb +16 -0
  80. data/config/initializers/mime_types.rb +5 -0
  81. data/config/initializers/redis.rb +17 -0
  82. data/config/initializers/secret_token.rb +12 -0
  83. data/config/initializers/session_store.rb +3 -0
  84. data/config/initializers/setup_email.rb +10 -0
  85. data/config/initializers/wrap_parameters.rb +14 -0
  86. data/config/locales/devise.en.yml +59 -0
  87. data/config/locales/en.yml +23 -0
  88. data/config/mongoid.yml +47 -0
  89. data/config/routes.rb +15 -0
  90. data/config/unicorn.rb +16 -0
  91. data/lib/assets/.keep +0 -0
  92. data/lib/putsreq/version.rb +3 -0
  93. data/lib/tasks/.keep +0 -0
  94. data/public/404.html +58 -0
  95. data/public/422.html +58 -0
  96. data/public/500.html +57 -0
  97. data/public/favicon.ico +0 -0
  98. data/public/images/.keep +0 -0
  99. data/public/images/favicon.png +0 -0
  100. data/public/images/favicon144.png +0 -0
  101. data/public/images/favicon152.png +0 -0
  102. data/public/images/glyphicons-halflings-white.png +0 -0
  103. data/public/images/glyphicons-halflings.png +0 -0
  104. data/public/images/logo.png +0 -0
  105. data/public/javascripts/vendor/ace/theme-monokai.js +1 -0
  106. data/public/javascripts/vendor/ace/theme-textmate.js +1 -0
  107. data/public/javascripts/vendor/ace/worker-javascript.js +1 -0
  108. data/public/javascripts/vendor/ace/worker-json.js +1 -0
  109. data/public/robots.txt +5 -0
  110. data/putsreq.gemspec +22 -0
  111. data/spec/controllers/buckets_controller_spec.rb +164 -0
  112. data/spec/interactors/create_request_spec.rb +34 -0
  113. data/spec/interactors/create_response_spec.rb +14 -0
  114. data/spec/interactors/eval_response_builder_spec.rb +63 -0
  115. data/spec/interactors/forward_request_spec.rb +39 -0
  116. data/spec/models/bucket_spec.rb +96 -0
  117. data/spec/models/user_spec.rb +5 -0
  118. data/spec/spec_helper.rb +66 -0
  119. data/vendor/assets/javascripts/.keep +0 -0
  120. data/vendor/assets/javascripts/ace/ace.js +10 -0
  121. data/vendor/assets/javascripts/ace/ext-searchbox.js +1 -0
  122. data/vendor/assets/javascripts/ace/ext-spellcheck.js +1 -0
  123. data/vendor/assets/javascripts/ace/ext-static_highlight.js +1 -0
  124. data/vendor/assets/javascripts/ace/ext-textarea.js +1 -0
  125. data/vendor/assets/javascripts/ace/keybinding-emacs.js +1 -0
  126. data/vendor/assets/javascripts/ace/keybinding-vim.js +1 -0
  127. data/vendor/assets/javascripts/ace/mode-abap.js +1 -0
  128. data/vendor/assets/javascripts/ace/mode-asciidoc.js +1 -0
  129. data/vendor/assets/javascripts/ace/mode-c9search.js +1 -0
  130. data/vendor/assets/javascripts/ace/mode-c_cpp.js +1 -0
  131. data/vendor/assets/javascripts/ace/mode-clojure.js +1 -0
  132. data/vendor/assets/javascripts/ace/mode-coffee.js +1 -0
  133. data/vendor/assets/javascripts/ace/mode-coldfusion.js +1 -0
  134. data/vendor/assets/javascripts/ace/mode-csharp.js +1 -0
  135. data/vendor/assets/javascripts/ace/mode-css.js +1 -0
  136. data/vendor/assets/javascripts/ace/mode-curly.js +1 -0
  137. data/vendor/assets/javascripts/ace/mode-dart.js +1 -0
  138. data/vendor/assets/javascripts/ace/mode-diff.js +1 -0
  139. data/vendor/assets/javascripts/ace/mode-django.js +1 -0
  140. data/vendor/assets/javascripts/ace/mode-dot.js +1 -0
  141. data/vendor/assets/javascripts/ace/mode-glsl.js +1 -0
  142. data/vendor/assets/javascripts/ace/mode-golang.js +1 -0
  143. data/vendor/assets/javascripts/ace/mode-groovy.js +1 -0
  144. data/vendor/assets/javascripts/ace/mode-haml.js +1 -0
  145. data/vendor/assets/javascripts/ace/mode-haxe.js +1 -0
  146. data/vendor/assets/javascripts/ace/mode-html.js +1 -0
  147. data/vendor/assets/javascripts/ace/mode-jade.js +1 -0
  148. data/vendor/assets/javascripts/ace/mode-java.js +1 -0
  149. data/vendor/assets/javascripts/ace/mode-javascript.js +1 -0
  150. data/vendor/assets/javascripts/ace/mode-json.js +1 -0
  151. data/vendor/assets/javascripts/ace/mode-jsp.js +1 -0
  152. data/vendor/assets/javascripts/ace/mode-jsx.js +1 -0
  153. data/vendor/assets/javascripts/ace/mode-latex.js +1 -0
  154. data/vendor/assets/javascripts/ace/mode-less.js +1 -0
  155. data/vendor/assets/javascripts/ace/mode-liquid.js +1 -0
  156. data/vendor/assets/javascripts/ace/mode-lisp.js +1 -0
  157. data/vendor/assets/javascripts/ace/mode-livescript.js +1 -0
  158. data/vendor/assets/javascripts/ace/mode-lua.js +1 -0
  159. data/vendor/assets/javascripts/ace/mode-luapage.js +1 -0
  160. data/vendor/assets/javascripts/ace/mode-lucene.js +1 -0
  161. data/vendor/assets/javascripts/ace/mode-makefile.js +1 -0
  162. data/vendor/assets/javascripts/ace/mode-markdown.js +1 -0
  163. data/vendor/assets/javascripts/ace/mode-objectivec.js +1 -0
  164. data/vendor/assets/javascripts/ace/mode-ocaml.js +1 -0
  165. data/vendor/assets/javascripts/ace/mode-perl.js +1 -0
  166. data/vendor/assets/javascripts/ace/mode-pgsql.js +1 -0
  167. data/vendor/assets/javascripts/ace/mode-php.js +1 -0
  168. data/vendor/assets/javascripts/ace/mode-powershell.js +1 -0
  169. data/vendor/assets/javascripts/ace/mode-python.js +1 -0
  170. data/vendor/assets/javascripts/ace/mode-r.js +1 -0
  171. data/vendor/assets/javascripts/ace/mode-rdoc.js +1 -0
  172. data/vendor/assets/javascripts/ace/mode-rhtml.js +1 -0
  173. data/vendor/assets/javascripts/ace/mode-ruby.js +1 -0
  174. data/vendor/assets/javascripts/ace/mode-scad.js +1 -0
  175. data/vendor/assets/javascripts/ace/mode-scala.js +1 -0
  176. data/vendor/assets/javascripts/ace/mode-scheme.js +1 -0
  177. data/vendor/assets/javascripts/ace/mode-scss.js +1 -0
  178. data/vendor/assets/javascripts/ace/mode-sh.js +1 -0
  179. data/vendor/assets/javascripts/ace/mode-sql.js +1 -0
  180. data/vendor/assets/javascripts/ace/mode-stylus.js +1 -0
  181. data/vendor/assets/javascripts/ace/mode-svg.js +1 -0
  182. data/vendor/assets/javascripts/ace/mode-tcl.js +1 -0
  183. data/vendor/assets/javascripts/ace/mode-tex.js +1 -0
  184. data/vendor/assets/javascripts/ace/mode-text.js +0 -0
  185. data/vendor/assets/javascripts/ace/mode-textile.js +1 -0
  186. data/vendor/assets/javascripts/ace/mode-tm_snippet.js +1 -0
  187. data/vendor/assets/javascripts/ace/mode-typescript.js +1 -0
  188. data/vendor/assets/javascripts/ace/mode-vbscript.js +1 -0
  189. data/vendor/assets/javascripts/ace/mode-xml.js +1 -0
  190. data/vendor/assets/javascripts/ace/mode-xquery.js +1 -0
  191. data/vendor/assets/javascripts/ace/mode-yaml.js +1 -0
  192. data/vendor/assets/javascripts/ace/theme-ambiance.js +1 -0
  193. data/vendor/assets/javascripts/ace/theme-chaos.js +1 -0
  194. data/vendor/assets/javascripts/ace/theme-chrome.js +1 -0
  195. data/vendor/assets/javascripts/ace/theme-clouds.js +1 -0
  196. data/vendor/assets/javascripts/ace/theme-clouds_midnight.js +1 -0
  197. data/vendor/assets/javascripts/ace/theme-cobalt.js +1 -0
  198. data/vendor/assets/javascripts/ace/theme-crimson_editor.js +1 -0
  199. data/vendor/assets/javascripts/ace/theme-dawn.js +1 -0
  200. data/vendor/assets/javascripts/ace/theme-dreamweaver.js +1 -0
  201. data/vendor/assets/javascripts/ace/theme-eclipse.js +1 -0
  202. data/vendor/assets/javascripts/ace/theme-github.js +1 -0
  203. data/vendor/assets/javascripts/ace/theme-idle_fingers.js +1 -0
  204. data/vendor/assets/javascripts/ace/theme-kr.js +1 -0
  205. data/vendor/assets/javascripts/ace/theme-merbivore.js +1 -0
  206. data/vendor/assets/javascripts/ace/theme-merbivore_soft.js +1 -0
  207. data/vendor/assets/javascripts/ace/theme-mono_industrial.js +1 -0
  208. data/vendor/assets/javascripts/ace/theme-monokai.js +1 -0
  209. data/vendor/assets/javascripts/ace/theme-pastel_on_dark.js +1 -0
  210. data/vendor/assets/javascripts/ace/theme-solarized_dark.js +1 -0
  211. data/vendor/assets/javascripts/ace/theme-solarized_light.js +1 -0
  212. data/vendor/assets/javascripts/ace/theme-textmate.js +1 -0
  213. data/vendor/assets/javascripts/ace/theme-tomorrow.js +1 -0
  214. data/vendor/assets/javascripts/ace/theme-tomorrow_night.js +1 -0
  215. data/vendor/assets/javascripts/ace/theme-tomorrow_night_blue.js +1 -0
  216. data/vendor/assets/javascripts/ace/theme-tomorrow_night_bright.js +1 -0
  217. data/vendor/assets/javascripts/ace/theme-tomorrow_night_eighties.js +1 -0
  218. data/vendor/assets/javascripts/ace/theme-twilight.js +1 -0
  219. data/vendor/assets/javascripts/ace/theme-vibrant_ink.js +1 -0
  220. data/vendor/assets/javascripts/ace/theme-xcode.js +1 -0
  221. data/vendor/assets/javascripts/ace/worker-coffee.js +1 -0
  222. data/vendor/assets/javascripts/ace/worker-css.js +1 -0
  223. data/vendor/assets/javascripts/ace/worker-javascript.js +1 -0
  224. data/vendor/assets/javascripts/ace/worker-json.js +1 -0
  225. data/vendor/assets/javascripts/ace/worker-php.js +1 -0
  226. data/vendor/assets/javascripts/ace/worker-xquery.js +1 -0
  227. data/vendor/assets/javascripts/jquery.tipsy.js +198 -0
  228. data/vendor/assets/javascripts/mode-javascript.js +1 -0
  229. data/vendor/assets/javascripts/theme-monokai.js +1 -0
  230. data/vendor/assets/javascripts/worker-javascript.js +1 -0
  231. data/vendor/assets/stylesheets/.keep +0 -0
  232. data/vendor/assets/stylesheets/tipsy.css +25 -0
  233. metadata +311 -0
@@ -0,0 +1,154 @@
1
+ .bg {background:#000 !important}
2
+ .block {display:block !important}
3
+ .border {border:1px solid black !important}
4
+ .breadcrumb {font-size:11px !important}
5
+ .bz {border: 0 !important}
6
+ .f9 {font-size:57px !important;}
7
+ .f8 {font-size:38px !important;}
8
+ .f7 {font-size:30px !important;}
9
+ .f6 {font-size:27px !important;}
10
+ .f5 {font-size:20px !important;}
11
+ .f4 {font-size:17px !important;}
12
+ .f3 {font-size:15px !important;}
13
+ .f2 {font-size:13px !important;}
14
+ .f1 {font-size:8px !important;}
15
+ .f10 {font-size:10px !important;}
16
+ .fw {width:100% !important}
17
+ .fwb {font-weight:bold !important}
18
+ .fsi {font-style:italic !important}
19
+ .fl {float:left !important}
20
+ .fr {float:right !important}
21
+ .h10 {height:10px !important}
22
+ .h20 {height:20px !important}
23
+ .h30 {height:30px !important}
24
+ .h40 {height:40px !important}
25
+ .h50 {height:50px !important}
26
+ .h80 {height:80px !important}
27
+ .h100 {height:100px !important}
28
+ .h150 {height:150px !important}
29
+ .h200 {height:200px !important}
30
+ .h250 {height:250px !important}
31
+ .h300 {height:300px !important}
32
+ .hidden {display: none !important}
33
+ .hr {border-top: 1px solid #c9c9c9;}
34
+ .left {float:left}
35
+ .lh5 {line-height:5px !important}
36
+ .lh10 {line-height:10px !important}
37
+ .lh15 {line-height:15px !important}
38
+ .lh20 {line-height:20px !important}
39
+ .lh25 {line-height:25px !important}
40
+ .lh30 {line-height:30px !important}
41
+ .lh35 {line-height:35px !important}
42
+ .lm0 {margin-left:0 !important}
43
+ .no-text-shadow {text-shadow: none;}
44
+ .p5 {padding: 5px !important;}
45
+ .right {float:right}
46
+ .tac {text-align:center !important}
47
+ .tal {text-align:left !important}
48
+ .tar {text-align:right !important}
49
+ .tm1 {margin-top:1px !important}
50
+ .tm2 {margin-top:2px !important}
51
+ .tm3 {margin-top:3px !important}
52
+ .tm4 {margin-top:4px !important}
53
+ .tm5 {margin-top:5px !important}
54
+ .tm6 {margin-top:6px !important}
55
+ .tm7 {margin-top:7px !important}
56
+ .tm8 {margin-top:8px !important}
57
+ .tm9 {margin-top:9px !important}
58
+ .tm10 {margin-top:10px !important}
59
+ .tm11 {margin-top:11px !important}
60
+ .tm12 {margin-top:12px !important}
61
+ .tm13 {margin-top:13px !important}
62
+ .tm14 {margin-top:14px !important}
63
+ .tm15 {margin-top:15px !important}
64
+ .tm20 {margin-top:20px !important}
65
+ .tm25 {margin-top:25px !important}
66
+ .tm30 {margin-top:30px !important}
67
+ .tm35 {margin-top:35px !important}
68
+ .tm40 {margin-top:40px !important}
69
+ .tm45 {margin-top:45px !important}
70
+ .tm50 {margin-top:50px !important}
71
+ .tm60 {margin-top:60px !important}
72
+ .tm70 {margin-top:70px !important}
73
+ .tm80 {margin-top:80px !important}
74
+ .tm90 {margin-top:90px !important}
75
+ .tm100 {margin-top:100px !important}
76
+ .tm130 {margin-top:130px !important}
77
+ .bm0 {margin-bottom:0 !important}
78
+ .bm5 {margin-bottom:5px !important}
79
+ .bm10 {margin-bottom:10px !important}
80
+ .bm15 {margin-bottom:15px !important}
81
+ .bm20 {margin-bottom:20px !important}
82
+ .bm25 {margin-bottom:25px !important}
83
+ .bm30 {margin-bottom:30px !important}
84
+ .bm35 {margin-bottom:35px !important}
85
+ .bm40 {margin-bottom:40px !important}
86
+ .bm45 {margin-bottom:45px !important}
87
+ .bm50 {margin-bottom:50px !important}
88
+ .pt1 {padding-top:1px !important}
89
+ .pt2 {padding-top:2px !important}
90
+ .pt3 {padding-top:3px !important}
91
+ .pt4 {padding-top:4px !important}
92
+ .pt5 {padding-top:5px !important}
93
+ .pt10 {padding-top:10px !important}
94
+ .pt20 {padding-top:20px !important}
95
+ .pt30 {padding-top:30px !important}
96
+ .pb1 {padding-bottom:1px !important}
97
+ .pb2 {padding-bottom:2px !important}
98
+ .pb3 {padding-bottom:3px !important}
99
+ .pb4 {padding-bottom:4px !important}
100
+ .pb5 {padding-bottom:5px !important}
101
+ .pb10 {padding-bottom:10px !important}
102
+ .pb20 {padding-bottom:20px !important}
103
+ .pb30 {padding-bottom:30px !important}
104
+ .pl10 {padding-left:10px !important}
105
+ .pl20 {padding-left:20px !important}
106
+ .pl30 {padding-left:30px !important}
107
+ .pr10 {padding-right:10px !important}
108
+ .pr20 {padding-right:20px !important}
109
+ .pr30 {padding-right:30px !important}
110
+ .lm1 {margin-left:1px !important}
111
+ .lm2 {margin-left:2px !important}
112
+ .lm3 {margin-left:3px !important}
113
+ .lm4 {margin-left:4px !important}
114
+ .lm5 {margin-left:5px !important}
115
+ .lm10 {margin-left:10px !important}
116
+ .lm15 {margin-left:15px !important}
117
+ .lm20 {margin-left:20px !important}
118
+ .lm25 {margin-left:25px !important}
119
+ .lm30 {margin-left:30px !important}
120
+ .lm35 {margin-left:35px !important}
121
+ .lm40 {margin-left:40px !important}
122
+ .lm45 {margin-left:45px !important}
123
+ .lm50 {margin-left:50px !important}
124
+ .pointer {cursor: pointer !important}
125
+ .rm1 {margin-right:1px !important}
126
+ .rm2 {margin-right:2px !important}
127
+ .rm3 {margin-right:3px !important}
128
+ .rm4 {margin-right:4px !important}
129
+ .rm5 {margin-right:5px !important}
130
+ .rm10 {margin-right:10px !important}
131
+ .rm15 {margin-right:15px !important}
132
+ .rm20 {margin-right:20px !important}
133
+ .rm25 {margin-right:25px !important}
134
+ .rm30 {margin-right:30px !important}
135
+ .rm35 {margin-right:35px !important}
136
+ .rm40 {margin-right:40px !important}
137
+ .rm45 {margin-right:45px !important}
138
+ .rm50 {margin-right:50px !important}
139
+ .w100 {width:100px !important}
140
+ .w200 {width:200px !important}
141
+ .w300 {width:300px !important}
142
+ .w400 {width:400px !important}
143
+ .w500 {width:500px !important}
144
+ .w5pc {width:5% !important;}
145
+ .w10pc {width:10% !important;}
146
+ .w20pc {width:10% !important;}
147
+ .w30pc {width:30% !important;}
148
+ .w40pc {width:40% !important;}
149
+ .w50pc {width:50% !important;}
150
+ .w60pc {width:60% !important;}
151
+ .w70pc {width:70% !important;}
152
+ .w80pc {width:80% !important;}
153
+ .w90pc {width:90% !important;}
154
+ .w100pc {width:100% !important;}
@@ -0,0 +1,35 @@
1
+ class ApplicationController < ActionController::Base
2
+ # Prevent CSRF attacks by raising an exception.
3
+ # For APIs, you may want to use :null_session instead.
4
+ protect_from_forgery with: :exception
5
+
6
+ helper_method :is_owner?
7
+
8
+ before_action :configure_permitted_parameters, if: :devise_controller?
9
+
10
+ protected
11
+
12
+ def check_ownership!
13
+ unless is_owner?(bucket)
14
+ redirect_to bucket_path(bucket.token), alert: 'Only the bucket owner can perform this operation'
15
+ end
16
+ end
17
+
18
+ def is_owner?(bucket)
19
+ owner_token == bucket.owner_token || (user_signed_in? && bucket.user == current_user)
20
+ end
21
+
22
+ def owner_token
23
+ cookies[:owner_token] ||= { value: SecureRandom.hex(24), expires: 1.year.from_now }
24
+ end
25
+
26
+ def bucket
27
+ @bucket ||= Bucket.find_by(token: params[:token])
28
+ end
29
+
30
+ def configure_permitted_parameters
31
+ devise_parameter_sanitizer.for(:sign_up) { |u| u.permit(:name, :email, :password, :password_confirmation, :remember_me) }
32
+ devise_parameter_sanitizer.for(:sign_in) { |u| u.permit(:name, :email, :password, :remember_me) }
33
+ devise_parameter_sanitizer.for(:account_update) { |u| u.permit(:name, :email, :password, :password_confirmation, :current_password) }
34
+ end
35
+ end
@@ -0,0 +1,88 @@
1
+ class BucketsController < ApplicationController
2
+ skip_before_action :verify_authenticity_token, only: :record
3
+
4
+ before_filter :check_ownership!, only: %i[clear destroy update]
5
+
6
+ def create
7
+ new_bucket = { owner_token: owner_token }
8
+ new_bucket[:user_id] = current_user.id if user_signed_in?
9
+
10
+ bucket = Bucket.create(new_bucket)
11
+
12
+ redirect_to bucket_path(bucket.token)
13
+ end
14
+
15
+ def fork
16
+ forked_bucket = Bucket.create(owner_token: owner_token,
17
+ response_builder: bucket.response_builder,
18
+ name: "Copy of #{bucket.name}",
19
+ fork: bucket)
20
+
21
+ redirect_to bucket_path(forked_bucket.token)
22
+ end
23
+
24
+ def clear
25
+ bucket.clear_history
26
+
27
+ redirect_to bucket_path(bucket.token)
28
+ end
29
+
30
+ def destroy
31
+ bucket.destroy
32
+
33
+ redirect_to root_path
34
+ end
35
+
36
+ def show
37
+ @requests = bucket.requests.page(params[:page]).per 1
38
+ end
39
+
40
+ def update
41
+ update_bucket = bucket_params
42
+ update_bucket[:user_id] = current_user.id if user_signed_in?
43
+
44
+ bucket.update_attributes update_bucket
45
+
46
+ redirect_to bucket_path(bucket.token)
47
+ end
48
+
49
+ def last
50
+ return render_request_not_found unless last_request = bucket.last_request
51
+
52
+ respond_to do |format|
53
+ format.html { render text: last_request.body }
54
+ format.json { render json: JSON.pretty_generate(last_request.attributes) }
55
+ end
56
+ end
57
+
58
+ def last_response
59
+ return render_request_not_found unless last_response = bucket.last_response
60
+
61
+ respond_to do |format|
62
+ format.html { render text: last_response.body }
63
+ format.json { render json: JSON.pretty_generate(last_response.attributes) }
64
+ end
65
+ end
66
+
67
+ def record
68
+ result = RecordRequest.call(bucket: bucket, rack_request: request)
69
+ recorded_response = result.response
70
+
71
+ response.headers.merge! recorded_response.headers.to_h
72
+
73
+ render text: recorded_response.body_as_string, status: recorded_response.status
74
+ end
75
+
76
+ private
77
+
78
+ def render_request_not_found
79
+ respond_to do |format|
80
+ format.html { redirect_to bucket_path(bucket.token), alert: 'Please submit a request first' }
81
+ format.json { render nothing: true, status: 404 }
82
+ end
83
+ end
84
+
85
+ def bucket_params
86
+ params.require(:bucket).permit(:response_builder, :name)
87
+ end
88
+ end
File without changes
@@ -0,0 +1,18 @@
1
+ class HomeController < ApplicationController
2
+ def index
3
+ if user_signed_in?
4
+ selector = Bucket.or([user: current_user], [owner_token: owner_token])
5
+ else
6
+ selector = Bucket.where(owner_token: owner_token)
7
+ end
8
+
9
+ @buckets = selector.order(:created_at.desc).limit(20)
10
+
11
+ @buckets.each do |bucket|
12
+ next if !user_signed_in? || bucket.user
13
+
14
+ # assign buckets created without login to the current logged user
15
+ bucket.update_attribute :user, current_user
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,14 @@
1
+ module ApplicationHelper
2
+ def dispatcher_route
3
+ controller_name = controller_path.gsub(/\//, "_")
4
+ "#{controller_name}##{action_name}"
5
+ end
6
+
7
+ def token_url(token)
8
+ "#{request.protocol}#{request.host_with_port}/#{token}"
9
+ end
10
+
11
+ def show_no_requests_found(bucket)
12
+ content_tag(:p, 'No requests found.')
13
+ end
14
+ end
@@ -0,0 +1,15 @@
1
+ class CreateRequest
2
+ include Interactor
3
+
4
+ delegate :bucket, :rack_request, to: :context
5
+
6
+ def call
7
+ context.request = bucket.requests.create(body: rack_request.body.read,
8
+ content_length: rack_request.content_length,
9
+ request_method: rack_request.request_method,
10
+ ip: rack_request.ip,
11
+ url: rack_request.url,
12
+ headers: FilterHeaders.call(headers: rack_request.env).headers,
13
+ params: rack_request.request_parameters)
14
+ end
15
+ end
@@ -0,0 +1,11 @@
1
+ class CreateResponse
2
+ include Interactor
3
+
4
+ delegate :bucket, :request, :built_response, to: :context
5
+
6
+ def call
7
+ built_response['request'] = request
8
+
9
+ context.response = bucket.responses.create(built_response)
10
+ end
11
+ end
@@ -0,0 +1,55 @@
1
+ class EvalResponseBuilder
2
+ include Interactor
3
+
4
+ delegate :request, to: :context
5
+
6
+ def call
7
+ v8_ctx = V8::Context.new timeout: timeout
8
+
9
+ eval_response_builder(v8_ctx)
10
+
11
+ eval_request(v8_ctx)
12
+
13
+ eval_response(v8_ctx)
14
+ rescue => e
15
+ context.built_response = { 'status' => 500,
16
+ 'headers' => { 'Content-Type' => 'text/plain' },
17
+ 'body' => e.message }
18
+ end
19
+
20
+ private
21
+
22
+ def eval_request(v8_ctx)
23
+ context.built_request = JSON.parse(v8_ctx.eval('JSON.stringify(request)'))
24
+ end
25
+
26
+ def eval_response(v8_ctx)
27
+ context.built_response = v8_ctx.eval('JSON.stringify(response)')
28
+
29
+ # filter allowed parameters
30
+ context.built_response = JSON.parse(context.built_response).select do |key, value|
31
+ %w(status headers body).include?(key) && value.to_s.present?
32
+ end
33
+ end
34
+
35
+ def initialize_response_builder_attrs(v8_ctx)
36
+ v8_ctx['response'] = { 'status' => 200,
37
+ 'headers' => {},
38
+ 'body' => 'ok' }
39
+
40
+ v8_ctx['request'] = { 'request_method' => request.request_method,
41
+ 'body' => request.body,
42
+ 'params' => request.params,
43
+ 'headers' => request.headers }
44
+ end
45
+
46
+ def eval_response_builder(v8_ctx)
47
+ initialize_response_builder_attrs(v8_ctx)
48
+
49
+ v8_ctx.eval(context.bucket.response_builder.to_s)
50
+ end
51
+
52
+ def timeout
53
+ context.timeout ||= 2500
54
+ end
55
+ end
@@ -0,0 +1,28 @@
1
+ class FilterHeaders
2
+ include Interactor
3
+
4
+ BLACKLIST_HEADERS = %w(HOST CF X-REQUEST X-FORWARDED CONNECT-TIME TOTAL-ROUTE-TIME VIA).freeze
5
+ WHITELIST_HEADERS = %w(HTTP_ CONTENT).freeze
6
+
7
+ delegate :headers, to: :context
8
+
9
+ def call
10
+ context.headers = client_supplied_headers
11
+ end
12
+
13
+ private
14
+
15
+ def client_supplied_headers
16
+ headers.to_h.each_with_object({}) do |(key, value), h|
17
+ next unless value.to_s.present?
18
+
19
+ next unless key.upcase.start_with?(*WHITELIST_HEADERS)
20
+
21
+ key = key.sub('HTTP_', '').tr('_', '-')
22
+
23
+ next if key.upcase.start_with?(*BLACKLIST_HEADERS)
24
+
25
+ h[key] = value
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,39 @@
1
+ class ForwardRequest
2
+ include Interactor
3
+
4
+ delegate :built_request, to: :context
5
+
6
+ def call
7
+ return unless forward_url = built_request.try(:[], 'forwardTo')
8
+
9
+ # use the response from the forwarded URL
10
+ context.built_response = forward_to(built_request, forward_url)
11
+ rescue => e
12
+ context.built_response = { 'status' => 500,
13
+ 'headers' => { 'Content-Type' => 'text/plain' },
14
+ 'body' => e.message }
15
+ end
16
+
17
+ private
18
+
19
+ def forward_to(built_request, forward_url)
20
+
21
+ options = { timeout: 5,
22
+ headers: built_request['headers'],
23
+ body: body }
24
+
25
+ forwarded_response = HTTParty.send(built_request['request_method'].downcase.to_sym, forward_url, options)
26
+
27
+ { 'status' => forwarded_response.code,
28
+ 'headers' => FilterHeaders.call(headers: forwarded_response.headers).headers,
29
+ 'body' => forwarded_response.body }
30
+ end
31
+
32
+ def body
33
+ if built_request['body'].is_a?(Hash)
34
+ JSON.dump(built_request['body'])
35
+ else
36
+ built_request['body'].to_s
37
+ end
38
+ end
39
+ end