putsreq 0.0.3 → 0.0.4

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 (141) hide show
  1. checksums.yaml +5 -5
  2. data/.babelrc +26 -0
  3. data/.codeclimate.yml +29 -5
  4. data/.env.docker +6 -0
  5. data/.eslintignore +4 -0
  6. data/.eslintrc +22 -0
  7. data/.gitignore +8 -0
  8. data/.postcssrc.yml +3 -0
  9. data/.prettierrc +4 -0
  10. data/.reek +12 -0
  11. data/.rubocop.yml +47 -25
  12. data/.ruby-version +1 -1
  13. data/.simplecov +6 -0
  14. data/.travis.yml +38 -4
  15. data/Dockerfile +44 -0
  16. data/Gemfile +40 -61
  17. data/Gemfile.lock +294 -186
  18. data/Procfile +1 -1
  19. data/README.md +51 -46
  20. data/Rakefile +1 -1
  21. data/{public → app/assets}/images/logo.png +0 -0
  22. data/app/assets/javascripts/application.js +1 -1
  23. data/app/assets/javascripts/buckets.js.coffee +1 -21
  24. data/app/assets/stylesheets/{application.css → application.scss} +2 -1
  25. data/app/assets/stylesheets/buckets.css.scss +0 -2
  26. data/app/controllers/application_controller.rb +11 -9
  27. data/app/controllers/buckets_controller.rb +24 -18
  28. data/app/controllers/home_controller.rb +5 -5
  29. data/app/controllers/requests_controller.rb +13 -2
  30. data/app/helpers/application_helper.rb +6 -2
  31. data/app/interactors/create_or_retrieve_bucket.rb +17 -0
  32. data/app/interactors/create_request.rb +25 -7
  33. data/app/interactors/eval_response_builder.rb +9 -9
  34. data/app/interactors/filter_headers.rb +3 -3
  35. data/app/interactors/forward_request.rb +4 -4
  36. data/app/interactors/record_request.rb +1 -1
  37. data/app/interactors/track.rb +44 -0
  38. data/app/javascript/actionTypes.js +7 -0
  39. data/app/javascript/actions/index.js +64 -0
  40. data/app/javascript/components/Bucket.jsx +91 -0
  41. data/app/javascript/components/Pagination.jsx +67 -0
  42. data/app/javascript/components/RequestCount.jsx +21 -0
  43. data/app/javascript/components/request/Header.jsx +31 -0
  44. data/app/javascript/components/request/Response.jsx +28 -0
  45. data/app/javascript/components/request/index.jsx +47 -0
  46. data/app/javascript/packs/application.js +25 -0
  47. data/app/javascript/packs/hello_react.jsx +26 -0
  48. data/app/javascript/reducers/index.js +23 -0
  49. data/app/javascript/request_poller.js +19 -0
  50. data/app/javascript/store.js +9 -0
  51. data/app/models/bucket.rb +16 -10
  52. data/app/models/request.rb +2 -3
  53. data/app/models/user.rb +2 -2
  54. data/app/serializers/bucket_serializer.rb +11 -0
  55. data/app/serializers/request_serializer.rb +69 -0
  56. data/app/views/buckets/_buttons.html.erb +3 -3
  57. data/app/views/buckets/_form.html.erb +6 -6
  58. data/app/views/buckets/_readonly_buttons.html.erb +1 -1
  59. data/app/views/buckets/show.html.erb +12 -25
  60. data/app/views/home/index.html.erb +22 -16
  61. data/app/views/layouts/application.html.erb +21 -22
  62. data/app/views/layouts/devise.html.erb +16 -18
  63. data/app/views/shared/_flash.html.erb +3 -1
  64. data/bin/byebug +21 -0
  65. data/bin/cc-tddium-post-worker +21 -0
  66. data/bin/codeclimate-test-reporter +21 -0
  67. data/bin/coderay +21 -0
  68. data/bin/dotenv +21 -0
  69. data/bin/htmldiff +21 -0
  70. data/bin/httparty +21 -0
  71. data/bin/httpclient +21 -0
  72. data/bin/ldiff +21 -0
  73. data/bin/mongo_console +21 -0
  74. data/bin/nokogiri +21 -0
  75. data/bin/pry +21 -0
  76. data/bin/putsreq +18 -71
  77. data/bin/rackup +21 -0
  78. data/bin/rails +1 -1
  79. data/bin/ri +21 -0
  80. data/bin/rollbar-rails-runner +21 -0
  81. data/bin/rspec +10 -5
  82. data/bin/safe_yaml +21 -0
  83. data/bin/sass +21 -0
  84. data/bin/sass-convert +21 -0
  85. data/bin/scss +21 -0
  86. data/bin/sdoc +21 -0
  87. data/bin/sdoc-merge +21 -0
  88. data/bin/setup +38 -0
  89. data/bin/sprockets +21 -0
  90. data/bin/thor +21 -0
  91. data/bin/tilt +21 -0
  92. data/bin/unicorn +21 -0
  93. data/bin/unicorn_rails +21 -0
  94. data/bin/update +29 -0
  95. data/bin/webpack +15 -0
  96. data/bin/webpack-dev-server +15 -0
  97. data/bin/yarn +11 -0
  98. data/config/application.rb +6 -4
  99. data/config/boot.rb +1 -1
  100. data/config/environment.rb +1 -1
  101. data/config/environments/development.rb +7 -3
  102. data/config/environments/production.rb +5 -2
  103. data/config/environments/test.rb +3 -1
  104. data/config/initializers/devise.rb +2 -2
  105. data/config/initializers/rack_attack.rb +24 -0
  106. data/config/initializers/rollbar.rb +58 -0
  107. data/config/initializers/setup_email.rb +7 -7
  108. data/config/mongoid.yml +2 -2
  109. data/config/newrelic.yml +45 -0
  110. data/config/puma.rb +15 -0
  111. data/config/routes.rb +2 -0
  112. data/config/webpack/development.js +5 -0
  113. data/config/webpack/environment.js +3 -0
  114. data/config/webpack/production.js +5 -0
  115. data/config/webpack/test.js +5 -0
  116. data/config/webpacker.yml +70 -0
  117. data/docker-compose.yml +25 -0
  118. data/lib/putsreq/cli_helper.rb +114 -0
  119. data/lib/putsreq/version.rb +1 -1
  120. data/package.json +30 -0
  121. data/putsreq.gemspec +6 -7
  122. data/spec/controllers/buckets_controller_spec.rb +54 -46
  123. data/spec/interactors/create_or_retrieve_bucket_spec.rb +25 -0
  124. data/spec/interactors/create_request_spec.rb +11 -8
  125. data/spec/interactors/create_response_spec.rb +1 -1
  126. data/spec/interactors/eval_response_builder_spec.rb +14 -17
  127. data/spec/interactors/forward_request_spec.rb +4 -4
  128. data/spec/lib/putsreq/cli_helper_spec.rb +114 -0
  129. data/spec/models/bucket_spec.rb +3 -3
  130. data/spec/spec_helper.rb +25 -25
  131. data/yarn.lock +7043 -0
  132. metadata +85 -20
  133. data/.hound.yml +0 -14
  134. data/app/interactors/notify_count.rb +0 -15
  135. data/app/models/.keep +0 -0
  136. data/config/initializers/redis.rb +0 -17
  137. data/config/unicorn.rb +0 -16
  138. data/lib/assets/.keep +0 -0
  139. data/public/images/.keep +0 -0
  140. data/vendor/assets/javascripts/.keep +0 -0
  141. data/vendor/assets/stylesheets/.keep +0 -0
data/Procfile CHANGED
@@ -1 +1 @@
1
- web: bundle exec unicorn -p $PORT -c ./config/unicorn.rb
1
+ web: bundle exec puma -C config/puma.rb
data/README.md CHANGED
@@ -10,53 +10,27 @@ Check this post: [Play Rock-paper-scissors with Slack and PutsReq](http://www.pa
10
10
 
11
11
  ### Getting Started
12
12
 
13
- Steps to run PutsReq in development.
14
-
15
- #### Install MongoDB
16
-
17
- ```bash
18
- brew install mongo
19
-
20
- mongod
21
- ```
22
-
23
- #### Start PutsReq
24
-
25
- ```
26
- cd ~/workspace
27
-
28
- git clone git@github.com:phstc/putsreq.git
29
-
30
- cd putsreq
31
-
32
- bundle install
33
-
34
- rails s
35
-
36
- open http://localhost:3000
37
- ```
38
-
39
13
  ### Response Builder
40
14
 
41
15
  The Response Builder is the place where you can create your responses using JavaScript V8.
42
16
 
43
- Here is the list of request attributes you can access to create your responses:
17
+ Check the list below with the request attributes you can access to create your own responses:
44
18
 
45
19
  #### request
46
20
 
47
21
  ```javascript
48
22
  // curl -X POST -H 'X-MyHeader: MyHeaderValue' -d 'name=Pablo' https://putsreq.com/<YOUR-TOKEN>
49
23
 
50
- request.request_method;
24
+ request.request_method
51
25
  // => POST
52
26
 
53
- request.body;
27
+ request.body
54
28
  // => name=Pablo
55
29
 
56
- request.params.name;
30
+ request.params.name
57
31
  // => Pablo
58
32
 
59
- request.headers['HTTP_X_MYHEADER'];
33
+ request.headers['HTTP_X_MYHEADER']
60
34
  // => MyHeaderValue
61
35
  ```
62
36
 
@@ -65,55 +39,55 @@ Parsing a JSON request:
65
39
  ```javascript
66
40
  // curl -i -X POST -H 'Content-Type: application/json' -d '{"message":"Hello World"}' https://putsreq.com/<YOUR-TOKEN>
67
41
 
68
- var parsedBody = JSON.parse(request.body);
42
+ var parsedBody = JSON.parse(request.body)
69
43
 
70
- parsedBody.message;
44
+ parsedBody.message
71
45
  // => Hello World
72
46
  ```
73
47
 
74
48
  #### response
75
49
 
76
50
  ```javascript
77
- response.status = 200; // default value
78
- response.headers = {}; // default value
79
- response.body = 'ok'; // default value
51
+ response.status = 200 // default value
52
+ response.headers = {} // default value
53
+ response.body = 'ok' // default value
80
54
  ```
81
55
 
82
56
  Returning a JSON response:
83
57
 
84
58
  ```javascript
85
- response.headers['Content-Type'] = 'application/json';
59
+ response.headers['Content-Type'] = 'application/json'
86
60
 
87
- response.body = { 'message': 'Hello World' };
61
+ response.body = { message: 'Hello World' }
88
62
  ```
89
63
 
90
64
  #### forwardTo
91
65
 
92
- If you only want to log your requests, you can use PutsReq as a proxy to forward them.
66
+ If you only want to log your requests, you can use PutsReq just as a proxy for your requests.
93
67
 
94
68
  ```javascript
95
- request.forwardTo = 'http://example.com/api';
69
+ request.forwardTo = 'http://example.com/api'
96
70
  ```
97
71
 
98
- You can also modify the requests before forwarding them.
72
+ But you can always modify requests before forwarding them.
99
73
 
100
74
  ```javascript
101
75
  // add or change a header
102
76
  request.headers['X-MyNewHeader'] = 'MyHeaderValue'
103
77
 
104
- var parsedBody = JSON.parse(request.body);
78
+ var parsedBody = JSON.parse(request.body)
105
79
 
106
80
  // add or change a value
107
- parsedBody['my_new_key'] = 'my new value';
81
+ parsedBody['my_new_key'] = 'my new value'
108
82
 
109
- request.body = parsedBody;
83
+ request.body = parsedBody
110
84
 
111
- request.forwardTo = 'http://example.com/api';
85
+ request.forwardTo = 'http://example.com/api'
112
86
  ```
113
87
 
114
88
  ### CLI
115
89
 
116
- Want to test Webhook calls against your localhost? PutsReq makes it easy!
90
+ Do want to test Webhook calls against your localhost? PutsReq makes it easy!
117
91
 
118
92
  You can think of it, as a kind of [ngrok](http://ngrok.io), but instead of creating a tunnel to your localhost, PutsReq polls requests from `YOUR-PUTSREQ-TOKEN` and forwards to your localhost.
119
93
 
@@ -159,6 +133,37 @@ PutsReq supports [CORS](https://en.wikipedia.org/wiki/Cross-origin_resource_shar
159
133
 
160
134
  https://github.com/phstc/putsreq_integration_sample
161
135
 
136
+ ### Steps to run PutsReq in development
137
+
138
+ For following the instructions below, you will need to install [Docker](https://www.docker.com/get-docker).
139
+
140
+ ```shell
141
+ cd ~/workspace
142
+
143
+ git clone git@github.com:phstc/putsreq.git
144
+
145
+ docker-compose up -d
146
+
147
+ open http://localhost:3000
148
+
149
+ docker-compose logs --follow --tail=100 app
150
+ ```
151
+
152
+ #### Running tests
153
+
154
+ ```shell
155
+ docker-compose run app bundle exec rspec
156
+ ```
157
+
158
+ ### Production
159
+
160
+ In production (Heroku), PutsReq runs on mLab sandbox, with a storage of 500 MB. For avoiding exceeding the capacity, the `requests` and `responses` collections must be converted into capped collections.
161
+
162
+ ```javascript
163
+ db.runCommand({ convertToCapped: 'requests', size: 15000000 })
164
+ db.runCommand({ convertToCapped: 'responses', size: 15000000 })
165
+ ```
166
+
162
167
  ### License
163
168
 
164
169
  Please see [LICENSE](https://github.com/phstc/putsreq/blob/master/LICENSE) for licensing details.
data/Rakefile CHANGED
@@ -1,7 +1,7 @@
1
1
  # Add your own tasks in files placed in lib/tasks ending in .rake,
2
2
  # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
3
3
 
4
- require File.expand_path('../config/application', __FILE__)
4
+ require File.expand_path('config/application', __dir__)
5
5
 
6
6
  PutsReq::Application.load_tasks
7
7
 
File without changes
@@ -15,7 +15,7 @@
15
15
  //= require bootstrap
16
16
  //= require jquery.tipsy
17
17
  //= require clipboard
18
- //= require favico.js
18
+ //= require favico.js.js
19
19
  //
20
20
  //= require ace/ace
21
21
  //= require ace/theme-chrome
@@ -2,7 +2,6 @@ App.buckets = {}
2
2
 
3
3
  App.buckets['share'] = App.buckets['show'] = ->
4
4
  App.buckets.initializeAce()
5
- RequestCountPoller.start()
6
5
 
7
6
  tipsyConfig = title: 'Copy to Clipboard', copiedHint: 'Copied!'
8
7
 
@@ -14,7 +13,7 @@ App.buckets['share'] = App.buckets['show'] = ->
14
13
  clipboard.on 'success', ->
15
14
  $copyButton.prop('title', tipsyConfig.copiedHint).tipsy('show')
16
15
  $copyButton.attr('original-title', tipsyConfig.title)
17
-
16
+
18
17
  App.buckets.initializeAce = ->
19
18
  autoResizeAce = ->
20
19
  # http://stackoverflow.com/questions/11584061/
@@ -47,22 +46,3 @@ App.buckets.initializeAce = ->
47
46
  # Whenever a change happens inside the ACE editor, update
48
47
  # the size again
49
48
  editor.getSession().on 'change', autoResizeAce
50
-
51
- RequestCountPoller =
52
- start: ->
53
- favicon = new Favico(bgColor: '#6C92C8', animation: 'none')
54
- favicon.badge($('#bucket-request-count').text())
55
-
56
- bucket = $('#putsreq-url-input').data('bucket-token')
57
-
58
- pusher = new Pusher('3466d56fe2ef1fdd2943')
59
- channel = pusher.subscribe("channel_requests_#{bucket}")
60
- channel.bind 'new', (data) ->
61
- try
62
- $('#bucket-request-count').text(data.count)
63
-
64
- favicon.badge(data.count)
65
- catch error
66
-
67
- $('#new-requests-info').hide().
68
- html('<em><a id="new-requests-received" href="javascript:window.location.reload();">New requests found. Load newer requests?</a></em>').fadeIn('slow')
@@ -8,8 +8,9 @@
8
8
  * You're free to add application-wide styles to this file and they'll appear at the top of the
9
9
  * compiled file, but it's generally better to create a new file per style scope.
10
10
  *
11
- *= require bootstrap
12
11
  *= require tipsy
13
12
  *= require_self
14
13
  *= require_tree .
15
14
  */
15
+ @import "bootstrap-sprockets";
16
+ @import "bootstrap";
@@ -64,9 +64,7 @@
64
64
  }
65
65
  .requests-header tbody tr:hover td{background:#d0dafd;}
66
66
  .history {
67
- float: right;
68
67
  background-color: #eee;
69
- margin: 0 0 0 20px;
70
68
  padding: 10px;
71
69
  border-left: 3px solid #428bca;
72
70
  }
@@ -1,9 +1,7 @@
1
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
2
  protect_from_forgery with: :exception
5
3
 
6
- helper_method :owner?, :body_as_string, :headers_as_string
4
+ helper_method :bucket, :owner?, :body_as_string, :headers_as_string
7
5
 
8
6
  before_action :configure_permitted_parameters, if: :devise_controller?
9
7
 
@@ -54,6 +52,8 @@ class ApplicationController < ActionController::Base
54
52
  end
55
53
 
56
54
  def owner?(bucket)
55
+ return true unless bucket.user
56
+
57
57
  owner_token == bucket.owner_token || (user_signed_in? && bucket.user == current_user)
58
58
  end
59
59
 
@@ -62,14 +62,16 @@ class ApplicationController < ActionController::Base
62
62
  end
63
63
 
64
64
  def bucket
65
- @bucket ||= Bucket.find_by(token: params[:token])
65
+ @_bucket ||= CreateOrRetrieveBucket.call!(
66
+ token: params[:token],
67
+ owner_token: owner_token,
68
+ user_id: (current_user.id if user_signed_in?)
69
+ ).bucket
66
70
  end
67
71
 
68
72
  def configure_permitted_parameters
69
- devise_parameter_sanitizer.for(:sign_up) { |u| u.permit(:name, :email, :password, :password_confirmation, :remember_me) }
70
- devise_parameter_sanitizer.for(:sign_in) { |u| u.permit(:name, :email, :password, :remember_me) }
71
- devise_parameter_sanitizer.for(:account_update) do |u|
72
- u.permit(:name, :email, :password, :password_confirmation, :current_password)
73
- end
73
+ devise_parameter_sanitizer.permit(:sign_up, keys: %i[name email password password_confirmation remember_me])
74
+ devise_parameter_sanitizer.permit(:sign_in, keys: %i[name email password remember_me])
75
+ devise_parameter_sanitizer.permit(:account_update, keys: %i[name email password password_confirmation current_password])
74
76
  end
75
77
  end
@@ -1,24 +1,25 @@
1
1
  class BucketsController < ApplicationController
2
2
  skip_before_action :verify_authenticity_token, only: :record
3
3
 
4
- before_filter :check_ownership!, only: %i(clear destroy update)
4
+ before_action :check_ownership!, only: %i[clear destroy update]
5
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)
6
+ def requests_count
7
+ render json: { requests_count: bucket.requests.count }
8
+ end
11
9
 
10
+ def create
12
11
  redirect_to bucket_path(bucket.token)
13
12
  end
14
13
 
15
14
  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)
15
+ fork = Bucket.create(
16
+ owner_token: owner_token,
17
+ response_builder: bucket.response_builder,
18
+ name: "Copy of #{bucket.name}",
19
+ fork: bucket
20
+ )
21
+
22
+ redirect_to bucket_path(fork.token)
22
23
  end
23
24
 
24
25
  def clear
@@ -34,14 +35,19 @@ class BucketsController < ApplicationController
34
35
  end
35
36
 
36
37
  def show
37
- @requests = bucket.requests.page(params[:page]).per 1
38
+ bucket.request = bucket.requests.page(params[:page]).per(1).first
39
+
40
+ respond_to do |format|
41
+ format.html { render }
42
+ format.json { render json: bucket, serializer: BucketSerializer }
43
+ end
38
44
  end
39
45
 
40
46
  def update
41
47
  update_bucket = bucket_params
42
48
  update_bucket[:user_id] = current_user.id if user_signed_in?
43
49
 
44
- bucket.update_attributes update_bucket
50
+ bucket.update update_bucket
45
51
 
46
52
  redirect_to bucket_path(bucket.token)
47
53
  end
@@ -50,7 +56,7 @@ class BucketsController < ApplicationController
50
56
  return render_request_not_found unless last_request = bucket.last_request
51
57
 
52
58
  respond_to do |format|
53
- format.html { render text: last_request.body }
59
+ format.html { render plain: last_request.body }
54
60
  format.json { render json: JSON.pretty_generate(last_request.attributes) }
55
61
  end
56
62
  end
@@ -59,7 +65,7 @@ class BucketsController < ApplicationController
59
65
  return render_request_not_found unless last_response = bucket.last_response
60
66
 
61
67
  respond_to do |format|
62
- format.html { render text: last_response.body }
68
+ format.html { render plain: last_response.body }
63
69
  format.json { render json: JSON.pretty_generate(last_response.attributes) }
64
70
  end
65
71
  end
@@ -70,7 +76,7 @@ class BucketsController < ApplicationController
70
76
 
71
77
  response.headers.merge! recorded_response.headers.to_h
72
78
 
73
- render text: body_as_string(recorded_response),
79
+ render plain: body_as_string(recorded_response),
74
80
  status: recorded_response.status
75
81
  end
76
82
 
@@ -79,7 +85,7 @@ class BucketsController < ApplicationController
79
85
  def render_request_not_found
80
86
  respond_to do |format|
81
87
  format.html { redirect_to bucket_path(bucket.token), alert: 'Please submit a request first' }
82
- format.json { render nothing: true, status: 404 }
88
+ format.json { head :not_found }
83
89
  end
84
90
  end
85
91
 
@@ -1,10 +1,10 @@
1
1
  class HomeController < ApplicationController
2
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
3
+ selector = if user_signed_in?
4
+ Bucket.or([user: current_user], [owner_token: owner_token])
5
+ else
6
+ Bucket.where(owner_token: owner_token)
7
+ end
8
8
 
9
9
  @buckets = selector.order(:created_at.desc).limit(20)
10
10
 
@@ -1,10 +1,21 @@
1
1
  class RequestsController < ApplicationController
2
+ def index
3
+ bucket = Bucket.find_by(token: params[:token])
4
+
5
+ requests = bucket.requests
6
+ requests = requests.gt(id: params[:last_request_id]) if params[:last_request_id].present?
7
+ requests = requests.limit(25).order(:id.asc)
8
+ requests = requests.map(&:attributes)
9
+
10
+ render json: JSON.generate(requests)
11
+ end
12
+
2
13
  def show
3
14
  request = Request.find(params[:id])
4
15
 
5
16
  respond_to do |format|
6
- format.html { render text: request.body }
17
+ format.html { render plain: request.body }
7
18
  format.json { render json: JSON.pretty_generate(request.attributes) }
8
19
  end
9
20
  end
10
- end
21
+ end
@@ -1,6 +1,6 @@
1
1
  module ApplicationHelper
2
2
  def dispatcher_route
3
- controller_name = controller_path.gsub(/\//, "_")
3
+ controller_name = controller_path.gsub(/\//, '_')
4
4
  "#{controller_name}##{action_name}"
5
5
  end
6
6
 
@@ -8,7 +8,11 @@ module ApplicationHelper
8
8
  "#{request.protocol}#{request.host_with_port}/#{token}"
9
9
  end
10
10
 
11
- def show_no_requests_found(bucket)
11
+ def show_no_requests_found(_bucket)
12
12
  content_tag(:p, 'No requests found.')
13
13
  end
14
+
15
+ def requests_recorded
16
+ number_with_delimiter(Rails.cache.fetch('requests_recorded', raw: true) { 0 })
17
+ end
14
18
  end