chaltron 1.1.7 → 2.0.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.
- checksums.yaml +4 -4
- data/app/assets/javascripts/chaltron.js +0 -18
- data/app/assets/javascripts/chaltron/core.js.erb +62 -0
- data/app/assets/javascripts/chaltron/datatables.js +69 -0
- data/app/assets/javascripts/chaltron/flash_messages.js +14 -0
- data/app/assets/javascripts/chaltron/ldap_create.js +44 -0
- data/app/assets/javascripts/chaltron/locales/en.json +25 -0
- data/app/assets/javascripts/chaltron/locales/it.json +25 -0
- data/app/assets/javascripts/chaltron/navbar.js +86 -0
- data/app/assets/stylesheets/chaltron.scss +0 -27
- data/app/helpers/chaltron/ldap_helper.rb +9 -0
- data/app/views/chaltron/ldap/_entry.html.erb +3 -1
- data/app/views/chaltron/ldap/multi_new.html.erb +6 -2
- data/config/initializers/devise.rb +259 -255
- data/config/initializers/warden.rb +27 -25
- data/config/routes.rb +1 -1
- data/lib/chaltron.rb +0 -1
- data/lib/chaltron/engine.rb +17 -18
- data/lib/chaltron/form_builder/bootstrap_form.rb +23 -0
- data/lib/chaltron/ldap/connection.rb +154 -152
- data/lib/chaltron/version.rb +1 -1
- data/lib/generators/chaltron/install_generator.rb +59 -5
- data/lib/generators/chaltron/templates/Procfile +2 -0
- data/lib/generators/chaltron/templates/app/assets/javascripts/{home.js.coffee → home.coffee} +0 -0
- data/lib/generators/chaltron/templates/app/assets/stylesheets/chaltron_custom.scss +24 -10
- data/lib/generators/chaltron/templates/app/assets/stylesheets/datatables.scss +2 -0
- data/lib/generators/chaltron/templates/app/views/layouts/application.html.erb +2 -2
- data/lib/generators/chaltron/templates/config/navigation.rb +8 -8
- metadata +13 -234
- data/app/assets/javascripts/chaltron/datatables.js.coffee +0 -103
- data/app/assets/javascripts/chaltron/localization.js.coffee +0 -59
- data/app/assets/javascripts/chaltron/main.js.coffee +0 -7
- data/app/assets/javascripts/chaltron/navbar.js.coffee +0 -62
- data/app/assets/javascripts/dataTables/dataTables.bootstrap4.min.js +0 -8
- data/lib/chaltron/bootstrap_form.rb +0 -21
- data/lib/generators/chaltron/install/templates/Procfile +0 -1
@@ -1,31 +1,33 @@
|
|
1
1
|
require 'chaltron/ldap/user'
|
2
2
|
|
3
|
-
Warden
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
3
|
+
if defined?(Warden)
|
4
|
+
Warden::Manager.after_set_user do |record, warden, options|
|
5
|
+
# LDAP callback. Last check before authentication
|
6
|
+
if record && record.ldap_user? &&
|
7
|
+
Chaltron.ldap_after_authenticate.call(record, Chaltron::LDAP::Connection.new).nil?
|
8
|
+
scope = options[:scope]
|
9
|
+
warden.logout(scope)
|
10
|
+
throw :warden, scope: scope, message: I18n.t('chaltron.not_allowed_to_sign_in')
|
11
|
+
end
|
10
12
|
end
|
11
|
-
end
|
12
13
|
|
13
|
-
# Log after authentication
|
14
|
-
Warden::Manager.after_authentication do |user,auth,opts|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
end
|
14
|
+
# Log after authentication
|
15
|
+
Warden::Manager.after_authentication do |user,auth,opts|
|
16
|
+
Log.create(
|
17
|
+
message: I18n.t('chaltron.logs.login', user: user.display_name),
|
18
|
+
category: :login,
|
19
|
+
severity: :info
|
20
|
+
) if user
|
21
|
+
end
|
21
22
|
|
22
|
-
Warden::Manager.before_logout do |user,auth,opts|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
23
|
+
Warden::Manager.before_logout do |user,auth,opts|
|
24
|
+
# LDAP callback
|
25
|
+
Chaltron.ldap_before_logout.call(user, Chaltron::LDAP::Connection.new) if user.ldap_user?
|
26
|
+
# Log before logout
|
27
|
+
Log.create(
|
28
|
+
message: I18n.t('chaltron.logs.logout', user: user.display_name),
|
29
|
+
category: :login,
|
30
|
+
severity: :info
|
31
|
+
) if user
|
32
|
+
end
|
31
33
|
end
|
data/config/routes.rb
CHANGED
data/lib/chaltron.rb
CHANGED
data/lib/chaltron/engine.rb
CHANGED
@@ -1,20 +1,3 @@
|
|
1
|
-
require 'devise'
|
2
|
-
require 'cancancan'
|
3
|
-
require 'omniauth'
|
4
|
-
require 'omniauth-ldap'
|
5
|
-
require 'bootstrap'
|
6
|
-
require 'autoprefixer-rails'
|
7
|
-
require 'font-awesome-sass'
|
8
|
-
require 'simple-navigation'
|
9
|
-
require 'ajax-datatables-rails'
|
10
|
-
require 'bootstrap_form'
|
11
|
-
require 'nprogress-rails'
|
12
|
-
require 'rails-i18n'
|
13
|
-
require 'jquery-rails'
|
14
|
-
require 'jquery-datatables'
|
15
|
-
|
16
|
-
SimpleNavigation.config_file_paths << File.expand_path('../../../config', __FILE__)
|
17
|
-
|
18
1
|
module Chaltron
|
19
2
|
class Engine < ::Rails::Engine
|
20
3
|
config.generators do |g|
|
@@ -33,11 +16,27 @@ module Chaltron
|
|
33
16
|
Chaltron::Engine.config.i18n.load_path += Dir[root.join('app/models', 'locales', '*.{rb,yml}')]
|
34
17
|
end
|
35
18
|
|
36
|
-
initializer('chaltron.
|
19
|
+
initializer('chaltron.controller') do |_app|
|
37
20
|
ActiveSupport.on_load(:action_controller) do
|
38
21
|
include Chaltron::Controllers::Helpers
|
39
22
|
before_action :configure_permitted_parameters, if: :devise_controller?
|
23
|
+
|
24
|
+
# to override devise views
|
25
|
+
prepend_view_path File.expand_path('../../../app/views', __FILE__)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
initializer('chaltron.simple_navigation') do |_app|
|
30
|
+
if defined?(SimpleNavigation)
|
31
|
+
SimpleNavigation.config_file_paths << File.expand_path('../../../config', __FILE__)
|
40
32
|
end
|
41
33
|
end
|
34
|
+
|
35
|
+
initializer('chaltron.bootstrap_form') do |_app|
|
36
|
+
if defined?(BootstrapForm)
|
37
|
+
require 'chaltron/form_builder/bootstrap_form'
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
42
41
|
end
|
43
42
|
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
if defined?(BootstrapForm)
|
2
|
+
class BootstrapForm::FormBuilder
|
3
|
+
|
4
|
+
def role_select(opts = {})
|
5
|
+
collection = Chaltron.roles.map { |role| [role, I18n.translate("roles.#{role}")] }
|
6
|
+
checked = @object.nil?? false : @object.roles
|
7
|
+
html = inputs_collection(:roles, collection, :first, :last, checked: checked) do |name, value, options|
|
8
|
+
options[:multiple] = true
|
9
|
+
options[:inline] = opts.fetch(:inline, true)
|
10
|
+
|
11
|
+
if value == opts[:disabled]
|
12
|
+
options[:disabled] = true
|
13
|
+
options[:checked] = true
|
14
|
+
end
|
15
|
+
check_box(name, options, value, nil)
|
16
|
+
end
|
17
|
+
|
18
|
+
hidden = opts[:disabled] || ''
|
19
|
+
hidden_field(:roles, { value: hidden, multiple: true }).concat(html)
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
@@ -1,190 +1,192 @@
|
|
1
|
-
|
2
|
-
require '
|
3
|
-
|
4
|
-
|
5
|
-
module
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
1
|
+
if defined?(Net::LDAP)
|
2
|
+
require 'net/ldap'
|
3
|
+
require 'chaltron/ldap/person'
|
4
|
+
|
5
|
+
module Chaltron
|
6
|
+
module LDAP
|
7
|
+
class Connection
|
8
|
+
NET_LDAP_ENCRYPTION_METHOD = {
|
9
|
+
simple_tls: :simple_tls,
|
10
|
+
start_tls: :start_tls,
|
11
|
+
plain: nil
|
12
|
+
}.freeze
|
13
|
+
|
14
|
+
attr_reader :ldap
|
15
|
+
|
16
|
+
def initialize(params = {})
|
17
|
+
@ldap = Net::LDAP.new(adapter_options)
|
18
|
+
end
|
18
19
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
20
|
+
def auth(login, password)
|
21
|
+
filter = Net::LDAP::Filter.eq(uid, login)
|
22
|
+
ldap.bind_as(base: base, filter: filter, password: password)
|
23
|
+
end
|
23
24
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
25
|
+
def find_by_uid(id)
|
26
|
+
opts = {}
|
27
|
+
opts[uid.to_sym] = id
|
28
|
+
ret = find_user(opts)
|
29
|
+
end
|
29
30
|
|
30
|
-
|
31
|
-
|
32
|
-
|
31
|
+
def find_user(*args)
|
32
|
+
find_users(*args).first
|
33
|
+
end
|
33
34
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
35
|
+
def ldap_search(*args)
|
36
|
+
results = ldap.search(*args)
|
37
|
+
if results.nil?
|
38
|
+
response = ldap.get_operation_result
|
39
|
+
unless response.code.zero?
|
40
|
+
Rails.logger.warn("LDAP search error: #{response.message}")
|
41
|
+
end
|
42
|
+
[]
|
43
|
+
else
|
44
|
+
results
|
40
45
|
end
|
41
|
-
[]
|
42
|
-
else
|
43
|
-
results
|
44
46
|
end
|
45
|
-
end
|
46
47
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
48
|
+
def find_users(args)
|
49
|
+
return [] if args.empty?
|
50
|
+
limit = args.delete(:limit)
|
51
|
+
fields = args.keys
|
52
|
+
|
53
|
+
if fields.include?(:dn)
|
54
|
+
options = {
|
55
|
+
base: args[:dn],
|
56
|
+
scope: Net::LDAP::SearchScope_BaseObject
|
57
|
+
}
|
58
|
+
else
|
59
|
+
filters = fields.map do |field|
|
60
|
+
f = translate_field(field)
|
61
|
+
Net::LDAP::Filter.eq(f, args[field]) if f
|
62
|
+
end
|
63
|
+
options = {
|
64
|
+
base: base,
|
65
|
+
filter: filters.inject { |sum, n| Net::LDAP::Filter.join(sum, n) }
|
66
|
+
}
|
61
67
|
end
|
68
|
+
options.merge!(size: limit) unless limit.nil?
|
69
|
+
ldap_search(options).map do |entry|
|
70
|
+
Chaltron::LDAP::Person.new(entry, uid) if entry.respond_to? uid
|
71
|
+
end.compact
|
72
|
+
end
|
73
|
+
|
74
|
+
def find_groups_by_member(entry)
|
62
75
|
options = {
|
63
|
-
base: base,
|
64
|
-
filter:
|
76
|
+
base: Chaltron.ldap_group_base || base,
|
77
|
+
filter: Chaltron.ldap_group_member_filter.call(entry)
|
65
78
|
}
|
79
|
+
ldap_search(options)
|
66
80
|
end
|
67
|
-
options.merge!(size: limit) unless limit.nil?
|
68
|
-
ldap_search(options).map do |entry|
|
69
|
-
Chaltron::LDAP::Person.new(entry, uid) if entry.respond_to? uid
|
70
|
-
end.compact
|
71
|
-
end
|
72
|
-
|
73
|
-
def find_groups_by_member(entry)
|
74
|
-
options = {
|
75
|
-
base: Chaltron.ldap_group_base || base,
|
76
|
-
filter: Chaltron.ldap_group_member_filter.call(entry)
|
77
|
-
}
|
78
|
-
ldap_search(options)
|
79
|
-
end
|
80
81
|
|
81
|
-
|
82
|
-
|
83
|
-
|
82
|
+
def update_attributes(dn, args)
|
83
|
+
ldap.modify dn: dn, operations: args.map { |k,v| [:replace, k, v] }
|
84
|
+
end
|
84
85
|
|
85
|
-
|
86
|
+
private
|
86
87
|
|
87
|
-
|
88
|
-
|
89
|
-
|
88
|
+
def options
|
89
|
+
Devise.omniauth_configs[:ldap].options
|
90
|
+
end
|
90
91
|
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
92
|
+
def translate_field field
|
93
|
+
return uid if field.to_sym == :uid
|
94
|
+
return Chaltron.ldap_field_mappings[field.to_sym] unless Chaltron.ldap_field_mappings[field.to_sym].nil?
|
95
|
+
field
|
96
|
+
end
|
96
97
|
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
98
|
+
def adapter_options
|
99
|
+
opts = {
|
100
|
+
host: options[:host],
|
101
|
+
port: options[:port],
|
102
|
+
encryption: encryption_options,
|
103
|
+
verbose: true
|
104
|
+
}
|
105
|
+
opts.merge!(auth_options) if has_auth?
|
106
|
+
opts
|
107
|
+
end
|
107
108
|
|
108
|
-
|
109
|
-
|
110
|
-
|
109
|
+
def base
|
110
|
+
options[:base]
|
111
|
+
end
|
111
112
|
|
112
|
-
|
113
|
-
|
114
|
-
|
113
|
+
def uid
|
114
|
+
options[:uid]
|
115
|
+
end
|
115
116
|
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
117
|
+
def encryption_options
|
118
|
+
method = translate_method
|
119
|
+
return unless method
|
120
|
+
{
|
121
|
+
method: method,
|
122
|
+
tls_options: tls_options
|
123
|
+
}
|
124
|
+
end
|
124
125
|
|
125
|
-
|
126
|
-
|
127
|
-
|
126
|
+
def translate_method
|
127
|
+
NET_LDAP_ENCRYPTION_METHOD[options[:encryption]&.to_sym]
|
128
|
+
end
|
128
129
|
|
129
|
-
|
130
|
-
|
130
|
+
def tls_options
|
131
|
+
return @tls_options if defined?(@tls_options)
|
131
132
|
|
132
|
-
|
133
|
-
|
133
|
+
method = translate_method
|
134
|
+
return unless method
|
134
135
|
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
136
|
+
opts = if options[:disable_verify_certificates]
|
137
|
+
# It is important to explicitly set verify_mode for two reasons:
|
138
|
+
# 1. The behavior of OpenSSL is undefined when verify_mode is not set.
|
139
|
+
# 2. The net-ldap gem implementation verifies the certificate hostname
|
140
|
+
# unless verify_mode is set to VERIFY_NONE.
|
141
|
+
{ verify_mode: OpenSSL::SSL::VERIFY_NONE }
|
142
|
+
else
|
143
|
+
# Dup so we don't accidentally overwrite the constant
|
144
|
+
OpenSSL::SSL::SSLContext::DEFAULT_PARAMS.dup
|
145
|
+
end
|
145
146
|
|
146
|
-
|
147
|
+
opts.merge!(custom_tls_options)
|
147
148
|
|
148
|
-
|
149
|
-
|
149
|
+
@tls_options = opts
|
150
|
+
end
|
150
151
|
|
151
|
-
|
152
|
-
|
152
|
+
def custom_tls_options
|
153
|
+
return {} unless options['tls_options']
|
153
154
|
|
154
|
-
|
155
|
-
|
156
|
-
|
155
|
+
# Dup so we don't overwrite the original value
|
156
|
+
custom_options = options['tls_options'].dup.delete_if { |_, value| value.nil? || value.blank? }
|
157
|
+
custom_options.symbolize_keys!
|
157
158
|
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
159
|
+
if custom_options[:cert]
|
160
|
+
begin
|
161
|
+
custom_options[:cert] = OpenSSL::X509::Certificate.new(custom_options[:cert])
|
162
|
+
rescue OpenSSL::X509::CertificateError => e
|
163
|
+
Rails.logger.error "LDAP TLS Options 'cert' is invalid for provider #{provider}: #{e.message}"
|
164
|
+
end
|
163
165
|
end
|
164
|
-
end
|
165
166
|
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
167
|
+
if custom_options[:key]
|
168
|
+
begin
|
169
|
+
custom_options[:key] = OpenSSL::PKey.read(custom_options[:key])
|
170
|
+
rescue OpenSSL::PKey::PKeyError => e
|
171
|
+
Rails.logger.error "LDAP TLS Options 'key' is invalid for provider #{provider}: #{e.message}"
|
172
|
+
end
|
171
173
|
end
|
174
|
+
custom_options
|
172
175
|
end
|
173
|
-
custom_options
|
174
|
-
end
|
175
176
|
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
177
|
+
def auth_options
|
178
|
+
{
|
179
|
+
auth: {
|
180
|
+
method: :simple,
|
181
|
+
username: options[:bind_dn],
|
182
|
+
password: options[:password]
|
183
|
+
}
|
182
184
|
}
|
183
|
-
|
184
|
-
end
|
185
|
+
end
|
185
186
|
|
186
|
-
|
187
|
-
|
187
|
+
def has_auth?
|
188
|
+
options[:password] || options[:bind_dn]
|
189
|
+
end
|
188
190
|
end
|
189
191
|
end
|
190
192
|
end
|