keycard 0.2.4 → 0.3.0

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: 289f06e8e7d3002eba8c6aa13bedf6be9fd2cd643f2923ce8cb5185aeaec6fda
4
- data.tar.gz: 885e1c86b158ff4778764ea0d2a5ee6bd18ff133e811af47032b42b7a56f0e24
3
+ metadata.gz: 3a653bd311fdb43e3c4f202e8761582c459ffa1c4e85a1e7309e337e8dd6e1f0
4
+ data.tar.gz: 846d43693d28a97cdd4a9fca88e0ee51c6a6289ac389122e078ccc9a8193a40f
5
5
  SHA512:
6
- metadata.gz: 1c510e8be9b90985c08d54c07489368b14911c28d595abe51748acea4ec9f2b5914a06c3425d97afc7e9eeae18c8a7a02b1ca8a3850bc0795f88fb897918b384
7
- data.tar.gz: d60d7e51da879687dd570c26382947a619f9978309de7cb797bde095e11043e71c28783e85847f22c12beff652b685db8b0dcdeb55b715197ea502fb0f6c7d4f
6
+ metadata.gz: 6b9185d2dc8a350988c52bfd56c3417840969d89167ee7824132ddc505630b99a4bbc757edd1ea8b644e67da856a3ca78fe88a927334d0ecd7cc16c606de423a
7
+ data.tar.gz: 343cab74ac29ded2ff832c19c141fd0d14dc6fdb7d0da3fb0ba7e32006ba29a0550445a1d42c204d15e569c2797c142a02769e8360cfa9ac8e72c375b2a0f9ad
data/.gitignore CHANGED
@@ -3,6 +3,8 @@
3
3
  /_yardoc/
4
4
  /coverage/
5
5
  /doc/
6
+ /docs/_build/
7
+ /docs/_yard/
6
8
  /pkg/
7
9
  /spec/reports/
8
10
  /tmp/
data/README.md CHANGED
@@ -1,5 +1,6 @@
1
1
  [![Build Status](https://travis-ci.org/mlibrary/keycard.svg?branch=master)](https://travis-ci.org/mlibrary/keycard?branch=master)
2
2
  [![Coverage Status](https://coveralls.io/repos/github/mlibrary/keycard/badge.svg?branch=master)](https://coveralls.io/github/mlibrary/keycard?branch=master)
3
+ [![Documentation Status](https://readthedocs.org/projects/keycard/badge/?version=latest)](https://keycard.readthedocs.io/en/latest/?badge=latest)
3
4
 
4
5
  # Keycard
5
6
 
data/bin/rake ADDED
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ #
5
+ # This file was generated by Bundler.
6
+ #
7
+ # The application 'rake' is installed as part of a gem, and
8
+ # this file is here to facilitate running it.
9
+ #
10
+
11
+ require "pathname"
12
+ ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
13
+ Pathname.new(__FILE__).realpath)
14
+
15
+ bundle_binstub = File.expand_path("../bundle", __FILE__)
16
+
17
+ if File.file?(bundle_binstub)
18
+ if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/
19
+ load(bundle_binstub)
20
+ else
21
+ abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
22
+ Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
23
+ end
24
+ end
25
+
26
+ require "rubygems"
27
+ require "bundler/setup"
28
+
29
+ load Gem.bin_path("rake", "rake")
data/docs/Makefile ADDED
@@ -0,0 +1,24 @@
1
+ # Minimal makefile for Sphinx documentation
2
+ #
3
+
4
+ # You can set these variables from the command line.
5
+ SPHINXOPTS =
6
+ SPHINXBUILD = sphinx-build
7
+ SPHINXPROJ = Keycard
8
+ AUTOBUILD = sphinx-autobuild
9
+ SOURCEDIR = .
10
+ BUILDDIR = _build
11
+
12
+ # Put it first so that "make" without argument is like "make help".
13
+ help:
14
+ @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
15
+
16
+ auto:
17
+ @$(AUTOBUILD) ${@:2} "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
18
+
19
+ .PHONY: auto help Makefile
20
+
21
+ # Catch-all target: route all unknown targets to Sphinx using the new
22
+ # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
23
+ %: Makefile
24
+ @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
File without changes
File without changes
@@ -0,0 +1,210 @@
1
+ Identity and Authentication
2
+ ===========================
3
+
4
+ Users can be identified in any number of ways and carry with them
5
+ attributes that determine the entirety of "who they are". Typical needs
6
+ include identifying a person by username or email address, and building a
7
+ profile of attributes such as geographical region (as determined by IP address),
8
+ or University status (student, staff, etc.). The identifiers and attributes are
9
+ intrinsic to the user and do not, by themselves, grant any permissions within
10
+ an application. Likewise, these attributes cannot be granted within an
11
+ application, but only inspected.
12
+
13
+ This document gives an overview of authentication terminology and scenarios
14
+ from an application perspective. Not all of these concepts are strictly in the
15
+ domain of Keycard (for example, we mention some typical authorization rules as
16
+ they relate to different user types). This background is presented here to
17
+ establish the environment within which Keycard operates and functionality it
18
+ seeks to support. How to use Keycard in an application is documented elsewhere
19
+ (TODO: complete examples and link API).
20
+
21
+ Authentication Glossary
22
+ -----------------------
23
+
24
+ There are many overlapping concepts and terms regarding identity, privacy,
25
+ security, and technology. These definitions give building blocks for the
26
+ discrete combination scenarios that require (or support) different business
27
+ rules.
28
+
29
+ As far as classifying users, there are three dimensions to consider. A user may
30
+ have only one status in a given dimension:
31
+
32
+ * **Identification** -- Anonymous, Unnamed, Named
33
+ * **Affiliation** -- Unaffiliated, Affiliated
34
+ * **Account Status** -- Nonmember, Member
35
+
36
+ * **Anonymous** -- individually indistinguishable from other people except
37
+ circumstantially (e.g., visiting from the same IP address)
38
+ * **Identified** -- a person whose identity has been verified; importantly, the
39
+ identity may not be known to all parties
40
+ * **Unnamed** -- identified, but only opaquely; that is, the person (principal)
41
+ is not revealed to the application, though the specific affiliation is,
42
+ usually an organizational role or roles
43
+ * **Named** -- personally identified; that is, a resolvable identifier for the
44
+ person (principal) is revealed, possibly along with name information
45
+ * **Session** -- a period of usage that is considered to be conducted by the
46
+ same person
47
+ * **Principal** -- a person with an organizational account (but not necessarily
48
+ an application account)
49
+ * **Partner** -- an organization with some agreement with the application
50
+ providers, in order to authenticate its users and offer access on its behalf
51
+ * **Affiliate** -- a person with at least one affiliation relationship with a
52
+ partner; asserted by the organization (e.g., a university asserts that a
53
+ person is a faculty member)
54
+ * **Visitor** -- a person with no identification or affiliation whatsoever;
55
+ effectively unrecognized by any means
56
+ * **Guest** -- a person with some identification or affiliation; recognized, but
57
+ transient, that is, not holding an account of any sort
58
+ * **Member** -- a person with identification; recognized, holding an account;
59
+ Visitors and Guests are considered non-members
60
+
61
+ Not all combinations are sensible for determining business rules. For example,
62
+ membership requires some form of identification, so there can be no anonymous
63
+ members.
64
+
65
+ To aid consideration of the rules for an application, this table names all of
66
+ the unique combinations, which are further defined below. It does not imply
67
+ that all applications should have seven user types, but that each combination
68
+ has unique characteristics that may need to be handled differently. A given
69
+ application may exclude certain types or treat different types the same in many
70
+ ways. For example, an application may completely disregard identification for
71
+ Guests, treating them all the same.
72
+
73
+ .. csv-table::
74
+ :header: "", "Unaffiliated Nonmember", "Unaffiliated Member", "Affiliated Nonmember", "Affiliated Member"
75
+ :stub-columns: 1
76
+
77
+ "Anonymous", "Visitor (Public)", "--", "Unknown Guest", "--"
78
+ "Unnamed", "--", "--", "Unnamed Guest", "Private Member"
79
+ "Named", "--", "Local Account", "Named Guest", "Member"
80
+
81
+
82
+
83
+ Authentication Scenarios / User Types
84
+ -------------------------------------
85
+
86
+ Visitor
87
+ ~~~~~~~
88
+
89
+ A person with no recognized identification or affiliation whatsoever. The user
90
+ is effectively unauthenticated by any means.
91
+
92
+ Anyone who can connect to the application (at the very least by obscuring their
93
+ identity and any affiliation) may act as a visitor, so there should be no
94
+ restrictions that apply to other users that do not apply to visitors. Entry or
95
+ modification of data should be permitted only under scrutiny, where vandalism
96
+ is of no concern and appropriate auditing and moderation are in place.
97
+
98
+ A visitor may have a session to enhance user experience, but all session data
99
+ should be transient and discarded after an appropriate inactivity period, if
100
+ stored server-side.
101
+
102
+ Visitor (Public)
103
+ ................
104
+ All Visitors are anonymous and should be treated as "any public user". This
105
+ typically means that they have access to a limited set of resources and cannot
106
+ receive any personalization features.
107
+
108
+ Guest
109
+ ~~~~~
110
+
111
+ A person with some recognized identification or affiliation. The user is
112
+ authenticated, but transient – that is, not holding an account of any sort.
113
+ This type of user is typically permitted access to restricted materials based
114
+ on agreements between organizations.
115
+
116
+ There may be useful distinctions applied or features available for different
117
+ types of Guest. For example, the text may be personalized for a Named Guest, or
118
+ additional features may be provided to Unnamed Guests with the "faculty"
119
+ designation.
120
+
121
+ Unknown Guest
122
+ .............
123
+ A user connecting from a recognized affiliate network, but with no
124
+ identification. All that can be asserted is that the user has a generic
125
+ affiliation implying that the person can access organizational computing
126
+ resources. This may be by way of public computers, campus networking,
127
+ or VPN access, as examples.
128
+
129
+ Unnamed Guest
130
+ .............
131
+ A person with specified affiliation and a persistent identifier. The identifier
132
+ is opaque, but stable; that is, the same identifier presented over time implies
133
+ that the user is the same person. It is expressly not human-friendly and should
134
+ not be displayed.
135
+
136
+ Keycard calls this persistent ID the user_pid. Generally, the affiliate will
137
+ not present different identifiers for the same person, but that is outside of
138
+ the control and knowledge of the application. It should be assumed that
139
+ different IDs represent different people.
140
+
141
+ The affiliation may be multi-valued and is *scoped*, meaning that it applies
142
+ within a security domain. Common semantics assert that a person has roles like
143
+ member and staff, or member and student, scoped to the entire affiliate
144
+ organization. An example of one scoped affiliation would be
145
+ ``faculty@umich.edu``.
146
+
147
+ Named Guest
148
+ ...........
149
+ A person with specified affiliation and both persistent and enterprise
150
+ identifiers. The persistent identifier is as for Unnamed Guests. The enterprise
151
+ identifier is name-based, meaning that it based on some account name for the
152
+ person used within the affiliate organization. It is expressly personally
153
+ identifiable, and often human-friendly, meaning that other people may recognize
154
+ it and it would be suitable for display.
155
+
156
+ Keycard calls the enterprise ID the ``user_eid``. It is single-valued and
157
+ often, but not always, matches an email address for the person. Generally, this
158
+ ID is stable between sessions, but there is no guarantee that it will not be
159
+ reassigned at some point.
160
+
161
+ Member
162
+ ~~~~~~
163
+
164
+ A person with recognized identification and an account for application features
165
+ such as content ownership. The user is authenticated and persistent.
166
+
167
+ The reasons to maintain Members may vary between application. For example,
168
+ those with a narrower audience may prefer the semantics that anyone
169
+ individually authenticated becomes a Member automatically to simplify data
170
+ modeling and reporting. Those with very broad audiences may choose to have many
171
+ Guests and only a few Members to reduce the number of dormant or single-use
172
+ accounts.
173
+
174
+ Local Account
175
+ .............
176
+ A user (person or machine user) that is only known the application, not an
177
+ identity authority. The application must manage any authentication directly.
178
+ This may not even be an interactive account, but used as a means to record
179
+ ownership or action by the system consistently alongside human users, for
180
+ example.
181
+
182
+ Some applications may have a dedicated super user with a special login
183
+ procedure, where others may manage those tasks by designating human Members as
184
+ administrative users.
185
+
186
+ Private Member
187
+ ..............
188
+ A person with specified affiliation and a privacy-preserving, persistent
189
+ identifier. This Member is very similar to an Unnamed Guest, but has been given
190
+ an account for some application purpose. Some applications may choose to have
191
+ only Unnamed Guests or Private Members, not both types.
192
+
193
+ The authentication information does not include anything personally
194
+ identifiable, so the application must decide whether to ask the user to supply
195
+ items like a display name or email address, or to deal with the lack of
196
+ human-friendly information in another way. For example, an application that
197
+ only maintains a set of favorite items for the user may find no need to provide
198
+ meaningful display to that member others as to whose favorites they are. By
199
+ contrast, an application that tracks and attributes comments to a Member would
200
+ generally need some label for the commenter.
201
+
202
+ Member
203
+ ......
204
+ A person with specified affiliation and both persistent and enterprise
205
+ identifiers. This Member is similar to a Named Guest, but has been given an
206
+ account for some application purpose. This Member fits the classical definition
207
+ of "named user"; that is, account and display information is maintained, likely
208
+ in order to grant individual permissions and display name information to other
209
+ users.
210
+
data/docs/conf.py ADDED
@@ -0,0 +1,46 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ import guzzle_sphinx_theme
4
+ from recommonmark.parser import CommonMarkParser
5
+
6
+ # -- General configuration ------------------------------------------------
7
+ project = u'Keycard'
8
+ copyright = u'2018, Regents of the University of Michigan'
9
+ author = u'Noah Botimer'
10
+ version = u'0.2.4'
11
+ release = u'0.2.4'
12
+
13
+
14
+ extensions = ['guzzle_sphinx_theme']
15
+ templates_path = ['_templates']
16
+ master_doc = 'index'
17
+
18
+ source_parsers = {
19
+ '.md': CommonMarkParser,
20
+ }
21
+ source_suffix = ['.rst', '.md']
22
+
23
+ language = None
24
+ exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
25
+ pygments_style = 'sphinx'
26
+ todo_include_todos = False
27
+
28
+
29
+ # -- Options for HTML output ----------------------------------------------
30
+ html_theme_path = guzzle_sphinx_theme.html_theme_path()
31
+ html_theme = 'guzzle_sphinx_theme'
32
+ html_static_path = ['_static']
33
+
34
+ # Guzzle theme options (see theme.conf for more information)
35
+ html_theme_options = {
36
+ "project_nav_name": "Keycard",
37
+ }
38
+
39
+ html_sidebars = {
40
+ '**': [
41
+ 'logo-text.html',
42
+ 'globaltoc.html',
43
+ 'searchbox.html',
44
+ ]
45
+ }
46
+
data/docs/index.rst ADDED
@@ -0,0 +1,37 @@
1
+ .. title:: Keycard, authentication for Ruby applications
2
+
3
+ Keycard Documentation
4
+ =====================
5
+
6
+ Keycard is both a Ruby library and an abstract model for authentication and
7
+ directory information for users of an application.
8
+
9
+ Keycard is primarily concerned with establishing identity and supplemental
10
+ attributes of users. It provides a data model for user information and
11
+ conveniences for building applications that will be deployed with reverse
12
+ proxies and single sign-on systems. It is well-suited to enterprise deployments
13
+ where there are external login and directory systems.
14
+
15
+ Authorization needs are not covered by Keycard at all. See Checkpoint_ for a
16
+ library that can store grants based on the Keycard attributes and enforce
17
+ policies against them.
18
+
19
+ Table of Contents
20
+ -----------------
21
+
22
+ .. toctree::
23
+ :maxdepth: 2
24
+
25
+ authentication.rst
26
+ runtime_context.rst
27
+
28
+ .. _Checkpoint: https://github.com/mlibrary/checkpoint
29
+
30
+
31
+ Naming
32
+ ------
33
+ Keycard takes its name from physical keycards, where a person presents a card
34
+ to a reader. The card may hold any number of attributes, including personal
35
+ identification, staff classification, or clearance levels. The reader (or
36
+ attached system) is left to make any authorization decisions or present the
37
+ information to a person to do so.
@@ -0,0 +1,4 @@
1
+ sphinx>=1.6.5,<1.7.0
2
+ sphinx-autobuild>=0.7.1,<0.8.0
3
+ guzzle_sphinx_theme>=0.7.11,<0.8.0
4
+ recommonmark>=0.4.0,<0.5.0
@@ -0,0 +1,42 @@
1
+ Runtime Context
2
+ ===============
3
+
4
+ An application can be run in different environments and configurations for
5
+ different purposes like development, testing, staging, or public use. There are
6
+ many overlapping terms in use, so, for our purposes here, we use the term
7
+ *Runtime Context* to give labels to the scenarios where the infrastructure is
8
+ different, and in what ways.
9
+
10
+ Development Context
11
+ -------------------
12
+
13
+ This means that the application is running with direct access by the client,
14
+ generally from a workstation. There is no front-end server, so all
15
+ authentication must be managed by the application. The Rails environment is
16
+ generally set to ``development``.
17
+
18
+ A proxy managing single sign-on may be emulated either at the Rack or
19
+ application level if needed. Generally, there is some bit of UI or cookie/param
20
+ handling exposed only in development mode to influence how the requests appear
21
+ to the application, or there is a login form for local accounts.
22
+
23
+ Deployment Context
24
+ ------------------
25
+
26
+ This means that the application is deployed to dedicated infrastructure. There
27
+ is a front-end server (proxy) that may or may not manage single sign-on. The
28
+ Rails environment is generally set to ``production``.
29
+
30
+ A typical configuration is to have an Apache web server proxying all traffic,
31
+ with either a module for Cosign, CAS, or Shibboleth configured. There is often
32
+ a fixed path (e.g., ``/login``) that is intercepted to require SSO
33
+ authentication. If the user is authenticated, the request is forwarded on with
34
+ headers in place. If the user cannot authenticate, the app never receives the
35
+ login path request. For Shibboleth scenarios, there is a Service Provider that
36
+ is set up for the endpoint (application URL).
37
+
38
+ With Shibboleth, it is also possible to have the headers present on each
39
+ request when there is an active session with the Service Provider. Some special
40
+ care must be taken here that sessions are initiated and terminated properly and
41
+ when desired (usually on login and logout requests).
42
+
data/keycard.gemspec CHANGED
@@ -26,14 +26,14 @@ Gem::Specification.new do |spec|
26
26
 
27
27
  spec.add_dependency "sequel"
28
28
 
29
- spec.add_development_dependency "bundler", "~> 1.16"
30
- spec.add_development_dependency "coveralls", "~> 0.8"
29
+ spec.add_development_dependency "bundler"
30
+ spec.add_development_dependency "coveralls"
31
31
  spec.add_development_dependency "pry"
32
- spec.add_development_dependency "rake", "~> 12.0"
33
- spec.add_development_dependency "rspec", "~> 3.0"
34
- spec.add_development_dependency "rubocop", "~> 0.52"
35
- spec.add_development_dependency "rubocop-rails", "~> 1.1"
36
- spec.add_development_dependency "rubocop-rspec", "~> 1.16"
32
+ spec.add_development_dependency "rake"
33
+ spec.add_development_dependency "rspec"
34
+ spec.add_development_dependency "rubocop"
35
+ spec.add_development_dependency "rubocop-rails"
36
+ spec.add_development_dependency "rubocop-rspec"
37
37
  spec.add_development_dependency "sqlite3"
38
- spec.add_development_dependency "yard", "~> 0.9"
38
+ spec.add_development_dependency "yard"
39
39
  end
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "digest"
4
+ require "securerandom"
5
+
6
+ # A typical digest or api key, ready to be encrypted.
7
+ class Keycard::DigestKey
8
+ class HiddenKeyError < StandardError; end
9
+ HIDDEN_KEY = "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX".freeze
10
+
11
+ # To simply mint a new key, call #new without any parameters.
12
+ # For wrapping existing, deserialized keys, pass the digest to the constructor.
13
+ # @param digest [String] The value of the hashed key
14
+ # @param key [String] Use this if you'd like to specify the unhashed key.
15
+ # If a digest is also provided, this parameter is ignored.
16
+ def initialize(digest = nil, key: nil)
17
+ if digest
18
+ @digest = digest
19
+ else
20
+ @key = key || SecureRandom.uuid
21
+ end
22
+ end
23
+
24
+ # A string representation of this key. For hidden keys, this returns an
25
+ # obfuscated value.
26
+ # @return [String]
27
+ def to_s
28
+ @key || HIDDEN_KEY
29
+ end
30
+
31
+ # The unhashed value of the key.
32
+ # @return [String]
33
+ # @raise [HiddenKeyError] This exception is raised if the unhashed key is
34
+ # not available.
35
+ def value
36
+ if @key
37
+ @key
38
+ else
39
+ raise HiddenKeyError, "Cannot display hashed/hidden keys"
40
+ end
41
+ end
42
+
43
+ # The result of hashing the key
44
+ # @return [String]
45
+ def digest
46
+ @digest ||= Digest::SHA256.hexdigest(@key)
47
+ end
48
+
49
+ def eql?(other)
50
+ digest == if other.is_a?(self.class)
51
+ other.digest
52
+ else
53
+ other.to_s
54
+ end
55
+ end
56
+ alias == eql?
57
+
58
+ end
59
+
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Keycard
4
- VERSION = "0.2.4"
4
+ VERSION = "0.3.0"
5
5
  end
data/lib/keycard.rb CHANGED
@@ -13,6 +13,7 @@ module Keycard
13
13
  end
14
14
  end
15
15
 
16
+ require "keycard/digest_key"
16
17
  require "keycard/db"
17
18
  require "keycard/railtie" if defined?(Rails)
18
19
  require "keycard/institution_finder"
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.2.4
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Noah Botimer
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: exe
11
11
  cert_chain: []
12
- date: 2018-07-20 00:00:00.000000000 Z
12
+ date: 2019-03-06 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: sequel
@@ -29,30 +29,30 @@ dependencies:
29
29
  name: bundler
30
30
  requirement: !ruby/object:Gem::Requirement
31
31
  requirements:
32
- - - "~>"
32
+ - - ">="
33
33
  - !ruby/object:Gem::Version
34
- version: '1.16'
34
+ version: '0'
35
35
  type: :development
36
36
  prerelease: false
37
37
  version_requirements: !ruby/object:Gem::Requirement
38
38
  requirements:
39
- - - "~>"
39
+ - - ">="
40
40
  - !ruby/object:Gem::Version
41
- version: '1.16'
41
+ version: '0'
42
42
  - !ruby/object:Gem::Dependency
43
43
  name: coveralls
44
44
  requirement: !ruby/object:Gem::Requirement
45
45
  requirements:
46
- - - "~>"
46
+ - - ">="
47
47
  - !ruby/object:Gem::Version
48
- version: '0.8'
48
+ version: '0'
49
49
  type: :development
50
50
  prerelease: false
51
51
  version_requirements: !ruby/object:Gem::Requirement
52
52
  requirements:
53
- - - "~>"
53
+ - - ">="
54
54
  - !ruby/object:Gem::Version
55
- version: '0.8'
55
+ version: '0'
56
56
  - !ruby/object:Gem::Dependency
57
57
  name: pry
58
58
  requirement: !ruby/object:Gem::Requirement
@@ -71,72 +71,72 @@ dependencies:
71
71
  name: rake
72
72
  requirement: !ruby/object:Gem::Requirement
73
73
  requirements:
74
- - - "~>"
74
+ - - ">="
75
75
  - !ruby/object:Gem::Version
76
- version: '12.0'
76
+ version: '0'
77
77
  type: :development
78
78
  prerelease: false
79
79
  version_requirements: !ruby/object:Gem::Requirement
80
80
  requirements:
81
- - - "~>"
81
+ - - ">="
82
82
  - !ruby/object:Gem::Version
83
- version: '12.0'
83
+ version: '0'
84
84
  - !ruby/object:Gem::Dependency
85
85
  name: rspec
86
86
  requirement: !ruby/object:Gem::Requirement
87
87
  requirements:
88
- - - "~>"
88
+ - - ">="
89
89
  - !ruby/object:Gem::Version
90
- version: '3.0'
90
+ version: '0'
91
91
  type: :development
92
92
  prerelease: false
93
93
  version_requirements: !ruby/object:Gem::Requirement
94
94
  requirements:
95
- - - "~>"
95
+ - - ">="
96
96
  - !ruby/object:Gem::Version
97
- version: '3.0'
97
+ version: '0'
98
98
  - !ruby/object:Gem::Dependency
99
99
  name: rubocop
100
100
  requirement: !ruby/object:Gem::Requirement
101
101
  requirements:
102
- - - "~>"
102
+ - - ">="
103
103
  - !ruby/object:Gem::Version
104
- version: '0.52'
104
+ version: '0'
105
105
  type: :development
106
106
  prerelease: false
107
107
  version_requirements: !ruby/object:Gem::Requirement
108
108
  requirements:
109
- - - "~>"
109
+ - - ">="
110
110
  - !ruby/object:Gem::Version
111
- version: '0.52'
111
+ version: '0'
112
112
  - !ruby/object:Gem::Dependency
113
113
  name: rubocop-rails
114
114
  requirement: !ruby/object:Gem::Requirement
115
115
  requirements:
116
- - - "~>"
116
+ - - ">="
117
117
  - !ruby/object:Gem::Version
118
- version: '1.1'
118
+ version: '0'
119
119
  type: :development
120
120
  prerelease: false
121
121
  version_requirements: !ruby/object:Gem::Requirement
122
122
  requirements:
123
- - - "~>"
123
+ - - ">="
124
124
  - !ruby/object:Gem::Version
125
- version: '1.1'
125
+ version: '0'
126
126
  - !ruby/object:Gem::Dependency
127
127
  name: rubocop-rspec
128
128
  requirement: !ruby/object:Gem::Requirement
129
129
  requirements:
130
- - - "~>"
130
+ - - ">="
131
131
  - !ruby/object:Gem::Version
132
- version: '1.16'
132
+ version: '0'
133
133
  type: :development
134
134
  prerelease: false
135
135
  version_requirements: !ruby/object:Gem::Requirement
136
136
  requirements:
137
- - - "~>"
137
+ - - ">="
138
138
  - !ruby/object:Gem::Version
139
- version: '1.16'
139
+ version: '0'
140
140
  - !ruby/object:Gem::Dependency
141
141
  name: sqlite3
142
142
  requirement: !ruby/object:Gem::Requirement
@@ -155,16 +155,16 @@ dependencies:
155
155
  name: yard
156
156
  requirement: !ruby/object:Gem::Requirement
157
157
  requirements:
158
- - - "~>"
158
+ - - ">="
159
159
  - !ruby/object:Gem::Version
160
- version: '0.9'
160
+ version: '0'
161
161
  type: :development
162
162
  prerelease: false
163
163
  version_requirements: !ruby/object:Gem::Requirement
164
164
  requirements:
165
- - - "~>"
165
+ - - ">="
166
166
  - !ruby/object:Gem::Version
167
- version: '0.9'
167
+ version: '0'
168
168
  description:
169
169
  email:
170
170
  - botimer@umich.edu
@@ -183,11 +183,21 @@ files:
183
183
  - README.md
184
184
  - Rakefile
185
185
  - bin/console
186
+ - bin/rake
186
187
  - bin/setup
187
188
  - db/migrations/1_create_tables.rb
189
+ - docs/Makefile
190
+ - docs/_static/.gitkeep
191
+ - docs/_templates/.gitkeep
192
+ - docs/authentication.rst
193
+ - docs/conf.py
194
+ - docs/index.rst
195
+ - docs/requirements.txt
196
+ - docs/runtime_context.rst
188
197
  - keycard.gemspec
189
198
  - lib/keycard.rb
190
199
  - lib/keycard/db.rb
200
+ - lib/keycard/digest_key.rb
191
201
  - lib/keycard/institution_finder.rb
192
202
  - lib/keycard/railtie.rb
193
203
  - lib/keycard/request.rb