keycard 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 04e5999db1a74c237714b9c8afae5bca2ac11c0c33bc8d56c174967082331ee7
4
- data.tar.gz: db2486afcc74b2777fb74f0ce02fd6f6c3499c69823d39af9db7bd4403d31bb7
3
+ metadata.gz: 5ba441d104509e55f853e1003f6dd2d8c39f362e5e93ee619b0dd9378f8c13b8
4
+ data.tar.gz: 0d503c7e8c4682348e2c6d1ba9d9d0425fdf61429a278882368bad5cb19c4823
5
5
  SHA512:
6
- metadata.gz: 671cff5c7be3e97ff2b4325ff94786f3dbb3d82ffb03e5efd015bf95a8e73a1d9c92a34ca47aa8c2eaf124bea691d0560f765ee854db4fa2e5127b3e4484f160
7
- data.tar.gz: 7ebe3ac9d5019acd351fc63f430e65c52e7d711db036713db96fc9be5b8c962013d7808bb4f3f5c1993b7f2526ad95719ab3733b628abf9c33b2d6ede48f8fdc
6
+ metadata.gz: 578ff3eb3e114a3060b0236f6c471fabf45e947b1f2184828f68206eab35071bfa182482cfbab4e9a1750a48e2e127d1aa4e4feda050a11e53c1937ad0778837
7
+ data.tar.gz: a268b75e7207d0de7626b8f675567eddce0c070158343e2f55d424c6868c06837bfcd03c0be68a3ff8b1edc42aa5798df7d3b59cbadb5b00bea1173a0e855e6d
data/README.md CHANGED
@@ -37,9 +37,44 @@ And then execute:
37
37
 
38
38
  $ bundle
39
39
 
40
- Or install it yourself as:
40
+ ## Configuration
41
41
 
42
- $ gem install keycard
42
+ There are two aspects of Keycard that are configurable: the database for IP
43
+ ranges as they map to institutions (IP blocks map to networks, and networks are
44
+ associated with institutions), and the access mode (whether your application is
45
+ served directly or behind a reverse proxy). These will be unified eventually,
46
+ but for now, they are configured separately.
47
+
48
+ ## For the Database
49
+
50
+ For the database, there is a Railtie that, when running in a Rails app,
51
+ attempts to use the same connection information as ActiveRecord. If you are
52
+ running in this configuration, you will need to run a `rake db:migrate` to
53
+ create the Keycard tables and add them to your `db/schema.rb`. From there forward,
54
+ running `db:setup` or `db:schema:load` will create these tables for you. There is
55
+ a `keycard:migrate` Rake task if you want to run it separately, but it hooks into
56
+ the Rails `db:migrate` by default for convenience.
57
+
58
+ If you need to customize the database configuration, which will be typical for
59
+ at least the production environment, the easiest way is to define an
60
+ initializer. In a multi-application environment, the database may be read-only,
61
+ which will require the `Keycard::DB.config` to have its `readonly` property set
62
+ to `true`. You can also set either the `Keycard::DB.config.opts` to the options
63
+ to pass to the Sequel connection or set `Keycard::DB.config.url` to use a
64
+ connction string. The latter is equivalent to setting the `KEYCARD_DATABASE_URL`
65
+ environment variable.
66
+
67
+ ## For the Access Mode
68
+
69
+ To extract the username and client IP from each request, Keycard must be
70
+ configured for an "access mode". This can be set in an initializer, under the
71
+ `Keycard.config.access` property, and should be either `:direct` if clients
72
+ will make HTTP requests directly to the Ruby webserver, or `:proxy` if a
73
+ reverse proxy will be used.
74
+
75
+ Under the hood, these modes amount to using either `REMOTE_USER` and
76
+ `REMOTE_ADDR` in the environment set by the Ruby webserver for direct mode or
77
+ the `X-Forwarded-User` and `X-Forwarded-For` headers set by a reverse proxy.
43
78
 
44
79
  ## License
45
80
 
data/keycard.gemspec CHANGED
@@ -25,7 +25,6 @@ Gem::Specification.new do |spec|
25
25
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
26
26
  spec.require_paths = ["lib"]
27
27
 
28
- spec.add_dependency "mysql2"
29
28
  spec.add_dependency "sequel"
30
29
 
31
30
  spec.add_development_dependency "bundler", "~> 1.16"
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Keycard
4
+ # This request wrapper should be used when the application will serve HTTP
5
+ # requests directly or through a proxy that sets up the usual environment.
6
+ class DirectRequest < SimpleDelegator
7
+ def self.for(request)
8
+ new(request)
9
+ end
10
+
11
+ def username
12
+ env['REMOTE_USER'] || ''
13
+ end
14
+
15
+ def client_ip
16
+ (env['REMOTE_ADDR'] || '').split(',').first || ''
17
+ end
18
+ end
19
+ end
@@ -26,7 +26,7 @@ module Keycard
26
26
  end
27
27
 
28
28
  def attributes_for(request)
29
- return {} unless (numeric_ip = numeric_ip(request.remote_ip))
29
+ return {} unless (numeric_ip = numeric_ip(request.client_ip))
30
30
 
31
31
  insts = insts_for_ip(numeric_ip)
32
32
 
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Keycard
4
+ # This request wrapper should be used when the application will be served
5
+ # behind a reverse proxy. It relies on the trusted relationship with the
6
+ # proxy to use HTTP headers for forwarded values.
7
+ #
8
+ # The typical headers forwarded are X-Forwarded-User and X-Forwarded-For,
9
+ # which, somewhat confusingly, are transposed into HTTP_X_REMOTE_USER and
10
+ # HTTP_X_FORWARDED_FOR once the Rack request is assembled.
11
+ class ProxiedRequest < SimpleDelegator
12
+ def self.for(request)
13
+ new(request)
14
+ end
15
+
16
+ def username
17
+ env['HTTP_X_REMOTE_USER'] || ''
18
+ end
19
+
20
+ def client_ip
21
+ (env['HTTP_X_FORWARDED_FOR'] || '').split(',').first || ''
22
+ end
23
+ end
24
+ end
@@ -66,9 +66,14 @@ module Keycard
66
66
  initializer "keycard.before_initializers", before: :load_config_initializers do
67
67
  config = Keycard::DB.config
68
68
  unless config.url
69
- opts = ActiveRecord::Base.connection.instance_variable_get(:@config).dup
70
- opts.delete(:flags)
71
- config[:opts] = opts
69
+ case Rails.env
70
+ when "development"
71
+ config[:opts] = { adapter: 'sqlite', database: "db/keycard_development.sqlite3" }
72
+ when "test"
73
+ config[:opts] = { adapter: 'sqlite' }
74
+ else
75
+ raise "Keycard::DB.config must be configured"
76
+ end
72
77
  end
73
78
 
74
79
  Railtie.before_blocks.each do |block|
@@ -5,9 +5,10 @@ module Keycard
5
5
  # complete set of things that determine the user's #identity), given a Rack
6
6
  # request.
7
7
  class RequestAttributes
8
- def initialize(request, finder: InstitutionFinder.new)
9
- @finder = finder
10
- @request = request
8
+ def initialize(request, finder: InstitutionFinder.new, request_factory: default_factory)
9
+ @request = request
10
+ @finder = finder
11
+ @request_factory = request_factory
11
12
  end
12
13
 
13
14
  def [](attr)
@@ -15,12 +16,34 @@ module Keycard
15
16
  end
16
17
 
17
18
  def all
18
- finder.attributes_for(request)
19
+ user_attributes.merge(finder.attributes_for(request))
19
20
  end
20
21
 
21
22
  private
22
23
 
24
+ def user_attributes
25
+ { username: request.username }
26
+ end
27
+
28
+ def request
29
+ request_factory.for(@request)
30
+ end
31
+
32
+ def default_factory
33
+ access = Keycard.config.access.to_sym
34
+ case access
35
+ when :direct
36
+ DirectRequest
37
+ when :proxy
38
+ ProxiedRequest
39
+ else
40
+ # TODO: Warn about this once to the appropriate log; probably in a config check, not here.
41
+ # puts "Keycard does not recognize the '#{access}' access mode, using 'direct'."
42
+ DirectRequest
43
+ end
44
+ end
45
+
23
46
  attr_reader :finder
24
- attr_reader :request
47
+ attr_reader :request_factory
25
48
  end
26
49
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Keycard
4
- VERSION = "0.1.1"
4
+ VERSION = "0.1.2"
5
5
  end
data/lib/keycard.rb CHANGED
@@ -2,12 +2,20 @@
2
2
 
3
3
  require "keycard/version"
4
4
  require "sequel"
5
+ require "ostruct"
5
6
 
6
7
  # All of the Keycard components are contained within this top-level module.
7
8
  module Keycard
9
+ def self.config
10
+ @config ||= OpenStruct.new(
11
+ access: :direct
12
+ )
13
+ end
8
14
  end
9
15
 
10
16
  require "keycard/db"
11
17
  require "keycard/railtie" if defined?(Rails)
12
18
  require "keycard/request_attributes"
13
19
  require "keycard/institution_finder"
20
+ require "keycard/direct_request"
21
+ require "keycard/proxied_request"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: keycard
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Noah Botimer
@@ -9,22 +9,8 @@ authors:
9
9
  autorequire:
10
10
  bindir: exe
11
11
  cert_chain: []
12
- date: 2018-03-23 00:00:00.000000000 Z
12
+ date: 2018-06-08 00:00:00.000000000 Z
13
13
  dependencies:
14
- - !ruby/object:Gem::Dependency
15
- name: mysql2
16
- requirement: !ruby/object:Gem::Requirement
17
- requirements:
18
- - - ">="
19
- - !ruby/object:Gem::Version
20
- version: '0'
21
- type: :runtime
22
- prerelease: false
23
- version_requirements: !ruby/object:Gem::Requirement
24
- requirements:
25
- - - ">="
26
- - !ruby/object:Gem::Version
27
- version: '0'
28
14
  - !ruby/object:Gem::Dependency
29
15
  name: sequel
30
16
  requirement: !ruby/object:Gem::Requirement
@@ -202,7 +188,9 @@ files:
202
188
  - keycard.gemspec
203
189
  - lib/keycard.rb
204
190
  - lib/keycard/db.rb
191
+ - lib/keycard/direct_request.rb
205
192
  - lib/keycard/institution_finder.rb
193
+ - lib/keycard/proxied_request.rb
206
194
  - lib/keycard/railtie.rb
207
195
  - lib/keycard/request_attributes.rb
208
196
  - lib/keycard/version.rb