gorilla_proxy 0.0.12

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.
@@ -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: []