putsreq 0.0.1

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 (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