Revision 1297:0a574315af3e .svn/pristine/28
| .svn/pristine/28/28353268d3c195811c8a35a1db4bfdbe62848deb.svn-base | ||
|---|---|---|
| 1 |
<h4><%= link_to h(document.title), document_path(document) %></h4> |
|
| 2 |
<p><em><%= format_time(document.updated_on) %></em></p> |
|
| 3 |
|
|
| 4 |
<div class="wiki"> |
|
| 5 |
<%= textilizable(truncate_lines(document.description), :object => document) %> |
|
| 6 |
</div> |
|
| .svn/pristine/28/28460f7863cf0e308a71ddfcfde8f112f06716f0.svn-base | ||
|---|---|---|
| 1 |
module ActiveRecord |
|
| 2 |
module Acts |
|
| 3 |
module Tree |
|
| 4 |
def self.included(base) |
|
| 5 |
base.extend(ClassMethods) |
|
| 6 |
end |
|
| 7 |
|
|
| 8 |
# Specify this +acts_as+ extension if you want to model a tree structure by providing a parent association and a children |
|
| 9 |
# association. This requires that you have a foreign key column, which by default is called +parent_id+. |
|
| 10 |
# |
|
| 11 |
# class Category < ActiveRecord::Base |
|
| 12 |
# acts_as_tree :order => "name" |
|
| 13 |
# end |
|
| 14 |
# |
|
| 15 |
# Example: |
|
| 16 |
# root |
|
| 17 |
# \_ child1 |
|
| 18 |
# \_ subchild1 |
|
| 19 |
# \_ subchild2 |
|
| 20 |
# |
|
| 21 |
# root = Category.create("name" => "root")
|
|
| 22 |
# child1 = root.children.create("name" => "child1")
|
|
| 23 |
# subchild1 = child1.children.create("name" => "subchild1")
|
|
| 24 |
# |
|
| 25 |
# root.parent # => nil |
|
| 26 |
# child1.parent # => root |
|
| 27 |
# root.children # => [child1] |
|
| 28 |
# root.children.first.children.first # => subchild1 |
|
| 29 |
# |
|
| 30 |
# In addition to the parent and children associations, the following instance methods are added to the class |
|
| 31 |
# after calling <tt>acts_as_tree</tt>: |
|
| 32 |
# * <tt>siblings</tt> - Returns all the children of the parent, excluding the current node (<tt>[subchild2]</tt> when called on <tt>subchild1</tt>) |
|
| 33 |
# * <tt>self_and_siblings</tt> - Returns all the children of the parent, including the current node (<tt>[subchild1, subchild2]</tt> when called on <tt>subchild1</tt>) |
|
| 34 |
# * <tt>ancestors</tt> - Returns all the ancestors of the current node (<tt>[child1, root]</tt> when called on <tt>subchild2</tt>) |
|
| 35 |
# * <tt>root</tt> - Returns the root of the current node (<tt>root</tt> when called on <tt>subchild2</tt>) |
|
| 36 |
module ClassMethods |
|
| 37 |
# Configuration options are: |
|
| 38 |
# |
|
| 39 |
# * <tt>foreign_key</tt> - specifies the column name to use for tracking of the tree (default: +parent_id+) |
|
| 40 |
# * <tt>order</tt> - makes it possible to sort the children according to this SQL snippet. |
|
| 41 |
# * <tt>counter_cache</tt> - keeps a count in a +children_count+ column if set to +true+ (default: +false+). |
|
| 42 |
def acts_as_tree(options = {})
|
|
| 43 |
configuration = { :foreign_key => "parent_id", :dependent => :destroy, :order => nil, :counter_cache => nil }
|
|
| 44 |
configuration.update(options) if options.is_a?(Hash) |
|
| 45 |
|
|
| 46 |
belongs_to :parent, :class_name => name, :foreign_key => configuration[:foreign_key], :counter_cache => configuration[:counter_cache] |
|
| 47 |
has_many :children, :class_name => name, :foreign_key => configuration[:foreign_key], :order => configuration[:order], :dependent => configuration[:dependent] |
|
| 48 |
|
|
| 49 |
class_eval <<-EOV |
|
| 50 |
include ActiveRecord::Acts::Tree::InstanceMethods |
|
| 51 |
|
|
| 52 |
def self.roots |
|
| 53 |
find(:all, :conditions => "#{configuration[:foreign_key]} IS NULL", :order => #{configuration[:order].nil? ? "nil" : %Q{"#{configuration[:order]}"}})
|
|
| 54 |
end |
|
| 55 |
|
|
| 56 |
def self.root |
|
| 57 |
find(:first, :conditions => "#{configuration[:foreign_key]} IS NULL", :order => #{configuration[:order].nil? ? "nil" : %Q{"#{configuration[:order]}"}})
|
|
| 58 |
end |
|
| 59 |
EOV |
|
| 60 |
end |
|
| 61 |
end |
|
| 62 |
|
|
| 63 |
module InstanceMethods |
|
| 64 |
# Returns list of ancestors, starting from parent until root. |
|
| 65 |
# |
|
| 66 |
# subchild1.ancestors # => [child1, root] |
|
| 67 |
def ancestors |
|
| 68 |
node, nodes = self, [] |
|
| 69 |
nodes << node = node.parent while node.parent |
|
| 70 |
nodes |
|
| 71 |
end |
|
| 72 |
|
|
| 73 |
# Returns list of descendants. |
|
| 74 |
# |
|
| 75 |
# root.descendants # => [child1, subchild1, subchild2] |
|
| 76 |
def descendants(depth=nil) |
|
| 77 |
depth ||= 0 |
|
| 78 |
result = children.dup |
|
| 79 |
unless depth == 1 |
|
| 80 |
result += children.collect {|child| child.descendants(depth-1)}.flatten
|
|
| 81 |
end |
|
| 82 |
result |
|
| 83 |
end |
|
| 84 |
|
|
| 85 |
# Returns list of descendants and a reference to the current node. |
|
| 86 |
# |
|
| 87 |
# root.self_and_descendants # => [root, child1, subchild1, subchild2] |
|
| 88 |
def self_and_descendants(depth=nil) |
|
| 89 |
[self] + descendants(depth) |
|
| 90 |
end |
|
| 91 |
|
|
| 92 |
# Returns the root node of the tree. |
|
| 93 |
def root |
|
| 94 |
node = self |
|
| 95 |
node = node.parent while node.parent |
|
| 96 |
node |
|
| 97 |
end |
|
| 98 |
|
|
| 99 |
# Returns all siblings of the current node. |
|
| 100 |
# |
|
| 101 |
# subchild1.siblings # => [subchild2] |
|
| 102 |
def siblings |
|
| 103 |
self_and_siblings - [self] |
|
| 104 |
end |
|
| 105 |
|
|
| 106 |
# Returns all siblings and a reference to the current node. |
|
| 107 |
# |
|
| 108 |
# subchild1.self_and_siblings # => [subchild1, subchild2] |
|
| 109 |
def self_and_siblings |
|
| 110 |
parent ? parent.children : self.class.roots |
|
| 111 |
end |
|
| 112 |
end |
|
| 113 |
end |
|
| 114 |
end |
|
| 115 |
end |
|
| .svn/pristine/28/284f5f782295ac4c8fe3dbacfe87f5903171e538.svn-base | ||
|---|---|---|
| 1 |
# Redmine - project management software |
|
| 2 |
# Copyright (C) 2006-2012 Jean-Philippe Lang |
|
| 3 |
# |
|
| 4 |
# This program is free software; you can redistribute it and/or |
|
| 5 |
# modify it under the terms of the GNU General Public License |
|
| 6 |
# as published by the Free Software Foundation; either version 2 |
|
| 7 |
# of the License, or (at your option) any later version. |
|
| 8 |
# |
|
| 9 |
# This program is distributed in the hope that it will be useful, |
|
| 10 |
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
| 11 |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| 12 |
# GNU General Public License for more details. |
|
| 13 |
# |
|
| 14 |
# You should have received a copy of the GNU General Public License |
|
| 15 |
# along with this program; if not, write to the Free Software |
|
| 16 |
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
|
| 17 |
|
|
| 18 |
require File.expand_path('../../../test_helper', __FILE__)
|
|
| 19 |
|
|
| 20 |
class ApiTest::IssueCategoriesTest < ActionController::IntegrationTest |
|
| 21 |
fixtures :projects, :users, :issue_categories, :issues, |
|
| 22 |
:roles, |
|
| 23 |
:member_roles, |
|
| 24 |
:members, |
|
| 25 |
:enabled_modules |
|
| 26 |
|
|
| 27 |
def setup |
|
| 28 |
Setting.rest_api_enabled = '1' |
|
| 29 |
end |
|
| 30 |
|
|
| 31 |
context "GET /projects/:project_id/issue_categories.xml" do |
|
| 32 |
should "return issue categories" do |
|
| 33 |
get '/projects/1/issue_categories.xml', {}, credentials('jsmith')
|
|
| 34 |
assert_response :success |
|
| 35 |
assert_equal 'application/xml', @response.content_type |
|
| 36 |
assert_tag :tag => 'issue_categories', |
|
| 37 |
:child => {:tag => 'issue_category', :child => {:tag => 'id', :content => '2'}}
|
|
| 38 |
end |
|
| 39 |
end |
|
| 40 |
|
|
| 41 |
context "GET /issue_categories/2.xml" do |
|
| 42 |
should "return requested issue category" do |
|
| 43 |
get '/issue_categories/2.xml', {}, credentials('jsmith')
|
|
| 44 |
assert_response :success |
|
| 45 |
assert_equal 'application/xml', @response.content_type |
|
| 46 |
assert_tag :tag => 'issue_category', |
|
| 47 |
:child => {:tag => 'id', :content => '2'}
|
|
| 48 |
end |
|
| 49 |
end |
|
| 50 |
|
|
| 51 |
context "POST /projects/:project_id/issue_categories.xml" do |
|
| 52 |
should "return create issue category" do |
|
| 53 |
assert_difference 'IssueCategory.count' do |
|
| 54 |
post '/projects/1/issue_categories.xml', {:issue_category => {:name => 'API'}}, credentials('jsmith')
|
|
| 55 |
end |
|
| 56 |
assert_response :created |
|
| 57 |
assert_equal 'application/xml', @response.content_type |
|
| 58 |
|
|
| 59 |
category = IssueCategory.first(:order => 'id DESC') |
|
| 60 |
assert_equal 'API', category.name |
|
| 61 |
assert_equal 1, category.project_id |
|
| 62 |
end |
|
| 63 |
|
|
| 64 |
context "with invalid parameters" do |
|
| 65 |
should "return errors" do |
|
| 66 |
assert_no_difference 'IssueCategory.count' do |
|
| 67 |
post '/projects/1/issue_categories.xml', {:issue_category => {:name => ''}}, credentials('jsmith')
|
|
| 68 |
end |
|
| 69 |
assert_response :unprocessable_entity |
|
| 70 |
assert_equal 'application/xml', @response.content_type |
|
| 71 |
|
|
| 72 |
assert_tag 'errors', :child => {:tag => 'error', :content => "Name can't be blank"}
|
|
| 73 |
end |
|
| 74 |
end |
|
| 75 |
end |
|
| 76 |
|
|
| 77 |
context "PUT /issue_categories/2.xml" do |
|
| 78 |
context "with valid parameters" do |
|
| 79 |
should "update issue category" do |
|
| 80 |
assert_no_difference 'IssueCategory.count' do |
|
| 81 |
put '/issue_categories/2.xml', {:issue_category => {:name => 'API Update'}}, credentials('jsmith')
|
|
| 82 |
end |
|
| 83 |
assert_response :ok |
|
| 84 |
assert_equal '', @response.body |
|
| 85 |
assert_equal 'API Update', IssueCategory.find(2).name |
|
| 86 |
end |
|
| 87 |
end |
|
| 88 |
|
|
| 89 |
context "with invalid parameters" do |
|
| 90 |
should "return errors" do |
|
| 91 |
assert_no_difference 'IssueCategory.count' do |
|
| 92 |
put '/issue_categories/2.xml', {:issue_category => {:name => ''}}, credentials('jsmith')
|
|
| 93 |
end |
|
| 94 |
assert_response :unprocessable_entity |
|
| 95 |
assert_equal 'application/xml', @response.content_type |
|
| 96 |
|
|
| 97 |
assert_tag 'errors', :child => {:tag => 'error', :content => "Name can't be blank"}
|
|
| 98 |
end |
|
| 99 |
end |
|
| 100 |
end |
|
| 101 |
|
|
| 102 |
context "DELETE /issue_categories/1.xml" do |
|
| 103 |
should "destroy issue categories" do |
|
| 104 |
assert_difference 'IssueCategory.count', -1 do |
|
| 105 |
delete '/issue_categories/1.xml', {}, credentials('jsmith')
|
|
| 106 |
end |
|
| 107 |
assert_response :ok |
|
| 108 |
assert_equal '', @response.body |
|
| 109 |
assert_nil IssueCategory.find_by_id(1) |
|
| 110 |
end |
|
| 111 |
|
|
| 112 |
should "reassign issues with :reassign_to_id param" do |
|
| 113 |
issue_count = Issue.count(:conditions => {:category_id => 1})
|
|
| 114 |
assert issue_count > 0 |
|
| 115 |
|
|
| 116 |
assert_difference 'IssueCategory.count', -1 do |
|
| 117 |
assert_difference 'Issue.count(:conditions => {:category_id => 2})', 3 do
|
|
| 118 |
delete '/issue_categories/1.xml', {:reassign_to_id => 2}, credentials('jsmith')
|
|
| 119 |
end |
|
| 120 |
end |
|
| 121 |
assert_response :ok |
|
| 122 |
assert_equal '', @response.body |
|
| 123 |
assert_nil IssueCategory.find_by_id(1) |
|
| 124 |
end |
|
| 125 |
end |
|
| 126 |
end |
|
| .svn/pristine/28/287ad425b706a1e849a16749d3a013cf82f1d342.svn-base | ||
|---|---|---|
| 1 |
# Redmine - project management software |
|
| 2 |
# Copyright (C) 2006-2012 Jean-Philippe Lang |
|
| 3 |
# |
|
| 4 |
# This program is free software; you can redistribute it and/or |
|
| 5 |
# modify it under the terms of the GNU General Public License |
|
| 6 |
# as published by the Free Software Foundation; either version 2 |
|
| 7 |
# of the License, or (at your option) any later version. |
|
| 8 |
# |
|
| 9 |
# This program is distributed in the hope that it will be useful, |
|
| 10 |
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
| 11 |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| 12 |
# GNU General Public License for more details. |
|
| 13 |
# |
|
| 14 |
# You should have received a copy of the GNU General Public License |
|
| 15 |
# along with this program; if not, write to the Free Software |
|
| 16 |
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
|
| 17 |
|
|
| 18 |
require File.expand_path('../../../../../test_helper', __FILE__)
|
|
| 19 |
|
|
| 20 |
class Redmine::Utils::DateCalculationTest < ActiveSupport::TestCase |
|
| 21 |
include Redmine::Utils::DateCalculation |
|
| 22 |
|
|
| 23 |
def test_working_days_without_non_working_week_days |
|
| 24 |
with_settings :non_working_week_days => [] do |
|
| 25 |
assert_working_days 18, '2012-10-09', '2012-10-27' |
|
| 26 |
assert_working_days 6, '2012-10-09', '2012-10-15' |
|
| 27 |
assert_working_days 5, '2012-10-09', '2012-10-14' |
|
| 28 |
assert_working_days 3, '2012-10-09', '2012-10-12' |
|
| 29 |
assert_working_days 3, '2012-10-14', '2012-10-17' |
|
| 30 |
assert_working_days 16, '2012-10-14', '2012-10-30' |
|
| 31 |
end |
|
| 32 |
end |
|
| 33 |
|
|
| 34 |
def test_working_days_with_non_working_week_days |
|
| 35 |
with_settings :non_working_week_days => %w(6 7) do |
|
| 36 |
assert_working_days 14, '2012-10-09', '2012-10-27' |
|
| 37 |
assert_working_days 4, '2012-10-09', '2012-10-15' |
|
| 38 |
assert_working_days 4, '2012-10-09', '2012-10-14' |
|
| 39 |
assert_working_days 3, '2012-10-09', '2012-10-12' |
|
| 40 |
assert_working_days 8, '2012-10-09', '2012-10-19' |
|
| 41 |
assert_working_days 8, '2012-10-11', '2012-10-23' |
|
| 42 |
assert_working_days 2, '2012-10-14', '2012-10-17' |
|
| 43 |
assert_working_days 11, '2012-10-14', '2012-10-30' |
|
| 44 |
end |
|
| 45 |
end |
|
| 46 |
|
|
| 47 |
def test_add_working_days_without_non_working_week_days |
|
| 48 |
with_settings :non_working_week_days => [] do |
|
| 49 |
assert_add_working_days '2012-10-10', '2012-10-10', 0 |
|
| 50 |
assert_add_working_days '2012-10-11', '2012-10-10', 1 |
|
| 51 |
assert_add_working_days '2012-10-12', '2012-10-10', 2 |
|
| 52 |
assert_add_working_days '2012-10-13', '2012-10-10', 3 |
|
| 53 |
assert_add_working_days '2012-10-25', '2012-10-10', 15 |
|
| 54 |
end |
|
| 55 |
end |
|
| 56 |
|
|
| 57 |
def test_add_working_days_with_non_working_week_days |
|
| 58 |
with_settings :non_working_week_days => %w(6 7) do |
|
| 59 |
assert_add_working_days '2012-10-10', '2012-10-10', 0 |
|
| 60 |
assert_add_working_days '2012-10-11', '2012-10-10', 1 |
|
| 61 |
assert_add_working_days '2012-10-12', '2012-10-10', 2 |
|
| 62 |
assert_add_working_days '2012-10-15', '2012-10-10', 3 |
|
| 63 |
assert_add_working_days '2012-10-31', '2012-10-10', 15 |
|
| 64 |
assert_add_working_days '2012-10-19', '2012-10-09', 8 |
|
| 65 |
assert_add_working_days '2012-10-23', '2012-10-11', 8 |
|
| 66 |
end |
|
| 67 |
end |
|
| 68 |
|
|
| 69 |
def assert_working_days(expected_days, from, to) |
|
| 70 |
assert_equal expected_days, working_days(from.to_date, to.to_date) |
|
| 71 |
end |
|
| 72 |
|
|
| 73 |
def assert_add_working_days(expected_date, from, working_days) |
|
| 74 |
assert_equal expected_date.to_date, add_working_days(from.to_date, working_days) |
|
| 75 |
end |
|
| 76 |
end |
|
| .svn/pristine/28/287b739e36a269ed72c54dcd10ebdefa5f23d6ee.svn-base | ||
|---|---|---|
| 1 |
# Redmine - project management software |
|
| 2 |
# Copyright (C) 2006-2012 Jean-Philippe Lang |
|
| 3 |
# |
|
| 4 |
# This program is free software; you can redistribute it and/or |
|
| 5 |
# modify it under the terms of the GNU General Public License |
|
| 6 |
# as published by the Free Software Foundation; either version 2 |
|
| 7 |
# of the License, or (at your option) any later version. |
|
| 8 |
# |
|
| 9 |
# This program is distributed in the hope that it will be useful, |
|
| 10 |
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
| 11 |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| 12 |
# GNU General Public License for more details. |
|
| 13 |
# |
|
| 14 |
# You should have received a copy of the GNU General Public License |
|
| 15 |
# along with this program; if not, write to the Free Software |
|
| 16 |
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
|
| 17 |
|
|
| 18 |
require 'iconv' |
|
| 19 |
require 'net/ldap' |
|
| 20 |
require 'net/ldap/dn' |
|
| 21 |
require 'timeout' |
|
| 22 |
|
|
| 23 |
class AuthSourceLdap < AuthSource |
|
| 24 |
validates_presence_of :host, :port, :attr_login |
|
| 25 |
validates_length_of :name, :host, :maximum => 60, :allow_nil => true |
|
| 26 |
validates_length_of :account, :account_password, :base_dn, :filter, :maximum => 255, :allow_blank => true |
|
| 27 |
validates_length_of :attr_login, :attr_firstname, :attr_lastname, :attr_mail, :maximum => 30, :allow_nil => true |
|
| 28 |
validates_numericality_of :port, :only_integer => true |
|
| 29 |
validates_numericality_of :timeout, :only_integer => true, :allow_blank => true |
|
| 30 |
validate :validate_filter |
|
| 31 |
|
|
| 32 |
before_validation :strip_ldap_attributes |
|
| 33 |
|
|
| 34 |
def initialize(attributes=nil, *args) |
|
| 35 |
super |
|
| 36 |
self.port = 389 if self.port == 0 |
|
| 37 |
end |
|
| 38 |
|
|
| 39 |
def authenticate(login, password) |
|
| 40 |
return nil if login.blank? || password.blank? |
|
| 41 |
|
|
| 42 |
with_timeout do |
|
| 43 |
attrs = get_user_dn(login, password) |
|
| 44 |
if attrs && attrs[:dn] && authenticate_dn(attrs[:dn], password) |
|
| 45 |
logger.debug "Authentication successful for '#{login}'" if logger && logger.debug?
|
|
| 46 |
return attrs.except(:dn) |
|
| 47 |
end |
|
| 48 |
end |
|
| 49 |
rescue Net::LDAP::LdapError => e |
|
| 50 |
raise AuthSourceException.new(e.message) |
|
| 51 |
end |
|
| 52 |
|
|
| 53 |
# test the connection to the LDAP |
|
| 54 |
def test_connection |
|
| 55 |
with_timeout do |
|
| 56 |
ldap_con = initialize_ldap_con(self.account, self.account_password) |
|
| 57 |
ldap_con.open { }
|
|
| 58 |
end |
|
| 59 |
rescue Net::LDAP::LdapError => e |
|
| 60 |
raise AuthSourceException.new(e.message) |
|
| 61 |
end |
|
| 62 |
|
|
| 63 |
def auth_method_name |
|
| 64 |
"LDAP" |
|
| 65 |
end |
|
| 66 |
|
|
| 67 |
private |
|
| 68 |
|
|
| 69 |
def with_timeout(&block) |
|
| 70 |
timeout = self.timeout |
|
| 71 |
timeout = 20 unless timeout && timeout > 0 |
|
| 72 |
Timeout.timeout(timeout) do |
|
| 73 |
return yield |
|
| 74 |
end |
|
| 75 |
rescue Timeout::Error => e |
|
| 76 |
raise AuthSourceTimeoutException.new(e.message) |
|
| 77 |
end |
|
| 78 |
|
|
| 79 |
def ldap_filter |
|
| 80 |
if filter.present? |
|
| 81 |
Net::LDAP::Filter.construct(filter) |
|
| 82 |
end |
|
| 83 |
rescue Net::LDAP::LdapError |
|
| 84 |
nil |
|
| 85 |
end |
|
| 86 |
|
|
| 87 |
def validate_filter |
|
| 88 |
if filter.present? && ldap_filter.nil? |
|
| 89 |
errors.add(:filter, :invalid) |
|
| 90 |
end |
|
| 91 |
end |
|
| 92 |
|
|
| 93 |
def strip_ldap_attributes |
|
| 94 |
[:attr_login, :attr_firstname, :attr_lastname, :attr_mail].each do |attr| |
|
| 95 |
write_attribute(attr, read_attribute(attr).strip) unless read_attribute(attr).nil? |
|
| 96 |
end |
|
| 97 |
end |
|
| 98 |
|
|
| 99 |
def initialize_ldap_con(ldap_user, ldap_password) |
|
| 100 |
options = { :host => self.host,
|
|
| 101 |
:port => self.port, |
|
| 102 |
:encryption => (self.tls ? :simple_tls : nil) |
|
| 103 |
} |
|
| 104 |
options.merge!(:auth => { :method => :simple, :username => ldap_user, :password => ldap_password }) unless ldap_user.blank? && ldap_password.blank?
|
|
| 105 |
Net::LDAP.new options |
|
| 106 |
end |
|
| 107 |
|
|
| 108 |
def get_user_attributes_from_ldap_entry(entry) |
|
| 109 |
{
|
|
| 110 |
:dn => entry.dn, |
|
| 111 |
:firstname => AuthSourceLdap.get_attr(entry, self.attr_firstname), |
|
| 112 |
:lastname => AuthSourceLdap.get_attr(entry, self.attr_lastname), |
|
| 113 |
:mail => AuthSourceLdap.get_attr(entry, self.attr_mail), |
|
| 114 |
:auth_source_id => self.id |
|
| 115 |
} |
|
| 116 |
end |
|
| 117 |
|
|
| 118 |
# Return the attributes needed for the LDAP search. It will only |
|
| 119 |
# include the user attributes if on-the-fly registration is enabled |
|
| 120 |
def search_attributes |
|
| 121 |
if onthefly_register? |
|
| 122 |
['dn', self.attr_firstname, self.attr_lastname, self.attr_mail] |
|
| 123 |
else |
|
| 124 |
['dn'] |
|
| 125 |
end |
|
| 126 |
end |
|
| 127 |
|
|
| 128 |
# Check if a DN (user record) authenticates with the password |
|
| 129 |
def authenticate_dn(dn, password) |
|
| 130 |
if dn.present? && password.present? |
|
| 131 |
initialize_ldap_con(dn, password).bind |
|
| 132 |
end |
|
| 133 |
end |
|
| 134 |
|
|
| 135 |
# Get the user's dn and any attributes for them, given their login |
|
| 136 |
def get_user_dn(login, password) |
|
| 137 |
ldap_con = nil |
|
| 138 |
if self.account && self.account.include?("$login")
|
|
| 139 |
ldap_con = initialize_ldap_con(self.account.sub("$login", Net::LDAP::DN.escape(login)), password)
|
|
| 140 |
else |
|
| 141 |
ldap_con = initialize_ldap_con(self.account, self.account_password) |
|
| 142 |
end |
|
| 143 |
login_filter = Net::LDAP::Filter.eq( self.attr_login, login ) |
|
| 144 |
object_filter = Net::LDAP::Filter.eq( "objectClass", "*" ) |
|
| 145 |
attrs = {}
|
|
| 146 |
|
|
| 147 |
search_filter = object_filter & login_filter |
|
| 148 |
if f = ldap_filter |
|
| 149 |
search_filter = search_filter & f |
|
| 150 |
end |
|
| 151 |
|
|
| 152 |
ldap_con.search( :base => self.base_dn, |
|
| 153 |
:filter => search_filter, |
|
| 154 |
:attributes=> search_attributes) do |entry| |
|
| 155 |
|
|
| 156 |
if onthefly_register? |
|
| 157 |
attrs = get_user_attributes_from_ldap_entry(entry) |
|
| 158 |
else |
|
| 159 |
attrs = {:dn => entry.dn}
|
|
| 160 |
end |
|
| 161 |
|
|
| 162 |
logger.debug "DN found for #{login}: #{attrs[:dn]}" if logger && logger.debug?
|
|
| 163 |
end |
|
| 164 |
|
|
| 165 |
attrs |
|
| 166 |
end |
|
| 167 |
|
|
| 168 |
def self.get_attr(entry, attr_name) |
|
| 169 |
if !attr_name.blank? |
|
| 170 |
entry[attr_name].is_a?(Array) ? entry[attr_name].first : entry[attr_name] |
|
| 171 |
end |
|
| 172 |
end |
|
| 173 |
end |
|
| .svn/pristine/28/28ad874b5f46ac1b00ddf0031a0a20aed5e4e9c0.svn-base | ||
|---|---|---|
| 1 |
Description: |
|
| 2 |
Generates a plugin model. |
|
| 3 |
|
|
| 4 |
Examples: |
|
| 5 |
./script/rails generate redmine_plugin_model meetings pool |
|
Also available in: Unified diff