ucb_rails_user 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +166 -0
- data/Rakefile +36 -0
- data/app/assets/config/ucb_rails_user_manifest.js +0 -0
- data/app/assets/javascripts/ucb_rails_user/datatables.js +15441 -0
- data/app/assets/javascripts/ucb_rails_user/scripts.js +15 -0
- data/app/assets/javascripts/ucb_rails_user/ucb_rails_user.js +39 -0
- data/app/assets/stylesheets/ucb_rails_user/components/_add_users_search_results_table.sass +2 -0
- data/app/assets/stylesheets/ucb_rails_user/components/_loader.sass +46 -0
- data/app/assets/stylesheets/ucb_rails_user/components/_users_table.sass +10 -0
- data/app/assets/stylesheets/ucb_rails_user/datatables.css +201 -0
- data/app/assets/stylesheets/ucb_rails_user/main.sass +2 -0
- data/app/assets/stylesheets/ucb_rails_user/styles.css +19 -0
- data/app/controllers/ucb_rails_user/concerns/controller_methods.rb +92 -0
- data/app/controllers/ucb_rails_user/concerns/home_controller.rb +17 -0
- data/app/controllers/ucb_rails_user/concerns/sessions_controller.rb +68 -0
- data/app/controllers/ucb_rails_user/concerns/users_controller.rb +132 -0
- data/app/controllers/ucb_rails_user/home_controller.rb +10 -0
- data/app/controllers/ucb_rails_user/sessions_controller.rb +9 -0
- data/app/controllers/ucb_rails_user/users_controller.rb +8 -0
- data/app/helpers/ucb_rails_user/users_helper.rb +18 -0
- data/app/helpers/ucb_rails_user_helper.rb +17 -0
- data/app/models/concerns/user_concerns.rb +53 -0
- data/app/models/ucb_rails_user/configuration/cas.rb +53 -0
- data/app/models/ucb_rails_user/configuration/configuration.rb +72 -0
- data/app/models/ucb_rails_user/configuration/email.rb +73 -0
- data/app/models/ucb_rails_user/configuration/exception_notification.rb +21 -0
- data/app/models/ucb_rails_user/configuration/ldap.rb +50 -0
- data/app/models/ucb_rails_user/ldap_person/entry.rb +62 -0
- data/app/models/ucb_rails_user/ldap_person/finder.rb +87 -0
- data/app/models/ucb_rails_user/ldap_person/test_finder.rb +57 -0
- data/app/models/ucb_rails_user/user_ldap_service.rb +65 -0
- data/app/models/ucb_rails_user/user_session_manager/active_in_user_table.rb +29 -0
- data/app/models/ucb_rails_user/user_session_manager/admin_in_user_table.rb +13 -0
- data/app/models/ucb_rails_user/user_session_manager/base.rb +54 -0
- data/app/models/ucb_rails_user/user_session_manager/in_people_ou.rb +27 -0
- data/app/models/ucb_rails_user/user_session_manager/in_people_ou_add_to_users_table.rb +21 -0
- data/app/models/ucb_rails_user/user_session_manager/ldap_person_user_wrapper.rb +29 -0
- data/app/models/user.rb +8 -0
- data/app/views/ucb_rails_user/home/logged_in.html.haml +5 -0
- data/app/views/ucb_rails_user/home/not_logged_in.html.haml +5 -0
- data/app/views/ucb_rails_user/lps/_form.html.haml +19 -0
- data/app/views/ucb_rails_user/lps/_modal.html.haml +9 -0
- data/app/views/ucb_rails_user/lps/_results.html.haml +34 -0
- data/app/views/ucb_rails_user/lps/search.js.haml +3 -0
- data/app/views/ucb_rails_user/users/_form.html.haml +14 -0
- data/app/views/ucb_rails_user/users/_search_results.html.haml +24 -0
- data/app/views/ucb_rails_user/users/_user.html.haml +12 -0
- data/app/views/ucb_rails_user/users/edit.html.haml +3 -0
- data/app/views/ucb_rails_user/users/index.html.haml +23 -0
- data/app/views/ucb_rails_user/users/new.html.haml +16 -0
- data/app/views/ucb_rails_user/users/search.js.haml +4 -0
- data/config/initializers/simple_form.rb +171 -0
- data/config/initializers/simple_form_bootstrap.rb +154 -0
- data/config/locales/simple_form.en.yml +31 -0
- data/config/routes.rb +20 -0
- data/db/migrate/20170324221936_create_users.rb +29 -0
- data/lib/tasks/ucb_rails_user_tasks.rake +4 -0
- data/lib/templates/erb/scaffold/_form.html.erb +13 -0
- data/lib/ucb_rails_user.rb +21 -0
- data/lib/ucb_rails_user/engine.rb +28 -0
- data/lib/ucb_rails_user/version.rb +3 -0
- metadata +277 -0
@@ -0,0 +1,73 @@
|
|
1
|
+
module UcbRailsUser
|
2
|
+
module Configuration
|
3
|
+
class Email
|
4
|
+
ArgumentError = Class.new(StandardError)
|
5
|
+
|
6
|
+
attr_accessor :hash
|
7
|
+
|
8
|
+
def self.configure(config)
|
9
|
+
new(config)
|
10
|
+
end
|
11
|
+
|
12
|
+
def initialize(configuration_hash)
|
13
|
+
return if configuration_hash.nil?
|
14
|
+
raise(ArgumentError, "expected a Hash, got: #{configuration_hash.inspect}") unless configuration_hash.is_a?(Hash)
|
15
|
+
|
16
|
+
self.hash = configuration_hash
|
17
|
+
process_configuration
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def process_configuration
|
23
|
+
process_default
|
24
|
+
process_delivery_method
|
25
|
+
process_default_url_options
|
26
|
+
process_raise_delivery_errors
|
27
|
+
process_sendmail_settings
|
28
|
+
process_smtp_settings
|
29
|
+
process_subject_prefix
|
30
|
+
end
|
31
|
+
|
32
|
+
# This merges values with existing values
|
33
|
+
def process_default
|
34
|
+
if hash.has_key?('default')
|
35
|
+
ActionMailer::Base.default hash['default']
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def process_delivery_method
|
40
|
+
ActionMailer::Base.delivery_method = hash.fetch('delivery_method', :smtp).to_sym
|
41
|
+
end
|
42
|
+
|
43
|
+
def process_default_url_options
|
44
|
+
if hash.has_key?('default_url_options')
|
45
|
+
ActionMailer::Base.default_url_options = hash.fetch('default_url_options').symbolize_keys
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def process_raise_delivery_errors
|
50
|
+
ActionMailer::Base.raise_delivery_errors = hash.fetch('raise_delivery_errors', true)
|
51
|
+
end
|
52
|
+
|
53
|
+
def process_sendmail_settings
|
54
|
+
if hash.has_key?('sendmail_settings')
|
55
|
+
ActionMailer::Base.sendmail_settings = hash.fetch('sendmail_settings').symbolize_keys
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def process_smtp_settings
|
60
|
+
if hash.has_key?('smtp_settings')
|
61
|
+
ActionMailer::Base.smtp_settings = hash.fetch('smtp_settings').symbolize_keys
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def process_subject_prefix
|
66
|
+
prefix = hash.fetch('subject_prefix', '')
|
67
|
+
prefix = prefix.gsub("{env}", Rails.env)
|
68
|
+
UcbRailsUser.config.email_subject_prefix = prefix
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module UcbRailsUser
|
2
|
+
module Configuration
|
3
|
+
|
4
|
+
class ExceptionNotification
|
5
|
+
|
6
|
+
class << self
|
7
|
+
|
8
|
+
def configure(config)
|
9
|
+
return if config.blank?
|
10
|
+
|
11
|
+
config = config.symbolize_keys
|
12
|
+
config[:email].symbolize_keys!
|
13
|
+
config[:email][:email_prefix] = config[:email][:email_prefix].gsub("{env}", RailsEnvironment.short)
|
14
|
+
|
15
|
+
Rails.application.config.middleware.use ::ExceptionNotification::Rack, config
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module UcbRailsUser
|
2
|
+
module Configuration
|
3
|
+
|
4
|
+
class Ldap
|
5
|
+
attr_accessor :config
|
6
|
+
|
7
|
+
def initialize(config)
|
8
|
+
self.config = config.presence || {}
|
9
|
+
end
|
10
|
+
|
11
|
+
def configure
|
12
|
+
configure_host
|
13
|
+
initialize_ldap
|
14
|
+
test_entries
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def configure_host
|
20
|
+
UCB::LDAP.host = config.fetch("host", default_host)
|
21
|
+
end
|
22
|
+
|
23
|
+
def initialize_ldap
|
24
|
+
username = config.fetch("username", "")
|
25
|
+
password = config.fetch("password", "")
|
26
|
+
host = config.fetch("host", "")
|
27
|
+
UCB::LDAP.initialize username, password, host
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_entries
|
31
|
+
UCB::LDAP::Person.include_test_entries = config.fetch("include_test_entries", default_include_test_entries)
|
32
|
+
end
|
33
|
+
|
34
|
+
def default_host
|
35
|
+
"nds.berkeley.edu"
|
36
|
+
end
|
37
|
+
|
38
|
+
def default_include_test_entries
|
39
|
+
!Rails.env.production?
|
40
|
+
end
|
41
|
+
|
42
|
+
class << self
|
43
|
+
def configure(config)
|
44
|
+
new(config).configure
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module UcbRailsUser::LdapPerson
|
2
|
+
class Entry
|
3
|
+
|
4
|
+
# include ActiveAttr::Model <--- doesn't work with 4.0 (mass assign. security)
|
5
|
+
include ::ActiveAttr::Attributes
|
6
|
+
include ::ActiveAttr::BasicModel
|
7
|
+
include ::ActiveAttr::BlockInitialization
|
8
|
+
include ::ActiveAttr::MassAssignment
|
9
|
+
|
10
|
+
attribute :uid
|
11
|
+
attribute :calnet_id
|
12
|
+
attribute :employee_id
|
13
|
+
attribute :student_id
|
14
|
+
attribute :first_name
|
15
|
+
attribute :last_name
|
16
|
+
attribute :email
|
17
|
+
attribute :phone
|
18
|
+
attribute :departments
|
19
|
+
attribute :affiliations
|
20
|
+
attribute :affiliate_id
|
21
|
+
attribute :inactive
|
22
|
+
|
23
|
+
def full_name
|
24
|
+
"#{first_name()} #{last_name()}"
|
25
|
+
end
|
26
|
+
|
27
|
+
def last_first
|
28
|
+
"#{last_name}, #{first_name}"
|
29
|
+
end
|
30
|
+
|
31
|
+
def last_first_downcase
|
32
|
+
last_first.downcase
|
33
|
+
end
|
34
|
+
|
35
|
+
# Currently only used in rspec
|
36
|
+
def ==(other)
|
37
|
+
uid == other.uid
|
38
|
+
end
|
39
|
+
|
40
|
+
class << self
|
41
|
+
|
42
|
+
def new_from_ldap_entry(ldap_entry)
|
43
|
+
new(
|
44
|
+
:uid => ldap_entry.uid,
|
45
|
+
:calnet_id => ldap_entry.berkeleyedukerberosprincipalstring.first,
|
46
|
+
:employee_id => ldap_entry.employeenumber,
|
47
|
+
:student_id => ldap_entry.attributes["student_id"],
|
48
|
+
:first_name => ldap_entry.givenname.first,
|
49
|
+
:last_name => ldap_entry.sn.first,
|
50
|
+
:email => ldap_entry.mail.first,
|
51
|
+
:phone => ldap_entry.phone,
|
52
|
+
:departments => ldap_entry.berkeleyeduunithrdeptname,
|
53
|
+
:affiliations => ldap_entry.berkeleyeduaffiliations,
|
54
|
+
:affiliate_id => ldap_entry.berkeleyeduaffid.first,
|
55
|
+
:inactive => ldap_entry.expired? || false
|
56
|
+
)
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
module UcbRailsUser::LdapPerson
|
2
|
+
class Finder
|
3
|
+
BlankSearchTermsError = Class.new(StandardError)
|
4
|
+
PersonNotFound = Class.new(StandardError)
|
5
|
+
|
6
|
+
def benchmark(message = "Benchmarking")
|
7
|
+
result = nil
|
8
|
+
ms = Benchmark.ms { result = yield }
|
9
|
+
Rails.logger.debug "#{message} #{ms}"
|
10
|
+
result
|
11
|
+
end
|
12
|
+
|
13
|
+
def find_by_uid(uid)
|
14
|
+
benchmark("find_by_uid(#{uid})") do
|
15
|
+
find_by_attributes(:uid => uid.to_s).first ||
|
16
|
+
find_expired_by_attributes(:uid => uid.to_s).first
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def find_by_uid!(uid)
|
21
|
+
find_by_uid(uid) or raise(PersonNotFound, "uid=#{uid.inspect}")
|
22
|
+
end
|
23
|
+
|
24
|
+
def find_by_first_last(first_name, last_name, options={})
|
25
|
+
raise BlankSearchTermsError unless first_name.present? || last_name.present?
|
26
|
+
|
27
|
+
find_by_attributes({:givenname => first_name, :sn => last_name}, options).tap do |entries|
|
28
|
+
if options[:sort]
|
29
|
+
sort_symbol = options[:sort]
|
30
|
+
entries.sort_by!(&options[:sort])
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def find_by_affiliate_id(affiliate_id)
|
36
|
+
find_by_attributes("berkeleyEduAffID" => affiliate_id)
|
37
|
+
end
|
38
|
+
|
39
|
+
def find_by_attributes(attributes, options={})
|
40
|
+
attributes.each { |k, v| attributes.delete(k) if v.blank? }
|
41
|
+
|
42
|
+
search_opts = { :filter => build_filter(attributes, options) }
|
43
|
+
search_opts[:return_result] = options[:return_result] if options.has_key?(:return_result)
|
44
|
+
search_opts[:size] = options[:size] if options.has_key?(:size)
|
45
|
+
|
46
|
+
UCB::LDAP::Person.
|
47
|
+
search(search_opts).
|
48
|
+
map { |ldap_entry| Entry.new_from_ldap_entry(ldap_entry) }
|
49
|
+
end
|
50
|
+
|
51
|
+
def find_expired_by_attributes(attributes)
|
52
|
+
attributes.each { |k, v| attributes.delete(k) if v.blank? }
|
53
|
+
UCB::LDAP::ExpiredPerson.
|
54
|
+
search(:filter => build_filter(attributes)).
|
55
|
+
map { |ldap_entry| Entry.new_from_ldap_entry(ldap_entry) }
|
56
|
+
end
|
57
|
+
|
58
|
+
def build_filter(attrs, options={})
|
59
|
+
operator = options[:operator] || :&
|
60
|
+
filter_parts = attrs.map { |k, values|
|
61
|
+
Array(values).map{|v| build_filter_part(k, v) }
|
62
|
+
}.flatten
|
63
|
+
filter = filter_parts.inject { |accum, filter| accum.send(operator, filter) }
|
64
|
+
filter
|
65
|
+
end
|
66
|
+
|
67
|
+
def build_filter_part(key, value)
|
68
|
+
value = key.to_s == 'uid' ? value : "#{value}*"
|
69
|
+
Net::LDAP::Filter.eq(key.to_s, value)
|
70
|
+
end
|
71
|
+
|
72
|
+
class << self
|
73
|
+
def klass
|
74
|
+
if Rails.env.test? || UcbRailsUser[:omniauth_provider] == :developer
|
75
|
+
UcbRailsUser::LdapPerson::TestFinder
|
76
|
+
else
|
77
|
+
UcbRailsUser::LdapPerson::Finder
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def method_missing(method, *args)
|
82
|
+
klass.new.send(method, *args)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
module UcbRailsUser::LdapPerson
|
2
|
+
class TestFinder
|
3
|
+
PersonNotFound = Class.new(StandardError)
|
4
|
+
|
5
|
+
def find_by_uid(uid)
|
6
|
+
uid.presence and find_by_attributes(:uid => uid.to_s).first
|
7
|
+
end
|
8
|
+
|
9
|
+
def find_by_uid!(uid)
|
10
|
+
find_by_uid(uid) || raise(PersonNotFound, "uid=#{uid.inspect}")
|
11
|
+
end
|
12
|
+
|
13
|
+
def find_by_first_last(first_name, last_name, options={})
|
14
|
+
find_by_attributes(:first_name => first_name, :last_name => last_name)
|
15
|
+
end
|
16
|
+
|
17
|
+
def find_by_affiliate_id(affiliate_id)
|
18
|
+
find_by_attributes("affiliate_id" => affiliate_id)
|
19
|
+
end
|
20
|
+
|
21
|
+
def find_by_attributes(attributes)
|
22
|
+
self.class.entries.select { |entry| entry_matches_attributes(entry, attributes) }
|
23
|
+
end
|
24
|
+
|
25
|
+
def entry_matches_attributes(entry, attributes)
|
26
|
+
attributes.keys.all? do |key|
|
27
|
+
value = attributes[key].to_s.downcase
|
28
|
+
value.blank? || (entry.respond_to?(key) && entry.send(key).to_s.downcase.include?(value))
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.entries
|
33
|
+
[
|
34
|
+
new_entry("1", 'art', "Art", "Andrews", "art@example.com", "999-999-0001", "Dept 1", "011"),
|
35
|
+
new_entry("2", 'beth', "Beth", "Brown", "beth@example.com", "999-999-0002", "Dept 2", "012"),
|
36
|
+
new_entry("61065", 'runner', "Steven", "Hansen", "runner@berkeley.edu", "999-999-9998", "EAS", "0161065"),
|
37
|
+
new_entry("191501", 'stevedowney', "Steve", "Downey", "sldowney@berkeley.edu", "999-999-9999", "EAS", "01191501"),
|
38
|
+
]
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.new_entry(uid, calnet_id, fn, ln, email, phone, depts, employee_id = nil, affiliate_id = nil)
|
42
|
+
::UcbRailsUser::LdapPerson::Entry.new(
|
43
|
+
:uid => uid,
|
44
|
+
:calnet_id => calnet_id,
|
45
|
+
:first_name => fn,
|
46
|
+
:last_name => ln,
|
47
|
+
:email => email,
|
48
|
+
:phone => phone,
|
49
|
+
:departments => depts,
|
50
|
+
:employee_id => employee_id,
|
51
|
+
:affiliate_id => affiliate_id,
|
52
|
+
:inactive => false
|
53
|
+
)
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
class UcbRailsUser::UserLdapService
|
2
|
+
|
3
|
+
class << self
|
4
|
+
|
5
|
+
def create_user_from_uid(uid)
|
6
|
+
UcbRailsUser.logger.debug "create_user_from_uid #{uid}"
|
7
|
+
|
8
|
+
ldap_entry = UcbRailsUser::LdapPerson::Finder.find_by_uid!(uid)
|
9
|
+
create_user_from_ldap_entry(ldap_entry)
|
10
|
+
end
|
11
|
+
|
12
|
+
def create_user_from_ldap_entry(ldap_entry)
|
13
|
+
UcbRailsUser.logger.debug "create_user_from_ldap_entry #{ldap_entry.uid}"
|
14
|
+
|
15
|
+
User.create! do |u|
|
16
|
+
u.ldap_uid = ldap_entry.uid
|
17
|
+
u.employee_id = ldap_entry.employee_id
|
18
|
+
u.affiliate_id = ldap_entry.affiliate_id
|
19
|
+
u.student_id = ldap_entry.student_id
|
20
|
+
u.first_name = ldap_entry.first_name
|
21
|
+
u.last_name = ldap_entry.last_name
|
22
|
+
u.email = ldap_entry.email
|
23
|
+
u.inactive_flag = ldap_entry.inactive
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def update_user_from_uid(uid)
|
28
|
+
UcbRailsUser.logger.debug "update_user_from_uid #{uid}"
|
29
|
+
|
30
|
+
ldap_entry = UcbRailsUser::LdapPerson::Finder.find_by_uid!(uid)
|
31
|
+
update_user_from_ldap_entry(ldap_entry)
|
32
|
+
end
|
33
|
+
|
34
|
+
def update_user_from_ldap_entry(ldap_entry)
|
35
|
+
UcbRailsUser.logger.debug "update_user_from_ldap_entry #{ldap_entry.uid}"
|
36
|
+
|
37
|
+
User.find_by_ldap_uid!(ldap_entry.uid).tap do |user|
|
38
|
+
user.employee_id = ldap_entry.employee_id if user.respond_to?(:employee_id=)
|
39
|
+
user.first_name = ldap_entry.first_name
|
40
|
+
user.last_name = ldap_entry.last_name
|
41
|
+
user.email = ldap_entry.email
|
42
|
+
user.save(validate: false)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def create_or_update_user(uid)
|
47
|
+
if user = User.find_by_ldap_uid(uid)
|
48
|
+
update_user_from_uid(uid)
|
49
|
+
else
|
50
|
+
create_user_from_uid(uid)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def create_or_update_user_from_entry(entry)
|
55
|
+
# LDAP returns some values as Net::BER::BerIdentifiedString instances, and not
|
56
|
+
# all DBs seem to handle that well (e.g. Oracle) - we might want to fix LDAP library
|
57
|
+
# to smooth this over?
|
58
|
+
if user = User.find_by_ldap_uid(entry.uid.to_s)
|
59
|
+
update_user_from_ldap_entry(entry)
|
60
|
+
else
|
61
|
+
create_user_from_ldap_entry(entry)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module UcbRailsUser
|
2
|
+
module UserSessionManager
|
3
|
+
class ActiveInUserTable < Base
|
4
|
+
|
5
|
+
def login(uid)
|
6
|
+
self.uid = uid
|
7
|
+
|
8
|
+
if user_table_entry && people_ou_entry
|
9
|
+
UcbRailsUser::UserLdapService.update_user_from_ldap_entry(people_ou_entry).tap do |user|
|
10
|
+
user.touch(:last_login_at)
|
11
|
+
end
|
12
|
+
else
|
13
|
+
false
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def current_user(uid)
|
18
|
+
User.find_by_ldap_uid(uid)
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def user_table_entry
|
24
|
+
active_user
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|