zero_auth 0.0.1.beta → 0.0.2.beta

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
  SHA1:
3
- metadata.gz: 3011392374e4a055d4748a3433882c41e2c4558a
4
- data.tar.gz: 3cdbc75b4eaff08e286acc940f0019f8cd961921
3
+ metadata.gz: 8e5293b8a8a5c64cb80f819e0afc5fe0da191223
4
+ data.tar.gz: 52511c99d61691eaf31db9a9effb837ef285ed0d
5
5
  SHA512:
6
- metadata.gz: 7884a750cfb742837bdf495fdd64790dcd82ee550a3a29f876f74eee3b87f824f9717ba0de47f02ce50057281ccd62538c8d464fd6b7e0c7253842899ac2967b
7
- data.tar.gz: f142dbaf426d7790f7bad103c4ee599b93c790edbd21bdac24ec53a65f30d79efd7d39070bee2a452958a8194b79419e4547d26131c5ef2e21278b7337746f96
6
+ metadata.gz: 32125971bae43ce2cae06f9dab77afae3eb58daa9f834ad288024067facd7afff2d5c1a9793e2c8e881419c6e30809ea7076203fc7dc4937cff7b40e7cac8c3a
7
+ data.tar.gz: 84c2a65e27f0a4d64f642196fdff381fb76105141633b3400fe6882879c766ae13b92c2255d87919e0e531968264bc29a54e3673275a3feddf235d24cf9072c3
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --color
2
+ --warnings
3
+ --require spec_helper
data/.travis.yml ADDED
@@ -0,0 +1,9 @@
1
+ language: ruby
2
+
3
+ install: "bundle install"
4
+
5
+ script: "bundle exec rake"
6
+
7
+ rvm:
8
+ - 2.0.0
9
+ - 2.1.0
data/.yardopts ADDED
@@ -0,0 +1,2 @@
1
+ --markup=markdown
2
+ lib/**/*.rb
data/README.md CHANGED
@@ -1,7 +1,9 @@
1
- # ZeroAuth
1
+ # ZeroAuth [![Build Status](https://travis-ci.org/bschaeffer/zero_auth.svg?branch=master)](https://travis-ci.org/bschaeffer/zero_auth) [![Inline docs](http://inch-ci.org/github/bschaeffer/zero_auth.png?branch=master)](http://inch-ci.org/github/bschaeffer/zero_auth)
2
2
 
3
3
  **Zero configuration** authentication starter for your Rails project.
4
4
 
5
+ * Docs: http://rdoc.info/github/bschaeffer/zero_auth
6
+
5
7
  ## Installation
6
8
 
7
9
  Add this line to your application's Gemfile:
@@ -18,8 +20,60 @@ Or install it yourself as:
18
20
 
19
21
  ## Usage
20
22
 
21
- Coming Soon...
23
+ ### Models
24
+
25
+ #### `ZeroAuth::Model::Password`
26
+
27
+ * Docs: http://rdoc.info/github/bschaeffer/zero_auth/ZeroAuth/Model/Password
28
+ * Provides password salting and hashing using `BCrypt`.
29
+ * Instance method authentication.
30
+ * **Requires** `password_salt` and `password_hash` attributes.
31
+
32
+ ```ruby
33
+ class User
34
+ include ZeroAuth::Model::Password
35
+ attr_accessor :password_salt, :password_hash
36
+ end
37
+
38
+ user = User.new
39
+ user.password = 'password'
40
+
41
+ user.password_salt # => BCrypt::Engine.generate_salt
42
+ user.password_hash # => BCrypt::Password
43
+
44
+ user.has_password?('password') # => true
45
+ user.has_password?('pa$$w0rD') # => false
46
+
47
+ user.authenticate!('password') # => true
48
+ user.authenticate!('pa$$word') # => raises ZeroAuth::Unauthorized
49
+ ```
50
+
51
+ ##### Rails Setup
52
+
53
+ ```ruby
54
+ # migration
55
+ change_table :users do |t|
56
+ t.string :password_salt, null: false, default: ""
57
+ t.string :password_hash, null: false, default: ""
58
+ end
59
+
60
+ # model
61
+ class User < ActiveRecord::Base
62
+ include ZeroAuth::Model::Password
63
+ end
64
+ ```
65
+
66
+ ##### MongoMapper Setup
67
+
68
+ ```ruby
69
+ class User < ActiveRecord::Base
70
+ include MongoMapper::Document
71
+ include ZeroAuth::Model::Password
22
72
 
73
+ key :password_salt, String
74
+ key :password_hash, String
75
+ end
76
+ ```
23
77
 
24
78
  ## Contributing
25
79
 
data/Rakefile CHANGED
@@ -1 +1,5 @@
1
- require "bundler/gem_tasks"
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+ task :default => :spec
@@ -0,0 +1,183 @@
1
+ module ZeroAuth
2
+ module Model
3
+ # The `Password` module includes the following features:
4
+ #
5
+ # * Password **salting** and **hashing** using `BCrypt`.
6
+ # * Instance level authentication method.
7
+ #
8
+ # ...yup, that's it. The idea is to provide a quick, secure way to store
9
+ # encrypted passwords. It is almost identical to Rails' own
10
+ # [has_secure_password](http://api.rubyonrails.org/classes/ActiveModel/SecurePassword/ClassMethods.html)
11
+ # method, with the only exception being ZeroAuth uses a unique salt stored
12
+ # alongside and used to compute a password's hash.
13
+ #
14
+ # ### Requirement
15
+ #
16
+ # Your object must be able to write to the `password_salt` and the
17
+ # `password_hash` attributes (we handle the `password` attribute), so you
18
+ # might want to do something like this in a Rails migration:
19
+ #
20
+ # ```ruby
21
+ # change_table :users do |t|
22
+ # t.string :password_salt, null: false, default: ""
23
+ # t.string :password_hash, null: false, default: ""
24
+ # end
25
+ # ```
26
+ #
27
+ # ...or something like this using [`MongoMapper`](http://mongomapper.com/):
28
+ #
29
+ # ```ruby
30
+ # class User
31
+ # include MongoMapper::Document
32
+ # include ZeroAuth::Model::Password
33
+ #
34
+ # key :password_salt, String
35
+ # key :password_hash, String
36
+ # end
37
+ # ```
38
+ #
39
+ # ### Usage
40
+ #
41
+ # ```ruby
42
+ # class User < ActiveRecord::Base
43
+ # include ZeroAuth::Model::Password
44
+ # end
45
+ #
46
+ # user = User.create(email: 'email@me.com', password: 'password')
47
+ #
48
+ # user.has_password?('password') # => true
49
+ # user.has_password?('pa$$w0rD') # => false
50
+ #
51
+ # user.authenticate!('password') # => true
52
+ # user.authenticate!('pa$$word') # => raises ZeroAuth::Unauthorized
53
+ # ```
54
+ #
55
+ # ### Implementing Validations
56
+ #
57
+ # This module provides a {#requires_password?} helper method that, by
58
+ # default, simply checks whether this object is a `#new_record?` (if
59
+ # we can check that) or if the `#password` attributes is `empty?`.
60
+ #
61
+ # Again, with ActiveRecord or ActiveModel as an example, you can utilize it
62
+ # like this:
63
+ #
64
+ # ```ruby
65
+ # class User < ActiveRecord
66
+ # include ZeroAuth::Model::Password
67
+ #
68
+ # with_options if: :requires_password? do |pw|
69
+ # pw.validates :password, length: {in: 8..40}, confirmation: true
70
+ # end
71
+ # end
72
+ # ```
73
+ #
74
+ # You can also simply override the {#requires_password?} method to require
75
+ # validation when an `:old_password` attribute is present:
76
+ #
77
+ # ```ruby
78
+ # attr_accesor :old_password
79
+ #
80
+ # def requires_password?
81
+ # super || old_password.present?
82
+ # end
83
+ # ```
84
+ #
85
+ # ### Customize Authentication Class Method
86
+ #
87
+ # The {ZeroAuth::Model::Password} module leaves record retreival and the
88
+ # exact authentication tree up to the developer, but implementing a
89
+ # custom class method is trivial. An example using `ActiveRecord` might look
90
+ # something like this:
91
+ #
92
+ # ```ruby
93
+ # class User < ActiveRecord::Base
94
+ # include ZeroAuth::Model::Password
95
+ #
96
+ # def self.authenticate(email, password)
97
+ # begin
98
+ # self.authenticate!(email, password)
99
+ # rescue ZeroAuth::Unauthorized
100
+ # end
101
+ # end
102
+ #
103
+ # def self.authenticate!(email, password)
104
+ # begin
105
+ # record = self.find_by!(email: email)
106
+ # record.authenticate!(password) && record
107
+ # rescue ActiveRecord::RecordNotFound
108
+ # fail ZeroAuth::Unauthorized
109
+ # end
110
+ # end
111
+ # end
112
+ # ```
113
+ #
114
+ # **Note** the use of the {ZeroAuth::Unauthorized} exception. This is a
115
+ # custom error class provided to allow a standard way for your application
116
+ # to capture exceptions regarding authentication and authorization.
117
+ #
118
+ # The implementation above is certainly a personal perference, but the
119
+ # logic, again, is left up to you.
120
+ #
121
+ module Password
122
+
123
+ # Calls `attr_reader :password` on the including class.
124
+ #
125
+ def self.included(base)
126
+ base.class_eval { attr_reader :password }
127
+ end
128
+
129
+ # If the given password is not `nil?`, generates a `password_salt` and
130
+ # encrypts the given password into the `password_hash` using that salt.
131
+ # The salt and hash are generated using {ZeroAuth::Password.generate_salt}
132
+ # and {ZeroAuth::Utils.create_password}.
133
+ #
134
+ # @param unencrypted_password [String] the unencrypted password_attribute
135
+ # @return [Mixed] the unencrypted password
136
+ #
137
+ def password=(unencrypted_password)
138
+ if unencrypted_password.nil?
139
+ @password = nil
140
+ self.password_salt = nil
141
+ self.password_hash = nil
142
+ else
143
+ @password = unencrypted_password
144
+ self.password_salt = ZeroAuth::Password.generate_salt
145
+ self.password_hash = ZeroAuth::Password.create(password, password_salt)
146
+ end
147
+ end
148
+
149
+ # Checks that the object is a `#new_record?` (if we can) or that the
150
+ # `password` attribute is not empty.
151
+ #
152
+ # @return [Boolean]
153
+ #
154
+ def requires_password?
155
+ is_new = (respond_to?(:new_record?) && new_record?)
156
+ is_new || !ZeroAuth::Utils.empty?(password)
157
+ end
158
+
159
+ # A helper method that takes a given password and raises a
160
+ # {ZeroAuth::Unauthorized} error if the call to `has_password?` fails.
161
+ #
162
+ # @params password [String] password to test
163
+ #
164
+ # @return [Nil]
165
+ # @raise {ZeroAuth::Unauthorized} if the given password is not valid
166
+ #
167
+ def authenticate!(test_password)
168
+ has_password?(test_password) || fail(ZeroAuth::Unauthorized)
169
+ end
170
+
171
+ # Compares the given password with the current password attributes using
172
+ # {ZeroAuth::Utils.compare_password}.
173
+ #
174
+ # @param test_password [String] password to test
175
+ # @return [Boolean]
176
+ #
177
+ def has_password?(test_password)
178
+ return false unless !ZeroAuth::Utils.empty?(password_hash)
179
+ ZeroAuth::Password.compare(password_hash, password_salt, test_password)
180
+ end
181
+ end
182
+ end
183
+ end
@@ -0,0 +1,39 @@
1
+ require 'bcrypt'
2
+
3
+ module ZeroAuth
4
+ class Password
5
+
6
+ # @return [String] a salt created by `BCrypt::Engine.generate_salt`
7
+ #
8
+ def self.generate_salt
9
+ BCrypt::Engine.generate_salt
10
+ end
11
+
12
+ # Generates a `BCrypt::Password` with a hard-coded cost of **9** (which
13
+ # will probably change soon).
14
+ #
15
+ # @param password [String] the given password
16
+ # @param salt [Sting] the password salt
17
+ #
18
+ # @return [BCrypt::Password]
19
+ #
20
+ def self.create(password, salt)
21
+ BCrypt::Password.create("#{password}#{salt}", cost: 9)
22
+ end
23
+
24
+ # Compares a given encrypted password and the salt used to generate it with
25
+ # an unencrypted_password. Uses {ZeroAuth::Utils.secure_compare}.
26
+ #
27
+ # @param encrypted [String] the encrypted password
28
+ # @param salt [String] the salt used to generate that password
29
+ # @param unencrypted [String] the plain text password to compare
30
+ #
31
+ # @return [Boolean] true if they are equal, false if they aren't
32
+ #
33
+ def self.compare(encrypted, salt, unencrypted)
34
+ bcrypt = BCrypt::Password.new(encrypted)
35
+ password = BCrypt::Engine.hash_secret("#{unencrypted}#{salt}", bcrypt.salt)
36
+ ZeroAuth::Utils.secure_compare(password, encrypted)
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,31 @@
1
+ require 'bcrypt'
2
+
3
+ module ZeroAuth
4
+ class Utils
5
+
6
+ # Uses a "constant time" comparison algorithm I would never have thought
7
+ # about so I copied it line for line from `Devise.secure_compare`:
8
+ #
9
+ # https://github.com/plataformatec/devise/blob/11c88754791322c8c4c5c123149f5435eda3b932/lib/devise.rb#L481
10
+ #
11
+ # @params a [String] first string to compare
12
+ # @params second [String] second string to compare
13
+ #
14
+ # @return [Boolean] true if they are equal, false if they aren't
15
+ #
16
+ def self.secure_compare(a, b)
17
+ return false if empty?(a) || empty?(b) || a.bytesize != b.bytesize
18
+ l = a.unpack "C#{a.bytesize}"
19
+
20
+ res = 0
21
+ b.each_byte { |byte| res |= byte ^ l.shift }
22
+ res == 0
23
+ end
24
+
25
+ #
26
+ # @!visibility private
27
+ def self.empty?(v)
28
+ v.respond_to?(:empty?) ? v.empty? : !v
29
+ end
30
+ end
31
+ end
@@ -1,3 +1,3 @@
1
1
  module ZeroAuth
2
- VERSION = "0.0.1.beta"
2
+ VERSION = "0.0.2.beta"
3
3
  end
data/lib/zero_auth.rb CHANGED
@@ -1,4 +1,16 @@
1
1
  require "zero_auth/version"
2
2
 
3
3
  module ZeroAuth
4
+ autoload :Utils, 'zero_auth/utils'
5
+ autoload :Password, 'zero_auth/password'
6
+
7
+ module Model
8
+ autoload :Password, 'zero_auth/model/password'
9
+ end
10
+
11
+ # Exception raised througout the library when a method expected to
12
+ # perform some type of authentication on user supplied parameters cannot be
13
+ # authenticated.
14
+ #
15
+ class Unauthorized < StandardError; end
4
16
  end
@@ -0,0 +1,86 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe ZeroAuth::Model::Password do
4
+ class User
5
+ include ZeroAuth::Model::Password
6
+ attr_accessor :password_salt, :password_hash
7
+ end
8
+
9
+ class ArUser < User
10
+ def new_record?
11
+ false
12
+ end
13
+ end
14
+
15
+ let(:user) { User.new }
16
+ before { user.password = "password" }
17
+
18
+ describe "#password=" do
19
+ it "sets the hash and salt to nil given a nil password" do
20
+ user.password = nil
21
+ expect(user.password_salt).to eq(nil)
22
+ expect(user.password_hash).to eq(nil)
23
+ end
24
+
25
+ it "sets the hash and salt given a non-nil password" do
26
+ user.password = "password"
27
+ salt = user.password_salt
28
+ hash = user.password_hash
29
+
30
+ expect(salt).to_not be_empty
31
+ expect(hash).to_not be_empty
32
+
33
+ expected_salt = ZeroAuth::Password.generate_salt
34
+ expect(salt.length).to eq(expected_salt.length)
35
+
36
+ hash_result = ZeroAuth::Password.compare(hash, salt, "password")
37
+ expect(hash_result).to eq(true)
38
+ end
39
+ end
40
+
41
+ describe "#has_password?" do
42
+ it "returns true given a valid password" do
43
+ expect(user.has_password?("password")).to eq(true)
44
+ end
45
+
46
+ it "returns false for an invalid password" do
47
+ expect(user.has_password?("test")).to eq(false)
48
+ end
49
+ end
50
+
51
+ describe "#authenticate!" do
52
+ it "raises a ZeroAuth::Unauthorized error for an invalid password" do
53
+ user.password = "password"
54
+ expect{user.authenticate!("other")}.to raise_error(ZeroAuth::Unauthorized)
55
+ end
56
+
57
+ it "returns true for a valid password" do
58
+ user.password = "password"
59
+ expect(user.authenticate!("password")).to eq(true)
60
+ end
61
+ end
62
+
63
+ describe "#requires_password?" do
64
+ let(:password) { nil }
65
+ before { user.password = password }
66
+ subject { user.requires_password? }
67
+
68
+ context "when the object is not a new #new_record?" do
69
+ context "and its password_hash is empty" do
70
+ it { is_expected.to eq(false) }
71
+ end
72
+
73
+ context "and its password is not-empty" do
74
+ let(:password) { "password" }
75
+ it { is_expected.to eq(true) }
76
+ end
77
+ end
78
+
79
+ context "when the object is a #new_record?" do
80
+ let(:user) { ArUser.new }
81
+ before { allow(user).to receive(:new_record?) { true } }
82
+
83
+ it { is_expected.to eq(true) }
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,31 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe ZeroAuth::Password do
4
+
5
+ describe ".generate_salt" do
6
+ it "returns a BCrypt generated salt" do
7
+ expect(ZeroAuth::Password.generate_salt).to match(/^\$2a\$\d+\$/)
8
+ end
9
+ end
10
+
11
+ describe ".create" do
12
+ it "returns a BCrypt::Password" do
13
+ password = ZeroAuth::Password.create("password", "salt")
14
+ expect(password).to be_a(BCrypt::Password)
15
+ end
16
+ end
17
+
18
+ describe ".compare" do
19
+ let(:password) { ZeroAuth::Password.create("password", "salt").to_s }
20
+
21
+ it "returns true for matching passwords" do
22
+ result = ZeroAuth::Password.compare(password, "salt", "password")
23
+ expect(result).to eq(true)
24
+ end
25
+
26
+ it "returns false for non-matching passwords" do
27
+ result = ZeroAuth::Password.compare(password, "salt", "other")
28
+ expect(result).to eq(false)
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,26 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe ZeroAuth::Utils do
4
+
5
+ describe ".secure_compare" do
6
+ it "returns true for equal values" do
7
+ expect(ZeroAuth::Utils.secure_compare("password", "password")).to eq(true)
8
+ end
9
+
10
+ it "returns false for non-equal values" do
11
+ expect(ZeroAuth::Utils.secure_compare("password", "other")).to eq(false)
12
+ end
13
+
14
+ it "returns false for empty strings" do
15
+ expect(ZeroAuth::Utils.secure_compare("password", "")).to eq(false)
16
+ expect(ZeroAuth::Utils.secure_compare("", "password")).to eq(false)
17
+ expect(ZeroAuth::Utils.secure_compare("", "")).to eq(false)
18
+ end
19
+
20
+ it "returns false for nil values" do
21
+ expect(ZeroAuth::Utils.secure_compare("password", nil)).to eq(false)
22
+ expect(ZeroAuth::Utils.secure_compare(nil, "password")).to eq(false)
23
+ expect(ZeroAuth::Utils.secure_compare(nil, nil)).to eq(false)
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,22 @@
1
+ require 'bundler/setup'
2
+ Bundler.setup
3
+
4
+ require 'zero_auth'
5
+
6
+ RSpec.configure do |config|
7
+ if config.files_to_run.one?
8
+ config.default_formatter = 'doc'
9
+ end
10
+
11
+ config.order = :random
12
+ Kernel.srand config.seed
13
+
14
+ config.expect_with :rspec do |expectations|
15
+ expectations.syntax = :expect
16
+ end
17
+
18
+ config.mock_with :rspec do |mocks|
19
+ mocks.syntax = :expect
20
+ mocks.verify_partial_doubles = true
21
+ end
22
+ end
data/zero_auth.gemspec CHANGED
@@ -17,6 +17,11 @@ Gem::Specification.new do |spec|
17
17
  spec.test_files = spec.files.grep(%r{^spec/})
18
18
  spec.require_paths = ["lib"]
19
19
 
20
- spec.add_development_dependency "bundler", "~> 1.5"
21
- spec.add_development_dependency "rake"
20
+ spec.add_dependency 'bcrypt', '~> 3.1.7'
21
+
22
+ spec.add_development_dependency 'bundler', '~> 1.5'
23
+ spec.add_development_dependency 'rake'
24
+ spec.add_development_dependency 'rspec', '~> 3.0'
25
+ spec.add_development_dependency 'redcarpet'
26
+ spec.add_development_dependency 'yard'
22
27
  end
metadata CHANGED
@@ -1,41 +1,97 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: zero_auth
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1.beta
4
+ version: 0.0.2.beta
5
5
  platform: ruby
6
6
  authors:
7
7
  - Braden Schaeffer
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-06-13 00:00:00.000000000 Z
11
+ date: 2014-08-27 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bcrypt
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 3.1.7
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 3.1.7
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: bundler
15
29
  requirement: !ruby/object:Gem::Requirement
16
30
  requirements:
17
- - - ~>
31
+ - - "~>"
18
32
  - !ruby/object:Gem::Version
19
33
  version: '1.5'
20
34
  type: :development
21
35
  prerelease: false
22
36
  version_requirements: !ruby/object:Gem::Requirement
23
37
  requirements:
24
- - - ~>
38
+ - - "~>"
25
39
  - !ruby/object:Gem::Version
26
40
  version: '1.5'
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: rake
29
43
  requirement: !ruby/object:Gem::Requirement
30
44
  requirements:
31
- - - '>='
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
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
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: redcarpet
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
+ - !ruby/object:Gem::Dependency
84
+ name: yard
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
32
88
  - !ruby/object:Gem::Version
33
89
  version: '0'
34
90
  type: :development
35
91
  prerelease: false
36
92
  version_requirements: !ruby/object:Gem::Requirement
37
93
  requirements:
38
- - - '>='
94
+ - - ">="
39
95
  - !ruby/object:Gem::Version
40
96
  version: '0'
41
97
  description: Zero configuration authentication starter for Rails.
@@ -45,13 +101,23 @@ executables: []
45
101
  extensions: []
46
102
  extra_rdoc_files: []
47
103
  files:
48
- - .gitignore
104
+ - ".gitignore"
105
+ - ".rspec"
106
+ - ".travis.yml"
107
+ - ".yardopts"
49
108
  - Gemfile
50
109
  - LICENSE.txt
51
110
  - README.md
52
111
  - Rakefile
53
112
  - lib/zero_auth.rb
113
+ - lib/zero_auth/model/password.rb
114
+ - lib/zero_auth/password.rb
115
+ - lib/zero_auth/utils.rb
54
116
  - lib/zero_auth/version.rb
117
+ - spec/lib/zero_auth/model/password_spec.rb
118
+ - spec/lib/zero_auth/password_spec.rb
119
+ - spec/lib/zero_auth/utils_spec.rb
120
+ - spec/spec_helper.rb
55
121
  - zero_auth.gemspec
56
122
  homepage: https://github.com/bschaeffer/zero_auth
57
123
  licenses:
@@ -63,18 +129,23 @@ require_paths:
63
129
  - lib
64
130
  required_ruby_version: !ruby/object:Gem::Requirement
65
131
  requirements:
66
- - - '>='
132
+ - - ">="
67
133
  - !ruby/object:Gem::Version
68
134
  version: '0'
69
135
  required_rubygems_version: !ruby/object:Gem::Requirement
70
136
  requirements:
71
- - - '>'
137
+ - - ">"
72
138
  - !ruby/object:Gem::Version
73
139
  version: 1.3.1
74
140
  requirements: []
75
141
  rubyforge_project:
76
- rubygems_version: 2.2.1
142
+ rubygems_version: 2.2.2
77
143
  signing_key:
78
144
  specification_version: 4
79
145
  summary: Zero configuration authentication starter for Rails.
80
- test_files: []
146
+ test_files:
147
+ - spec/lib/zero_auth/model/password_spec.rb
148
+ - spec/lib/zero_auth/password_spec.rb
149
+ - spec/lib/zero_auth/utils_spec.rb
150
+ - spec/spec_helper.rb
151
+ has_rdoc: