fx-auth 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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