accounts 0.0.1
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.
- data/.gitignore +2 -0
- data/.rvmrc +53 -0
- data/Gemfile +2 -0
- data/Gemfile.lock +167 -0
- data/README.mkd +105 -0
- data/Rakefile +24 -0
- data/accounts.gemspec +52 -0
- data/demo/views/change_email.haml +14 -0
- data/demo/views/change_password.haml +36 -0
- data/demo/views/forgot_password.haml +21 -0
- data/demo/views/logon.haml +24 -0
- data/demo/views/register.haml +15 -0
- data/demo/web_app.rb +99 -0
- data/features/change-email.feature +51 -0
- data/features/change-password.feature +89 -0
- data/features/register.feature +42 -0
- data/features/step_definitions/steps.rb +102 -0
- data/features/step_definitions/web_steps.rb +228 -0
- data/features/support/env.rb +18 -0
- data/features/support/paths.rb +29 -0
- data/features/support/unused.rb +29 -0
- data/lib/accounts.rb +79 -0
- data/lib/accounts/configure.rb +122 -0
- data/lib/accounts/helpers.rb +90 -0
- data/lib/accounts/model.rb +126 -0
- data/lib/accounts/version.rb +5 -0
- data/spec/user_model_spec.rb +105 -0
- metadata +263 -0
@@ -0,0 +1,90 @@
|
|
1
|
+
# Copyright Westside Consulting LLC, Ann Arbor, MI, USA, 2012
|
2
|
+
|
3
|
+
module Accounts
|
4
|
+
module Helpers
|
5
|
+
class ::Accounts::AccountsError < Exception
|
6
|
+
attr_accessor :code
|
7
|
+
attr_accessor :message
|
8
|
+
|
9
|
+
def initialize(code, message)
|
10
|
+
@code = code
|
11
|
+
@message = message
|
12
|
+
end
|
13
|
+
|
14
|
+
def return_error_page
|
15
|
+
[ @code, @message ]
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def site
|
20
|
+
scheme = request.env['rack.url_scheme']
|
21
|
+
host = request.env['HTTP_HOST'] # includes port number
|
22
|
+
"#{scheme}://#{host}"
|
23
|
+
end
|
24
|
+
|
25
|
+
def send_change_password_link(account)
|
26
|
+
tok = ::Accounts::ActionToken.create({ :account => account, :action => 'reset password' })
|
27
|
+
link = "#{site}/response-token/#{tok.id}"
|
28
|
+
Accounts.deliver_change_password_link[account.email, link]
|
29
|
+
end
|
30
|
+
|
31
|
+
def send_change_email_confirmation(account, new_email)
|
32
|
+
tok = ::Accounts::ActionToken.create({
|
33
|
+
:account => account,
|
34
|
+
:action => 'change email',
|
35
|
+
:params => {:new_email => new_email}
|
36
|
+
})
|
37
|
+
link = "#{site}/response-token/#{tok.id}"
|
38
|
+
Accounts.deliver_change_email_confirmation[account.email, new_email, link]
|
39
|
+
end
|
40
|
+
|
41
|
+
def on_email_confirmed(account)
|
42
|
+
account.status << :email_confirmed
|
43
|
+
account.taint! :status # taint!() defined in model.rb
|
44
|
+
account.save
|
45
|
+
Accounts.deliver_new_account_admin_notification[account.email]
|
46
|
+
end
|
47
|
+
|
48
|
+
def respond_to_token(id)
|
49
|
+
token = ::Accounts::ActionToken.get(id)
|
50
|
+
|
51
|
+
raise ::Accounts::AccountsError.new 404, %Q{Page not found. Go to <a href="/">home page</a>.} \
|
52
|
+
unless token
|
53
|
+
|
54
|
+
begin
|
55
|
+
on_email_confirmed token.account \
|
56
|
+
unless token.account.status.include? :email_confirmed
|
57
|
+
|
58
|
+
case token.action
|
59
|
+
when 'change email' then
|
60
|
+
token.account.email = token.params[:new_email]
|
61
|
+
token.account.save or return "We are unable to change your e-mail right now. Try again later."
|
62
|
+
session[:account_id] = token.account.id # this visitor is authenticated
|
63
|
+
redirect to("/logon?email=#{token.params[:new_email]}")
|
64
|
+
when 'reset password' then
|
65
|
+
session[:account_id] = token.account.id # this visitor is authenticated
|
66
|
+
redirect '/change-password'
|
67
|
+
else
|
68
|
+
nil
|
69
|
+
end
|
70
|
+
ensure
|
71
|
+
token.destroy or raise "Failed to destroy token #{token.id}"
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def authenticate!(email, password)
|
76
|
+
account = ::Accounts::Account.first(:email => email) \
|
77
|
+
or return false
|
78
|
+
account.confirm_password(password) or return false
|
79
|
+
session[:account_id] = account.id
|
80
|
+
end
|
81
|
+
|
82
|
+
def register_new_account(email)
|
83
|
+
account = ::Accounts::Account.create ({ :email => email })
|
84
|
+
account.saved? or return "We are unable to register you at this time. Please try again later."
|
85
|
+
tok = ::Accounts::ActionToken.create({ :account => account, :action => 'reset password' })
|
86
|
+
link = "#{site}/response-token/#{tok.id}"
|
87
|
+
Accounts.deliver_registration_confirmation[account.email, link]
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
@@ -0,0 +1,126 @@
|
|
1
|
+
# Copyright Westside Consulting LLC, Ann Arbor, MI, USA, 2012
|
2
|
+
|
3
|
+
require 'data_mapper'
|
4
|
+
require 'dm-types/enum'
|
5
|
+
require 'dm-types/flag'
|
6
|
+
require 'digest/sha2'
|
7
|
+
|
8
|
+
DataMapper.setup(:default, ENV['DATABASE_URL'] || 'postgres:accounts')
|
9
|
+
DataMapper::Property::String.length(255)
|
10
|
+
DataMapper::Property::Boolean.allow_nil(false)
|
11
|
+
DataMapper::Property::Boolean.default(false)
|
12
|
+
|
13
|
+
#DataMapper::Model.raise_on_save_failure = true
|
14
|
+
|
15
|
+
#=begin
|
16
|
+
# Override definition in dm-core / lib / dm-core / resource.rb
|
17
|
+
# http://github.com/datamapper/dm-core/blob/master/lib/dm-core/resource.rb
|
18
|
+
# Get it to log messages when there is a problem saving.
|
19
|
+
module DataMapper
|
20
|
+
module Resource
|
21
|
+
|
22
|
+
#@@logger = Logger.new(STDOUT)
|
23
|
+
|
24
|
+
# override .save
|
25
|
+
# @see http://blog.jayfields.com/2006/12/ruby-alias-method-alternative.html
|
26
|
+
base_save = self.instance_method(:save)
|
27
|
+
|
28
|
+
define_method(:save) do |*a|
|
29
|
+
result = base_save.bind(self).call(*a)
|
30
|
+
|
31
|
+
if !result then
|
32
|
+
STDERR.puts "Cannot save #{self.class.to_s}"
|
33
|
+
STDERR.puts self.pretty_inspect
|
34
|
+
self.errors.each {|e| STDERR.puts e.to_s}
|
35
|
+
end
|
36
|
+
result
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
#=end
|
41
|
+
|
42
|
+
# modified from https://gist.github.com/763374
|
43
|
+
module DataMapper
|
44
|
+
module Resource
|
45
|
+
def taint! property
|
46
|
+
self.persistence_state = PersistenceState::Dirty.new(self) \
|
47
|
+
unless self.persistence_state.kind_of?(PersistenceState::Dirty)
|
48
|
+
self.persistence_state.original_attributes[properties[property]] = Object.new
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
# Example:
|
54
|
+
# my_resource.array_prop << 123
|
55
|
+
# my_resource.taint! :array_prop
|
56
|
+
# my_resource.save
|
57
|
+
|
58
|
+
module Accounts
|
59
|
+
|
60
|
+
class Account
|
61
|
+
include DataMapper::Resource
|
62
|
+
property :id, Serial
|
63
|
+
property :email, String, :unique => true
|
64
|
+
property :password, String, :required => false # a hash
|
65
|
+
property :status, Flag[:suspended, :email_confirmed]
|
66
|
+
property :last_logon, DateTime, :required => false
|
67
|
+
timestamps :created_at
|
68
|
+
timestamps :updated_at
|
69
|
+
|
70
|
+
def set_password(arg)
|
71
|
+
self.update :password => self.class.hashpasswd(arg)
|
72
|
+
end
|
73
|
+
|
74
|
+
def confirm_password(arg)
|
75
|
+
self.class.hashpasswd(arg) == self.password
|
76
|
+
end
|
77
|
+
|
78
|
+
private
|
79
|
+
|
80
|
+
@@digest = Digest::SHA2.new
|
81
|
+
SALT = 'b593b7bf01cd29d9cc15d11f9d81f586e255fd252fab264129e6046934876c23' # random
|
82
|
+
|
83
|
+
# Can't name this "hash". Name already taken.
|
84
|
+
def self.hashpasswd(arg)
|
85
|
+
@@digest.hexdigest(SALT + arg)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
# An action-token represents permission for the agent to perform an action on behalf of a user.
|
90
|
+
class ActionToken
|
91
|
+
include DataMapper::Resource
|
92
|
+
|
93
|
+
@@digest = Digest::SHA2.new
|
94
|
+
|
95
|
+
property :id, String, :key => true, :default => lambda { |res, tok| @@digest.hexdigest(rand.to_s) }
|
96
|
+
property :action, String, :unique => :account
|
97
|
+
property :params, Object, :allow_nil => true # a hash of key => value
|
98
|
+
belongs_to :account
|
99
|
+
property :expires, DateTime, :default => Time.new + 24 * 3600 # one day
|
100
|
+
|
101
|
+
# override .save
|
102
|
+
# @see http://blog.jayfields.com/2006/12/ruby-alias-method-alternative.html
|
103
|
+
base_save = self.instance_method(:save)
|
104
|
+
|
105
|
+
define_method(:save) do |*args|
|
106
|
+
# If there is a previous instance, delete it
|
107
|
+
if self.class.count(:action => self.action, :account => self.account) then
|
108
|
+
self.class.destroy
|
109
|
+
end
|
110
|
+
result = base_save.bind(self).call(*args)
|
111
|
+
#STDERR.puts "#{self.inspect}.save returned #{result}"
|
112
|
+
end
|
113
|
+
|
114
|
+
base_destroy = self.instance_method(:destroy)
|
115
|
+
|
116
|
+
define_method(:destroy) do |*args|
|
117
|
+
# If there is a previous instance, delete it
|
118
|
+
result = base_destroy.bind(self).call(*args)
|
119
|
+
#STDERR.puts "#{self.inspect}.destroy returned #{result}"
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
end
|
124
|
+
|
125
|
+
DataMapper.finalize
|
126
|
+
DataMapper.auto_upgrade! # preserve existing database
|
@@ -0,0 +1,105 @@
|
|
1
|
+
$: << '../lib'
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'rspec'
|
5
|
+
|
6
|
+
# suppress excessive warnings from DataMapper libraries
|
7
|
+
$VERBOSE=nil
|
8
|
+
require 'accounts/model'
|
9
|
+
$VERBOSE=false
|
10
|
+
|
11
|
+
# Make sure we're still seeing warnings about our own code
|
12
|
+
FOO=:bar
|
13
|
+
FOO=:baz
|
14
|
+
|
15
|
+
begin
|
16
|
+
DataMapper.auto_migrate! # empty database
|
17
|
+
STDERR.puts "called DataMapper.auto_migrate!"
|
18
|
+
end
|
19
|
+
|
20
|
+
describe Accounts::Account do
|
21
|
+
|
22
|
+
it 'contains e-mails and passwords and flags' do
|
23
|
+
account = Accounts::Account.create :email => "stewie@family.guy"
|
24
|
+
account.should be_saved
|
25
|
+
account.password.should be_nil
|
26
|
+
account.status.should have(0).flags
|
27
|
+
account.last_logon.should be_nil
|
28
|
+
account.created_at.should_not be_nil
|
29
|
+
account.updated_at.should_not be_nil
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'cannot create account with duplicate e-mail' do
|
33
|
+
account = Accounts::Account.create :email => "stewie@family.guy"
|
34
|
+
account.should_not be_saved
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'new user e-mail is initially invalid' do
|
38
|
+
account = Accounts::Account.create :email => "lois@family.guy"
|
39
|
+
#puts account.status.inspect
|
40
|
+
account.status.include?(:email_confirmed).should be_false
|
41
|
+
account.status.include?(:suspended).should be_false
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'responds to .set_password' do
|
45
|
+
account = Accounts::Account.create :email => "brian@family.guy"
|
46
|
+
account.should respond_to :set_password
|
47
|
+
account.set_password('hotforlois').should be_true
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'can confirm password' do
|
51
|
+
account = Accounts::Account.create :email => "peter@family.guy"
|
52
|
+
account.set_password('notsosmart').should be_true
|
53
|
+
account.confirm_password('notsosmart').should be_true
|
54
|
+
account.confirm_password('notsobright').should be_false
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'stores passwords as hashes' do
|
58
|
+
Accounts::Account.all.each do |acct|
|
59
|
+
if !acct.password.nil?
|
60
|
+
acct.password.should be_instance_of String
|
61
|
+
acct.password.length.should be == 64
|
62
|
+
acct.password.should_not match(/[^0-9a-f]/)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
describe Accounts::ActionToken do
|
69
|
+
before :all do
|
70
|
+
@meg = Accounts::Account.create :email => 'meg@familyguy.com'
|
71
|
+
@chris = Accounts::Account.create :email => 'chris@familyguy.com'
|
72
|
+
end
|
73
|
+
|
74
|
+
it 'can create a token for a user to perform a specific action' do
|
75
|
+
tok = Accounts::ActionToken.create :account => @meg, :action => 'party'
|
76
|
+
tok.should be_saved
|
77
|
+
tok.id.should be_instance_of String
|
78
|
+
tok.id.length.should be == 64
|
79
|
+
tok.id.should_not match(/[^0-9a-f]/)
|
80
|
+
end
|
81
|
+
|
82
|
+
it 'creating a new TokenAction for an action replaces any previous token' do
|
83
|
+
tas = Accounts::ActionToken.all(:account => @meg, :action => 'party')
|
84
|
+
tas.should_not be_nil
|
85
|
+
tas.should have(1).item
|
86
|
+
|
87
|
+
tok = Accounts::ActionToken.create :account => @meg, :action => 'party'
|
88
|
+
tok.should be_saved
|
89
|
+
tok.id.should_not be == tas[0].id
|
90
|
+
end
|
91
|
+
|
92
|
+
it 'can return account and action given token' do
|
93
|
+
tok = Accounts::ActionToken.create :account => @chris, :action => 'act stupid'
|
94
|
+
ta_found = Accounts::ActionToken.get(tok.id)
|
95
|
+
ta_found.account.should be == @chris
|
96
|
+
ta_found.action.should be == 'act stupid'
|
97
|
+
end
|
98
|
+
|
99
|
+
it 'has an expire date' do
|
100
|
+
Accounts::ActionToken.all.each do |tok|
|
101
|
+
tok.expires.should be_kind_of DateTime
|
102
|
+
tok.expires.should > DateTime.new
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
metadata
ADDED
@@ -0,0 +1,263 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: accounts
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Larry Siden, Westside Consulting LLC
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-01-02 00:00:00.000000000Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: capybara
|
16
|
+
requirement: &83116690 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *83116690
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: cucumber
|
27
|
+
requirement: &83116290 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ! '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0'
|
33
|
+
type: :development
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *83116290
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: rspec
|
38
|
+
requirement: &83115900 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ! '>='
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '0'
|
44
|
+
type: :development
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *83115900
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: rdoc
|
49
|
+
requirement: &83115290 !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ! '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
type: :development
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: *83115290
|
58
|
+
- !ruby/object:Gem::Dependency
|
59
|
+
name: sinatra-contrib
|
60
|
+
requirement: &83048450 !ruby/object:Gem::Requirement
|
61
|
+
none: false
|
62
|
+
requirements:
|
63
|
+
- - ! '>='
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: '0'
|
66
|
+
type: :development
|
67
|
+
prerelease: false
|
68
|
+
version_requirements: *83048450
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: mail-store-agent
|
71
|
+
requirement: &83047670 !ruby/object:Gem::Requirement
|
72
|
+
none: false
|
73
|
+
requirements:
|
74
|
+
- - ! '>='
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: '0'
|
77
|
+
type: :development
|
78
|
+
prerelease: false
|
79
|
+
version_requirements: *83047670
|
80
|
+
- !ruby/object:Gem::Dependency
|
81
|
+
name: mail-single_file_delivery
|
82
|
+
requirement: &83043620 !ruby/object:Gem::Requirement
|
83
|
+
none: false
|
84
|
+
requirements:
|
85
|
+
- - ! '>='
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
version: '0'
|
88
|
+
type: :development
|
89
|
+
prerelease: false
|
90
|
+
version_requirements: *83043620
|
91
|
+
- !ruby/object:Gem::Dependency
|
92
|
+
name: haml
|
93
|
+
requirement: &83042990 !ruby/object:Gem::Requirement
|
94
|
+
none: false
|
95
|
+
requirements:
|
96
|
+
- - ! '>='
|
97
|
+
- !ruby/object:Gem::Version
|
98
|
+
version: '0'
|
99
|
+
type: :development
|
100
|
+
prerelease: false
|
101
|
+
version_requirements: *83042990
|
102
|
+
- !ruby/object:Gem::Dependency
|
103
|
+
name: rack
|
104
|
+
requirement: &83041620 !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ~>
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: 1.3.6
|
110
|
+
type: :runtime
|
111
|
+
prerelease: false
|
112
|
+
version_requirements: *83041620
|
113
|
+
- !ruby/object:Gem::Dependency
|
114
|
+
name: sinatra
|
115
|
+
requirement: &83041110 !ruby/object:Gem::Requirement
|
116
|
+
none: false
|
117
|
+
requirements:
|
118
|
+
- - ! '>='
|
119
|
+
- !ruby/object:Gem::Version
|
120
|
+
version: '0'
|
121
|
+
type: :runtime
|
122
|
+
prerelease: false
|
123
|
+
version_requirements: *83041110
|
124
|
+
- !ruby/object:Gem::Dependency
|
125
|
+
name: thin
|
126
|
+
requirement: &83028320 !ruby/object:Gem::Requirement
|
127
|
+
none: false
|
128
|
+
requirements:
|
129
|
+
- - ! '>='
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0'
|
132
|
+
type: :runtime
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: *83028320
|
135
|
+
- !ruby/object:Gem::Dependency
|
136
|
+
name: data_mapper
|
137
|
+
requirement: &83027720 !ruby/object:Gem::Requirement
|
138
|
+
none: false
|
139
|
+
requirements:
|
140
|
+
- - ! '>='
|
141
|
+
- !ruby/object:Gem::Version
|
142
|
+
version: '0'
|
143
|
+
type: :runtime
|
144
|
+
prerelease: false
|
145
|
+
version_requirements: *83027720
|
146
|
+
- !ruby/object:Gem::Dependency
|
147
|
+
name: dm-types
|
148
|
+
requirement: &83027240 !ruby/object:Gem::Requirement
|
149
|
+
none: false
|
150
|
+
requirements:
|
151
|
+
- - ! '>='
|
152
|
+
- !ruby/object:Gem::Version
|
153
|
+
version: '0'
|
154
|
+
type: :runtime
|
155
|
+
prerelease: false
|
156
|
+
version_requirements: *83027240
|
157
|
+
- !ruby/object:Gem::Dependency
|
158
|
+
name: dm-timestamps
|
159
|
+
requirement: &83026620 !ruby/object:Gem::Requirement
|
160
|
+
none: false
|
161
|
+
requirements:
|
162
|
+
- - ! '>='
|
163
|
+
- !ruby/object:Gem::Version
|
164
|
+
version: '0'
|
165
|
+
type: :runtime
|
166
|
+
prerelease: false
|
167
|
+
version_requirements: *83026620
|
168
|
+
- !ruby/object:Gem::Dependency
|
169
|
+
name: dm-postgres-adapter
|
170
|
+
requirement: &83026060 !ruby/object:Gem::Requirement
|
171
|
+
none: false
|
172
|
+
requirements:
|
173
|
+
- - ! '>='
|
174
|
+
- !ruby/object:Gem::Version
|
175
|
+
version: '0'
|
176
|
+
type: :runtime
|
177
|
+
prerelease: false
|
178
|
+
version_requirements: *83026060
|
179
|
+
- !ruby/object:Gem::Dependency
|
180
|
+
name: mail
|
181
|
+
requirement: &83025360 !ruby/object:Gem::Requirement
|
182
|
+
none: false
|
183
|
+
requirements:
|
184
|
+
- - ! '>='
|
185
|
+
- !ruby/object:Gem::Version
|
186
|
+
version: '0'
|
187
|
+
type: :runtime
|
188
|
+
prerelease: false
|
189
|
+
version_requirements: *83025360
|
190
|
+
- !ruby/object:Gem::Dependency
|
191
|
+
name: logger
|
192
|
+
requirement: &83024820 !ruby/object:Gem::Requirement
|
193
|
+
none: false
|
194
|
+
requirements:
|
195
|
+
- - ! '>='
|
196
|
+
- !ruby/object:Gem::Version
|
197
|
+
version: '0'
|
198
|
+
type: :runtime
|
199
|
+
prerelease: false
|
200
|
+
version_requirements: *83024820
|
201
|
+
description: ! "\nAccounts::Server defines the following paths for your web-app:\n\n*
|
202
|
+
POST '/logon'\n* POST '/register'\n* POST '/forgot-password'\n* POST '/change-password'\n*
|
203
|
+
POST '/change-email'\n\nYour app must provide the pages and forms that will post
|
204
|
+
to these paths.\n "
|
205
|
+
email:
|
206
|
+
- lsiden@westside-consulting.com
|
207
|
+
executables: []
|
208
|
+
extensions: []
|
209
|
+
extra_rdoc_files: []
|
210
|
+
files:
|
211
|
+
- .gitignore
|
212
|
+
- .rvmrc
|
213
|
+
- Gemfile
|
214
|
+
- Gemfile.lock
|
215
|
+
- README.mkd
|
216
|
+
- Rakefile
|
217
|
+
- accounts.gemspec
|
218
|
+
- demo/views/change_email.haml
|
219
|
+
- demo/views/change_password.haml
|
220
|
+
- demo/views/forgot_password.haml
|
221
|
+
- demo/views/logon.haml
|
222
|
+
- demo/views/register.haml
|
223
|
+
- demo/web_app.rb
|
224
|
+
- features/change-email.feature
|
225
|
+
- features/change-password.feature
|
226
|
+
- features/register.feature
|
227
|
+
- features/step_definitions/steps.rb
|
228
|
+
- features/step_definitions/web_steps.rb
|
229
|
+
- features/support/env.rb
|
230
|
+
- features/support/paths.rb
|
231
|
+
- features/support/unused.rb
|
232
|
+
- lib/accounts.rb
|
233
|
+
- lib/accounts/configure.rb
|
234
|
+
- lib/accounts/helpers.rb
|
235
|
+
- lib/accounts/model.rb
|
236
|
+
- lib/accounts/version.rb
|
237
|
+
- spec/user_model_spec.rb
|
238
|
+
homepage: https://github.com/lsiden/accounts
|
239
|
+
licenses: []
|
240
|
+
post_install_message:
|
241
|
+
rdoc_options: []
|
242
|
+
require_paths:
|
243
|
+
- lib
|
244
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
245
|
+
none: false
|
246
|
+
requirements:
|
247
|
+
- - ! '>='
|
248
|
+
- !ruby/object:Gem::Version
|
249
|
+
version: '0'
|
250
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
251
|
+
none: false
|
252
|
+
requirements:
|
253
|
+
- - ! '>='
|
254
|
+
- !ruby/object:Gem::Version
|
255
|
+
version: '0'
|
256
|
+
requirements: []
|
257
|
+
rubyforge_project: accounts
|
258
|
+
rubygems_version: 1.8.10
|
259
|
+
signing_key:
|
260
|
+
specification_version: 3
|
261
|
+
summary: ! '*accounts* is a website plug-in that offers than the basic user-account
|
262
|
+
management and authentication features that many sites need.'
|
263
|
+
test_files: []
|