entrance 0.3.4 → 0.4.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.
@@ -1,5 +1,5 @@
1
1
  class User < ActiveRecord::Base
2
2
  include Entrance::Model
3
-
4
- validate_entrance! # ensures everything is in order, and sets up password validations
3
+
4
+ provides_entrance
5
5
  end
@@ -28,7 +28,7 @@ class User
28
28
  key :reset_token
29
29
  key :reset_token_expires_at, Time
30
30
 
31
- validate_entrance! # ensures everything is in order, and sets up password validations
31
+ provides_entrance
32
32
 
33
33
  def active?
34
34
  state.to_sym == :active
@@ -43,6 +43,8 @@ module Example
43
43
  post '/login' do
44
44
  if user = User.authenticate(params[:email], params[:password]) and user.active?
45
45
  remember = ['on', '1'].include?(params[:remember_me])
46
+
47
+ puts user.inspect
46
48
  login!(user, remember)
47
49
 
48
50
  flash[:success] = 'Welcome back!'
@@ -20,18 +20,8 @@ module Entrance
20
20
  @secret = nil
21
21
  @stretches = 10
22
22
 
23
- # fields
24
- @salt_attr = nil
25
- @unique_key = 'id'
26
- @username_attr = 'email'
27
- @password_attr = 'password_hash'
28
- @remember_token_attr = 'remember_token'
29
- @remember_until_attr = 'remember_token_expires_at'
30
- @reset_token_attr = 'reset_token'
31
- @reset_until_attr = 'reset_token_expires_at'
32
-
33
23
  # access denied
34
- @access_denied_redirect_to = '/'
24
+ @access_denied_redirect_to = '/login'
35
25
  @access_denied_message_key = nil # e.g. 'messages.access_denied'
36
26
 
37
27
  # reset password
@@ -45,11 +35,6 @@ module Entrance
45
35
  @cookie_secure = true
46
36
  @cookie_path = '/'
47
37
  @cookie_httponly = false
48
-
49
- # for omniauth support
50
- @name_attr = 'name'
51
- @auth_provider_attr = 'auth_provider'
52
- @auth_uid_attr = 'auth_uid'
53
38
  end
54
39
 
55
40
  def validate!
@@ -50,7 +50,7 @@ module Entrance
50
50
  # new_user may be nil (when logging out) or an instance of the Entrance.model class
51
51
  def current_user=(new_user)
52
52
  raise "Invalid user: #{new_user}" unless new_user.nil? or new_user.is_a?(Entrance.model)
53
- session[:user_id] = new_user ? new_user.send(Entrance.config.unique_key) : nil
53
+ session[:user_id] = new_user ? new_user.send(Entrance.fields.unique_key) : nil
54
54
  @current_user = new_user # should be nil when logging out
55
55
  end
56
56
 
@@ -78,7 +78,7 @@ module Entrance
78
78
 
79
79
  def login_from_session
80
80
  query = {}
81
- query[Entrance.config.unique_key] = session[:user_id]
81
+ query[Entrance.fields.unique_key] = session[:user_id]
82
82
  self.current_user = Entrance.model.where(query).first if session[:user_id]
83
83
  end
84
84
 
@@ -86,9 +86,9 @@ module Entrance
86
86
  return unless Entrance.config.can?(:remember) && request.cookies[REMEMBER_ME_TOKEN]
87
87
 
88
88
  query = {}
89
- query[Entrance.config.remember_token_attr] = request.cookies[REMEMBER_ME_TOKEN]
89
+ query[Entrance.fields.remember_token] = request.cookies[REMEMBER_ME_TOKEN]
90
90
  if user = Entrance.model.where(query).first \
91
- and user.send(Entrance.config.remember_until_attr) > Time.now
91
+ and user.send(Entrance.fields.remember_until) > Time.now
92
92
  self.current_user = user
93
93
  # user.update_remember_token_expiration!
94
94
  user
@@ -0,0 +1,79 @@
1
+ module Entrance
2
+
3
+ class Fields
4
+
5
+ attr_accessor *%w(
6
+ unique_key salt username password
7
+ remember_token remember_until reset_token reset_until
8
+ name auth_provider auth_uid
9
+ )
10
+
11
+ def initialize
12
+ @unique_key = 'id'
13
+ @salt = nil
14
+ @username = 'email'
15
+ @password = 'password_hash'
16
+
17
+ # remember and reset
18
+ @remember_token = 'remember_token'
19
+ @remember_until = 'remember_token_expires_at'
20
+ @reset_token = 'reset_token'
21
+ @reset_until = 'reset_token_expires_at'
22
+
23
+ # omniauth
24
+ @name = 'name'
25
+ @auth_provider = 'auth_provider'
26
+ @auth_uid = 'auth_uid'
27
+ end
28
+
29
+ def validate!
30
+ raise "Invalid model: #{Entrance.config.model}!" unless Kernel.const_defined?(Entrance.config.model)
31
+
32
+ fields = get_model_fields
33
+
34
+ %w(username password).each do |attr|
35
+ field = send(attr)
36
+ unless fields.include?(field.to_sym)
37
+ raise "Couldn't find '#{field}' in the #{Entrance.model.name} model."
38
+ end
39
+ end
40
+
41
+ %w(remember reset).each do |what|
42
+ if field = send("#{what}_token")
43
+ until_field = send("#{what}_until")
44
+
45
+ unless fields.include?(field.to_sym)
46
+ raise "No #{field} field found. \
47
+ Set the fields.#{what} option to nil to disable the #{what} option."
48
+ end
49
+
50
+ if until_field
51
+ unless fields.include?(until_field.to_sym)
52
+ raise "Couldn't find a #{until_field} field. Cannot continue."
53
+ end
54
+ else
55
+ puts "Disabling expiration timestamp for the #{what} option. This is a VERY bad idea."
56
+ end
57
+
58
+ Entrance.config.can?(what, true)
59
+
60
+ mod = what.to_sym == :remember ? Entrance::Model::RememberMethods : Entrance::Model::ResetMethods
61
+ Entrance.model.send(:include, mod)
62
+ end
63
+ end
64
+ end
65
+
66
+ def get_model_fields
67
+ model = Entrance.model
68
+ if model.respond_to?(:columns) # ActiveRecord::Base
69
+ model.columns.collect(&:name)
70
+ elsif model.respond_to?(:keys) # MongoMapper::Document
71
+ model.keys.keys
72
+ else # just get setters in the class
73
+ model.instance_methods(false).select { |m| m[/\=$/] }.map { |s| s.to_s.sub('=', '') }
74
+ end.map { |el| el.to_sym }
75
+ end
76
+
77
+ end
78
+
79
+ end
@@ -2,57 +2,25 @@ module Entrance
2
2
  module Model
3
3
 
4
4
  def self.included(base)
5
-
6
- # if the target model class does not have a Model.where() method,
7
- # then login_by_session wont work, nor the ClassMethods below.
8
- # won't work so we cannot continue.
9
- unless base.respond_to?(:where)
10
- raise "#{base.name} does not have a .where() finder class method. Cannot continue."
11
- end
12
-
13
5
  base.extend(ClassMethods)
14
6
  end
15
7
 
16
8
  module ClassMethods
17
9
 
18
- def validate_entrance!
19
- fields = if self.respond_to?(:columns) # ActiveRecord::Base
20
- columns.collect(&:name)
21
- elsif self.respond_to?(:keys) # MongoMapper::Document
22
- keys.keys
23
- else # just get setters in the class
24
- instance_methods(false).select { |m| m[/\=$/] }.map { |s| s.to_s.sub('=', '') }
25
- end.map { |el| el.to_sym }
26
-
27
- %w(username_attr password_attr).each do |key|
28
- field = Entrance.config.send(key)
29
- unless fields.include?(field.to_sym)
30
- raise "Couldn't find '#{field}' in #{self.name} model."
31
- end
32
- end
10
+ def provides_entrance(&block)
11
+ Entrance.config.model = self.name
33
12
 
34
- %w(remember reset).each do |what|
35
- if field = Entrance.config.send("#{what}_token_attr")
36
- until_field = Entrance.config.send("#{what}_until_attr")
37
-
38
- unless fields.include?(field.to_sym)
39
- raise "No #{Entrance.config.send("#{what}_token_attr")} field found. \
40
- Set the config.#{what}_token_attr option to nil to disable the #{what} option."
41
- end
42
-
43
- if until_field
44
- unless fields.include?(until_field.to_sym)
45
- raise "Couldn't find a #{Entrance.config.send("#{what}_until_attr")} field. Cannot continue."
46
- end
47
- else
48
- puts "Disabling expiration timestamp for the #{what} option. This is a VERY bad idea."
49
- end
50
-
51
- Entrance.config.can?(what, true)
52
- self.send(:include, what.to_sym == :remember ? RememberMethods : ResetMethods)
53
- end
13
+ # if the target model class does not have a Model.where() method,
14
+ # then login_by_session wont work, nor the ClassMethods below.
15
+ # won't work so we cannot continue.
16
+ unless self.respond_to?(:where)
17
+ raise "#{self.name} does not have a .where() finder class method. Cannot continue."
54
18
  end
55
19
 
20
+ fields = Entrance.fields
21
+ yield fields if block_given?
22
+ fields.validate!
23
+
56
24
  if self.respond_to?(:validates)
57
25
  validates :password, :presence => true, :length => 6..32, :if => :password_required?
58
26
  validates :password, :confirmation => true, :if => :password_required?
@@ -64,7 +32,7 @@ module Entrance
64
32
  return if [username, password].any? { |v| v.nil? || v.strip == '' }
65
33
 
66
34
  query = {}
67
- query[Entrance.config.username_attr] = username.to_s.downcase.strip
35
+ query[Entrance.fields.username] = username.to_s.downcase.strip
68
36
  if u = where(query).first
69
37
  return u.authenticated?(password) ? u : nil
70
38
  end
@@ -75,9 +43,9 @@ module Entrance
75
43
  return if token.nil?
76
44
 
77
45
  query = {}
78
- query[Entrance.config.reset_token_attr] = token.to_s.strip
46
+ query[Entrance.fields.reset_token] = token.to_s.strip
79
47
  if u = where(query).first \
80
- and (!Doorman.config.reset_until_attr || u.send(Doorman.config.reset_until_attr) > Time.now)
48
+ and (!Entrance.fields.reset_until || u.send(Entrance.fields.reset_until) > Time.now)
81
49
  return u
82
50
  end
83
51
  end
@@ -87,10 +55,10 @@ module Entrance
87
55
  module ResetMethods
88
56
 
89
57
  def request_password_reset!
90
- send(Entrance.config.reset_token_attr + '=', Entrance.generate_token)
91
- if Doorman.config.reset_until_attr
58
+ send(Entrance.fields.reset_token + '=', Entrance.generate_token)
59
+ if Entrance.fields.reset_until
92
60
  timestamp = Time.now + Entrance.config.reset_password_window
93
- update_attribute(Entrance.config.reset_until_attr, timestamp)
61
+ update_attribute(Entrance.fields.reset_until, timestamp)
94
62
  end
95
63
  if save(:validate => false)
96
64
  method = Entrance.config.reset_password_method
@@ -104,19 +72,19 @@ module Entrance
104
72
 
105
73
  def remember_me!(until_date = nil)
106
74
  token = Entrance.generate_token
107
- update_attribute(Entrance.config.remember_token_attr, token) or return
108
- update_remember_token_expiration!(until_date) if Entrance.config.remember_until_attr
75
+ update_attribute(Entrance.fields.remember_token, token) or return
76
+ update_remember_token_expiration!(until_date) if Entrance.fields.remember_until
109
77
  token
110
78
  end
111
79
 
112
80
  def update_remember_token_expiration!(until_date = nil)
113
81
  timestamp = Time.now + (until_date || Entrance.config.remember_for).to_i
114
- update_attribute(Entrance.config.remember_until_attr, timestamp)
82
+ update_attribute(Entrance.fields.remember_until, timestamp)
115
83
  end
116
84
 
117
85
  def forget_me!
118
- update_attribute(Entrance.config.remember_token_attr, nil)
119
- update_attribute(Entrance.config.remember_until_attr, nil) if Entrance.config.remember_until_attr
86
+ update_attribute(Entrance.fields.remember_token, nil)
87
+ update_attribute(Entrance.fields.remember_until, nil) if Entrance.fields.remember_until
120
88
  end
121
89
 
122
90
  end
@@ -136,18 +104,18 @@ module Entrance
136
104
  @password_changed = true
137
105
 
138
106
  # if we're using salt and it is empty, generate one
139
- if Entrance.config.salt_attr \
140
- and send(Entrance.config.salt_attr).nil?
141
- self.send(Entrance.config.salt_attr + '=', Entrance.generate_token)
107
+ if Entrance.fields.salt \
108
+ and send(Entrance.fields.salt).nil?
109
+ self.send(Entrance.fields.salt + '=', Entrance.generate_token)
142
110
  end
143
111
 
144
- self.send(Entrance.config.password_attr + '=', encrypt_password(new_password))
112
+ self.send(Entrance.fields.password + '=', encrypt_password(new_password))
145
113
  end
146
114
 
147
115
  private
148
116
 
149
117
  def read_password
150
- send(Entrance.config.password_attr)
118
+ send(Entrance.fields.password)
151
119
  end
152
120
 
153
121
  def encrypt_password(string)
@@ -155,7 +123,7 @@ module Entrance
155
123
  end
156
124
 
157
125
  def get_salt
158
- Entrance.config.salt_attr && send(Entrance.config.salt_attr)
126
+ Entrance.fields.salt && send(Entrance.fields.salt)
159
127
  end
160
128
 
161
129
  def password_required?
@@ -1,7 +1,7 @@
1
1
  module Entrance
2
2
  MAJOR = 0
3
- MINOR = 3
4
- PATCH = 4
3
+ MINOR = 4
4
+ PATCH = 0
5
5
 
6
6
  VERSION = [MAJOR, MINOR, PATCH].join('.')
7
7
  end
data/lib/entrance.rb CHANGED
@@ -2,6 +2,7 @@ require 'entrance/controller'
2
2
  require 'entrance/model'
3
3
  require 'entrance/ciphers'
4
4
  require 'entrance/config'
5
+ require 'entrance/fields'
5
6
  require 'digest/sha1'
6
7
 
7
8
  module Entrance
@@ -10,15 +11,19 @@ module Entrance
10
11
  @config ||= Config.new
11
12
  end
12
13
 
14
+ def self.model
15
+ @model ||= Kernel.const_get(config.model)
16
+ end
17
+
18
+ def self.fields
19
+ @fields ||= Fields.new
20
+ end
21
+
13
22
  def self.configure
14
23
  yield config
15
24
  config.validate!
16
25
  end
17
26
 
18
- def self.model
19
- @model ||= Kernel.const_get(config.model)
20
- end
21
-
22
27
  def self.generate_token(length = 40)
23
28
  str = Digest::SHA1.hexdigest([Time.now, rand].join)
24
29
  str[0..(length-1)]
data/spec/fake_model.rb CHANGED
@@ -1,15 +1,7 @@
1
1
  require 'entrance'
2
2
 
3
3
  Entrance.configure do |config|
4
- config.model = 'FakeUser'
5
- config.unique_key = 'email'
6
- config.username_attr = 'email'
7
- config.password_attr = 'password'
8
4
 
9
- # disabling reset password and remember options
10
- config.reset_token_attr = nil
11
- config.remember_token_attr = nil
12
- # config.cookie_secure = false
13
5
 
14
6
  config.access_denied_redirect_to = '/login'
15
7
  end
@@ -18,6 +10,7 @@ end
18
10
  # admin user model
19
11
 
20
12
  class FakeUser
13
+ include Entrance::Model
21
14
  attr_accessor :email, :password #, :remember_token
22
15
 
23
16
  USERS = {
@@ -47,6 +40,14 @@ class FakeUser
47
40
  password == string
48
41
  end
49
42
 
50
- include Entrance::Model # ensure after we declare the .where method
43
+ provides_entrance do |fields|
44
+ fields.unique_key = 'email'
45
+ fields.username = 'email'
46
+ fields.password = 'password'
47
+
48
+ # disabling reset password and remember options
49
+ fields.reset_token = nil
50
+ fields.remember_token = nil
51
+ end
51
52
 
52
53
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: entrance
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.4
4
+ version: 0.4.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -117,6 +117,7 @@ files:
117
117
  - lib/entrance/ciphers.rb
118
118
  - lib/entrance/config.rb
119
119
  - lib/entrance/controller.rb
120
+ - lib/entrance/fields.rb
120
121
  - lib/entrance/model.rb
121
122
  - lib/entrance/version.rb
122
123
  - spec/controller_spec.rb