putsreq 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
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