ucb_rails_user 0.9.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.
Files changed (64) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +166 -0
  4. data/Rakefile +36 -0
  5. data/app/assets/config/ucb_rails_user_manifest.js +0 -0
  6. data/app/assets/javascripts/ucb_rails_user/datatables.js +15441 -0
  7. data/app/assets/javascripts/ucb_rails_user/scripts.js +15 -0
  8. data/app/assets/javascripts/ucb_rails_user/ucb_rails_user.js +39 -0
  9. data/app/assets/stylesheets/ucb_rails_user/components/_add_users_search_results_table.sass +2 -0
  10. data/app/assets/stylesheets/ucb_rails_user/components/_loader.sass +46 -0
  11. data/app/assets/stylesheets/ucb_rails_user/components/_users_table.sass +10 -0
  12. data/app/assets/stylesheets/ucb_rails_user/datatables.css +201 -0
  13. data/app/assets/stylesheets/ucb_rails_user/main.sass +2 -0
  14. data/app/assets/stylesheets/ucb_rails_user/styles.css +19 -0
  15. data/app/controllers/ucb_rails_user/concerns/controller_methods.rb +92 -0
  16. data/app/controllers/ucb_rails_user/concerns/home_controller.rb +17 -0
  17. data/app/controllers/ucb_rails_user/concerns/sessions_controller.rb +68 -0
  18. data/app/controllers/ucb_rails_user/concerns/users_controller.rb +132 -0
  19. data/app/controllers/ucb_rails_user/home_controller.rb +10 -0
  20. data/app/controllers/ucb_rails_user/sessions_controller.rb +9 -0
  21. data/app/controllers/ucb_rails_user/users_controller.rb +8 -0
  22. data/app/helpers/ucb_rails_user/users_helper.rb +18 -0
  23. data/app/helpers/ucb_rails_user_helper.rb +17 -0
  24. data/app/models/concerns/user_concerns.rb +53 -0
  25. data/app/models/ucb_rails_user/configuration/cas.rb +53 -0
  26. data/app/models/ucb_rails_user/configuration/configuration.rb +72 -0
  27. data/app/models/ucb_rails_user/configuration/email.rb +73 -0
  28. data/app/models/ucb_rails_user/configuration/exception_notification.rb +21 -0
  29. data/app/models/ucb_rails_user/configuration/ldap.rb +50 -0
  30. data/app/models/ucb_rails_user/ldap_person/entry.rb +62 -0
  31. data/app/models/ucb_rails_user/ldap_person/finder.rb +87 -0
  32. data/app/models/ucb_rails_user/ldap_person/test_finder.rb +57 -0
  33. data/app/models/ucb_rails_user/user_ldap_service.rb +65 -0
  34. data/app/models/ucb_rails_user/user_session_manager/active_in_user_table.rb +29 -0
  35. data/app/models/ucb_rails_user/user_session_manager/admin_in_user_table.rb +13 -0
  36. data/app/models/ucb_rails_user/user_session_manager/base.rb +54 -0
  37. data/app/models/ucb_rails_user/user_session_manager/in_people_ou.rb +27 -0
  38. data/app/models/ucb_rails_user/user_session_manager/in_people_ou_add_to_users_table.rb +21 -0
  39. data/app/models/ucb_rails_user/user_session_manager/ldap_person_user_wrapper.rb +29 -0
  40. data/app/models/user.rb +8 -0
  41. data/app/views/ucb_rails_user/home/logged_in.html.haml +5 -0
  42. data/app/views/ucb_rails_user/home/not_logged_in.html.haml +5 -0
  43. data/app/views/ucb_rails_user/lps/_form.html.haml +19 -0
  44. data/app/views/ucb_rails_user/lps/_modal.html.haml +9 -0
  45. data/app/views/ucb_rails_user/lps/_results.html.haml +34 -0
  46. data/app/views/ucb_rails_user/lps/search.js.haml +3 -0
  47. data/app/views/ucb_rails_user/users/_form.html.haml +14 -0
  48. data/app/views/ucb_rails_user/users/_search_results.html.haml +24 -0
  49. data/app/views/ucb_rails_user/users/_user.html.haml +12 -0
  50. data/app/views/ucb_rails_user/users/edit.html.haml +3 -0
  51. data/app/views/ucb_rails_user/users/index.html.haml +23 -0
  52. data/app/views/ucb_rails_user/users/new.html.haml +16 -0
  53. data/app/views/ucb_rails_user/users/search.js.haml +4 -0
  54. data/config/initializers/simple_form.rb +171 -0
  55. data/config/initializers/simple_form_bootstrap.rb +154 -0
  56. data/config/locales/simple_form.en.yml +31 -0
  57. data/config/routes.rb +20 -0
  58. data/db/migrate/20170324221936_create_users.rb +29 -0
  59. data/lib/tasks/ucb_rails_user_tasks.rake +4 -0
  60. data/lib/templates/erb/scaffold/_form.html.erb +13 -0
  61. data/lib/ucb_rails_user.rb +21 -0
  62. data/lib/ucb_rails_user/engine.rb +28 -0
  63. data/lib/ucb_rails_user/version.rb +3 -0
  64. 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