Skip to content
This repository was archived by the owner on Feb 14, 2019. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion app/controllers/ldap_settings_controller.rb
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ def js_request?
end

def update_ldap_setting_from_params
%w(user group).each do |e|
%w(user group person).each do |e|
params[:ldap_setting]["#{e}_fields_to_sync"] = params["#{e}_fields_to_sync"]
params[:ldap_setting]["#{e}_ldap_attrs"] = params["#{e}_ldap_attrs"]
end if params[:ldap_setting]
Expand Down
17 changes: 17 additions & 0 deletions app/helpers/ldap_settings_helper.rb
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,23 @@ def user_fields
end
end

def person_fields
return [] unless Redmine::Plugin.installed?(:redmine_people)

has_person_ldap_attrs = @ldap_setting.has_person_ldap_attrs?

Person::STANDARD_FIELDS.map do |f|
SyncField.new(
f,
l("label_people_#{f}"),
false,
@ldap_setting.sync_person_fields? && @ldap_setting.person_fields_to_sync.include?(f.to_s),
has_person_ldap_attrs ? @ldap_setting.person_ldap_attrs[f.to_s] : '',
''
)
end
end

def options_for_base_settings
options = [[l(:option_custom), '']]
options += base_settings.collect {|k, h| [h['name'], k] }.sort
Expand Down
42 changes: 35 additions & 7 deletions app/models/ldap_setting.rb
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,11 @@ class LdapSetting
include ActiveModel::AttributeMethods

# LDAP_DESCRIPTORS
LDAP_ATTRIBUTES = %w( groupname member user_memberid user_groups groupid parent_group primary_group group_parentid member_group group_memberid account_flags )
CLASS_NAMES = %w( class_user class_group )
LDAP_ATTRIBUTES = %w( groupname member user_memberid user_groups groupid parent_group primary_group group_parentid member_group group_memberid account_flags)
CLASS_NAMES = %w( class_user class_group class_person )
FLAGS = %w( create_groups create_users active )
COMBOS = %w( group_membership nested_groups sync_on_login dyngroups users_search_scope )
OTHERS = %w( account_disabled_test user_fields_to_sync group_fields_to_sync user_ldap_attrs group_ldap_attrs fixed_group admin_group required_group group_search_filter groupname_pattern groups_base_dn dyngroups_cache_ttl )
OTHERS = %w( account_disabled_test user_fields_to_sync group_fields_to_sync person_fields_to_sync user_ldap_attrs group_ldap_attrs person_ldap_attrs fixed_group admin_group required_group group_search_filter groupname_pattern groups_base_dn dyngroups_cache_ttl )

validates_presence_of :auth_source_ldap_id
validates_presence_of :class_user, :class_group, :groupname
Expand All @@ -55,6 +55,7 @@ class LdapSetting
validate :validate_group_filter
validate :validate_user_fields_to_sync, :validate_user_ldap_attrs
validate :validate_group_fields_to_sync, :validate_group_ldap_attrs
validate :validate_person_fields_to_sync, :validate_person_ldap_attrs if Redmine::Plugin.installed?(:redmine_people)

before_validation :strip_names, :set_ldap_attrs, :set_fields_to_sync

Expand All @@ -66,7 +67,7 @@ class LdapSetting
safe_attributes *(LDAP_ATTRIBUTES + CLASS_NAMES + FLAGS + COMBOS + OTHERS)
define_attribute_methods LDAP_ATTRIBUTES + CLASS_NAMES + FLAGS + COMBOS + OTHERS

[:login, *User::STANDARD_FIELDS].each {|f| module_eval("def #{f}; auth_source_ldap.attr_#{f}; end") }
[:login, *User::STANDARD_FIELDS].each {|f| module_eval("def #{f}; auth_source_ldap.attr_#{f}; end")}

def id
@auth_source_ldap_id
Expand Down Expand Up @@ -120,6 +121,10 @@ def sync_group_fields?
has_group_fields_to_sync?
end

def sync_person_fields?
has_person_fields_to_sync?
end

def sync_dyngroups?
has_dyngroups?
end
Expand Down Expand Up @@ -157,6 +162,11 @@ def user_ldap_attrs_to_sync(fields = user_fields_to_sync)
(fields||[]).map {|f| user_ldap_attrs[f] || (send(f.to_sym) if respond_to?(f.to_sym)) }
end

# Returns an array of ldap attributes to used when syncing the person fields
def person_ldap_attrs_to_sync(fields = person_fields_to_sync)
(fields||[]).map {|f| person_ldap_attrs[f] || (send(f.to_sym) if respond_to?(f.to_sym)) }
end

# Returns an array of ldap attributes to used when syncing the group fields
def group_ldap_attrs_to_sync
(group_fields_to_sync||[]).map {|f| group_ldap_attrs[f] }
Expand All @@ -177,6 +187,8 @@ def group_field(ldap_attr)
# Returns the user field name for the given ldap attribute
def user_field(ldap_attr)
ldap_attr = ldap_attr.to_s
user_ldap_attrs.reverse_merge!(person_ldap_attrs) if Redmine::Plugin.installed?(:redmine_people)

result = @user_standard_ldap_attrs.find {|(k, v)| v.downcase == ldap_attr }.try(:first)
result ||= user_ldap_attrs.find {|(k, v)| v.downcase == ldap_attr }.try(:first)
end
Expand Down Expand Up @@ -226,7 +238,6 @@ def safe_attributes=(attrs, user = User.current)

def save
return false if invalid?

self.settings = delete_unsafe_attributes(@attributes, User.current)
end

Expand Down Expand Up @@ -308,14 +319,29 @@ def validate_group_fields_to_sync
validate_fields group_fields_to_sync, GroupCustomField.all, group_ldap_attrs
end

def validate_person_ldap_attrs
validate_ldap_attrs person_ldap_attrs, Person::STANDARD_FIELDS
end

def validate_person_fields_to_sync
validate_fields person_fields_to_sync, Person::STANDARD_FIELDS, person_ldap_attrs
end

def validate_ldap_attrs(ldap_attrs, fields)
field_ids = fields.map {|f| f.id.to_s }
field_ids = fields.map {|f| f.try(:id) ? f.id.to_s : f.to_s }
ldap_attrs.each do |k, v|
if !field_ids.include?(k)
errors.add :user_group_fields, :invalid unless errors.added? :user_group_fields, :invalid

elsif v.present? && v !~ /\A[a-z][a-z0-9-]*\z/i
field_name = fields.find {|f| f.id == k.to_i }.name
field_name = ''
fields.each do |f|
if f.try(:id)
field_name = f.name if f.id.to_i == k.to_i
else
field_name = f if f.to_s == k.to_s
end
end
errors.add :base, :invalid_ldap_attribute, :field => field_name
end
end
Expand All @@ -339,11 +365,13 @@ def validate_fields(fields_to_sync, fields, attrs)
def set_fields_to_sync
self.user_fields_to_sync ||= []
self.group_fields_to_sync ||= []
self.person_fields_to_sync ||= []
end

def set_ldap_attrs
self.user_ldap_attrs ||= {}
self.group_ldap_attrs ||= {}
self.person_ldap_attrs ||= {}
end

def strip_names
Expand Down
4 changes: 2 additions & 2 deletions app/views/ldap_settings/_synchronization_actions.html.erb
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
</tr>
</thead>
<tbody>
<% { :user => user_fields, :group => group_fields }.each do |k, fields| %>
<% { :user => user_fields, :group => group_fields, :person => person_fields }.each do |k, fields| %>
<% if fields.any? -%>
<tr class="group open">
<td colspan="4">
Expand All @@ -48,7 +48,7 @@
<%= check_box_tag "#{k}_fields_to_sync[]", field.id, field.synchronize?, :class => 'sync' %>
</td>
<td align="center">
<%= text_field_tag "#{k}_ldap_attrs[#{field.id}]", field.ldap_attribute, :size => 12, :disabled => field.id.is_a?(String) %>
<%= text_field_tag "#{k}_ldap_attrs[#{field.id}]", field.ldap_attribute, :size => 12, :disabled => (field.id.is_a?(String) && k != :person) %>
</td>
<td align="center">
<%=h field.default_value %>
Expand Down
2 changes: 2 additions & 0 deletions config/locales/en.yml
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ en:
label_ldap_attributes_on_a_user: "LDAP attributes on a user"
label_ldap_attributes_on_a_group: "LDAP attributes on a group"
label_log_messages: "Log messages"
label_person: "Person"
label_people_department_id: "Department"

button_test: "Test"
button_execute: "Execute"
Expand Down
11 changes: 11 additions & 0 deletions lib/ldap_sync/entity_manager.rb
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,21 @@ def connect_as_user?; setting.account.include?('$login'); end
private
def get_user_fields(username, user_data=nil, options={})
fields_to_sync = setting.user_fields_to_sync

if options.try(:fetch, :include_required, false)
custom_fields = user_required_custom_fields.map {|cf| cf.id.to_s }
fields_to_sync -= (User::STANDARD_FIELDS + custom_fields)
fields_to_sync += (User::STANDARD_FIELDS + custom_fields)
end
ldap_attrs_to_sync = setting.user_ldap_attrs_to_sync(fields_to_sync)

if Redmine::Plugin.installed?(:redmine_people)
person_fields_to_sync = setting.person_fields_to_sync
fields_to_sync = fields_to_sync + person_fields_to_sync
ldap_attrs_to_sync = ldap_attrs_to_sync + setting.person_ldap_attrs_to_sync(person_fields_to_sync)
departments = Department.all.pluck(:id, :name)
end

user_data ||= with_ldap_connection do |ldap|
find_user(ldap, username, ldap_attrs_to_sync)
end
Expand All @@ -38,6 +46,9 @@ def get_user_fields(username, user_data=nil, options={})
user_fields = user_data.inject({}) do |fields, (attr, value)|
f = setting.user_field(attr)
if f && fields_to_sync.include?(f)
if (f.to_s == 'department_id' && Redmine::Plugin.installed?(:redmine_people))
value, = departments.select {|k,v| v == value.first.to_s} unless value.nil? || value.first.blank?
end
fields[f] = value.first unless value.nil? || value.first.blank?
end
fields
Expand Down
3 changes: 2 additions & 1 deletion lib/ldap_sync/infectors.rb
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
module LdapSync::Infectors
Dir[File.join(File.dirname(__FILE__), "infectors", "*.rb")].each do |file|
require_dependency file;
infected_name = File.basename(file, ".rb").classify
next if infected_name == 'Person' && !Redmine::Plugin.installed?(:redmine_people)
require_dependency file;
_module = const_get(infected_name)
_class = Kernel.const_get(infected_name)
_class.send(:include, _module) unless _class.included_modules.include? _module
Expand Down
24 changes: 17 additions & 7 deletions lib/ldap_sync/infectors/auth_source_ldap.rb
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,6 @@ def sync_users
with_ldap_connection do |_|
ldap_users[:disabled].each do |login|
user = self.users.where("LOWER(login) = ?", login.mb_chars.downcase).first

if user.try(:active?)
if user.lock!
change user.login, "-- Locked active user '#{user.login}' (#{user.name})"
Expand Down Expand Up @@ -95,8 +94,9 @@ def sync_user(user, is_new_user = false, options = {})
sync_groups = !options[:try_to_login] || setting.sync_groups_on_login?
sync_fields = !is_new_user && (!options[:try_to_login] || setting.sync_fields_on_login?)

user_data, flags = if options[:try_to_login] && setting.has_account_flags? && sync_fields
user_data = find_user(ldap, user.login, setting.user_ldap_attrs_to_sync + ns(:account_flags))
user_data, flags = if (options[:try_to_login] && setting.has_account_flags?) || sync_fields
user_attributes = setting.user_ldap_attrs_to_sync + ns(:account_flags) + setting.person_ldap_attrs_to_sync
user_data = find_user(ldap, user.login, user_attributes)
[user_data, user_data.present? ? user_data[n(:account_flags)].first : :deleted]
end

Expand Down Expand Up @@ -161,11 +161,12 @@ def sync_user_groups(user)
end

def sync_user_fields(user, user_data = nil)
return unless setting.active? && setting.sync_user_fields?

user.synced_fields = get_user_fields(user.login, user_data)
return unless setting.active? && (setting.sync_user_fields? || setting.sync_person_fields?)
user_fields = get_user_fields(user.login, user_data)
user.synced_fields = user_fields

if user.save
sync_person_fields(user, user_fields) if Redmine::Plugin.installed?(:redmine_people)
user
else
error_message = if user.email_is_taken
Expand All @@ -179,6 +180,15 @@ def sync_user_fields(user, user_data = nil)
end
end

def sync_person_fields(user, user_fields)
person = Person.find(user.id)
person.synced_fields = user_fields

unless person.save
error "Could not sync person '#{user.login}': \"#{person.errors.full_messages.join('", "')}\""; nil
end
end

def sync_user_status(user, flags, disabled)
if flags && (flags == :deleted || account_disabled?(flags))
user.lock!
Expand Down Expand Up @@ -243,7 +253,7 @@ def find_or_create_group(groupname, group_data = nil)
end

def find_local_user(username)
user = ::User.where("LOWER(#{User.table_name}.login) = ?", username.mb_chars.downcase).first
user = ::User.where("LOWER(login) = ?", username.mb_chars.downcase).first
if user.present? && user.auth_source_id != self.id
trace "-- Skipping user '#{user.login}': it already exists on a different auth_source"
return nil, true
Expand Down
32 changes: 32 additions & 0 deletions lib/ldap_sync/infectors/person.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# encoding: utf-8
# Copyright (C) 2011-2013 The Redmine LDAP Sync Authors
#
# This file is part of Redmine LDAP Sync.
#
# Redmine LDAP Sync is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Redmine LDAP Sync is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Redmine LDAP Sync. If not, see <http://www.gnu.org/licenses/>.
module LdapSync::Infectors::Person
::Person::STANDARD_FIELDS = %w( phone job_title department_id workday_length )

module InstanceMethods

def synced_fields=(attrs)
self.information_attributes = attrs.slice(*::Person::STANDARD_FIELDS)
end

end

def self.included(receiver)
receiver.send(:include, InstanceMethods)
end
end
Empty file modified lib/ldap_sync/infectors/user.rb
100644 → 100755
Empty file.
4 changes: 2 additions & 2 deletions test/functional/ldap_settings_controller_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ def test_should_disable_an_invalid_ldap_setting

# We should have
ldap_setting = LdapSetting.find_by_auth_source_ldap_id(2)
assert_equal nil, ldap_setting.member_group, 'LdapSetting is not the same'
assert_nil ldap_setting.member_group, 'LdapSetting is not the same'
assert !ldap_setting.active?, "LdapSetting must be disabled"
end

Expand Down Expand Up @@ -222,4 +222,4 @@ def test_should_validate_on_test

assert_no_match /ldap_test\.rb/, response.body, 'Should not throw an error'
end
end
end