gorilla_proxy 0.0.12

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 86f374477f98ffc938956f4bf21a673296373ab6
4
+ data.tar.gz: b40b64d0abdf5dc8e3026cedd797c7126e2af301
5
+ SHA512:
6
+ metadata.gz: 0ec890c924924ae90731b547e0efd79523aae5e374adcde9689b62ced96e37ca4577eba57e9f1d6e32c31b0d4529aa1314bea52a07aa81ee90bce444ccf68194
7
+ data.tar.gz: 61e5958816caefbc7519e1d2fe666f79d90266a08b876217858db1239de977a92a217267925820646782f0c18f2f94d3d4f738f6be031aa9adc1bb3284620e21
@@ -0,0 +1,20 @@
1
+ Copyright 2015 Braden Schaeffer
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,123 @@
1
+ # GorillaProxy
2
+
3
+ Configurable Rails Engine for proxying API requests to the Gorilla API.
4
+
5
+ - [Installation](#installation)
6
+ - [Configuration](#configuration)
7
+ - [CSRF Protection](#csrf-protection)
8
+ - [Routes and Proxying](#routes-and-proxying)
9
+ * [List of Routes](#list-of-routes)
10
+
11
+ ## Installation
12
+
13
+ Add it to the Gemfile using Gorilla's private gem source:
14
+
15
+ ```ruby
16
+ source 'https://TdrhpteD4VdUEx8DzQgt@gem.fury.io/gorilla/' do
17
+ gem 'gorilla_proxy'
18
+ end
19
+ ```
20
+
21
+ Then mount it in the client Rails application:
22
+
23
+ ```ruby
24
+ Rails.application.routes.draw do
25
+ mount GorillaProxy::Engine => '/'
26
+ end
27
+ ```
28
+
29
+ ## Configuration
30
+
31
+ ### Setup Application Keys
32
+
33
+ By default, the proxy will look for the following environment variables:
34
+
35
+ - `GORILLA_APP_KEY` - The application's key
36
+ - `GORILLA_APP_SECRET` - The application's secret
37
+
38
+ You should probably just put those values in the `ENV`, but, if you have to do
39
+ it manually, you can do so in an initializer:
40
+
41
+ ```ruby
42
+ GorillaProxy.configure do |c|
43
+ c.app_key = 'app-key-which-not-stored-in-the-repo'
44
+ c.app_secret = 'app-secret-which-not-stored-in-the-repo'
45
+ end
46
+ ```
47
+
48
+ ## CSRF Protection
49
+
50
+ One of the benefits of proxying the API is the added advantage of CSRF
51
+ protection natively with Rails. Mainting CSRF protected connections is really
52
+ easy, and there are only a few steps you need to follow.
53
+
54
+ 1. **Initialization** - When the user visits the page and we load the client
55
+ layout, make sure the CSRF token is stored in the typical `meta` tag
56
+ attribute in the `head`.
57
+
58
+ ```
59
+ <%= csrf_meta_tags %>
60
+ ```
61
+
62
+ 2. **AJAX Requests and `X-CSRF-Token`** - Take the value of that tag and
63
+ send it along with any AJAX requests in the `X-CSRF-Token` header. Rails
64
+ will handle validating the token.
65
+
66
+ 3. **Caching the new token** - Your AJAX request handler should also look for
67
+ a `X-CSRF-Token` in the response. Store that new token so it can be re-used
68
+ in step #2.
69
+
70
+ Here's an example:
71
+
72
+ ```javascript
73
+ // On Application load
74
+ window.csrfToken = $('meta[name="csrf-token"]').attr('content');
75
+
76
+ // Set an ajax prefilter for the CSRF Token
77
+ $.ajaxPrefilter(function(options, originalOptions, xhr) {
78
+ xhr.setRequestHeader('X-CSRF-Token', window.csrfToken);
79
+ });
80
+
81
+ // Set an ajax completion handler on the document
82
+ $(document).ajaxComplete(function(event, xhr, settings) {
83
+ var newToken = xhr.getResponseHeader('X-CSRF-Token');
84
+ if (newToken) { window.csrfToken = newToken; }
85
+ });
86
+ ```
87
+
88
+
89
+ ## Routes and Proxying
90
+
91
+ Proxying is handled by directly processing relative endpoints. For example, a
92
+ call to the app's backend like so:
93
+
94
+ ```
95
+ PUT /api/forms/1
96
+ Host: app.gorilla.io
97
+
98
+ {"name": 'New form name'}
99
+ ```
100
+
101
+ Get's translated into:
102
+
103
+ ```
104
+ PUT /forms/1
105
+ Content-Type: application/json
106
+ Accept: application/vnd.gorilla.v1+json
107
+ Host: api.gorilla.io
108
+
109
+ {"name": 'New form name'}
110
+ ```
111
+
112
+ The response from the call to the app's backend will mirror the response from
113
+ Gorilla API **exactly**.
114
+
115
+ ### List of Routes
116
+
117
+ Proxy Route | App Route | Authentication
118
+ ------------|-----------|----------------
119
+ `/api/apps/:path` | `api.gorilla.io/apps/:path` | Application Signature
120
+ `/api/:path` | `api.gorilla.io/:path` | Bearer Token
121
+ `/auth/login` | `api.gorilla.io/apps/tokens/authorize` | Application Signature
122
+ `/auth/logout` | `api.gorilla.io/apps/tokens/revoke` | Application Signature
123
+ `/auth/refresh` | `api.gorilla.io/apps/tokens/refresh` | Application Signature
@@ -0,0 +1,36 @@
1
+ begin
2
+ require 'bundler/setup'
3
+ rescue LoadError
4
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
5
+ end
6
+
7
+ APP_RAKEFILE = File.expand_path("../spec/dummy/Rakefile", __FILE__)
8
+ load 'rails/tasks/engine.rake'
9
+
10
+ Bundler::GemHelper.install_tasks
11
+
12
+ Dir[File.join(File.dirname(__FILE__), 'tasks/**/*.rake')].each {|f| load f }
13
+
14
+ require 'rspec/core'
15
+ require 'rspec/core/rake_task'
16
+
17
+ desc "Run all specs in spec directory (excluding plugin specs)"
18
+ RSpec::Core::RakeTask.new(:spec => 'app:db:test:prepare')
19
+
20
+ task :default => :spec
21
+
22
+ desc 'Build a package, create a release commit, tag it and push to fury'
23
+ task fury: :build do
24
+ `fury push pkg/gorilla_proxy-#{GorillaProxy::VERSION}.gem --as gorilla`
25
+ Rake::Task[:github_release].execute
26
+ end
27
+
28
+ desc 'Tag and push the gem to github'
29
+ task :github_release do
30
+ `bundle install`
31
+ `git add Gemfile.lock lib/gorilla_proxy/version.rb`
32
+ `git commit --message "Release v#{GorillaProxy::VERSION}"`
33
+ `git tag v#{GorillaProxy::VERSION}`
34
+ `git push`
35
+ `git push --tags`
36
+ end
@@ -0,0 +1,15 @@
1
+ /*
2
+ * This is a manifest file that'll be compiled into application.css, which will include all the files
3
+ * listed below.
4
+ *
5
+ * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
6
+ * or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path.
7
+ *
8
+ * You're free to add application-wide styles to this file and they'll appear at the bottom of the
9
+ * compiled file so the styles you add here take precedence over styles defined in any styles
10
+ * defined in the other CSS/SCSS files in this directory. It is generally better to create a new
11
+ * file per style scope.
12
+ *
13
+ *= require_tree .
14
+ *= require_self
15
+ */
@@ -0,0 +1,16 @@
1
+ module GorillaProxy
2
+ class ApiController < ::GorillaProxy::ApplicationController
3
+
4
+ before_filter :require_token!, only: [:user_proxy]
5
+
6
+ def app_proxy
7
+ res = app_client.send(proxy_method, "/apps#{proxy_path}", proxy_params)
8
+ render_api_response(res)
9
+ end
10
+
11
+ def user_proxy
12
+ res = user_client.send(proxy_method, proxy_path, proxy_params)
13
+ render_api_response(res)
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,27 @@
1
+ module GorillaProxy
2
+ class ApplicationController < ActionController::Base
3
+ include GorillaProxy::ParamsHelper,
4
+ GorillaProxy::CurrentTokenHelper,
5
+ GorillaProxy::ClientHelper,
6
+ GorillaProxy::ResponseHelper
7
+
8
+ protect_from_forgery with: :exception
9
+
10
+ rescue_from Gorilla::Error, with: :gorilla_error
11
+
12
+ def gorilla_error(error)
13
+ render_api_response(error.response)
14
+ end
15
+
16
+ def require_token!
17
+ unless current_token.token?
18
+ render json: {
19
+ error: {
20
+ code: 'token_missing',
21
+ message: 'You are not currently signed in.'
22
+ }
23
+ }, status: :unauthorized
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,38 @@
1
+ module GorillaProxy
2
+ class AuthController < ::GorillaProxy::ApplicationController
3
+
4
+ before_filter :require_token!, only: [:logout, :refresh_token]
5
+
6
+ def login
7
+ res = app_client.post('/apps/tokens/authorize', login_params)
8
+ remember_token!(res.body['token'])
9
+ render json: res.body.except('token'), status: res.status
10
+ end
11
+
12
+ def logout
13
+ res = app_client.delete('/apps/tokens/revoke', logout_params)
14
+ forget_token!
15
+ render_api_response(res)
16
+ end
17
+
18
+ def refresh
19
+ res = app_client.post('/apps/tokens/refresh', refresh_params)
20
+ remember_token!(res.body['token'])
21
+ render json: res.body.except('token'), status: res.status
22
+ end
23
+
24
+ private
25
+
26
+ def login_params
27
+ params.permit(:email, :password)
28
+ end
29
+
30
+ def logout_params
31
+ {token: current_token.token}
32
+ end
33
+
34
+ def refresh_params
35
+ {refresh_token: current_token.refresh_token}
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,34 @@
1
+ module GorillaProxy
2
+ module ClientHelper
3
+
4
+ def app_client
5
+ @app_client ||= begin
6
+ Gorilla::Client.new(application_config) do |conn|
7
+ conn.response :http_exceptions
8
+ end
9
+ end
10
+ end
11
+
12
+ def user_client
13
+ @user_client ||= begin
14
+ Gorilla::VanillaClient.new(application_config) do |conn, options|
15
+ conn.request :bearer_token, bearer_token
16
+ conn.response :http_exceptions
17
+ end
18
+ end
19
+ end
20
+
21
+ private
22
+
23
+ def application_config
24
+ {
25
+ key: GorillaProxy.configuration.app_key,
26
+ secret: GorillaProxy.configuration.app_secret
27
+ }
28
+ end
29
+
30
+ def bearer_token
31
+ current_token.token
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,31 @@
1
+ module GorillaProxy
2
+ module CurrentTokenHelper
3
+
4
+ def gorilla_token
5
+ cookies.signed[token_session_key]
6
+ end
7
+
8
+ def remember_token!(token)
9
+ @current_token = nil
10
+ cookies.signed[token_session_key] = {
11
+ value: token,
12
+ expires: 1.year.from_now
13
+ }
14
+ end
15
+
16
+ def forget_token!
17
+ cookies.delete(token_session_key)
18
+ @current_token = nil
19
+ end
20
+
21
+ def current_token
22
+ @current_token ||= GorillaProxy::Token.new(gorilla_token)
23
+ end
24
+
25
+ private
26
+
27
+ def token_session_key
28
+ GorillaProxy.configuration.token_session_key
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,26 @@
1
+ module GorillaProxy
2
+ module ParamsHelper
3
+
4
+ EXCEPT_PARAMS = %i{proxy_path controller action}
5
+
6
+ def proxy_path
7
+ '/' + params[:proxy_path].to_s.gsub(/^\//, '')
8
+ end
9
+
10
+ def proxy_method
11
+ request.request_method.downcase
12
+ end
13
+
14
+ def proxy_params
15
+ params.except(*EXCEPT_PARAMS).tap do |prepped|
16
+ prepped.delete(controller_param_namespace)
17
+ end
18
+ end
19
+
20
+ private
21
+
22
+ def controller_param_namespace
23
+ params[:controller].split('/').last
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,9 @@
1
+ module GorillaProxy
2
+ module ResponseHelper
3
+
4
+ def render_api_response(api_response)
5
+ response.headers['X-CSRF-Token'] = form_authenticity_token
6
+ render json: api_response.body, status: api_response.status
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,13 @@
1
+ module ActionDispatch
2
+ module Http
3
+ class UploadedFile
4
+ def length
5
+ @tempfile.size
6
+ end
7
+
8
+ def local_path
9
+ @tempfile.path
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,15 @@
1
+ GorillaProxy::Engine.routes.draw do
2
+
3
+ constraints format: :json do
4
+ scope path: 'auth' do
5
+ post :login, to: 'auth#login'
6
+ delete :logout, to: 'auth#logout'
7
+ post :refresh, to: 'auth#refresh'
8
+ end
9
+
10
+ with_options via: [:get, :put, :post, :delete] do |proxy|
11
+ proxy.match '/api/apps/*proxy_path', to: 'api#app_proxy'
12
+ proxy.match '/api/*proxy_path', to: 'api#user_proxy'
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,25 @@
1
+ require 'configurations'
2
+ require 'gorilla-io'
3
+ require 'active_model'
4
+
5
+ require 'gorilla_proxy/faraday/bearer_token_middleware'
6
+ require 'gorilla_proxy/token'
7
+
8
+ require 'gorilla_proxy/engine'
9
+
10
+ module GorillaProxy
11
+ include Configurations
12
+
13
+ configurable :app_key
14
+ configurable :app_secret
15
+ configurable :token_session_key
16
+
17
+ configuration_defaults do |c|
18
+ c.app_key = ENV['GORILLA_APP_KEY']
19
+ c.app_secret = ENV['GORILLA_APP_SECRET']
20
+ c.token_session_key = 'gorilla_proxy_token'
21
+ end
22
+
23
+ ::Faraday::Request.register_middleware \
24
+ bearer_token: GorillaProxy::Faraday::BearerTokenMiddleware
25
+ end
@@ -0,0 +1,9 @@
1
+ module GorillaProxy
2
+ class Engine < ::Rails::Engine
3
+ isolate_namespace GorillaProxy
4
+
5
+ config.generators do |g|
6
+ g.test_framework :rspec
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,16 @@
1
+ module GorillaProxy
2
+ module Faraday
3
+ class BearerTokenMiddleware < ::Faraday::Middleware
4
+
5
+ def initialize(app, token)
6
+ super(app)
7
+ @token = token
8
+ end
9
+
10
+ def call(env)
11
+ env[:request_headers]['Authorization'] = "Bearer #{@token}"
12
+ @app.call(env)
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,16 @@
1
+ module GorillaProxy
2
+ class Token
3
+ include ::ActiveModel::Model
4
+
5
+ attr_accessor :token, :refresh_token
6
+ attr_reader :expires_at
7
+
8
+ def expires_at=(time_string)
9
+ @expires_at = Time.parse(time_string)
10
+ end
11
+
12
+ def token?
13
+ token.present?
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,3 @@
1
+ module GorillaProxy
2
+ VERSION = "0.0.12"
3
+ end
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :gorilla_proxy do
3
+ # # Task goes here
4
+ # end
metadata ADDED
@@ -0,0 +1,133 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: gorilla_proxy
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.12
5
+ platform: ruby
6
+ authors:
7
+ - Braden Schaeffer
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-05-29 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rails
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 4.2.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 4.2.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: gorilla-io
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 0.0.7
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 0.0.7
41
+ - !ruby/object:Gem::Dependency
42
+ name: configurations
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec-rails
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '3.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '3.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: gemfury
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ description: Proxies requests to the Gorilla.io API using the Gorilla Ruby Client.
84
+ email:
85
+ - braden.schaeffer@gmail.com
86
+ executables: []
87
+ extensions: []
88
+ extra_rdoc_files: []
89
+ files:
90
+ - MIT-LICENSE
91
+ - README.md
92
+ - Rakefile
93
+ - app/assets/stylesheets/gorilla_proxy/application.css
94
+ - app/controllers/gorilla_proxy/api_controller.rb
95
+ - app/controllers/gorilla_proxy/application_controller.rb
96
+ - app/controllers/gorilla_proxy/auth_controller.rb
97
+ - app/helpers/gorilla_proxy/client_helper.rb
98
+ - app/helpers/gorilla_proxy/current_token_helper.rb
99
+ - app/helpers/gorilla_proxy/params_helper.rb
100
+ - app/helpers/gorilla_proxy/response_helper.rb
101
+ - config/initializers/faraday_action_dispatch.rb
102
+ - config/routes.rb
103
+ - lib/gorilla_proxy.rb
104
+ - lib/gorilla_proxy/engine.rb
105
+ - lib/gorilla_proxy/faraday/bearer_token_middleware.rb
106
+ - lib/gorilla_proxy/token.rb
107
+ - lib/gorilla_proxy/version.rb
108
+ - lib/tasks/gorilla_proxy_tasks.rake
109
+ homepage: https://github.com/thinkmechanic/gorilla_proxy
110
+ licenses:
111
+ - MIT
112
+ metadata: {}
113
+ post_install_message:
114
+ rdoc_options: []
115
+ require_paths:
116
+ - lib
117
+ required_ruby_version: !ruby/object:Gem::Requirement
118
+ requirements:
119
+ - - ">="
120
+ - !ruby/object:Gem::Version
121
+ version: '0'
122
+ required_rubygems_version: !ruby/object:Gem::Requirement
123
+ requirements:
124
+ - - ">="
125
+ - !ruby/object:Gem::Version
126
+ version: '0'
127
+ requirements: []
128
+ rubyforge_project:
129
+ rubygems_version: 2.4.3
130
+ signing_key:
131
+ specification_version: 4
132
+ summary: Proxies requests to the Gorilla.io API.
133
+ test_files: []