fx-auth 0.1.0

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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 57a67abeea5df179fa62f86a82ba34b0c1a08b81
4
+ data.tar.gz: 5c0516ed115cb9629c306322c970077e1feb988c
5
+ SHA512:
6
+ metadata.gz: 17fd49fa8252c7f5724cff8c608b48b416e78daf1819a0ff9fa6f2b4000271c51785d3212a11ecc625eb9075cce6dc7b18b493e9ed6d21bf2e4315c20e6b2612
7
+ data.tar.gz: ea8287ffd64bc9c3adf7ac72d2d57b69b7966c88fc6ad5261ecbdaf3634aedf0936078ec4244c000b181befb974e62887e7d31f0984058d6957867d25738266c
data/.gitignore ADDED
@@ -0,0 +1,18 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ .idea
7
+ Gemfile.lock
8
+ InstalledFiles
9
+ _yardoc
10
+ coverage
11
+ doc/
12
+ lib/bundler/man
13
+ pkg
14
+ rdoc
15
+ spec/reports
16
+ test/tmp
17
+ test/version_tmp
18
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Dave Jackson
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,29 @@
1
+ # AuthFx
2
+
3
+ TODO: Write a gem description
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'fx-auth'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install fx-auth
18
+
19
+ ## Usage
20
+
21
+ TODO: Write usage instructions here
22
+
23
+ ## Contributing
24
+
25
+ 1. Fork it
26
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
27
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
28
+ 4. Push to the branch (`git push origin my-new-feature`)
29
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,9 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rubygems'
3
+ require 'cucumber'
4
+ require 'cucumber/rake/task'
5
+
6
+
7
+ Cucumber::Rake::Task.new :test do |task|
8
+ task.cucumber_opts = 'features --format pretty'
9
+ end
@@ -0,0 +1,8 @@
1
+ Feature: Authenticate
2
+
3
+ Scenario: Session Times Out
4
+
5
+ Given I have a User Profile
6
+ And I sign on with valid credentials
7
+ When My session times out
8
+ Then I am offline
@@ -0,0 +1,9 @@
1
+ Feature: Sign Off
2
+
3
+ Scenario: Sign Off
4
+
5
+ Given I have a User Profile
6
+ And I sign on with valid credentials
7
+ And I am online
8
+ When I sign off
9
+ Then I am offline
@@ -0,0 +1,25 @@
1
+ Feature: Sign On
2
+
3
+ Scenario: Valid Credentials
4
+
5
+ Given I have a User Profile
6
+ When I sign on with valid credentials
7
+ Then I am online
8
+
9
+
10
+
11
+ Scenario: Invalid Credentials
12
+
13
+ Given I have a User Profile
14
+ When I try to sign on with invalid credentials
15
+ Then I am offline
16
+
17
+
18
+
19
+ Scenario: Locked Account
20
+
21
+ Given I have a User Profile
22
+ When I try to sign on with invalid credentials
23
+ And I try to sign on with invalid credentials
24
+ And I try to sign on with invalid credentials
25
+ Then I am locked out
@@ -0,0 +1,34 @@
1
+ Feature: Sign Up
2
+
3
+ Scenario: Valid Sign Up
4
+
5
+ When I sign up with valid credentials
6
+ Then I am online
7
+
8
+
9
+
10
+ Scenario: Sign Up with Duplicate Email
11
+
12
+ When I try to sign up with a duplicate email
13
+ Then I receive a duplicate email error
14
+
15
+
16
+
17
+ Scenario: Sign Up with Invalid Email
18
+
19
+ When I try to sign up with an invalid email address
20
+ Then I receive an invalid email error
21
+
22
+
23
+
24
+ Scenario: Sign Up with Missing Email
25
+
26
+ When I try to sign up with a missing email address
27
+ Then I receive an missing email error
28
+
29
+
30
+
31
+ # Scenario: Sign Up with Missing Password
32
+ #
33
+ # When I try to sign up with a missing password
34
+ # Then I receive a missing password error
@@ -0,0 +1,4 @@
1
+
2
+ When /^My session times out$/ do
3
+ @user.pass_key.expires_at = Time.now - 30 * 60 # expired 30 minutes ago
4
+ end
@@ -0,0 +1,10 @@
1
+
2
+ When /^I sign off$/ do
3
+ @user.sign_off
4
+ end
5
+
6
+
7
+ Then /^I am offline$/ do
8
+ @user.status.should == :offline
9
+ end
10
+
@@ -0,0 +1,8 @@
1
+
2
+ When /^I try to sign on with invalid credentials$/ do
3
+ begin
4
+ @user.sign_on 'bad@email.com', 'bad-password'
5
+ rescue => e
6
+ puts e.message
7
+ end
8
+ end
@@ -0,0 +1,3 @@
1
+ Then /^I am locked out$/ do
2
+ @user.status.should == :locked
3
+ end
@@ -0,0 +1,15 @@
1
+
2
+ Given /^I have a User Profile$/ do
3
+ @user = FactoryGirl.create :user_profile
4
+ @user.save # TODO Determine why this is necessary
5
+ end
6
+
7
+
8
+ When /^I sign on with valid credentials$/ do
9
+ @user.sign_on @user.email, 'password'
10
+ end
11
+
12
+
13
+ Then /^I am online$/ do
14
+ @user.status.should == :online
15
+ end
@@ -0,0 +1,15 @@
1
+ When /^I try to sign up with a duplicate email$/ do
2
+ email = FactoryGirl.generate :email
3
+
4
+ begin
5
+ @user = AuthFx::UserProfile.sign_up email, 'password'
6
+ @user = AuthFx::UserProfile.sign_up email, 'password'
7
+ rescue => e
8
+ @message = e.message
9
+ end
10
+ end
11
+
12
+
13
+ Then /^I receive a duplicate email error$/ do
14
+ @message.should == 'We already have that email.'
15
+ end
@@ -0,0 +1,11 @@
1
+
2
+ When /^I try to sign up with an invalid email address$/ do
3
+ @user = AuthFx::UserProfile.sign_up 'bad.email.com', 'password'
4
+ end
5
+
6
+
7
+ Then /^I receive an invalid email error$/ do
8
+ received = JSON.parse({:errors => @user.errors.to_h}.to_json)
9
+ expected = JSON.parse({:errors => {:email => ['Doesn''t look like an email address to me ...']}}.to_json)
10
+ received.should == expected
11
+ end
@@ -0,0 +1,24 @@
1
+
2
+ When /^I try to sign up with a missing email address$/ do
3
+ @user = AuthFx::UserProfile.sign_up '', 'password'
4
+ end
5
+
6
+
7
+ Then /^I receive an missing email error$/ do
8
+ received = JSON.parse({:errors => @user.errors.to_h}.to_json)
9
+ expected = JSON.parse({:errors => {:email => ['We need your email address.']}}.to_json)
10
+ received.should == expected
11
+ end
12
+
13
+
14
+ When /^I try to sign up with a missing password$/ do
15
+ email = FactoryGirl.generate :email
16
+ @user = AuthFx::UserProfile.sign_up email, ''
17
+ end
18
+
19
+
20
+ Then /^I receive a missing password error$/ do
21
+ received = JSON.parse({:errors => @user.errors.to_h}.to_json)
22
+ expected = JSON.parse({:errors => {:pass_phrase => ['Pass phrase must be between 5 and 50 characters long']}}.to_json)
23
+ received.should == expected
24
+ end
@@ -0,0 +1,5 @@
1
+
2
+ Given /^I sign up with valid credentials$/ do
3
+ email = FactoryGirl.generate :email
4
+ @user = AuthFx::UserProfile.sign_up email, 'password'
5
+ end
@@ -0,0 +1,2 @@
1
+ require 'lib/fx-auth/models'
2
+ require './test/factories'
data/fx-auth.gemspec ADDED
@@ -0,0 +1,31 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ lib = File.expand_path('../lib', __FILE__)
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+
6
+ require 'fx-auth/version'
7
+
8
+
9
+ Gem::Specification.new do |gem|
10
+ gem.name = 'fx-auth'
11
+ gem.version = AuthFx::VERSION
12
+
13
+ gem.authors = ['Dave Jackson']
14
+ gem.email = %w(dave.jackson@anywarefx.com)
15
+ gem.description = %q{AuthFx - DataMapper models for RESTful Authentication}
16
+ gem.summary = %q{AuthFx - DataMapper models for RESTful Authentication}
17
+ gem.homepage = ''
18
+
19
+ gem.files = `git ls-files`.split($/)
20
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
21
+ gem.test_files = gem.files.grep(%r{^(features|spec|features)/})
22
+ gem.require_paths = %w(lib)
23
+
24
+ gem.add_dependency 'data_mapper'
25
+
26
+ gem.add_development_dependency 'rake'
27
+ gem.add_development_dependency 'cucumber'
28
+ gem.add_development_dependency 'rspec'
29
+ gem.add_development_dependency 'factory_girl'
30
+ gem.add_development_dependency 'dm-sqlite-adapter'
31
+ end
@@ -0,0 +1,35 @@
1
+ module AuthFx
2
+
3
+ class UserError < StandardError
4
+ end
5
+
6
+
7
+ class MissingUserError < UserError
8
+ def initialize
9
+ super "We can't find a user with that ID." # TODO localize
10
+ end
11
+ end
12
+
13
+
14
+ class DuplicateUserError < UserError
15
+ def initialize
16
+ super "We already have that email." # TODO localize
17
+ end
18
+ end
19
+
20
+
21
+ class InvalidUserError < UserError
22
+ def initialize
23
+ super "The email or pass phrase you provided doesn't match our records." # TODO localize
24
+ end
25
+ end
26
+
27
+
28
+ class LockedUserError < UserError
29
+ def initialize locked_until
30
+ super "Your account is locked. You can try to sign on again in 30 minutes." # TODO localize
31
+ @locked_until = locked_until # TODO display time in message?
32
+ end
33
+ end
34
+
35
+ end
@@ -0,0 +1,15 @@
1
+ require 'data_mapper'
2
+ require 'uuidtools'
3
+
4
+
5
+ %w(
6
+
7
+ errors
8
+ pass_key
9
+ role
10
+ user_profile
11
+
12
+ ).each do |model|
13
+
14
+ require "#{File.dirname(__FILE__)}/#{model}"
15
+ end
@@ -0,0 +1,48 @@
1
+ module AuthFx
2
+
3
+ class PassKey
4
+ include DataMapper::Resource
5
+
6
+ belongs_to :user_profile
7
+
8
+ property :id, Serial
9
+ property :created_at, DateTime
10
+ property :updated_at, DateTime
11
+
12
+ property :token, String, :length => 36, :unique => true
13
+ property :expires_at, Time, :required => true
14
+
15
+
16
+ before :create do
17
+ self.token = UUIDTools::UUID.random_create.to_s
18
+ self.expires_at = Time.now + 30 * 60 # expires 30 minutes from now
19
+ end
20
+
21
+
22
+ def authenticate? token
23
+ self.token == token and !expired?
24
+ end
25
+
26
+
27
+ # TODO Regenerate for each request?
28
+ def regenerate
29
+ self.token = UUIDTools::UUID.random_create.to_s
30
+ reset_timer
31
+ self.token
32
+ end
33
+
34
+
35
+ def expired?
36
+ Time.now > self.expires_at
37
+ end
38
+
39
+
40
+ def reset_timer
41
+ self.expires_at = Time.now + 30 * 60 # the user has another 30 minutes - TODO make configurable
42
+ save
43
+ self.expires_at
44
+ end
45
+
46
+ end
47
+
48
+ end
@@ -0,0 +1,29 @@
1
+ module AuthFx
2
+
3
+ class Role
4
+ include DataMapper::Resource
5
+
6
+ has n, :user_roles, :constraint => :destroy
7
+ has n, :user_profiles, :through => :user_roles
8
+
9
+ property :id, Serial
10
+ property :created_at, DateTime
11
+ property :updated_at, DateTime
12
+
13
+ property :name, String, :required => true, :unique => true
14
+ property :description, Text
15
+ end
16
+
17
+
18
+ class UserRole
19
+ include DataMapper::Resource
20
+
21
+ belongs_to :user_profile
22
+ belongs_to :role
23
+
24
+ property :id, Serial
25
+ property :created_at, DateTime
26
+ property :updated_at, DateTime
27
+ end
28
+
29
+ end
@@ -0,0 +1,166 @@
1
+ module AuthFx
2
+
3
+ class UserProfile
4
+ include DataMapper::Resource
5
+
6
+ has 1, :pass_key, :constraint => :destroy
7
+ has n, :user_roles, :constraint => :destroy
8
+ has n, :roles, :through => :user_roles
9
+
10
+ property :id, Serial
11
+ property :created_at, DateTime
12
+ property :updated_at, DateTime
13
+
14
+ property :email, String,
15
+ :required => true,
16
+ :unique => true,
17
+ :format => :email_address,
18
+ :messages => {
19
+ :presence => "We need your email address.",
20
+ :is_unique => "We already have that email.",
21
+ :format => "Doesn't look like an email address to me ..."
22
+ }
23
+ property :gravatar, String, :length => 255
24
+
25
+ property :email_verification_code, String, :length => 36, :unique => true
26
+ property :verification_code_sent_at, DateTime
27
+ property :verification_code_expires_at, DateTime
28
+ property :email_verified_at, DateTime
29
+
30
+ property :pass_phrase, String, :length => 5..50
31
+ property :pass_phrase_crypt, BCryptHash
32
+ property :pass_phrase_expires_at, Time
33
+
34
+ property :status, Enum[:online, :offline, :locked], :default => :offline
35
+ property :sign_on_attempts, Integer, :default => 0
36
+ property :locked_until, Time
37
+
38
+
39
+ before :create do
40
+ self.email_verification_code = UUIDTools::UUID.random_create.to_s
41
+ user_role = Role.first :name => :user
42
+ self.roles << user_role if user_role
43
+ end
44
+
45
+
46
+ after :valid? do
47
+ self.gravatar = "http://www.gravatar.com/avatar/#{Digest::MD5.hexdigest self.email}"
48
+ if self.pass_phrase != '*****'
49
+ self.pass_phrase_crypt = self.pass_phrase
50
+ self.pass_phrase = '*****'
51
+ end
52
+ end
53
+
54
+
55
+ def self.sign_up email, pass_phrase
56
+ user = UserProfile.first :email => email
57
+ raise DuplicateUserError if user
58
+
59
+ user = UserProfile.new :email => email, :pass_phrase => pass_phrase
60
+ if user.valid?
61
+ user.status = :online
62
+ user.save
63
+ end
64
+ user
65
+ end
66
+
67
+
68
+ def sign_on email, pass_phrase
69
+ self.status = :offline if self.pass_key and self.pass_key.expired?
70
+ self.status = :offline if self.status == :locked and self.lock_expired?
71
+
72
+ if self.status == :online
73
+ self.pass_key
74
+
75
+ elsif self.status == :offline
76
+ if self.email == email and self.pass_phrase_crypt == pass_phrase
77
+ self.status = :online
78
+ save
79
+ self.pass_key
80
+
81
+ else
82
+ self.sign_on_attempts += 1
83
+ save
84
+ raise InvalidUserError unless self.sign_on_attempts >= 3 # TODO make configurable
85
+
86
+ self.status = :locked
87
+ save
88
+ raise LockedUserError.new self.locked_until
89
+ end
90
+
91
+ else # :locked
92
+ raise LockedUserError.new self.locked_until
93
+ end
94
+ end
95
+
96
+
97
+ def sign_off
98
+ self.status = :offline
99
+ save
100
+ end
101
+
102
+
103
+ def status=(value)
104
+ if value == :online
105
+ self.locked_until = Time.now - 30 * 60 # Unlocked 30 minutes ago - TODO make configurable
106
+ self.sign_on_attempts = 0
107
+ self.pass_key = PassKey.new
108
+
109
+ elsif value == :offline
110
+ self.locked_until = Time.now - 30 * 60 # Unlocked 30 minutes ago - TODO make configurable
111
+ self.sign_on_attempts = 0
112
+ self.pass_key.destroy if self.pass_key
113
+
114
+ elsif value == :locked
115
+ self.locked_until = Time.now + 30 * 60 # Lock for 30 minutes - TODO make configurable
116
+ self.pass_key.destroy if self.pass_key
117
+ end
118
+
119
+ super
120
+ end
121
+
122
+
123
+ def status
124
+ self.status = :offline if super == :online and
125
+ self.pass_key and
126
+ self.pass_key.expires_at and
127
+ Time.now > self.pass_key.expires_at
128
+ super
129
+ end
130
+
131
+
132
+ def authenticate? token
133
+ authenticated = (self.status == :online and
134
+ self.pass_key and
135
+ self.pass_key.authenticate? token
136
+ )
137
+ self.pass_key.reset_timer if authenticated
138
+ authenticated
139
+ end
140
+
141
+
142
+ def authorized? *roles
143
+ roles.any? { |role| self.in_role? role }
144
+ end
145
+
146
+
147
+ def in_role? role
148
+ found = self.roles.first :name => role
149
+ !found.nil?
150
+ end
151
+
152
+
153
+ def verify_email? email, code
154
+ self.email_verified = (self.email == email and self.email_verification_code == code)
155
+ save
156
+ self.email_verified
157
+ end
158
+
159
+
160
+ def lock_expired?
161
+ Time.now > self.locked_until
162
+ end
163
+
164
+ end
165
+
166
+ end
@@ -0,0 +1,5 @@
1
+ module AuthFx
2
+
3
+ VERSION = '0.1.0'
4
+
5
+ end
data/lib/fx-auth.rb ADDED
@@ -0,0 +1,3 @@
1
+ require 'fx-auth/version'
2
+ require 'fx-auth/models'
3
+
data/test/factories.rb ADDED
@@ -0,0 +1,17 @@
1
+ require 'factory_girl'
2
+ require 'test/seeds'
3
+
4
+
5
+ FactoryGirl.define do
6
+
7
+ sequence :email do |n|
8
+ "profile#{n}@example.com"
9
+ end
10
+
11
+
12
+ factory :user_profile, :class => AuthFx::UserProfile do
13
+ email
14
+ pass_phrase 'password'
15
+ end
16
+
17
+ end
data/test/seeds.rb ADDED
@@ -0,0 +1,23 @@
1
+ require 'lib/fx-auth/models'
2
+
3
+
4
+ DataMapper::Logger.new $stdout, :debug
5
+ DataMapper.setup :default, 'sqlite::memory:'
6
+ DataMapper.auto_migrate!
7
+
8
+
9
+ AuthFx::UserProfile.create(
10
+ {
11
+ :email => 'admin@authfx.com',
12
+ :pass_phrase => 'password',
13
+
14
+ :roles => [
15
+ {
16
+ :name => 'admin'
17
+ },
18
+ {
19
+ :name => 'user'
20
+ }
21
+ ]
22
+ }
23
+ )
metadata ADDED
@@ -0,0 +1,170 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fx-auth
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Dave Jackson
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-12-11 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - '>='
17
+ - !ruby/object:Gem::Version
18
+ version: '0'
19
+ name: data_mapper
20
+ prerelease: false
21
+ type: :runtime
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ name: rake
34
+ prerelease: false
35
+ type: :development
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ requirement: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - '>='
45
+ - !ruby/object:Gem::Version
46
+ version: '0'
47
+ name: cucumber
48
+ prerelease: false
49
+ type: :development
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ requirement: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - '>='
59
+ - !ruby/object:Gem::Version
60
+ version: '0'
61
+ name: rspec
62
+ prerelease: false
63
+ type: :development
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ requirement: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - '>='
73
+ - !ruby/object:Gem::Version
74
+ version: '0'
75
+ name: factory_girl
76
+ prerelease: false
77
+ type: :development
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - '>='
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ requirement: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - '>='
87
+ - !ruby/object:Gem::Version
88
+ version: '0'
89
+ name: dm-sqlite-adapter
90
+ prerelease: false
91
+ type: :development
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - '>='
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ description: AuthFx - DataMapper models for RESTful Authentication
98
+ email:
99
+ - dave.jackson@anywarefx.com
100
+ executables: []
101
+ extensions: []
102
+ extra_rdoc_files: []
103
+ files:
104
+ - .gitignore
105
+ - Gemfile
106
+ - LICENSE.txt
107
+ - README.md
108
+ - Rakefile
109
+ - features/authenticate.feature
110
+ - features/sign_off.feature
111
+ - features/sign_on.feature
112
+ - features/sign_up.feature
113
+ - features/step_definitions/authenticate/session_times_out.rb
114
+ - features/step_definitions/sign_off/sign_off.rb
115
+ - features/step_definitions/sign_on/invalid_credentials.rb
116
+ - features/step_definitions/sign_on/locked_account.rb
117
+ - features/step_definitions/sign_on/valid_credentials.rb
118
+ - features/step_definitions/sign_up/duplicate_email.rb
119
+ - features/step_definitions/sign_up/invalid_email.rb
120
+ - features/step_definitions/sign_up/missing_credentials.rb
121
+ - features/step_definitions/sign_up/valid_sign_up.rb
122
+ - features/support/env.rb
123
+ - fx-auth.gemspec
124
+ - lib/fx-auth.rb
125
+ - lib/fx-auth/errors.rb
126
+ - lib/fx-auth/models.rb
127
+ - lib/fx-auth/pass_key.rb
128
+ - lib/fx-auth/role.rb
129
+ - lib/fx-auth/user_profile.rb
130
+ - lib/fx-auth/version.rb
131
+ - test/factories.rb
132
+ - test/seeds.rb
133
+ homepage: ''
134
+ licenses: []
135
+ metadata: {}
136
+ post_install_message:
137
+ rdoc_options: []
138
+ require_paths:
139
+ - lib
140
+ required_ruby_version: !ruby/object:Gem::Requirement
141
+ requirements:
142
+ - - '>='
143
+ - !ruby/object:Gem::Version
144
+ version: '0'
145
+ required_rubygems_version: !ruby/object:Gem::Requirement
146
+ requirements:
147
+ - - '>='
148
+ - !ruby/object:Gem::Version
149
+ version: '0'
150
+ requirements: []
151
+ rubyforge_project:
152
+ rubygems_version: 2.1.9
153
+ signing_key:
154
+ specification_version: 4
155
+ summary: AuthFx - DataMapper models for RESTful Authentication
156
+ test_files:
157
+ - features/authenticate.feature
158
+ - features/sign_off.feature
159
+ - features/sign_on.feature
160
+ - features/sign_up.feature
161
+ - features/step_definitions/authenticate/session_times_out.rb
162
+ - features/step_definitions/sign_off/sign_off.rb
163
+ - features/step_definitions/sign_on/invalid_credentials.rb
164
+ - features/step_definitions/sign_on/locked_account.rb
165
+ - features/step_definitions/sign_on/valid_credentials.rb
166
+ - features/step_definitions/sign_up/duplicate_email.rb
167
+ - features/step_definitions/sign_up/invalid_email.rb
168
+ - features/step_definitions/sign_up/missing_credentials.rb
169
+ - features/step_definitions/sign_up/valid_sign_up.rb
170
+ - features/support/env.rb