theworkinggroup-wristband 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +130 -0
- data/Rakefile +39 -0
- data/generators/wristband/templates/app/controllers/sessions_controller.rb +50 -0
- data/generators/wristband/templates/app/controllers/users_controller.rb +47 -0
- data/generators/wristband/templates/app/models/user.rb +30 -0
- data/generators/wristband/templates/app/models/user_notifier.rb +54 -0
- data/generators/wristband/templates/app/views/sessions/new.html.haml +17 -0
- data/generators/wristband/templates/app/views/user_notifier/email_verification.text.html.rhtml +7 -0
- data/generators/wristband/templates/app/views/user_notifier/email_verification.text.plain.rhtml +9 -0
- data/generators/wristband/templates/app/views/user_notifier/forgot_password.text.html.rhtml +10 -0
- data/generators/wristband/templates/app/views/user_notifier/forgot_password.text.plain.rhtml +10 -0
- data/generators/wristband/templates/app/views/users/forgot_password.html.haml +10 -0
- data/generators/wristband/templates/app/views/users/index.html.haml +6 -0
- data/generators/wristband/templates/db/migrate/create_wristband_tables.rb +28 -0
- data/generators/wristband/wristband_generator.rb +69 -0
- data/init.rb +1 -0
- data/lib/wristband.rb +121 -0
- data/lib/wristband/application_extensions.rb +78 -0
- data/lib/wristband/authority_check.rb +160 -0
- data/lib/wristband/support.rb +28 -0
- data/lib/wristband/user_extensions.rb +89 -0
- data/test/database.yml +3 -0
- data/test/fixtures/crypted_password_users.yml +12 -0
- data/test/fixtures/plain_text_password_users.yml +4 -0
- data/test/fixtures/users.yml +23 -0
- data/test/schema.rb +34 -0
- data/test/test_helper.rb +40 -0
- data/test/unit/crypted_password_users_test.rb +81 -0
- data/test/unit/has_authorities_test.rb +49 -0
- data/test/unit/plain_text_password_user_test.rb +92 -0
- data/wristband.gemspec +32 -0
- metadata +97 -0
@@ -0,0 +1,89 @@
|
|
1
|
+
module Wristband
|
2
|
+
module UserExtensions
|
3
|
+
def self.included(base)
|
4
|
+
base.send(:extend, Wristband::UserExtensions::ClassMethods)
|
5
|
+
base.send(:include, Wristband::UserExtensions::InstanceMethods)
|
6
|
+
base.send(:extend, Wristband::Support)
|
7
|
+
end
|
8
|
+
|
9
|
+
module ClassMethods
|
10
|
+
def authenticate(username, password)
|
11
|
+
self.execute_authentication_chain(self, self.wristband[:before_authentication_chain]) == false and return
|
12
|
+
user = nil
|
13
|
+
wristband[:login_with_fields].find do |field|
|
14
|
+
user = send("find_by_#{field}", username)
|
15
|
+
end
|
16
|
+
(user and user.password_match?(password)) || return
|
17
|
+
self.execute_authentication_chain(user, self.wristband[:after_authentication_chain]) == false and return
|
18
|
+
user
|
19
|
+
end
|
20
|
+
|
21
|
+
def execute_authentication_chain(object, list)
|
22
|
+
list.each do |func|
|
23
|
+
case func
|
24
|
+
when Symbol,String
|
25
|
+
object.send(func) == false and return false
|
26
|
+
when Proc
|
27
|
+
func.call(object) == false and return false
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def verify_email!(email_validation_key)
|
33
|
+
if user = find_by_email_validation_key(email_validation_key)
|
34
|
+
user.update_attribute(:validated_at, Time.now.to_s(:db))
|
35
|
+
user
|
36
|
+
else
|
37
|
+
raise UserVerificationError, 'We were not able to verify your account or it may have been verified already. Please contact us for assistance.'.t
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
|
43
|
+
module InstanceMethods
|
44
|
+
|
45
|
+
def has_authority_to?(action, options = { })
|
46
|
+
self.class.wristband[:authority_class].new(self, action, options).allowed_to?
|
47
|
+
end
|
48
|
+
|
49
|
+
def has_objections_to?(action, options = { })
|
50
|
+
self.class.wristband[:authority_class].new(self, action, options).denied_for_reasons
|
51
|
+
end
|
52
|
+
|
53
|
+
def initialize_salt
|
54
|
+
self.password_salt = Wristband::Support.random_salt
|
55
|
+
end
|
56
|
+
|
57
|
+
def initialize_token
|
58
|
+
self.remember_token = Wristband::Support.random_salt(16)
|
59
|
+
end
|
60
|
+
|
61
|
+
def encrypt_password
|
62
|
+
initialize_salt if new_record?
|
63
|
+
return if self.password.blank?
|
64
|
+
self.send("#{self.class.wristband[:password_column]}=", Wristband::Support.encrypt_with_salt(self.password, self.password_salt))
|
65
|
+
end
|
66
|
+
|
67
|
+
def password_match?(string)
|
68
|
+
if self.class.wristband[:plain_text_password]
|
69
|
+
self.send(self.class.wristband[:password_column]) == string
|
70
|
+
else
|
71
|
+
self.send(self.class.wristband[:password_column]) == Wristband::Support.encrypt_with_salt(string, self.password_salt)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def password_crypted?
|
76
|
+
self.password_salt and !self.password_salt.empty?
|
77
|
+
end
|
78
|
+
|
79
|
+
def password_crypt=(value)
|
80
|
+
if (value != read_attribute(:password_crypt))
|
81
|
+
initialize_token
|
82
|
+
end
|
83
|
+
|
84
|
+
write_attribute(:password_crypt, value)
|
85
|
+
end
|
86
|
+
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
data/test/database.yml
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
scott:
|
2
|
+
username: scott_tadman
|
3
|
+
email: scott@theworkinggroup.ca
|
4
|
+
password_crypt: passpass
|
5
|
+
role: admin
|
6
|
+
|
7
|
+
jack:
|
8
|
+
username: jack_neto
|
9
|
+
email: jack@theworkinggroup.ca
|
10
|
+
password_crypt: 7d103e2aee36a422ac5f619705e244b03c9e1328
|
11
|
+
password_salt: ad28d83c111a5ab70cef9d0896e5b18e84d899ef
|
12
|
+
role: regular_user
|
@@ -0,0 +1,23 @@
|
|
1
|
+
scott:
|
2
|
+
username: scott
|
3
|
+
email: scott@theworkinggroup.ca
|
4
|
+
password_crypt: passpass
|
5
|
+
|
6
|
+
jack:
|
7
|
+
username: jack
|
8
|
+
email: jack@theworkinggroup.ca
|
9
|
+
password_crypt: 7d103e2aee36a422ac5f619705e244b03c9e1328
|
10
|
+
password_salt: ad28d83c111a5ab70cef9d0896e5b18e84d899ef
|
11
|
+
|
12
|
+
oleg:
|
13
|
+
username: oleg
|
14
|
+
email: oleg@theworkinggroup.ca
|
15
|
+
password_crypt: 7d103e2aee36a422ac5f619705e244b03c9e1328
|
16
|
+
password_salt: ad28d83c111a5ab70cef9d0896e5b18e84d899ef
|
17
|
+
|
18
|
+
hesham:
|
19
|
+
username: hesham
|
20
|
+
email: hesham@theworkinggroup.ca
|
21
|
+
password_crypt: 7d103e2aee36a422ac5f619705e244b03c9e1328
|
22
|
+
password_salt: ad28d83c111a5ab70cef9d0896e5b18e84d899ef
|
23
|
+
|
data/test/schema.rb
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
ActiveRecord::Schema.define(:version => 1) do
|
2
|
+
|
3
|
+
create_table :crypted_password_users do |t|
|
4
|
+
t.string :username
|
5
|
+
t.string :email
|
6
|
+
t.string :password_crypt, :limit => 40
|
7
|
+
t.string :password_salt, :limit => 40
|
8
|
+
t.string :remember_token
|
9
|
+
t.string :role
|
10
|
+
t.datetime :created_at
|
11
|
+
t.datetime :updated_at
|
12
|
+
end
|
13
|
+
|
14
|
+
create_table :plain_text_password_users do |t|
|
15
|
+
t.string :username
|
16
|
+
t.string :email
|
17
|
+
t.string :password
|
18
|
+
t.string :remember_token
|
19
|
+
t.string :email_validation_key
|
20
|
+
t.datetime :created_at
|
21
|
+
t.datetime :updated_at
|
22
|
+
end
|
23
|
+
|
24
|
+
create_table :users do |t|
|
25
|
+
t.string :username
|
26
|
+
t.string :email
|
27
|
+
t.string :password_crypt, :limit => 40
|
28
|
+
t.string :password_salt, :limit => 40
|
29
|
+
t.string :remember_token
|
30
|
+
t.datetime :created_at
|
31
|
+
t.datetime :updated_at
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
$:.unshift(File.dirname(__FILE__) + '/../lib')
|
2
|
+
|
3
|
+
require 'test/unit'
|
4
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '../../../../config/environment.rb'))
|
5
|
+
require 'rubygems'
|
6
|
+
# require 'active_support/breakpoint'
|
7
|
+
require 'active_record/fixtures'
|
8
|
+
|
9
|
+
config = YAML::load(IO.read( File.join(File.dirname(__FILE__),'database.yml')))
|
10
|
+
|
11
|
+
# cleanup logs and databases between test runs
|
12
|
+
#FileUtils.rm File.join(File.dirname(__FILE__), "debug.log"), :force => true
|
13
|
+
FileUtils.rm File.join(RAILS_ROOT, config['sqlite3'][:dbfile]), :force => true
|
14
|
+
|
15
|
+
ActiveRecord::Base.logger = Logger.new(File.join(File.dirname(__FILE__), "debug.log"))
|
16
|
+
ActiveRecord::Base.establish_connection(config[ENV['DB'] || 'sqlite3'])
|
17
|
+
|
18
|
+
load(File.join(File.dirname(__FILE__), "schema.rb"))
|
19
|
+
|
20
|
+
Test::Unit::TestCase.fixture_path = File.dirname(__FILE__) + "/fixtures/"
|
21
|
+
$LOAD_PATH.unshift(Test::Unit::TestCase.fixture_path)
|
22
|
+
|
23
|
+
class Test::Unit::TestCase #:nodoc:
|
24
|
+
def create_fixtures(*table_names)
|
25
|
+
if block_given?
|
26
|
+
Fixtures.create_fixtures(Test::Unit::TestCase.fixture_path, table_names) { yield }
|
27
|
+
else
|
28
|
+
Fixtures.create_fixtures(Test::Unit::TestCase.fixture_path, table_names)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
# Turn off transactional fixtures if you're working with MyISAM tables in MySQL
|
33
|
+
self.use_transactional_fixtures = true
|
34
|
+
|
35
|
+
# Instantiated fixtures are slow, but give you @david where you otherwise would need people(:david)
|
36
|
+
self.use_instantiated_fixtures = false
|
37
|
+
|
38
|
+
# Instantiated fixtures are slow, but give you @david where you otherwise would need people(:david)
|
39
|
+
|
40
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '../test_helper')
|
2
|
+
|
3
|
+
class CryptedPasswordUser < ActiveRecord::Base
|
4
|
+
wristband :roles => [:admin, :regular_user]
|
5
|
+
end
|
6
|
+
|
7
|
+
|
8
|
+
class CryptedPasswordUserTest < Test::Unit::TestCase
|
9
|
+
fixtures :crypted_password_users
|
10
|
+
|
11
|
+
def setup
|
12
|
+
@scott = crypted_password_users(:scott)
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_user_instance_methods
|
16
|
+
%w{
|
17
|
+
has_authority_to?
|
18
|
+
has_objections_to?
|
19
|
+
initialize_salt
|
20
|
+
initialize_token
|
21
|
+
encrypt_password
|
22
|
+
password_match?
|
23
|
+
password_crypted?
|
24
|
+
password_crypt=
|
25
|
+
is_admin?
|
26
|
+
is_regular_user?
|
27
|
+
}.each do |method|
|
28
|
+
assert @scott.respond_to?(method), "On '#{method}' method"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_user_class_methods
|
33
|
+
%w{
|
34
|
+
authenticate
|
35
|
+
execute_authentication_chain
|
36
|
+
verify_email!
|
37
|
+
wristband
|
38
|
+
}.each do |method|
|
39
|
+
assert CryptedPasswordUser.respond_to?(method), "On '#{method}' method"
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def test_user_class_private_methods
|
44
|
+
%w{
|
45
|
+
random_string
|
46
|
+
encrypt_with_salt
|
47
|
+
random_salt
|
48
|
+
}.each do |method|
|
49
|
+
assert CryptedPasswordUser.private_methods.include?(method), "On '#{method}' method"
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def test_assigned_options
|
54
|
+
assert_equal CryptedPasswordUser.wristband[:login_with_fields], [:username]
|
55
|
+
assert_equal CryptedPasswordUser.wristband[:plain_text_password], false
|
56
|
+
assert_equal CryptedPasswordUser.wristband[:before_authentication_chain], []
|
57
|
+
assert_equal CryptedPasswordUser.wristband[:after_authentication_chain], []
|
58
|
+
assert_equal CryptedPasswordUser.wristband[:password_column], :password_crypt
|
59
|
+
assert_equal CryptedPasswordUser.wristband[:roles], [:admin, :regular_user]
|
60
|
+
end
|
61
|
+
|
62
|
+
def test_authentication_by_username
|
63
|
+
assert_equal @scott, CryptedPasswordUser.authenticate(@scott.username, @scott.password_crypt)
|
64
|
+
end
|
65
|
+
|
66
|
+
def test_authentication_fails
|
67
|
+
assert_nil CryptedPasswordUser.authenticate('-bugus-', @scott.password_crypt)
|
68
|
+
assert_nil CryptedPasswordUser.authenticate(@scott.email, '-bugus-')
|
69
|
+
end
|
70
|
+
|
71
|
+
def test_password_match
|
72
|
+
assert @scott.password_match?(@scott.password_crypt)
|
73
|
+
assert crypted_password_users(:jack).password_match?('passpass')
|
74
|
+
end
|
75
|
+
|
76
|
+
def test_user_roles
|
77
|
+
assert crypted_password_users(:jack).is_regular_user?
|
78
|
+
assert crypted_password_users(:scott).is_admin?
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '../test_helper')
|
2
|
+
|
3
|
+
class UserAuthorityCheck < AuthorityCheck
|
4
|
+
before_check :is_admin?
|
5
|
+
|
6
|
+
def is_admin?
|
7
|
+
unless (@user.username.match(/^scott/i))
|
8
|
+
fail!("Only scott can be an admin.")
|
9
|
+
else
|
10
|
+
allow!
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def wear_shoes?
|
15
|
+
unless (@user.username.match(/^s/i))
|
16
|
+
fail!("Only people with names that start with 'S' can wear shoes.")
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def walk_outside?
|
21
|
+
wear_shoes?
|
22
|
+
unless (@user.username.match(/^j/i))
|
23
|
+
fail!("Only people with names that start with 'J' or 'S' can walk outside.")
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
class User < ActiveRecord::Base
|
30
|
+
wristband :has_authorities => true
|
31
|
+
end
|
32
|
+
|
33
|
+
|
34
|
+
class HasAuthoritiesTest < Test::Unit::TestCase
|
35
|
+
fixtures :users
|
36
|
+
|
37
|
+
def test_has_authority_to_with_fail
|
38
|
+
assert users(:scott).has_authority_to?(:wear_shoes)
|
39
|
+
assert !users(:jack).has_authority_to?(:wear_shoes)
|
40
|
+
assert_equal users(:jack).has_objections_to?(:wear_shoes), ["Only scott can be an admin.", "Only people with names that start with 'S' can wear shoes."]
|
41
|
+
|
42
|
+
|
43
|
+
assert users(:scott).has_authority_to?(:walk_outside)
|
44
|
+
assert !users(:jack).has_authority_to?(:walk_outside)
|
45
|
+
assert_equal users(:jack).has_objections_to?(:walk_outside), ["Only scott can be an admin.", "Only people with names that start with 'S' can wear shoes."]
|
46
|
+
assert !users(:oleg).has_authority_to?(:walk_outside)
|
47
|
+
assert_equal users(:oleg).has_objections_to?(:walk_outside), ["Only scott can be an admin.", "Only people with names that start with 'S' can wear shoes.", "Only people with names that start with 'J' or 'S' can walk outside."]
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '../test_helper')
|
2
|
+
|
3
|
+
class PlainTextPasswordUser < ActiveRecord::Base
|
4
|
+
wristband :login_with => [:username, :email],
|
5
|
+
:plain_text_password => true,
|
6
|
+
:after_authentication => :email_is_verified?,
|
7
|
+
:password_column => :password
|
8
|
+
|
9
|
+
def email_is_verified?
|
10
|
+
return self.email_validation_key.blank?
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
|
15
|
+
|
16
|
+
class PlainTextPasswordUserTest < Test::Unit::TestCase
|
17
|
+
fixtures :plain_text_password_users
|
18
|
+
|
19
|
+
def setup
|
20
|
+
@jack = plain_text_password_users(:jack)
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_user_instance_methods
|
24
|
+
%w{
|
25
|
+
has_authority_to?
|
26
|
+
has_objections_to?
|
27
|
+
initialize_salt
|
28
|
+
initialize_token
|
29
|
+
encrypt_password
|
30
|
+
password_match?
|
31
|
+
password_crypted?
|
32
|
+
password_crypt=
|
33
|
+
}.each do |method|
|
34
|
+
assert @jack.respond_to?(method), "On '#{method}' method"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_user_class_methods
|
39
|
+
%w{
|
40
|
+
authenticate
|
41
|
+
execute_authentication_chain
|
42
|
+
verify_email!
|
43
|
+
wristband
|
44
|
+
}.each do |method|
|
45
|
+
assert PlainTextPasswordUser.respond_to?(method), "On '#{method}' method"
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def test_user_class_private_methods
|
50
|
+
%w{
|
51
|
+
random_string
|
52
|
+
encrypt_with_salt
|
53
|
+
random_salt
|
54
|
+
}.each do |method|
|
55
|
+
assert PlainTextPasswordUser.private_methods.include?(method), "On '#{method}' method"
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def test_assigned_options
|
60
|
+
assert_equal PlainTextPasswordUser.wristband[:login_with_fields], [:username, :email]
|
61
|
+
assert_equal PlainTextPasswordUser.wristband[:plain_text_password], true
|
62
|
+
assert_equal PlainTextPasswordUser.wristband[:before_authentication_chain], []
|
63
|
+
assert_equal PlainTextPasswordUser.wristband[:after_authentication_chain], [:email_is_verified?]
|
64
|
+
assert_equal PlainTextPasswordUser.wristband[:password_column], :password
|
65
|
+
assert_equal PlainTextPasswordUser.wristband[:roles], []
|
66
|
+
end
|
67
|
+
|
68
|
+
def test_authentication_by_username
|
69
|
+
assert_equal @jack, PlainTextPasswordUser.authenticate(@jack.username, @jack.password)
|
70
|
+
end
|
71
|
+
|
72
|
+
def test_authentication_by_email
|
73
|
+
assert_equal @jack, PlainTextPasswordUser.authenticate(@jack.email, @jack.password)
|
74
|
+
end
|
75
|
+
|
76
|
+
def test_authentication_fails
|
77
|
+
assert_nil PlainTextPasswordUser.authenticate('-bugus-', @jack.password)
|
78
|
+
assert_nil PlainTextPasswordUser.authenticate(@jack.email, '-bugus-')
|
79
|
+
end
|
80
|
+
|
81
|
+
def test_after_authentication_chain
|
82
|
+
@jack.update_attribute(:email_validation_key, Time.now)
|
83
|
+
assert_nil PlainTextPasswordUser.authenticate(@jack.username, @jack.password)
|
84
|
+
|
85
|
+
@jack.update_attribute(:email_validation_key, nil)
|
86
|
+
assert_equal @jack, PlainTextPasswordUser.authenticate(@jack.username, @jack.password)
|
87
|
+
end
|
88
|
+
|
89
|
+
def test_password_match
|
90
|
+
assert @jack.password_match?(@jack.password)
|
91
|
+
end
|
92
|
+
end
|
data/wristband.gemspec
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = %q{wristband}
|
5
|
+
s.version = "1.0.0"
|
6
|
+
|
7
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
|
8
|
+
s.authors = ["Jack Neto"]
|
9
|
+
s.date = %q{2009-03-26}
|
10
|
+
s.description = %q{Simplifies the process of authenticating and authorizing users.}
|
11
|
+
s.email = %q{jack@theworkinggroup.ca}
|
12
|
+
s.extra_rdoc_files = ["lib/wristband/application_extensions.rb", "lib/wristband/authority_check.rb", "lib/wristband/support.rb", "lib/wristband/user_extensions.rb", "lib/wristband.rb", "README.rdoc"]
|
13
|
+
s.files = ["generators/wristband/templates/app/controllers/sessions_controller.rb", "generators/wristband/templates/app/controllers/users_controller.rb", "generators/wristband/templates/app/models/user.rb", "generators/wristband/templates/app/models/user_notifier.rb", "generators/wristband/templates/app/views/sessions/new.html.haml", "generators/wristband/templates/app/views/user_notifier/email_verification.text.html.rhtml", "generators/wristband/templates/app/views/user_notifier/email_verification.text.plain.rhtml", "generators/wristband/templates/app/views/user_notifier/forgot_password.text.html.rhtml", "generators/wristband/templates/app/views/user_notifier/forgot_password.text.plain.rhtml", "generators/wristband/templates/app/views/users/forgot_password.html.haml", "generators/wristband/templates/app/views/users/index.html.haml", "generators/wristband/templates/db/migrate/create_wristband_tables.rb", "generators/wristband/wristband_generator.rb", "init.rb", "lib/wristband/application_extensions.rb", "lib/wristband/authority_check.rb", "lib/wristband/support.rb", "lib/wristband/user_extensions.rb", "lib/wristband.rb", "Manifest", "Rakefile", "README.rdoc", "test/database.yml", "test/fixtures/crypted_password_users.yml", "test/fixtures/plain_text_password_users.yml", "test/fixtures/users.yml", "test/schema.rb", "test/test_helper.rb", "test/unit/crypted_password_users_test.rb", "test/unit/has_authorities_test.rb", "test/unit/plain_text_password_user_test.rb", "wristband.gemspec"]
|
14
|
+
s.has_rdoc = true
|
15
|
+
s.homepage = %q{http://github.com/theworkinggroup/wristband}
|
16
|
+
s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Wristband", "--main", "README.rdoc"]
|
17
|
+
s.require_paths = ["lib"]
|
18
|
+
s.rubyforge_project = %q{wristband}
|
19
|
+
s.rubygems_version = %q{1.3.1}
|
20
|
+
s.summary = %q{Simplifies the process of authenticating and authorizing users.}
|
21
|
+
s.test_files = ["test/test_helper.rb", "test/unit/crypted_password_users_test.rb", "test/unit/has_authorities_test.rb", "test/unit/plain_text_password_user_test.rb"]
|
22
|
+
|
23
|
+
if s.respond_to? :specification_version then
|
24
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
25
|
+
s.specification_version = 2
|
26
|
+
|
27
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
28
|
+
else
|
29
|
+
end
|
30
|
+
else
|
31
|
+
end
|
32
|
+
end
|