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,68 @@
1
+ module UcbRailsUser::Concerns::SessionsController
2
+ extend ActiveSupport::Concern
3
+
4
+ included do
5
+ skip_before_action :ensure_authenticated_user, :log_request
6
+ end
7
+
8
+ # Redirects to authentication provider
9
+ #
10
+ # @return [nil]
11
+ def new
12
+ provider = UcbRailsUser[:omniauth_provider] || :cas
13
+ redirect_to "/auth/#{provider}"
14
+ end
15
+
16
+ # Login user after authentication by provider
17
+ #
18
+ # @return [nil]
19
+ def create
20
+ uid = request.env['omniauth.auth'].uid
21
+ session[:omniauth_provider] = request.env['omniauth.auth'].provider
22
+
23
+ if user_session_manager.login(uid)
24
+ session[:uid] = uid
25
+ redirect_to session[:original_url] || root_path
26
+ else
27
+ redirect_to not_authorized_path
28
+ end
29
+ end
30
+
31
+ # Log user out
32
+ #
33
+ # @return [nil]
34
+ def destroy
35
+ user_session_manager.logout(current_user)
36
+ provider = session[:omniauth_provider]
37
+ reset_session
38
+ p "using #{redirect_url(provider)}"
39
+ redirect_to redirect_url(provider)
40
+ end
41
+
42
+ # Action called when unauthorized access attempted
43
+ #
44
+ # @return [nil]
45
+ def not_authorized
46
+ render(:text => "Not Authorized", :status => 401)
47
+ end
48
+
49
+ # Handler for authentication failure.
50
+ #
51
+ # @return [nil]
52
+ def failure
53
+ Rails.logger.debug("Authentication Failed for: #{request.env['omniauth.auth']}")
54
+ render(:text => "Not Authorized", :status => 401)
55
+ end
56
+
57
+ private
58
+
59
+ def redirect_url(provider)
60
+ if provider.to_s == 'cas'
61
+ "https://#{UcbRailsUser[:cas_host]}/cas/logout?service=#{root_url}"
62
+ else
63
+ root_path
64
+ end
65
+ end
66
+
67
+
68
+ end
@@ -0,0 +1,132 @@
1
+ module UcbRailsUser::Concerns::UsersController
2
+ extend ActiveSupport::Concern
3
+
4
+ included do
5
+ before_action :find_user, :only => [:edit, :update, :destroy]
6
+ before_action :ensure_admin_user
7
+ skip_before_action :ensure_admin_user, if: ->{ action_name == "toggle_superuser" && Rails.env.development? }
8
+ end
9
+
10
+ def index
11
+ @users = User.all
12
+ respond_to do |format|
13
+ format.html { @users = User.all }
14
+ format.json { render json: UcbRails::UsersDatatable.new(view_context).as_json }
15
+ end
16
+ end
17
+
18
+ def search
19
+ @results = UcbRailsUser::LdapPerson::Finder.find_by_attributes(
20
+ {
21
+ givenname: params.fetch(:first_name),
22
+ sn: params.fetch(:last_name),
23
+ employeenumber: params.fetch(:employee_id)
24
+ },
25
+ sort: :last_first_downcase
26
+ )
27
+ end
28
+
29
+ def edit
30
+ end
31
+
32
+ def new
33
+ end
34
+
35
+ def create
36
+ uid = params.fetch(:ldap_uid)
37
+ user = nil
38
+ if user = User.find_by_ldap_uid(uid)
39
+ flash[:warning] = "User already exists"
40
+ else
41
+ begin
42
+ user = UcbRailsUser::UserLdapService.create_user_from_uid(uid)
43
+ flash[:notice] = "Record created"
44
+ rescue Exception => e
45
+ raise e
46
+ flash[:danger] = "Unable to create new user - please try again"
47
+ return redirect_to new_admin_user_path()
48
+ end
49
+ end
50
+ redirect_to edit_admin_user_path(user)
51
+ end
52
+
53
+ def update
54
+ if @user.update_attributes(user_params)
55
+ redirect_to(admin_users_path, notice: 'Record updated')
56
+ else
57
+ render("edit")
58
+ end
59
+ end
60
+
61
+ def destroy
62
+ if @user.destroy
63
+ flash[:notice] = 'Record deleted'
64
+ else
65
+ flash[:error] = @user.errors[:base].first
66
+ end
67
+
68
+ redirect_to(admin_users_path)
69
+ end
70
+
71
+ def ldap_search
72
+ # FIXME: this was retrofitted to support typeahead ajax json queries
73
+ if(query = params[:query])
74
+ @lps_entries = UcbRails::OmniUserTypeahead.new.ldap_results(query)
75
+ @lps_entries.map!{|entry|
76
+ attrs = entry.attributes.tap{|attrs| attrs["first_last_name"] = "#{attrs['first_name']} #{attrs['last_name']}" }
77
+ attrs.as_json
78
+ }
79
+
80
+ render json: @lps_entries
81
+
82
+ else
83
+ @lps_entries = UcbRails::LdapPerson::Finder.find_by_first_last(
84
+ params.fetch(:first_name),
85
+ params.fetch(:last_name),
86
+ :sort => :last_first_downcase
87
+ )
88
+ @lps_existing_uids = User.where(ldap_uid: @lps_entries.map(&:uid)).pluck(:uid)
89
+ render 'lps/search'
90
+ end
91
+
92
+ end
93
+
94
+ def typeahead_search
95
+ uta = UcbRails::UserTypeahead.new
96
+ render json: uta.results(params.fetch(:query))
97
+ end
98
+
99
+ def omni_typeahead_search
100
+ uta = UcbRails::OmniUserTypeahead.new
101
+ render json: uta.results(params.fetch(:query))
102
+ end
103
+
104
+ def toggle_superuser
105
+ current_user.try(:superuser!, !superuser?)
106
+ redirect_to root_path
107
+ end
108
+
109
+ private
110
+
111
+ def user_params
112
+ params.require(:user).permit(
113
+ :superuser_flag,
114
+ :inactive_flag,
115
+ :first_name,
116
+ :last_name,
117
+ :email,
118
+ :alternate_email,
119
+ :phone,
120
+ :last_request_at,
121
+ :last_logout_at,
122
+ :last_login_at,
123
+ :uid
124
+ )
125
+ end
126
+
127
+ def find_user
128
+ @user ||= User.find(params.fetch(:id))
129
+ end
130
+
131
+ end
132
+
@@ -0,0 +1,10 @@
1
+ class UcbRailsUser::HomeController < ApplicationController
2
+ include UcbRailsUser::Concerns::ControllerMethods
3
+ include UcbRailsUser::Concerns::HomeController
4
+
5
+ # Don't add anything more here - any logic for this class should go into
6
+ # Concerns::HomeController. This will make it much easier for host
7
+ # apps to customize behavior if they need to
8
+ # http://guides.rubyonrails.org/engines.html#implementing-decorator-pattern-using-activesupport-concern
9
+ end
10
+
@@ -0,0 +1,9 @@
1
+ # Manages starting and ending of sessions, i.e., logging in and out.
2
+ class UcbRailsUser::SessionsController < ApplicationController
3
+ include UcbRailsUser::Concerns::SessionsController
4
+
5
+ # Don't add anything more here - any logic for this class should go into
6
+ # Concerns::SessionsController. This will make it much easier for host
7
+ # apps to customize behavior if they need to
8
+ # http://guides.rubyonrails.org/engines.html#implementing-decorator-pattern-using-activesupport-concern
9
+ end
@@ -0,0 +1,8 @@
1
+ class UcbRailsUser::UsersController < ApplicationController
2
+ include UcbRailsUser::Concerns::UsersController
3
+
4
+ # Don't add anything more here - any logic for this controller should go into
5
+ # Concerns::UserController. This will make it much easier for host apps to customize
6
+ # behavior if they need to
7
+ # http://guides.rubyonrails.org/engines.html#implementing-decorator-pattern-using-activesupport-concern
8
+ end
@@ -0,0 +1,18 @@
1
+ module UcbRailsUser
2
+ module UsersHelper
3
+
4
+ def link_to_new_user
5
+ text = 'New User'
6
+ # text = image_tag('ucb_rails/glyphicons_006_user_add.png', size: '14x14')
7
+ button(text, :primary,
8
+ class: 'ldap-person-search',
9
+ data: {
10
+ search_url: "",
11
+ result_link_url: new_admin_user_path,
12
+ result_link_http_method: 'post',
13
+ }
14
+ )
15
+ end
16
+
17
+ end
18
+ end
@@ -0,0 +1,17 @@
1
+ # These methods should be extracted into own gem.
2
+ module UcbRailsUserHelper
3
+
4
+ def ucbr_table_tag(*args)
5
+ options = canonicalize_options(args.extract_options!)
6
+
7
+ ar_class = args.first
8
+ if ar_class.respond_to?(:haml_attributes)
9
+ options[:id] ||= ar_class.haml_attributes["id"]
10
+ options = ensure_class(options, ar_class.haml_attributes["class"])
11
+ end
12
+
13
+ bs_table_tag(options) do
14
+ yield
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,53 @@
1
+ module UserConcerns
2
+ extend ActiveSupport::Concern
3
+
4
+ # Overridden by application
5
+ def roles
6
+ []
7
+ end
8
+
9
+ def has_role?(role)
10
+ superuser? || roles.include?(role)
11
+ end
12
+
13
+ def active?
14
+ !inactive?
15
+ end
16
+
17
+ def inactive?
18
+ inactive_flag
19
+ end
20
+
21
+ def superuser!(_superuser=true)
22
+ update_attribute(:superuser_flag, _superuser)
23
+ end
24
+
25
+ def superuser?
26
+ superuser_flag
27
+ end
28
+
29
+ def inactive!(_inactive=true)
30
+ update_attribute(:inactive_flag, _inactive)
31
+ end
32
+
33
+ def ldap_entry
34
+ UcbRailsUser::LdapPerson::Finder.find_by_uid!(uid)
35
+ end
36
+
37
+ def full_name
38
+ return nil unless first_name || last_name
39
+ "#{first_name} #{last_name}".strip
40
+ end
41
+
42
+ class_methods do
43
+ def active
44
+ where(inactive_flag: false)
45
+ end
46
+
47
+ def superuser
48
+ where(superuser_flag: true)
49
+ end
50
+ end
51
+
52
+ end
53
+
@@ -0,0 +1,53 @@
1
+ module UcbRailsUser
2
+ module Configuration
3
+
4
+ class Cas
5
+ attr_accessor :config
6
+
7
+ def initialize(config)
8
+ self.config = config.presence || {}
9
+ end
10
+
11
+ def configure
12
+ configure_omniauth
13
+ set_ucb_rails_cas_host
14
+ end
15
+
16
+ def configure_omniauth
17
+ host_name = host
18
+ Rails.application.config.middleware.use OmniAuth::Builder do
19
+
20
+ unless Rails.env.production?
21
+ provider(:developer, fields: [:uid], uid_field: :uid)
22
+ end
23
+
24
+ provider :cas,
25
+ host: host_name,
26
+ login_url: '/cas/login?renew=true', # renew=true forces the login screen to appear each time
27
+ service_validate_url: '/cas/serviceValidate'
28
+ end
29
+ end
30
+
31
+ def set_ucb_rails_cas_host
32
+ UcbRailsUser.config.cas_host = host
33
+ end
34
+
35
+ private
36
+
37
+ def host
38
+ config.fetch('host', default_host)
39
+ end
40
+
41
+ def default_host
42
+ Rails.env.production? ? 'auth.berkeley.edu' : 'auth-test.berkeley.edu'
43
+ end
44
+
45
+ class << self
46
+ def configure(config)
47
+ new(config).configure
48
+ end
49
+ end
50
+ end
51
+
52
+ end
53
+ end
@@ -0,0 +1,72 @@
1
+ module UcbRailsUser
2
+ module Configuration
3
+
4
+ # Manage configuration from file. Per environment or overall.
5
+ #
6
+ # @example
7
+ # # config/config.yml
8
+ # test:
9
+ # ldap:
10
+ # username: test_username
11
+ # password: test_password
12
+ #
13
+ # ldap:
14
+ # username: top_username
15
+ # password: top_password
16
+ #
17
+ # # in config/initializers/ucb_rails.rb (e.g.)
18
+ # config = UcbRailsUser::Credentials.new
19
+ #
20
+ # # in production -- pulls from top level, since no 'production' key
21
+ # config.for('ldap') #=> { 'username' => 'top_username', 'password' => 'top_password' }
22
+ #
23
+ # # in test -- pulls from 'test' key
24
+ # config.for('ldap') #=> { 'username' => 'test_username', 'password' => 'test_password' }
25
+ class Configuration
26
+ FileNotFound = Class.new(StandardError)
27
+ KeyNotFound = Class.new(StandardError)
28
+
29
+ attr_accessor :config_filename, :config_yaml
30
+
31
+ def initialize(filename=Rails.root.join('config/config.yml'))
32
+ self.config_filename = filename.to_s
33
+ load_file
34
+ end
35
+
36
+ # Return configuration value for _key_.
37
+ # @param key [String]
38
+ def for(key)
39
+ from_environment(key) || from_top_level(key)
40
+ end
41
+
42
+ # Return configuration value for _key_.
43
+ # @raise [UcbRailsUser::Configuration::KeyNotFound] if _key_ not in configuration file.
44
+ def for!(key)
45
+ self.for(key) or raise(KeyNotFound, key.inspect)
46
+ end
47
+
48
+ private
49
+
50
+ def from_environment(key)
51
+ environment_value && environment_value[key]
52
+ end
53
+
54
+ def from_top_level(key)
55
+ config_yaml[key]
56
+ end
57
+
58
+ def environment_value
59
+ config_yaml[Rails.env]
60
+ end
61
+
62
+ def load_file
63
+ if File.exists?(config_filename)
64
+ self.config_yaml = YAML.load_file(config_filename)
65
+ else
66
+ raise(FileNotFound, config_filename)
67
+ end
68
+ end
69
+ end
70
+
71
+ end
72
+ end